File Coverage

blib/lib/DBIx/RunSQL.pm
Criterion Covered Total %
statement 55 157 35.0
branch 15 84 17.8
condition 9 38 23.6
subroutine 12 19 63.1
pod 7 8 87.5
total 98 306 32.0


line stmt bran cond sub pod time code
1             package DBIx::RunSQL;
2 11     11   1674465 use 5.020;
  11         46  
3 11     11   5673 use experimental 'signatures';
  11         44829  
  11         78  
4 11     11   8021 use stable 'postderef';
  11         5066  
  11         69  
5 11     11   18685 use DBI;
  11         273736  
  11         1119  
6 11     11   7465 use Module::Load 'load';
  11         17436  
  11         109  
7 11     11   1012 use Carp 'croak';
  11         27  
  11         40289  
8              
9             our $VERSION = '0.26';
10              
11             =encoding utf8
12              
13             =head1 NAME
14              
15             DBIx::RunSQL - run SQL from a file
16              
17             =cut
18              
19             =head1 SYNOPSIS
20              
21             #!/usr/bin/perl -w
22             use strict;
23             use DBIx::RunSQL;
24              
25             my $test_dbh = DBIx::RunSQL->create(
26             dsn => 'dbi:SQLite:dbname=:memory:',
27             sql => 'sql/create.sql',
28             options => { PrintError => 0, RaiseError => 1 },
29             force => 1,
30             verbose => 1,
31             formatter => 'Text::Table',
32             rotate => 1,
33             null => '(Null)',
34             );
35              
36             # now run your tests with a DB setup fresh from setup.sql
37              
38             =head1 METHODS
39              
40             =head2 C<< DBIx::RunSQL->create ARGS >>
41              
42             =head2 C<< DBIx::RunSQL->run ARGS >>
43              
44             Runs the SQL commands and returns the database handle.
45             In list context, it returns the database handle and the
46             suggested exit code.
47              
48             =over 4
49              
50             =item *
51              
52             C - name of the file containing the SQL statements
53              
54             The default is C
55              
56             If C is a reference to a glob or a filehandle,
57             the SQL will be read from that. B
58              
59             If C is undefined, the C<$::DATA> or the C<0> filehandle will
60             be read until exhaustion. B
61              
62             This allows one to create SQL-as-programs as follows:
63              
64             #!/usr/bin/perl -w -MDBIx::RunSQL -e 'create()'
65             create table ...
66              
67             If you want to run SQL statements from a scalar,
68             you can simply pass in a reference to a scalar containing the SQL:
69              
70             sql => \"update mytable set foo='bar';",
71              
72             =item *
73              
74             C, C, C, C - DBI parameters for connecting to the DB
75              
76             =item *
77              
78             C - a premade database handle to be used instead of C
79              
80             =item *
81              
82             C - continue even if errors are encountered
83              
84             =item *
85              
86             C - print each SQL statement as it is run
87              
88             =item *
89              
90             C - callback to call with each SQL statement instead of C
91              
92             =item *
93              
94             C - filehandle to write to instead of C
95              
96             =back
97              
98             =cut
99              
100             sub create {
101 0     0 1 0 my ($self,%args) = @_;
102 0   0     0 $args{sql} ||= 'sql/create.sql';
103              
104 0   0     0 $args{options} ||= {};
105              
106 0         0 my $dbh = delete $args{ dbh };
107 0 0       0 if (! $dbh) {
108             $dbh = DBI->connect($args{dsn}, $args{user}, $args{password}, $args{options})
109 0 0       0 or die "Couldn't connect to DSN '$args{dsn}' : " . DBI->errstr;
110             };
111              
112 0         0 my $errors = $self->run_sql_file(
113             dbh => $dbh,
114             %args,
115             );
116 0 0       0 return wantarray ? ($dbh, $errors) : $dbh;
117             };
118             *run = *run = \&create;
119              
120             =head2 C<< DBIx::RunSQL->run_sql_file ARGS >>
121              
122             my $dbh = DBI->connect(...)
123              
124             for my $file (sort glob '*.sql') {
125             DBIx::RunSQL->run_sql_file(
126             verbose => 1,
127             dbh => $dbh,
128             sql => $file,
129             );
130             };
131              
132             Runs an SQL file on a prepared database handle.
133             Returns the number of errors encountered.
134              
135             If the statement returns rows, these are printed
136             separated with tabs.
137              
138             =over 4
139              
140             =item *
141              
142             C - a premade database handle
143              
144             =item *
145              
146             C - name of the file containing the SQL statements
147              
148             =item *
149              
150             C - filehandle to the file containing the SQL statements
151              
152             =item *
153              
154             C - continue even if errors are encountered
155              
156             =item *
157              
158             C - print each SQL statement as it is run
159              
160             =item *
161              
162             C - callback to call with each SQL statement instead of
163             C
164              
165             =item *
166              
167             C - filehandle to write to instead of C
168              
169             =item *
170              
171             C - whether to exit with a nonzero exit code if any row is found
172              
173             This makes the function return a nonzero value even if there is no error
174             but a row was found.
175              
176             =item *
177              
178             C - whether to output the (one) row and column, without any
179             headers
180              
181             =item *
182              
183             C - see the C<> option of C<< ->format_results >>
184              
185             =item *
186              
187             C - rotate the table by 90° , outputting columns as rows
188              
189             =item *
190              
191             C - string to replace SQL C columns by
192              
193             =back
194              
195             =cut
196              
197             sub run_sql_file {
198 0     0 1 0 my ($self,%args) = @_;
199 0 0       0 if( ! $args{ fh }) {
200             open $args{ fh }, "<:crlf", $args{sql}
201 0 0       0 or die "Couldn't read '$args{sql}' : $!";
202 0         0 delete $args{ sql };
203             };
204 0         0 $self->run_sql(
205             %args,
206             );
207             }
208              
209             =head2 C<< DBIx::RunSQL->run_sql ARGS >>
210              
211             my $dbh = DBI->connect(...)
212              
213             DBIx::RunSQL->run_sql(
214             verbose => 1,
215             dbh => $dbh,
216             sql => \@sql_statements,
217             );
218              
219             Runs an SQL string on a prepared database handle.
220             Returns the number of errors encountered.
221              
222             If the statement returns rows, these are printed
223             separated with tabs, but see the C and C options.
224              
225             =over 4
226              
227             =item *
228              
229             C - a premade database handle
230              
231             =item *
232              
233             C - string or array reference containing the SQL statements
234              
235             =item *
236              
237             C - continue even if errors are encountered
238              
239             =item *
240              
241             C - print each SQL statement as it is run
242              
243             =item *
244              
245             C - callback to call with each SQL statement instead of C
246              
247             =item *
248              
249             C - filehandle to write to instead of C
250              
251             =item *
252              
253             C - whether to exit with a nonzero exit code if any row is found
254              
255             This makes the function return a nonzero value even if there is no error
256             but a row was found.
257              
258             =item *
259              
260             C - whether to output the (one) row and column, without any headers
261              
262             =item *
263              
264             C - see the C<> option of C<< ->format_results >>
265              
266             =item *
267              
268             C - rotate the table by 90° , outputting columns as rows
269              
270             =item *
271              
272             C - string to replace SQL C columns by
273              
274             =back
275              
276             =cut
277              
278             sub run_sql {
279 0     0 1 0 my ($self,%args) = @_;
280 0         0 my $errors = 0;
281              
282 0 0       0 if( ! $args{ verbose_handler }) {
283 0   0     0 $args{ verbose_fh } //= \*main::STDOUT;
284             $args{ verbose_handler } = sub {
285 0     0   0 print { $args{ verbose_fh } } "$_[0]\n";
  0         0  
286             }
287 0         0 };
288 0         0 my $status = delete $args{ verbose_handler };
289              
290 0 0       0 if( $args{ fh }) {
291 0         0 $args{ sql } = delete $args{ fh };
292             };
293              
294 0         0 while( defined(my $statement = $self->split_sql($args{ sql }))) {
295             # skip "statements" that consist only of comments
296 0 0       0 next unless $statement =~ /^\s*[A-Z][A-Z]/mi;
297 0 0       0 $status->($statement) if $args{verbose};
298              
299 0         0 my $sth = $args{dbh}->prepare($statement);
300 0 0       0 if(! $sth) {
301 0 0       0 if (!$args{force}) {
302 0         0 die "[SQL ERROR]: $statement\n";
303             } else {
304 0         0 warn "[SQL ERROR]: $statement\n";
305             };
306             } else {
307 0         0 my $status= $sth->execute();
308 0 0 0     0 if(! $status) {
    0          
309 0 0       0 if (!$args{force}) {
310 0         0 die "[SQL ERROR]: $statement\n";
311             } else {
312 0         0 warn "[SQL ERROR]: $statement\n";
313             };
314             } elsif( defined $sth->{NUM_OF_FIELDS} and 0 < $sth->{NUM_OF_FIELDS} ) {
315             # SELECT statement, output results
316 0 0       0 if( $args{ output_bool }) {
    0          
317 0         0 my $res = $self->format_results(
318             sth => $sth,
319             no_header_when_empty => 1,
320             %args
321             );
322 0         0 print $res;
323             # Set the exit code depending on the length of $res because
324             # we lost the information on how many rows the result
325             # set had ...
326 0         0 $errors = length $res > 0;
327              
328             } elsif( $args{ output_string }) {
329 0         0 local $args{formatter} = 'tab';
330 0         0 print $self->format_results(
331             sth => $sth,
332             no_header_when_empty => 1,
333             %args
334             );
335              
336             } else {
337 0         0 print $self->format_results( sth => $sth, %args );
338             };
339             };
340             };
341             };
342 0         0 $errors
343             }
344              
345             =head2 C<< DBIx::RunSQL->format_results %options >>
346              
347             my $sth= $dbh->prepare( 'select * from foo' );
348             $sth->execute();
349             print DBIx::RunSQL->format_results( sth => $sth );
350              
351             Executes C<< $sth->fetchall_arrayref >> and returns
352             the results either as tab separated string
353             or formatted using L if the module is available.
354              
355             If you find yourself using this often to create reports,
356             you may really want to look at L instead.
357              
358             =over 4
359              
360             =item *
361              
362             C - the executed statement handle
363              
364             =item *
365              
366             C - if you want to force C or C
367             usage, you can do it through that parameter.
368             In fact, the module will use anything other than C
369             as the class name and assume that the interface is compatible
370             to C.
371              
372             =item *
373              
374             C - don't print anything if there are no results
375              
376             =item *
377              
378             C - rotate the table by 90° , outputting columns as rows
379              
380             =item *
381              
382             C - string to replace SQL C columns by
383              
384             =back
385              
386             Note that the query results are returned as one large string,
387             so you really do not want to run this for large(r) result
388             sets.
389              
390             =cut
391              
392             sub _nullstr {
393 0     0   0 my $str = shift;
394 0 0       0 map { defined $_ ? $_ : $str } @_
  0         0  
395             }
396              
397             sub format_results {
398 0     0 1 0 my( $self, %options )= @_;
399 0         0 my $sth= delete $options{ sth };
400              
401 0 0       0 if( ! $options{ formatter }) {
402 0 0       0 if( eval { require "Text/Table.pm" }) {
  0         0  
403 0         0 $options{ formatter }= 'Text::Table';
404             } else {
405 0         0 $options{ formatter }= 'tab';
406             };
407             };
408              
409 0   0     0 my $nullstr = $options{ null } // ''; # / , for Filter::Simple
410              
411 0         0 my @columns= @{ $sth->{NAME} };
  0         0  
412 0         0 my $res= $sth->fetchall_arrayref();
413 0         0 my @rows = map { [ _nullstr( $nullstr, @$_ ) ] } @$res;
  0         0  
414              
415 0         0 my $no_header_when_empty = $options{ no_header_when_empty };
416 0   0     0 my $print_header = not exists $options{ header } || $options{ header };
417 0         0 my $rotate = $options{ rotate };
418              
419 0 0       0 if( $rotate ) {
420             # Rotate our output
421             my @new_rows = map {
422 0         0 my $i = $_;
  0         0  
423 0         0 [$columns[$i], map { $_->[$i] } @rows]
  0         0  
424             } (0..$#columns);
425 0         0 @rows = @new_rows;
426 0         0 @columns = @{shift @rows};
  0         0  
427             }
428              
429 0         0 my $result='';
430 0 0       0 if( @columns ) {
431             # Output as print statement
432 0 0 0     0 if( $no_header_when_empty and ! @$res ) {
    0          
433             # Nothing to do
434              
435             } elsif( 'tab' eq $options{ formatter } ) {
436             $result = join "\n",
437             $print_header ? join( "\t", @columns ) : (),
438 0 0       0 map { join( "\t", @$_ ) } @rows
  0         0  
439             ;
440              
441             } else {
442 0         0 my $class = $options{ formatter };
443              
444 0 0 0     0 if( !( $class->can('table') || $class->can('new'))) {
445             # Try to load the module, just in case it isn't present in
446             # memory already
447              
448 0         0 eval { load $class; };
  0         0  
449             };
450              
451             # Now dispatch according to the apparent type
452 0 0 0     0 if( !$class->isa('Text::Table') and my $table = $class->can('table') ) {
453             # Text::Table::Any interface
454 0         0 $result = $table->( header_row => $print_header,
455             rows => [\@columns, @rows ],
456             );
457             } else {;
458             # Text::Table interface
459 0         0 my $t= $options{formatter}->new(@columns);
460 0         0 $t->load( @rows );
461 0         0 $result= $t;
462             };
463             };
464             };
465 0         0 "$result"; # Yes, sorry - we stringify everything
466             }
467              
468             =head2 C<< DBIx::RunSQL->split_sql ARGS >>
469              
470             my $sql = <<'SQL';
471             create table foo (name varchar(64));
472             create trigger foo_insert on foo before insert;
473             new.name= 'foo-'||old.name;
474             end;
475             insert into foo name values ('bar');
476             SQL
477             while( defined( my $s = DBIx::RunSQL->split_sql( $sql ))) {
478             push @statements, $s;
479             }
480             # @statements has three elements
481              
482             This is a helper subroutine to split a sequence of (semicolon-newline-delimited)
483             SQL statements into separate statements. It is documented because
484             it is not a very smart subroutine and you might want to
485             override or replace it. It might also be useful outside the context
486             of L if you need to split up a large blob
487             of SQL statements into smaller pieces.
488              
489             This routine takes a string, filehandle or an iterator as its parameter.
490             This iterator should return the next statement.
491             A filehandle or a string will be split at C< ;\n >.
492              
493             C will try to reassemble C
494             statements from the list of statements.
495              
496             =cut
497              
498             sub next_sql {
499 3 100   3 0 45 $_[1] =~ /\G\s*(\S.*?)(?:;[ \t]*\r?\n|\s*;?\s*\z)/sg
500             or return undef;
501 2         8 return "$1";
502             }
503              
504             sub split_sql {
505 3     3 1 235972 my $self = shift;
506 3         6 my $iterator;
507              
508 3 50       11 if( ! ref $_[0] ) {
    0          
    0          
509             # We got an SQL string, make up an iterator
510 3         7 my $s = \$_[0];
511 3     3   12 $iterator = sub { $self->next_sql($$s) };
  3         9  
512             } elsif( ref $_[0] eq 'CODE' ) {
513 0         0 $iterator = $_[0]
514             } elsif( ref $_[0] eq 'GLOB' ) {
515 0         0 my $fh = $_[0];
516 0     0   0 $iterator = sub { local $/ = ";\n"; <$fh> }
  0         0  
517 0         0 } else {
518 0         0 croak "Don't know how to handle reference type " . ref $_[0];
519             }
520              
521 3         6 my $statement = $iterator->();
522             return undef
523 3 100       11 if not defined $statement;
524 2         3 my $trigger;
525              
526 2 50       10 if( $statement =~ /^\s*CREATE\s+TRIGGER\b/i ) {
527 0 0       0 if( $statement !~ /END$/i ) {
528             # Multiline CREATE TRIGGER statement
529 0         0 $trigger = $statement;
530              
531 0         0 my $next;
532 0   0     0 do {
533 0         0 $next = $iterator->();
534 0 0       0 $trigger .= ";" if $trigger !~ /;$/;
535 0 0       0 $trigger .= "\n$next"
536             if defined $next;
537             } until (! defined $next or $next =~ /END$/i);
538             } else {
539             # Single-line CREATE TRIGGER statement
540 0         0 $trigger = $statement;
541             }
542 0         0 $statement = $trigger;
543             };
544              
545 2         11 return $statement
546             }
547              
548             1;
549              
550             =head2 C<< DBIx::RunSQL->parse_command_line >>
551              
552             my $options = DBIx::RunSQL->parse_command_line( 'my_application', \@ARGV );
553              
554             Helper function to turn a command line array into options for DBIx::RunSQL
555             invocations. The array of command line items is modified in-place.
556              
557             If the reference to the array of command line items is missing, C<@ARGV>
558             will be modified instead.
559              
560             =cut
561              
562             sub parse_command_line {
563 4     4 1 14 my ($package,$appname,$argv) = @_;
564 4         2849 require Getopt::Long; Getopt::Long->import('GetOptionsFromArray');
  4         17521  
565              
566 4 100       484 if (! $argv) { $argv = \@ARGV };
  1         4  
567              
568 4 50       22 if (GetOptionsFromArray( $argv,
569             'user=s' => \my $user,
570             'password=s' => \my $password,
571             'dsn=s' => \my $dsn,
572             'verbose' => \my $verbose,
573             'force|f' => \my $force,
574             'sql=s' => \my $sql,
575             'bool' => \my $output_bool,
576             'string' => \my $output_string,
577             'quiet' => \my $no_header_when_empty,
578             'format=s' => \my $formatter_class,
579             'rotate' => \my $rotate,
580             'null=s' => \my $nullstr,
581             'help|h' => \my $help,
582             'man' => \my $man,
583             )) {
584 11     11   105 no warnings 'newline';
  11         20  
  11         6574  
585 4   100     5819 $sql ||= join " ", @$argv;
586 4 100 66     151 if( $sql and ! -f $sql ) {
587 2         12 $sql = \"$sql",
588             };
589 4         7 my $fh;
590 4 50 66     21 if( ! $sql and not @$argv) {
591             # Assume we'll read the SQL from stdin
592 2         5 $fh = \*STDIN;
593             };
594             return {
595 4         63 user => $user,
596             password => $password,
597             dsn => $dsn,
598             verbose => $verbose,
599             force => $force,
600             sql => $sql,
601             fh => $fh,
602             no_header_when_empty => $no_header_when_empty,
603             output_bool => $output_bool,
604             output_string => $output_string,
605             formatter => $formatter_class,
606             rotate => $rotate,
607             null => $nullstr,
608             help => $help,
609             man => $man,
610             };
611             } else {
612 0         0 return undef;
613             };
614             }
615              
616             sub handle_command_line {
617 4     4 1 230595 my ($package,$appname,$argv) = @_;
618 4         862 require Pod::Usage; Pod::Usage->import();
  4         73160  
619              
620 4 50       26 my $opts = $package->parse_command_line($appname,$argv)
621             or pod2usage(2);
622 4 50       18 pod2usage(1) if $opts->{help};
623 4 50       14 pod2usage(-verbose => 2) if $opts->{man};
624              
625 4   66     33 $opts->{dsn} ||= sprintf 'dbi:SQLite:dbname=db/%s.sqlite', $appname;
626 4         60 my( $dbh, $exitcode) = $package->create(
627             %$opts
628             );
629 4         77 return $exitcode
630             }
631              
632             =head2 C<< DBIx::RunSQL->handle_command_line >>
633              
634             DBIx::RunSQL->handle_command_line( 'my_application', \@ARGV );
635              
636             Helper function to run the module functionality from the command line. See below
637             how to use this function in a good self-contained script.
638             This function
639             passes the following command line arguments and options to C<< ->create >>:
640              
641             --user
642             --password
643             --dsn
644             --sql
645             --quiet
646             --format
647             --force
648             --verbose
649             --bool
650             --string
651             --rotate
652             --null
653              
654             In addition, it handles the following switches through L:
655              
656             --help
657             --man
658              
659             If no SQL is given, this function will read the SQL from STDIN.
660              
661             If no dsn is given, this function will use
662             C< dbi:SQLite:dbname=db/$appname.sqlite >
663             as the default database.
664              
665             See also the section PROGRAMMER USAGE for a sample program to set
666             up a database from an SQL file.
667              
668             =head1 PROGRAMMER USAGE
669              
670             This module abstracts away the "run these SQL statements to set up
671             your database" into a module. In some situations you want to give the
672             setup SQL to a database admin, but in other situations, for example testing,
673             you want to run the SQL statements against an in-memory database. This
674             module abstracts away the reading of SQL from a file and allows for various
675             command line parameters to be passed in. A skeleton C
676             looks like this:
677              
678             #!/usr/bin/perl -w
679             use strict;
680             use DBIx::RunSQL;
681              
682             my $exitcode = DBIx::RunSQL->handle_command_line('myapp', \@ARGV);
683             exit $exitcode;
684              
685             =head1 NAME
686              
687             create-db.pl - Create the database
688              
689             =head1 SYNOPSIS
690              
691             create-db.pl "select * from mytable where 1=0"
692              
693             =head1 ABSTRACT
694              
695             This sets up the database. The following
696             options are recognized:
697              
698             =head1 OPTIONS
699              
700             =over 4
701              
702             =item C<--user> USERNAME
703              
704             =item C<--password> PASSWORD
705              
706             =item C<--dsn> DSN
707              
708             The DBI DSN to use for connecting to
709             the database
710              
711             =item C<--sql> SQLFILE
712              
713             The alternative SQL file to use
714             instead of C.
715              
716             =item C<--quiet>
717              
718             Output no headers for empty SELECT resultsets
719              
720             =item C<--bool>
721              
722             Set the exit code to 1 if at least one result row was found
723              
724             =item C<--string>
725              
726             Output the (single) column that the query returns as a string without
727             any headers
728              
729             =item C<--format> formatter
730              
731             Use a different formatter for table output. Supported formatters are
732              
733             tab - output results as tab delimited columns
734              
735             Text::Table - output results as ASCII table
736              
737             =item C<--force>
738              
739             Don't stop on errors
740              
741             =item C<--help>
742              
743             Show this message.
744              
745             =back
746              
747             =cut
748              
749             =head1 NOTES
750              
751             =head2 COMMENT FILTERING
752              
753             The module tries to keep the SQL as much verbatim as possible. It
754             filters all lines that end in semicolons but contain only SQL comments. All
755             other comments are passed through to the database with the next statement.
756              
757             =head2 TRIGGER HANDLING
758              
759             This module uses a very simplicistic approach to recognize triggers.
760             Triggers are problematic because they consist of multiple SQL statements
761             and this module does not implement a full SQL parser. An trigger is
762             recognized by the following sequence of lines
763              
764             CREATE TRIGGER
765             ...
766             END;
767              
768             If your SQL dialect uses a different syntax, it might still work to put
769             the whole trigger on a single line in the input file.
770              
771             =head2 OTHER APPROACHES
772              
773             If you find yourself wanting to write SELECT statements,
774             consider looking at L instead, which is geared towards that
775             and even has an interface for Excel or HTML output.
776              
777             If you find yourself wanting to write parametrized queries as
778             C<.sql> files, consider looking at L
779             or potentially L.
780              
781             =head1 SEE ALSO
782              
783             L
784              
785             L - SQLite setup/teardown for tests, mostly geared towards
786             testing, not general database setup
787              
788             =head1 REPOSITORY
789              
790             The public repository of this module is
791             L.
792              
793             =head1 SUPPORT
794              
795             The public support forum of this module is
796             L.
797              
798             =head1 BUG TRACKER
799              
800             Please report bugs in this module via the RT CPAN bug queue at
801             L
802             or via mail to L.
803              
804             =head1 AUTHOR
805              
806             Max Maischein C
807              
808             =head1 COPYRIGHT (c)
809              
810             Copyright 2009-2021 by Max Maischein C.
811              
812             =head1 LICENSE
813              
814             This module is released under the same terms as Perl itself.
815              
816             =cut