line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MySQL::Insert; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
23522
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
4
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1544
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $MAX_ROWS_TO_QUERY = 1000; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
MySQL::Insert - extended inserts for MySQL via DBI |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=cut |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = '0.06'; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 SYNOPSIS |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Insert two rows into sample_table using $dbh database handle |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use MySQL::Insert; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
$MySQL::Insert::MAX_ROWS_TO_QUERY = 1000; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
my $inserter = MySQL::Insert->new( $dbh, 'sample_table', [ @field_names ], %param ); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# Param can be: |
27
|
|
|
|
|
|
|
# statement = 'INSERT' | 'REPLACE' | 'INSERT IGNORE' (by default) |
28
|
|
|
|
|
|
|
# on_duplicate_update = { field_name => field_value, .. } (not used by default) |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# simple insertion |
31
|
|
|
|
|
|
|
$inserter->insert_row( { fldname => 'fldvalue1' } ); |
32
|
|
|
|
|
|
|
$inserter->insert_row( { fldname => 'fldvalue2' } ); |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# multirow insertion |
35
|
|
|
|
|
|
|
$inserter->insert_row( { fldname => 'fldvalue3' }, { fldname => 'fldvalue4' } ); |
36
|
|
|
|
|
|
|
$inserter->insert_row( [ 'fldvalue5' ], [ 'fldvalue6' ] } ); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# Insert row into sample_table using $dbh database handle |
39
|
|
|
|
|
|
|
# If fldvalue3 is passed as scalar ref then it is not quoted |
40
|
|
|
|
|
|
|
# Used to insert MySQL built-in functions like NOW() and NULL values. |
41
|
|
|
|
|
|
|
# @field_names must be predefined in case of arrayref row data usage |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
$inserter->insert_row( { fldname => \'NOW()' } ); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
undef $inserter; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 DESCRIPTION |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
Use multiple-row INSERT syntax that include several VALUES lists. |
50
|
|
|
|
|
|
|
(for example INSERT INTO test VALUES ('1',Some data',2234),('2','Some More Data',23444)). |
51
|
|
|
|
|
|
|
EXTENDED INSERT syntax is more efficient of execution many insert queries. |
52
|
|
|
|
|
|
|
It is not compatible with most RDBMSes. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head1 FUNCTIONS / METHODS |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
The following methods are available: |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 new |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Create new MySQL::Insert object |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=cut |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub new { |
65
|
0
|
|
|
0
|
1
|
|
my $type = shift; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
|
|
|
my $self = { }; |
68
|
0
|
|
|
|
|
|
$self = bless $self, $type; |
69
|
0
|
|
|
|
|
|
$self->_init( @_ ); |
70
|
0
|
|
|
|
|
|
return $self; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub _init { |
74
|
0
|
|
|
0
|
|
|
my ( $self, $dbh, $table, $fields, %ext_params ) = @_; |
75
|
|
|
|
|
|
|
|
76
|
0
|
|
|
|
|
|
$self->{_dbh} = $dbh; |
77
|
0
|
|
|
|
|
|
$self->{_table} = $table; |
78
|
|
|
|
|
|
|
|
79
|
0
|
|
|
|
|
|
$self->set_fields( $fields ); |
80
|
|
|
|
|
|
|
|
81
|
0
|
|
|
|
|
|
$self->{_total_rows} = 0; |
82
|
0
|
|
|
|
|
|
$self->{_do_append_row_to_query} = 0; |
83
|
0
|
|
|
|
|
|
$self->{_query_exists} = 0; |
84
|
0
|
|
0
|
|
|
|
$self->{_statement} = $ext_params{statement} || 'INSERT IGNORE'; |
85
|
0
|
|
|
|
|
|
$self->{_on_duplicate_update} = $ext_params{on_duplicate_update}; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=head2 set_fields |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Set fields list (by plain list or list reference) |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=cut |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub set_fields { |
95
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
96
|
|
|
|
|
|
|
|
97
|
0
|
0
|
0
|
|
|
|
return unless @_ && $_[0]; |
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
my @fields = ref $_[0] ? @{$_[0]} : @_; |
|
0
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
0
|
|
|
|
|
|
$self->{_fields} = \@fields; |
102
|
0
|
|
|
|
|
|
$self->{_name_fields} = "( " . ( join ", ", map "`$_`", @fields ) . " )"; |
103
|
|
|
|
|
|
|
|
104
|
0
|
|
|
|
|
|
return 1; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=head2 get_fields |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Get fields list (or its quantity in scalar context) |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=cut |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub get_fields { |
114
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
115
|
|
|
|
|
|
|
|
116
|
0
|
0
|
|
|
|
|
return unless $self->{_fields}; |
117
|
0
|
0
|
|
|
|
|
return wantarray ? @{$self->{_fields}} : scalar @{$self->{_fields}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
DESTROY { |
121
|
0
|
|
|
0
|
|
|
my $self = shift; |
122
|
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
$self->_finish_current_row; |
124
|
|
|
|
|
|
|
|
125
|
0
|
|
|
|
|
|
$self->_execute_query(); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=head2 insert_row |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Schedule row for insertion |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=cut |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub insert_row { |
135
|
0
|
|
|
0
|
1
|
|
my ( $self, @new_rows ) = @_; |
136
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my $query_executed = 0; |
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
foreach my $new_row ( @new_rows ) { |
140
|
0
|
0
|
|
|
|
|
$query_executed = 1 if $self->_finish_current_row(); |
141
|
|
|
|
|
|
|
|
142
|
0
|
|
|
|
|
|
$self->{_do_append_row_to_query} = 1; |
143
|
0
|
|
|
|
|
|
$self->{_current_row} = $new_row; |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
0
|
|
|
|
|
|
return $query_executed; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# Private methods |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub _finish_current_row { |
152
|
0
|
|
|
0
|
|
|
my $self = shift; |
153
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
my $query_executed; |
155
|
|
|
|
|
|
|
|
156
|
0
|
0
|
|
|
|
|
if ( $self->{_do_append_row_to_query} ) { |
157
|
|
|
|
|
|
|
|
158
|
0
|
0
|
|
|
|
|
if ( $self->{_total_rows} >= $MAX_ROWS_TO_QUERY ) { |
159
|
0
|
|
|
|
|
|
$query_executed = $self->_execute_query(); |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
0
|
|
|
|
|
|
$self->_append_row_to_query_rows; |
163
|
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
$self->{_do_append_row_to_query} = 0; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
0
|
|
|
|
|
|
return $query_executed; |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
sub _execute_query { |
171
|
0
|
|
|
0
|
|
|
my $self = shift; |
172
|
|
|
|
|
|
|
|
173
|
0
|
0
|
|
|
|
|
return if ! $self->{_query_exists}; |
174
|
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
|
my $values = join ',', @{$self->{_query_rows}}; |
|
0
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
|
my $query = "$self->{_statement} $self->{_table} $self->{_name_fields} VALUES $values"; |
178
|
|
|
|
|
|
|
|
179
|
0
|
0
|
0
|
|
|
|
if ( $self->{_statement} =~ /^INSERT/i && $self->{_on_duplicate_update} ) { |
180
|
|
|
|
|
|
|
|
181
|
0
|
|
|
|
|
|
my $update_statement = join ', ', |
182
|
0
|
|
|
|
|
|
map { "$_ = " . $self->_prepare_value( $self->{_on_duplicate_update}->{$_} ) } |
183
|
0
|
|
|
|
|
|
keys %{ $self->{_on_duplicate_update} }; |
184
|
|
|
|
|
|
|
|
185
|
0
|
|
|
|
|
|
$query .= ' ON DUPLICATE KEY UPDATE ' . $update_statement; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
0
|
0
|
|
|
|
|
my $result = $self->{_dbh}->do( $query ) or return; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# clear everyting |
191
|
0
|
|
|
|
|
|
$self->{_query_exists} = 0; |
192
|
0
|
|
|
|
|
|
$self->{_total_rows} = 0; |
193
|
0
|
|
|
|
|
|
$self->{_query_rows} = []; |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
return $result; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
sub _append_row_to_query_rows { |
199
|
0
|
|
|
0
|
|
|
my ( $self ) = @_; |
200
|
|
|
|
|
|
|
|
201
|
0
|
0
|
|
|
|
|
unless ( $self->get_fields() ) { |
202
|
0
|
0
|
|
|
|
|
die 'Undefined field names!' unless ref $self->{_current_row} eq 'HASH'; |
203
|
|
|
|
|
|
|
|
204
|
0
|
|
|
|
|
|
$self->set_fields( keys %{$self->{_current_row}} ); |
|
0
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
|
my @data_row; |
208
|
|
|
|
|
|
|
|
209
|
0
|
0
|
|
|
|
|
if ( ref $self->{_current_row} eq 'HASH' ) { |
210
|
0
|
|
|
|
|
|
for my $field ( $self->get_fields() ) { |
211
|
0
|
|
|
|
|
|
push @data_row, $self->_prepare_value( $self->{_current_row}->{ $field } ); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
else { |
215
|
0
|
|
|
|
|
|
push @data_row, map { $self->_prepare_value( $_ ) } @{ $self->{_current_row} }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
0
|
|
|
|
|
|
push @{$self->{_query_rows}}, "\n\t( ".join(', ', @data_row)." )"; |
|
0
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
|
$self->{_query_exists} = 1; |
221
|
0
|
|
|
|
|
|
$self->{_total_rows}++; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub _prepare_value { |
225
|
0
|
|
|
0
|
|
|
my ( $self, $value ) = @_; |
226
|
|
|
|
|
|
|
|
227
|
0
|
0
|
|
|
|
|
if ( ref $value eq 'SCALAR' ) { |
228
|
0
|
|
0
|
|
|
|
return ${ $value } || q{''}; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
else { |
231
|
0
|
|
|
|
|
|
return $self->{_dbh}->quote( $value ); |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head1 AUTHORS |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Gleb Tumanov C<< >> (original author) |
239
|
|
|
|
|
|
|
Walery Studennikov C<< >> (CPAN distribution) |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=head1 BUGS |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
244
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
245
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head1 LICENSE |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
250
|
|
|
|
|
|
|
under the same terms as Perl itself. |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=cut |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
1; # End of MySQL::Insert |