File Coverage

blib/lib/DBIx/RunSQL.pm
Criterion Covered Total %
statement 45 143 31.4
branch 13 74 17.5
condition 9 37 24.3
subroutine 8 14 57.1
pod 7 7 100.0
total 82 275 29.8


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