File Coverage

blib/lib/DBIx/RunSQL.pm
Criterion Covered Total %
statement 45 127 35.4
branch 13 70 18.5
condition 9 33 27.2
subroutine 8 13 61.5
pod 7 7 100.0
total 82 250 32.8


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