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