File Coverage

blib/lib/DBIx/Insert/Multi/Batch.pm
Criterion Covered Total %
statement 36 49 73.4
branch 4 14 28.5
condition n/a
subroutine 14 16 87.5
pod 1 1 100.0
total 55 80 68.7


line stmt bran cond sub pod time code
1             package DBIx::Insert::Multi::Batch;
2 2     2   13 use Moo;
  2         3  
  2         10  
3              
4             =head1 NAME
5              
6             DBIx::Insert::Multi::Batch -- Batch of records to insert
7              
8             =cut
9              
10 2     2   531 use Carp;
  2         5  
  2         98  
11 2     2   1031 use autobox::Core;
  2         37026  
  2         15  
12 2     2   2252 use autobox::Transform;
  2         61942  
  2         14  
13 2     2   2146 use Scalar::Util qw/ blessed /;
  2         4  
  2         1224  
14              
15              
16              
17             has dbh => ( is => "ro", required => 1 );
18             has table => ( is => "ro", required => 1 );
19             has records => ( is => "ro", required => 1 );
20             has insert_sql_fragment => ( is => "ro", required => 1 );
21             has is_last_insert_id_required => ( is => "ro", required => 1 );
22              
23              
24              
25             has column_names => ( is => "lazy" );
26             sub _build_column_names {
27 3     3   23 my $self = shift;
28 3 50       16 my $record = $self->records->[0] or return [];
29 3         27 return $record->keys->order, # Assume all records are uniform
30             }
31              
32             has record_placeholders => ( is => "lazy" );
33             sub _build_record_placeholders {
34 2     2   4148 my $self = shift;
35 2     6   28 my $record = " (" . $self->column_names->map(sub { "?" })->join(", ") . ")";
  6         611  
36 2     4   66 return $self->records->map(sub { $record })->join(",\n") . "\n";
  4         18  
37             }
38              
39             has record_values => ( is => "lazy" );
40             sub _build_record_values {
41 1     1   3103 my $self = shift;
42 1         14 my @columns = $self->column_names->elements;
43             return $self->records
44 2     2   8 ->map(sub { @{ $_ }{ @columns } })
  2         7  
45 1 100   6   507 ->map(sub { blessed($_) ? "$_" : $_ }); # Stringify objects
  6         90  
46             }
47              
48             has sql => ( is => "lazy" );
49             sub _build_sql {
50 1     1   9658 my $self = shift;
51 1 50       16 $self->column_names->length or return undef;
52              
53 1         545 my $table = $self->table;
54 1         4 my $dbh = $self->dbh;
55             my $column_names = $self->column_names
56 3     3   34 ->map(sub { $dbh->quote_identifier($_) })
57 1         18 ->join(", ");
58              
59 1         19 return sprintf(
60             "%s %s (%s) VALUES\n%s",
61             $self->insert_sql_fragment,
62             $dbh->quote_identifier($table),
63             $column_names,
64             $self->record_placeholders,
65             );
66             }
67              
68             # For MySQL this is the id of the first of the rows
69             # For Postgres, this seems to be the id of the last of the rows
70             sub _get_insert_id {
71 0     0     my $self = shift;
72 0           my ($dbh) = @_;
73              
74 0           my $last_insert_id = $dbh->last_insert_id(
75             undef, undef, $self->table, undef,
76             );
77             # This will return 0 if any of the inserts failed and you were
78             # using ->insert_sql_fragment "INSERT IGNORE INTO".
79 0 0         if( ! defined $last_insert_id ) {
80 0 0         if($self->is_last_insert_id_required) {
81 0           croak("No dbh last_insert_id returned");
82             }
83 0           return undef;
84             }
85              
86 0           return $last_insert_id;
87             }
88              
89             =head2 insert() :
90              
91             Perform the insert into ->table of all the records in ->records.
92              
93             The return value not specified. If the query fails, die.
94              
95             =cut
96              
97             sub insert {
98 0     0 1   my $self = shift;
99 0 0         my $sql = $self->sql or return undef;
100 0           my $dbh = $self->dbh;
101 0 0         $dbh->do( $sql, {}, $self->record_values->elements )
102             or croak( "Could not insert rows: " . $dbh->errstr );
103 0           return $self->_get_insert_id( $dbh );
104             }
105              
106             1;