line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DBIx::Insert::Multi; |
2
|
2
|
|
|
2
|
|
124986
|
use 5.010000; |
|
2
|
|
|
|
|
15
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
our $VERSION = "0.003"; |
5
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
907
|
use Moo; |
|
2
|
|
|
|
|
19736
|
|
|
2
|
|
|
|
|
11
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
DBIx::Insert::Multi -- Insert multiple table rows in a single statement |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use DBIx::Insert::Multi; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my $dbh = DBI->connect(...); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my $multi = DBIx::Insert::Multi->new({ dbh => $dbh, }); |
19
|
|
|
|
|
|
|
$multi->insert( |
20
|
|
|
|
|
|
|
book => [ |
21
|
|
|
|
|
|
|
{ |
22
|
|
|
|
|
|
|
title => "Winnie the Pooh", |
23
|
|
|
|
|
|
|
author => "Milne", |
24
|
|
|
|
|
|
|
publication_date => DateTime->new(year => 1926)->ymd, |
25
|
|
|
|
|
|
|
}, |
26
|
|
|
|
|
|
|
{ |
27
|
|
|
|
|
|
|
title => "Paddington", |
28
|
|
|
|
|
|
|
author => "Bond", |
29
|
|
|
|
|
|
|
publication_date => DateTime->new(year => 1958)->ymd, |
30
|
|
|
|
|
|
|
}, |
31
|
|
|
|
|
|
|
], |
32
|
|
|
|
|
|
|
); # die on error |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Database specific INSERT statement |
35
|
|
|
|
|
|
|
# MySQL: don't stop on errors |
36
|
|
|
|
|
|
|
my $multi = DBIx::Insert::Multi->new({ |
37
|
|
|
|
|
|
|
... |
38
|
|
|
|
|
|
|
insert_sql_fragment => "INSERT IGNORE INTO", |
39
|
|
|
|
|
|
|
}); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=head1 DESCRIPTION |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Bulk insert many db rows using a single INSERT INTO statement, e.g. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
INSERT INTO book (author, publication_date, title) VALUES |
46
|
|
|
|
|
|
|
( ?, ?, ? ), |
47
|
|
|
|
|
|
|
( ?, ?, ? ); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head2 Restrictions |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
All the hashrefs with row data should be shaped the same, i.e. have |
52
|
|
|
|
|
|
|
the same keys. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
You should only use values that can be inserted into a database. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
That means no data structures (refs), and no objects. However, objects |
57
|
|
|
|
|
|
|
will be stringified, so if they have overloaded stringification that |
58
|
|
|
|
|
|
|
will work. |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Note that L<DateTime> objects are stringified to a format that is |
61
|
|
|
|
|
|
|
unlikely to work correctly with your database date format (and without |
62
|
|
|
|
|
|
|
a timezone), so make sure you construct strings manually before |
63
|
|
|
|
|
|
|
inserting them. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
Undefs become NULL as usual. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head1 ISSUES |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head2 last_insert_id |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
It may be that you need to get hold of the PK ids of the inserted |
74
|
|
|
|
|
|
|
rows. This is very non-standard and fiddly, so at this point this |
75
|
|
|
|
|
|
|
module doesn't officially do any of that. |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
You can do this yourself though, but I wouldn't bet it's very |
78
|
|
|
|
|
|
|
reliable. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
$dbh->last_insert_id(undef, undef, $table, undef); |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Calling "$dbh->last_insert_id" returns a newly inserted row PK |
83
|
|
|
|
|
|
|
value. It seems to vary between databases whether this is the id of |
84
|
|
|
|
|
|
|
the first row or the last one. For instance: |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=over |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=item * |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
MySQL: first |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item * |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Postgres: last |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=back |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
If the PK is an auto-increment / sequence, it is probably not |
99
|
|
|
|
|
|
|
B<guaranteed> that these ids are in an unbroken series, but at least |
100
|
|
|
|
|
|
|
MySQL B<seems> to do that. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Read more about all the caveats here: L<DBI/"last_insert_id">. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=head3 Returning ids |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Some databases (Postgres) support INSERT INTO ... RETURNING, which can |
108
|
|
|
|
|
|
|
be used to retrieve data from the inserted rows. This seems to be the |
109
|
|
|
|
|
|
|
only reliable way to do this. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
This module can't do this at the moment, but patches are |
112
|
|
|
|
|
|
|
welcome. Please submit a bug to open a discission about what the API |
113
|
|
|
|
|
|
|
should look like. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=cut |
116
|
|
|
|
|
|
|
|
117
|
2
|
|
|
2
|
|
3309
|
use DBIx::Insert::Multi::Batch; |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
283
|
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
has dbh => ( is => "ro", required => 1 ); |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
has insert_sql_fragment => ( is => "lazy" ); |
124
|
0
|
|
|
0
|
|
|
sub _build_insert_sql_fragment { "INSERT INTO" } |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
has is_last_insert_id_required => ( is => "lazy" ); |
127
|
0
|
|
|
0
|
|
|
sub _build_is_last_insert_id_required { 0 } |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=head1 METHODS |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 insert($table_name, $records_arrayref) |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Perform the insert into $table_name of all the rows in |
136
|
|
|
|
|
|
|
$records_arrayref (arrayref with hashrefs, where the hashref keys are |
137
|
|
|
|
|
|
|
the column names, and the values are the column values). |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
The return value not specified. If the query fails, die. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=cut |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub insert { |
144
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
145
|
0
|
|
|
|
|
|
my ($table, $records) = @_; |
146
|
0
|
|
|
|
|
|
return DBIx::Insert::Multi::Batch->new({ |
147
|
|
|
|
|
|
|
dbh => $self->dbh, |
148
|
|
|
|
|
|
|
insert_sql_fragment => $self->insert_sql_fragment, |
149
|
|
|
|
|
|
|
is_last_insert_id_required => $self->is_last_insert_id_required, |
150
|
|
|
|
|
|
|
table => $table, |
151
|
|
|
|
|
|
|
records => $records, |
152
|
|
|
|
|
|
|
})->insert(); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
1; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head1 SEE ALSO |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 DBIx::Class |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
If you already have a L<DBIx::Class> schema, you can bulk insert rows |
165
|
|
|
|
|
|
|
efficiently using the L<DBIx::Class::ResultSet/populate> method (note: |
166
|
|
|
|
|
|
|
in void context!). You won't get back the new ids. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=head1 DEVELOPMENT |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head2 Author |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Johan Lindstrom, C<< <johanl [AT] cpan.org> >> |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 Source code |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
L<https://github.com/jplindstrom/p5-DBIx-Insert-Multi> |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=head2 Bug reports |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Please report any bugs or feature requests on GitHub: |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
L<https://github.com/jplindstrom/p5-DBIx-Insert-Multi/issues>. |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Copyright 2019- Broadbean Technologies, All Rights Reserved. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
195
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Thanks to Broadbean for providing time to open source this module. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=cut |