File Coverage

blib/lib/DBIx/MultiStatementDo.pm
Criterion Covered Total %
statement 2 4 50.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 4 6 66.6


line stmt bran cond sub pod time code
1             ## no critic
2             package DBIx::MultiStatementDo;
3             BEGIN {
4 1     1   18878 $DBIx::MultiStatementDo::VERSION = '1.00009';
5             }
6             ## use critic
7              
8 1     1   230 use Moose;
  0            
  0            
9             use Carp qw(croak);
10              
11             use SQL::SplitStatement 1.00009;
12              
13             has 'dbh' => (
14             is => 'rw',
15             isa => 'DBI::db',
16             required => 1
17             );
18              
19             has 'splitter_options' => (
20             is => 'rw',
21             isa => 'Maybe[HashRef[Bool]]',
22             trigger => \&_set_splitter,
23             default => undef
24             );
25              
26             sub _set_splitter {
27             my ($self, $new_options) = @_;
28             $self->_splitter( SQL::SplitStatement->new($new_options) )
29             }
30              
31             has '_splitter' => (
32             is => 'rw',
33             isa => 'SQL::SplitStatement',
34             handles => [ qw(split split_with_placeholders) ],
35             lazy => 1,
36             default => sub { SQL::SplitStatement->new }
37             );
38              
39             has 'rollback' => (
40             is => 'rw',
41             isa => 'Bool',
42             default => 1
43             );
44              
45             sub do {
46             my ($self, $code, $attr, @bind_values) = @_;
47            
48             my ( $statements, $placeholders )
49             = ! ref($code)
50             ? $self->split_with_placeholders($code)
51             : ref( $code->[0] ) eq 'ARRAY'
52             ? @$code
53             : ( $code, undef );
54            
55             my @compound_bind_values;
56             if ( @bind_values >= 1 ) {
57             if ( ! ref $bind_values[0] ) {
58             # @bind_values was a FLAT LIST
59             ref($placeholders) ne 'ARRAY' and croak(
60             q[Bind values as a flat list require the placeholder numbers listref to be passed as well]
61             );
62             push @compound_bind_values, [ splice @bind_values, 0, $_ ]
63             foreach @$placeholders
64             } else {
65             @compound_bind_values = @{ $bind_values[0] }
66             }
67             }
68            
69            
70             my $dbh = $self->dbh;
71             my @results;
72            
73             if ( $self->rollback ) {
74             local $dbh->{AutoCommit} = 0;
75             local $dbh->{RaiseError} = 1;
76             eval {
77             @results = $self->_do_statements(
78             $statements, $attr, \@compound_bind_values
79             );
80             $dbh->commit;
81             1
82             } or eval {
83             $dbh->rollback
84             }
85             } else {
86             @results = $self->_do_statements(
87             $statements, $attr, \@compound_bind_values
88             )
89             }
90            
91             return @results if wantarray; # List context.
92             return 1 if @results == @$statements; # Scalar context and success.
93             return # Scalar context and failure.
94             }
95              
96             sub _do_statements {
97             my ($self, $statements, $attr, $compound_bind_values) = @_;
98            
99             my @results;
100             my $dbh = $self->dbh;
101            
102             for my $statement ( @$statements ) {
103             my $result = $dbh->do(
104             $statement, $attr, @{ shift(@$compound_bind_values) || [] }
105             );
106             last unless $result;
107             push @results, $result
108             }
109            
110             return @results
111             }
112              
113             no Moose;
114             __PACKAGE__->meta->make_immutable;
115              
116             1;
117              
118             __END__
119              
120             =head1 NAME
121              
122             DBIx::MultiStatementDo - Multiple SQL statements in a single do() call with any DBI driver
123              
124             =head1 VERSION
125              
126             version 1.00009
127              
128             =head1 SYNOPSIS
129              
130             use DBI;
131             use DBIx::MultiStatementDo;
132            
133             # Multiple SQL statements in a single string
134             my $sql_code = <<'SQL';
135             CREATE TABLE parent (a, b, c , d );
136             CREATE TABLE child (x, y, "w;", "z;z");
137             /* C-style comment; */
138             CREATE TRIGGER "check;delete;parent;" BEFORE DELETE ON parent WHEN
139             EXISTS (SELECT 1 FROM child WHERE old.a = x AND old.b = y)
140             BEGIN
141             SELECT RAISE(ABORT, 'constraint failed;'); -- Inlined SQL comment
142             END;
143             -- Standalone SQL; comment; w/ semicolons;
144             INSERT INTO parent (a, b, c, d) VALUES ('pippo;', 'pluto;', NULL, NULL);
145             SQL
146            
147             my $dbh = DBI->connect( 'dbi:SQLite:dbname=my.db', '', '' );
148            
149             my $batch = DBIx::MultiStatementDo->new( dbh => $dbh );
150            
151             # Multiple SQL statements in a single call
152             my @results = $batch->do( $sql_code )
153             or die $batch->dbh->errstr;
154            
155             print scalar(@results) . ' statements successfully executed!';
156             # 4 statements successfully executed!
157              
158             =head1 DESCRIPTION
159              
160             Some DBI drivers don't support the execution of multiple statements in a single
161             C<do()> call. This module tries to overcome such limitation, letting you execute
162             any number of SQL statements (of any kind, not only DDL statements) in a single
163             batch, with any DBI driver.
164              
165             Here is how DBIx::MultiStatementDo works: behind the scenes it parses the SQL
166             code, splits it into the atomic statements it is composed of and executes them
167             one by one. To split the SQL code L<SQL::SplitStatement> is used, which uses a
168             more sophisticated logic than a raw C<split> on the C<;> (semicolon) character:
169             first, various different statement terminator I<tokens> are recognized, then
170             L<SQL::SplitStatement> is able to correctly handle the presence of said tokens
171             inside identifiers, values, comments, C<BEGIN ... END> blocks (even nested),
172             I<dollar-quoted> strings, MySQL custom C<DELIMITER>s, procedural code etc.,
173             as (partially) exemplified in the L</SYNOPSIS> above.
174              
175             Automatic transactions support is offered by default, so that you'll have the
176             I<all-or-nothing> behaviour you would probably expect; if you prefer, you can
177             anyway disable it and manage the transactions yourself.
178              
179             =head1 METHODS
180              
181             =head2 C<new>
182              
183             =over 4
184              
185             =item * C<< DBIx::MultiStatementDo->new( %options ) >>
186              
187             =item * C<< DBIx::MultiStatementDo->new( \%options ) >>
188              
189             =back
190              
191             It creates and returns a new DBIx::MultiStatementDo object. It accepts its
192             options either as an hash or an hashref.
193              
194             The following options are recognized:
195              
196             =over 4
197              
198             =item * C<dbh>
199              
200             The database handle object as returned by L<DBI::connect()|DBI/connect>. This
201             option B<is required>.
202              
203             =item * C<rollback>
204              
205             A Boolean option which enables (when true) or disables (when false) automatic
206             transactions. It is set to a true value by default.
207              
208             =item * C<splitter_options>
209              
210             This is the options hashref which is passed unaltered to C<<
211             SQL::SplitStatement->new() >> to build the I<splitter object>, which is then
212             internally used by DBIx::MultiStatementDo to split the given SQL string.
213              
214             It defaults to C<undef>, which should be the best value if the given SQL string
215             contains only standard SQL. If it contains contains also procedural code, you
216             may need to fine tune this option.
217              
218             Please refer to L<< SQL::SplitStatement::new()|SQL::SplitStatement/new >> to see
219             the options it takes.
220              
221             =back
222              
223             =head2 C<do>
224              
225             =over 4
226              
227             =item * C<< $batch->do( $sql_string | \@sql_statements ) >>
228              
229             =item * C<< $batch->do( $sql_string | \@sql_statements , \%attr ) >>
230              
231             =item * C<< $batch->do( $sql_string | \@sql_statements , \%attr, \@bind_values | @bind_values ) >>
232              
233             =back
234              
235             This is the method which actually executes the SQL statements against your db.
236             As its first (mandatory) argument, it takes an SQL string containing one or more
237             SQL statements. The SQL string is split into its atomic statements, which are
238             then executed one-by-one, in the same order they appear in the given string.
239              
240             The first argument can also be a reference to a list of (already split)
241             statements, in which case no split is performed and the statements are executed
242             as they appear in the list. The list can also be a two-elements list, where the
243             first element is the statements listref as above, and the second is the
244             I<placeholder numbers> listref, exactly as returned by the
245             L<< SQL::SplitStatement::split_with_placeholders()|SQL::SplitStatement/split_with_placeholders >>
246             method.
247              
248             Analogously to DBI's C<do()>, it optionally also takes an hashref of attributes
249             (which is passed unaltered to C<< $batch->dbh->do() >> for each atomic
250             statement), and the I<bind values>, either as a listref or a flat list (see
251             below for the difference).
252              
253             In list context, C<do> returns a list containing the values returned by the
254             C<< $batch->dbh->do() >> call on each single atomic statement.
255              
256             If the C<rollback> option has been set (and therefore automatic transactions are
257             enabled), in case one of the atomic statements fails, all the other succeeding
258             statements executed so far, if any, are rolled back and the method (immediately)
259             returns an empty list (since no statements have actually been committed).
260              
261             If the C<rollback> option is set to a false value (and therefore automatic
262             transactions are disabled), the method immediately returns at the first failing
263             statement as above, but it does not roll back any prior succeeding statement,
264             and therefore a list containing the values returned by the statements
265             (successfully) executed so far is returned (and these statements are actually
266             committed to the db, if C<< $dbh->{AutoCommit} >> is set).
267              
268             In scalar context it returns, regardless of the value of the C<rollback> option,
269             C<undef> if any of the atomic statements failed, or a true value if all of the
270             atomic statements succeeded.
271              
272             Note that to activate the automatic transactions you don't have to do anything
273             more than setting the C<rollback> option to a true value (or simply do nothing,
274             as it is the default): DBIx::MultiStatementDo will automatically (and
275             temporarily, via C<local>) set C<< $dbh->{AutoCommit} >> and
276             C<< $dbh->{RaiseError} >> as needed.
277             No other DBI db handle attribute is ever touched, so that you can for example
278             set C<< $dbh->{PrintError} >> and enjoy its effects in case of a failing
279             statement.
280              
281             If you want to disable the automatic transactions and manage them by yourself,
282             you can do something along this:
283              
284             my $batch = DBIx::MultiStatementDo->new(
285             dbh => $dbh,
286             rollback => 0
287             );
288            
289             my @results;
290            
291             $batch->dbh->{AutoCommit} = 0;
292             $batch->dbh->{RaiseError} = 1;
293             eval {
294             @results = $batch->do( $sql_string );
295             $batch->dbh->commit;
296             1
297             } or eval {
298             $batch->dbh->rollback
299             };
300              
301             =head3 Bind Values as a List Reference
302              
303             The bind values can be passed as a reference to a list of listrefs, each of
304             which contains the bind values for the atomic statement it corresponds to. The
305             bind values I<inner> lists must match the corresponding atomic statements as
306             returned by the internal I<splitter object>, with C<undef> (or empty listref)
307             elements where the corresponding atomic statements have no I<placeholders>.
308              
309             Here is an example:
310              
311             # 7 statements (SQLite valid SQL)
312             my $sql_code = <<'SQL';
313             CREATE TABLE state (id, name);
314             INSERT INTO state (id, name) VALUES (?, ?);
315             CREATE TABLE city (id, name, state_id);
316             INSERT INTO city (id, name, state_id) VALUES (?, ?, ?);
317             INSERT INTO city (id, name, state_id) VALUES (?, ?, ?);
318             DROP TABLE city;
319             DROP TABLE state
320             SQL
321            
322             # Only 5 elements are required in the bind values list
323             my $bind_values = [
324             undef , # or []
325             [ 1, 'Nevada' ] ,
326             [] , # or undef
327             [ 1, 'Las Vegas' , 1 ],
328             [ 2, 'Carson City', 1 ]
329             ];
330            
331             my $batch = DBIx::MultiStatementDo->new( dbh => $dbh );
332            
333             my @results = $batch->do( $sql_code, undef, $bind_values )
334             or die $batch->dbh->errstr;
335              
336             If the last statements have no placeholders, the corresponding C<undef>s don't
337             need to be present in the bind values list, as shown above.
338             The bind values list can also have more elements than the number of the atomic
339             statements, in which case the excess elements will simply be ignored.
340              
341             =head3 Bind Values as a Flat List
342              
343             This is a much more powerful feature of C<do>: when it gets the bind values as a
344             flat list, it automatically assigns them to the corresponding placeholders (no
345             I<interleaving> C<undef>s are necessary in this case).
346              
347             In other words, you can regard the given SQL code as a single big statement and
348             pass the bind values exactly as you would do with the ordinary DBI C<do> method.
349              
350             For example, given C<$sql_code> from the example above, you could simply do:
351              
352             my @bind_values = ( 1, 'Nevada', 1, 'Las Vegas', 1, 2, 'Carson City', 1 );
353            
354             my @results = $batch->do( $sql_code, undef, @bind_values )
355             or die $batch->dbh->errstr;
356              
357             and get exactly the same result.
358              
359             =head3 Difference between Bind Values as a List Reference and as a Flat List
360              
361             If you want to pass the bind values as a flat list as described above, you must
362             pass the first parameter to C<do> either as a string (so that the internal
363             splitting is performed) or, if you want to disable the internal splitting, as a
364             reference to the two-elements list containing both the statements and the
365             placeholder numbers listrefs (as described above in L<do>).
366              
367             In other words, you can't pass the bind values as a flat list and pass at the
368             same time the (already split) statements without the placeholder numbers
369             listref. To do so, you need to pass the bind values as a list reference instead,
370             otherwise C<do> throws an exception.
371              
372             To summarize, bind values as a flat list is easier to use but it suffers from
373             this subtle limitation, while bind values as a list reference is a little bit
374             more cumbersome to use, but it has no limitations and can therefore always be
375             used.
376              
377             =head3 Recognized Placeholders
378              
379             The recognized placeholders are:
380              
381             =over 4
382              
383             =item * I<question mark> placeholders, represented by the C<?> character;
384              
385             =item * I<dollar sign numbered> placeholders, represented by the
386             C<$1, $2, ..., $n> strings;
387              
388             =item * I<named parameters>, such as C<:foo>, C<:bar>, C<:baz> etc.
389              
390             =back
391              
392             =head2 C<dbh>
393              
394             =over 4
395              
396             =item * C<< $batch->dbh >>
397              
398             =item * C<< $batch->dbh( $new_dbh ) >>
399              
400             Getter/setter method for the C<dbh> option explained above.
401              
402             =back
403              
404             =head2 C<rollback>
405              
406             =over 4
407              
408             =item * C<< $batch->rollback >>
409              
410             =item * C<< $batch->rollback( $boolean ) >>
411              
412             Getter/setter method for the C<rollback> option explained above.
413              
414             =back
415              
416             =head2 C<splitter_options>
417              
418             =over 4
419              
420             =item * C<< $batch->splitter_options >>
421              
422             =item * C<< $batch->splitter_options( \%options ) >>
423              
424             Getter/setter method for the C<splitter_options> option explained above.
425              
426             =back
427              
428             =head2 C<split> and C<split_with_placeholders>
429              
430             =over 4
431              
432             =item * C<< $batch->split( $sql_code ) >>
433              
434             =item * C<< $batch->split_with_placeholders( $sql_code ) >>
435              
436             =back
437              
438             These are the methods used internally to split the given SQL code.
439             They call respectively C<split> and C<split_with_placeholders> on a
440             SQL::SplitStatement instance built with the C<splitter_options>
441             described above.
442              
443             Normally they shouldn't be used directly, but they could be useful if
444             you want to see how your SQL code has been split.
445              
446             If you want instead to see how your SQL code I<will be> split, that is
447             before executing C<do>, you can use SQL::SplitStatement by yourself:
448              
449             use SQL::SplitStatement;
450             my $splitter = SQL::SplitStatement->new( \%splitter_options );
451             my @statements = $splitter->split( $sql_code );
452             # Now you can check @statements if you want...
453              
454             and then you can execute your statements preventing C<do> from performing
455             the splitting again, by passing C<\@statements> to it:
456              
457             my $batch = DBIx::MultiStatementDo->new( dbh => $dbh );
458             my @results = $batch->do( \@statements ); # This does not perform the splitting again.
459              
460             B<Warning!> In previous versions, the C<split_with_placeholders> (public) method
461             documented above did not work, so there is the possibility that someone
462             used the (private, undocumented) C<_split_with_placeholders> method instead
463             (which worked correctly).
464             In this case, please start using the public method (which now works as
465             advertised), since the private method will be removed in future versions.
466              
467             =head1 LIMITATIONS
468              
469             Please look at: L<< SQL::SplitStatement LIMITATIONS|SQL::SplitStatement/LIMITATIONS >>
470              
471             =head1 DEPENDENCIES
472              
473             DBIx::MultiStatementDo depends on the following modules:
474              
475             =over 4
476              
477             =item * L<SQL::SplitStatement> 0.10000 or newer
478              
479             =item * L<Moose>
480              
481             =back
482              
483             =head1 AUTHOR
484              
485             Emanuele Zeppieri, C<< <emazep@cpan.org> >>
486              
487             =head1 BUGS
488              
489             No known bugs so far.
490              
491             Please report any bugs or feature requests to
492             C<bug-dbix-MultiStatementDo at rt.cpan.org>, or through the web interface at
493             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBIx-MultiStatementDo>.
494             I will be notified, and then you'll automatically be notified of progress
495             on your bug as I make changes.
496              
497             =head1 SUPPORT
498              
499             You can find documentation for this module with the perldoc command.
500              
501             perldoc DBIx::MultiStatementDo
502              
503             You can also look for information at:
504              
505             =over 4
506              
507             =item * RT: CPAN's request tracker
508              
509             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBIx-MultiStatementDo>
510              
511             =item * AnnoCPAN: Annotated CPAN documentation
512              
513             L<http://annocpan.org/dist/DBIx-MultiStatementDo>
514              
515             =item * CPAN Ratings
516              
517             L<http://cpanratings.perl.org/d/DBIx-MultiStatementDo>
518              
519             =item * Search CPAN
520              
521             L<http://search.cpan.org/dist/DBIx-MultiStatementDo/>
522              
523             =back
524              
525             =head1 ACKNOWLEDGEMENTS
526              
527             Matt S Trout, for having suggested a much more suitable name
528             for this module.
529              
530             =head1 SEE ALSO
531              
532             =over 4
533              
534             =item * L<SQL::SplitStatement>
535              
536             =item * L<DBI>
537              
538             =back
539              
540             =head1 LICENSE AND COPYRIGHT
541              
542             Copyright 2010-2011 Emanuele Zeppieri.
543              
544             This program is free software; you can redistribute it and/or modify it
545             under the terms of either: the GNU General Public License as published
546             by the Free Software Foundation, or the Artistic License.
547              
548             See http://dev.perl.org/licenses/ for more information.
549              
550             =cut