File Coverage

blib/lib/DBIx/SecureCGI.pm
Criterion Covered Total %
statement 29 336 8.6
branch 8 202 3.9
condition 5 111 4.5
subroutine 8 39 20.5
pod 1 1 100.0
total 51 689 7.4


line stmt bran cond sub pod time code
1             package DBIx::SecureCGI;
2              
3 21     21   723230 use warnings;
  21         46  
  21         838  
4 21     21   93 use strict;
  21         28  
  21         588  
5 21     21   1904 use utf8;
  21         53  
  21         124  
6 21     21   575 use feature ':5.10';
  21         27  
  21         1905  
7 21     21   90 use Carp;
  21         29  
  21         1438  
8              
9 21     21   9981 use version; our $VERSION = qv('2.0.6'); # REMINDER: update Changes
  21         33183  
  21         112  
10              
11             # REMINDER: update dependencies in Build.PL
12 21     21   6532 use DBI;
  21         47512  
  21         125222  
13              
14              
15             ## no critic (ProhibitPostfixControls Capitalization ProhibitEnumeratedClasses)
16              
17             my $PRIVATE = 'private_' . __PACKAGE__;
18             my $INT = qr/\A-?\d+\s+(?:SECOND|MINUTE|HOUR|DAY|MONTH|YEAR)\z/msi;
19             my $IDENT = qr/((?!__)\w[a-zA-Z0-9]*(?:_(?!_)[a-zA-Z0-9]*)*)/ms;
20             my %Func = ();
21              
22              
23             DefineFunc(eq => sub {
24             my ($dbh, $f, $v) = @_;
25             my (@val, $null, @expr);
26             @val = ref $v ? @{$v} : $v;
27             $null = grep {!defined} @val;
28             @val = grep {defined} @val;
29             push @expr, sprintf '%s IS NULL', $f if $null;
30             push @expr, sprintf '%s = %s', $f, $dbh->quote($val[0]) if @val==1;
31             push @expr, sprintf '%s IN (%s)',
32             $f, join q{,}, map { $dbh->quote($_) } @val if @val>1;
33             push @expr, 'NOT 1' if !@expr;
34             return @expr==1 ? $expr[0] : '('.join(' OR ', @expr).')';
35             });
36             DefineFunc(ne => sub {
37             my ($dbh, $f, $v) = @_;
38             my (@val, $null, @expr);
39             @val = ref $v ? @{$v} : $v;
40             $null = grep {!defined} @val;
41             @val = grep {defined} @val;
42             push @expr, sprintf '%s IS NOT NULL', $f if $null && !@val;
43             push @expr, sprintf '%s IS NULL', $f if !$null && @val;
44             push @expr, sprintf '%s != %s', $f,$dbh->quote($val[0]) if @val==1;
45             push @expr, sprintf '%s NOT IN (%s)', $f,
46             join q{,}, map { $dbh->quote($_) } @val if @val>1;
47             push @expr, 'NOT 0' if !@expr;
48             return @expr==1 ? $expr[0] : '('.join(' OR ', @expr).')';
49             });
50             DefineFunc(lt => '%s < %s');
51             DefineFunc(gt => '%s > %s');
52             DefineFunc(le => '%s <= %s');
53             DefineFunc(ge => '%s >= %s');
54             DefineFunc(like => '%s LIKE %s');
55             DefineFunc(not_like => '%s NOT LIKE %s');
56             DefineFunc(date_eq => [$INT, '%s = DATE_ADD(NOW(), INTERVAL %s)']);
57             DefineFunc(date_ne => [$INT, '%s != DATE_ADD(NOW(), INTERVAL %s)']);
58             DefineFunc(date_lt => [$INT, '%s < DATE_ADD(NOW(), INTERVAL %s)']);
59             DefineFunc(date_gt => [$INT, '%s > DATE_ADD(NOW(), INTERVAL %s)']);
60             DefineFunc(date_le => [$INT, '%s <= DATE_ADD(NOW(), INTERVAL %s)']);
61             DefineFunc(date_ge => [$INT, '%s >= DATE_ADD(NOW(), INTERVAL %s)']);
62             DefineFunc(set_date => sub {
63             my ($dbh, $f, $v) = @_;
64             if (uc $v eq 'NOW') {
65             return sprintf '%s = NOW()', $f;
66             } elsif ($v =~ /$INT/mso) {
67             return sprintf '%s = DATE_ADD(NOW(), INTERVAL %s)', $f, $dbh->quote($v),
68             }
69             return;
70             });
71             DefineFunc(set_add => sub {
72             my ($dbh, $f, $v) = @_;
73             return sprintf '%s = %s + %s', $f, $f, $dbh->quote($v);
74             });
75              
76              
77             sub DefineFunc {
78 336     336 1 574 my ($func, $cmd) = @_;
79 336 50 33     2295 if (!$func || ref $func || $func !~ /\A[A-Za-z]\w*\z/ms) {
      33        
80 0         0 croak "bad function name: $func";
81             }
82 336 100       716 if (!ref $cmd) {
    100          
    50          
83 126 50       402 if (2 != (() = $cmd =~ /%s/msg)) {
84 0         0 croak "bad function: $cmd";
85             }
86             } elsif (ref $cmd eq 'ARRAY') {
87 126 50 33     108 if (2 != @{$cmd}
  126   33     1081  
      33        
88             || ref $cmd->[0] ne 'Regexp'
89             || (ref $cmd->[1] || 2 != (() = $cmd->[1] =~ /%s/msg))) {
90 0         0 croak "bad function: [@$cmd]";
91             }
92             } elsif (ref $cmd ne 'CODE') {
93 0         0 croak 'bad function';
94             }
95 336         645 $Func{$func} = $cmd;
96 336         442 return;
97             }
98              
99             sub _ret {
100 0     0     my $cb = shift;
101 0 0         if ($cb) {
102 0           return $cb->(@_);
103             } else {
104 0 0         return wantarray ? @_ : $_[0];
105             }
106             }
107              
108             sub _ret1 {
109 0     0     my ($cb, $ret, $h) = @_;
110 0 0         if ($cb) {
111 0           return $cb->($ret, $h);
112             } else {
113 0           return $ret;
114             }
115             }
116              
117             sub _retdo {
118 0     0     my ($dbh, $sql, $cb) = @_;
119 0 0         if (!$cb) {
120 0           return $dbh->do($sql);
121             }
122 0           return $dbh->do($sql, undef, $cb);
123             }
124              
125             # Set cache to given HASHREF, if any.
126             # Initialize cache, if needed.
127             # Return current cache.
128             sub DBI::db::SecureCGICache {
129 0     0     my ($dbh, $cache) = @_;
130 0 0 0       if ($cache && ref $cache eq 'HASH') {
131 0           $dbh->{$PRIVATE} = $cache;
132             } else {
133 0   0       $dbh->{$PRIVATE} //= {};
134             }
135 0           return $dbh->{$PRIVATE};
136             }
137              
138             # Ensure $dbh->All("DESC $table") is cached.
139             # Return cached $dbh->All("DESC $table").
140             # On error set $dbh->err and return nothing.
141             sub DBI::db::ColumnInfo {
142 0     0     my ($dbh, $table, $cb) = @_;
143 0           my $cache = $dbh->SecureCGICache();
144 0 0         if ($cache->{$table}) {
145 0           return _ret($cb, $cache->{$table});
146             }
147              
148 0 0         if (!$cb) {
149 0           my @desc = $dbh->All('DESC '.$dbh->quote_identifier($table));
150 0           return _set_column_info($dbh, $cache, $table, undef, @desc);
151             }
152             return $dbh->All('DESC '.$dbh->quote_identifier($table), sub {
153 0     0     my @desc = @_;
154 0           return _set_column_info($dbh, $cache, $table, $cb, @desc);
155 0           });
156             }
157              
158             sub _set_column_info {
159 0     0     my ($dbh, $cache, $table, $cb, @desc) = @_;
160 0 0         if (@desc) {
161 0           my @pk = grep {$desc[$_]{Key} eq 'PRI'} 0 .. $#desc;
  0            
162 0 0 0       if (1 != @pk || $pk[0] != 0) {
163 0           return _ret($cb, $dbh->set_err($DBI::stderr, "first field must be primary key: $table\n", undef, 'ColumnInfo'));
164             }
165 0           $cache->{$table} = \@desc;
166             }
167 0           return _ret($cb, $cache->{$table});
168             }
169              
170             # Ensure DESC for all $tables cached.
171             # Return $dbh->SecureCGICache().
172             # On error set $dbh->err and return nothing.
173             sub DBI::db::TableInfo {
174 0     0     my ($dbh, $tables, $cb) = @_;
175 0 0         my @tables = ref $tables eq 'ARRAY' ? @{$tables} : ($tables);
  0            
176 0 0 0       if (!@tables || grep {/\A\z|\s/ms} @tables) {
  0            
177 0           return _ret($cb, $dbh->set_err($DBI::stderr, "bad tables: [@tables]\n", undef, 'TableInfo'));
178             }
179              
180 0 0         if (!$cb) {
181 0           while (@tables) {
182 0           my $desc = $dbh->ColumnInfo(shift @tables);
183 0 0         if (!$desc) {
184 0           return;
185             }
186             }
187 0           return $dbh->SecureCGICache();
188             }
189 0           my $code; $code = sub {
190 0     0     my ($desc) = @_;
191 0 0         if (!$desc) {
192 0           undef $code;
193 0           return $cb->();
194             }
195 0 0         if (@tables) {
196 0           return $dbh->ColumnInfo(shift @tables, $code);
197             }
198 0           undef $code;
199 0           return $cb->( $dbh->SecureCGICache() );
200 0           };
201 0           return $dbh->ColumnInfo(shift @tables, $code);
202             }
203              
204             sub DBI::db::GetSQL {
205 0     0     my ($dbh, $tables, $P, $cb) = @_;
206             # remove possible JOIN info from table names for TableInfo()
207 0 0         my @tables = map {my $s=$_;$s=~s/\s.*//ms;$s} ref $tables ? @{$tables} : $tables; ## no critic
  0            
  0            
  0            
  0            
208 0 0         if (!$cb) {
209 0           my $cache = $dbh->TableInfo(\@tables);
210 0           return _get_sql($dbh, $cache, $tables, $P);
211             }
212             return $dbh->TableInfo(\@tables, sub {
213 0     0     my $cache = shift;
214 0           return _get_sql($dbh, $cache, $tables, $P, $cb);
215 0           });
216             }
217              
218             sub _get_sql { ## no critic (ProhibitExcessComplexity)
219 0     0     my ($dbh, $cache, $tables, $P, $cb) = @_;
220 0 0         if (!$cache) {
221 0           return _ret($cb);
222             }
223              
224             # Extract JOIN type info from table names
225 0           my (@tables, @jointype);
226 0 0         for (ref $tables eq 'ARRAY' ? @{$tables} : $tables) {
  0            
227 0 0         if (!/\A(\S+)(?:\s+(LEFT|INNER))?\s*\z/msi) {
228 0           return _ret($cb, $dbh->set_err($DBI::stderr, "unknown join type: $_\n", undef, 'GetSQL'));
229             }
230 0           push @tables, $1;
231 0   0       push @jointype, $2 // 'INNER';
232             }
233              
234 0           my %SQL = (
235             Table => $tables[0],
236             ID => $cache->{ $tables[0] }[0]{Field},
237             Select => q{},
238             From => q{},
239             Set => q{},
240             Where => q{},
241             UpdateWhere => q{},
242             Order => q{},
243             Group => q{},
244             Limit => q{},
245             SelectLimit => q{},
246             );
247              
248             # Detect keys which should be used for JOINing tables
249 0           $SQL{From} = $dbh->quote_identifier($tables[0]);
250 0           my @field = map {{ map {$_->{Field}=>1} @{ $cache->{$_} } }} @tables; ## no critic
  0            
  0            
  0            
251             TABLE:
252 0           for my $right (1..$#tables) {
253             ## no critic (ProhibitAmbiguousNames)
254 0           my $rkey = $cache->{ $tables[$right] }[0]{Field};
255 0           for my $left (0..$right-1) {
256 0           my $lkey = $cache->{ $tables[$left] }[0]{Field};
257 0 0         my $key = $field[$left]{$rkey} ? $rkey :
    0          
258             $field[$right]{$lkey} ? $lkey : next;
259 0           $SQL{From} .= sprintf ' %s JOIN %s ON (%s.%s = %s.%s)',
260             $jointype[$right],
261 0           map { $dbh->quote_identifier($_) }
262             $tables[$right], $tables[$right], $key, $tables[$left], $key;
263 0           next TABLE;
264             }
265 0           return _ret($cb, $dbh->set_err($DBI::stderr, "can't join table: $tables[$right]\n", undef, 'GetSQL'));
266             }
267              
268             # Set $SQL{Select} using qualified field names and without duplicates
269 0           my %qualify;
270 0           for my $t (@tables) {
271 0           for my $f (map {$_->{Field}} @{ $cache->{$t} }) {
  0            
  0            
272 0 0         next if $qualify{$f};
273 0           $qualify{$f} = sprintf '%s.%s',
274 0           map { $dbh->quote_identifier($_) } $t, $f;
275 0           $SQL{Select} .= ', '.$qualify{$f};
276             }
277             }
278 0           $SQL{Select} =~ s/\A, //ms;
279              
280             # Set $SQL{Set}, $SQL{Where}, $SQL{UpdateWhere}
281 0           for my $k (keys %{$P}) {
  0            
282 0 0         $k =~ /\A$IDENT(?:__(?!_)$IDENT)?\z/ms or next; # ignore non-field keys
283 0 0         my $f = $qualify{$1} or next; # ignore non-field keys
284 0   0       my $func= $2 // q{};
285 0   0       my $cmd = $Func{$func || 'eq'};
286 0 0         if (!$cmd) {
287 0           return _ret($cb, $dbh->set_err($DBI::stderr, "unknown function: $k\n", undef, 'GetSQL'));
288             }
289 0 0 0       if (!$func && ref $P->{$k}) {
290 0           return _ret($cb, $dbh->set_err($DBI::stderr, "ARRAYREF without function: $k\n", undef, 'GetSQL'));
291             }
292             # WARNING functions `eq' and `ne' must process value array themselves:
293 0   0       my $is_list = ref $P->{$k} && $func ne 'eq' && $func ne 'ne';
294 0 0         for my $v ($is_list ? @{$P->{$k}} : $P->{$k}) {
  0            
295 0 0 0       my $expr
    0          
296             = ref $cmd eq 'CODE' ? $cmd->($dbh, $f, $v)
297             : ref $cmd eq 'ARRAY' ? ($v =~ /$cmd->[0]/ms && sprintf $cmd->[1], $f, $v)
298             : sprintf $cmd, $f, $dbh->quote($v);
299 0 0         if (!$expr) {
300 0           return _ret($cb, $dbh->set_err($DBI::stderr, "bad value for $k: $v\n", undef, 'GetSQL'));
301             }
302 0 0 0       $SQL{Set} .= ", $expr" if !$func || $func =~ /\Aset_/ms;
303 0 0         $SQL{Where} .= " AND $expr" if $func !~ /\Aset_/ms;
304 0 0 0       $SQL{UpdateWhere} .= " AND $expr" if $func && $func !~ /\Aset_/ms;
305 0 0         $SQL{UpdateWhere} .= " AND $expr" if $k eq $SQL{ID};
306             }
307             }
308 0           $SQL{Set} =~ s/\A, //ms;
309 0           $SQL{Where} =~ s/\A AND //ms;
310 0           $SQL{UpdateWhere} =~ s/\A AND //ms;
311 0           $SQL{Set} =~ s/\s+IS\s+NULL/ = NULL/msg;
312 0   0       $SQL{Where} ||= '1';
313 0   0       $SQL{UpdateWhere} ||= '1';
314              
315             # Set $SQL{Order} and $SQL{Group}
316 0 0         for my $order (ref $P->{__order} ? @{$P->{__order}} : $P->{__order}) {
  0            
317 0 0         next if !defined $order;
318 0 0 0       if ($order !~ /\A(\w+)\s*( ASC| DESC|)\z/ms || !$qualify{$1}) {
319 0           return _ret($cb, $dbh->set_err($DBI::stderr, "bad __order value: $order\n", undef, 'GetSQL'));
320             }
321 0           $SQL{Order} .= ", $qualify{$1}$2";
322             }
323 0 0         for my $group (ref $P->{__group} ? @{$P->{__group}} : $P->{__group}) {
  0            
324 0 0         next if !defined $group;
325 0 0 0       if ($group !~ /\A(\w+)\s*( ASC| DESC|)\z/ms || !$qualify{$1}) {
326 0           return _ret($cb, $dbh->set_err($DBI::stderr, "bad __group value: $group\n", undef, 'GetSQL'));
327             }
328 0           $SQL{Group} .= ", $qualify{$1}$2";
329             }
330 0           $SQL{Order} =~ s/\A, //ms;
331 0           $SQL{Group} =~ s/\A, //ms;
332              
333             # Set $SQL{Limit}, $SQL{SelectLimit}
334 0 0 0       my @limit = ref $P->{__limit} ? @{$P->{__limit}} : $P->{__limit} // ();
  0            
335 0           for (grep {!m/\A\d+\z/ms} @limit) {
  0            
336 0           return _ret($cb, $dbh->set_err($DBI::stderr, "bad __limit value: $_\n", undef, 'GetSQL'));
337             }
338 0 0         if (@limit == 1) {
    0          
    0          
339 0           $SQL{Limit} = " $limit[0]"; # make __limit=>0 true value
340 0           $SQL{SelectLimit} = " $limit[0]"; # make __limit=>0 true value
341             }
342             elsif (@limit == 2) {
343 0           $SQL{SelectLimit} = join q{,}, @limit;
344             }
345             elsif (@limit > 2) {
346 0           return _ret($cb, $dbh->set_err($DBI::stderr, "too many __limit values: [@limit]\n", undef, 'GetSQL'));
347             }
348              
349 0           return _ret($cb, \%SQL);
350             }
351              
352             sub DBI::db::Insert {
353 0     0     my ($dbh, $table, $P, $cb) = @_;
354 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
355              
356 0           my $sql = sprintf 'INSERT INTO %s SET %s',
357             $dbh->quote_identifier($SQL->{Table}), $SQL->{Set};
358              
359 0 0         if (!$cb) {
360 0 0         return $dbh->do($sql) ? $dbh->{mysql_insertid} : undef;
361             }
362             return $dbh->do($sql, undef, sub {
363 0     0     my ($rv, $dbh) = @_; ## no critic (ProhibitReusedNames)
364 0 0         return $cb->(($rv ? $dbh->{mysql_insertid} : undef), $dbh);
365 0           });
366             }
367              
368             sub DBI::db::InsertIgnore {
369 0     0     my ($dbh, $table, $P, $cb) = @_;
370 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
371              
372 0           my $sql = sprintf 'INSERT IGNORE INTO %s SET %s',
373             $dbh->quote_identifier($SQL->{Table}), $SQL->{Set};
374 0           return _retdo($dbh, $sql, $cb);
375             }
376              
377             sub DBI::db::Update {
378 0     0     my ($dbh, $table, $P, $cb) = @_;
379 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
380 0 0 0       if ($SQL->{UpdateWhere} eq '1' && !$P->{__force}) {
381 0           return _ret1($cb, $dbh->set_err($DBI::stderr, "empty WHERE require {__force=>1}\n", undef, 'Update'), $dbh);
382             }
383              
384 0 0 0       my $sql = sprintf 'UPDATE %s SET %s WHERE %s' . ($SQL->{Limit} ? ' LIMIT %s' : q{}),
385             $dbh->quote_identifier($SQL->{Table}), $SQL->{Set}, $SQL->{UpdateWhere},
386             $SQL->{Limit} || ();
387 0           return _retdo($dbh, $sql, $cb);
388             }
389              
390             sub DBI::db::Replace {
391 0     0     my ($dbh, $table, $P, $cb) = @_;
392 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
393              
394 0           my $sql = sprintf 'REPLACE INTO %s SET %s',
395             $dbh->quote_identifier($SQL->{Table}), $SQL->{Set};
396 0           return _retdo($dbh, $sql, $cb);
397             }
398              
399             sub _find_tables_for_delete {
400 0     0     my ($dbh, $fields, $tables, $P, $cb) = @_;
401 0 0         if (!@{$tables}) {
  0            
402 0           return _ret1($cb, undef, $dbh);
403             }
404              
405 0           my $found = [];
406 0 0         if (!$cb) {
407 0           for my $t (@{$tables}) {
  0            
408 0           my $desc = $dbh->ColumnInfo($t);
409 0 0         if ($desc) {
410 0           my @columns = map {$_->{Field}} @{$desc};
  0            
  0            
411 0           my %seen;
412 0 0         if (@{$fields} == grep {++$seen{$_}==2} @{$fields}, @columns) {
  0            
  0            
  0            
413 0           push @{$found}, $t;
  0            
414             }
415             }
416             }
417 0           return $dbh->Delete($found, $P);
418             }
419 0           my $code; $code = sub {
420 0     0     my ($desc) = @_;
421 0           my $t = shift @{$tables};
  0            
422 0 0         if ($desc) {
423 0           my @columns = map {$_->{Field}} @{$desc};
  0            
  0            
424 0           my %seen;
425 0 0         if (@{$fields} == grep {++$seen{$_}==2} @{$fields}, @columns) {
  0            
  0            
  0            
426 0           push @{$found}, $t;
  0            
427             }
428             }
429 0 0         if (@{$tables}) {
  0            
430 0           return $dbh->ColumnInfo($tables->[0], $code);
431             }
432 0           undef $code;
433 0           return $dbh->Delete($found, $P, $cb);
434 0           };
435 0           return $dbh->ColumnInfo($tables->[0], $code);
436             }
437              
438             sub DBI::db::Delete { ## no critic (ProhibitExcessComplexity)
439 0     0     my ($dbh, $table, $P, $cb) = @_;
440              
441 0 0         if (!defined $table) {
442 0 0         my %fields = map {/\A$IDENT(?:__(?!_)$IDENT)?\z/ms ? ($1=>1) : ()} keys %{$P};
  0            
  0            
443 0           my @fields = keys %fields;
444 0 0         if (!@fields) {
445 0           return _ret1($cb, $dbh->set_err($DBI::stderr, "table undefined, require params\n", undef, 'Delete'), $dbh);
446             }
447 0 0         if (!$cb) {
448 0           return _find_tables_for_delete($dbh, \@fields, [$dbh->Col('SHOW TABLES')], $P);
449             }
450             return $dbh->Col('SHOW TABLES', sub {
451 0     0     my (@tables) = @_;
452 0           return _find_tables_for_delete($dbh, \@fields, \@tables, $P, $cb);
453 0           });
454             }
455              
456 0 0         my @tables = ref $table ? @{$table} : $table;
  0            
457 0 0         if (!$cb) {
458 0           my $res;
459 0           for my $t (@tables) {
460 0 0         my $SQL = $dbh->GetSQL($t, $P) or return;
461 0 0 0       if ($SQL->{Where} eq '1' && !$P->{__force}) {
462 0           return $dbh->set_err($DBI::stderr, "empty WHERE require {__force=>1}\n", undef, 'Delete');
463             }
464 0 0 0       my $sql = sprintf 'DELETE FROM %s WHERE %s' . ($SQL->{Limit} ? ' LIMIT %s' : q{}),
465             $dbh->quote_identifier($SQL->{Table}), $SQL->{Where}, $SQL->{Limit} || ();
466 0 0         $res = $dbh->do($sql) or return;
467             }
468 0           return $res;
469             }
470 0           my $code; $code = sub {
471 0     0     my ($SQL) = @_;
472 0           my $t = shift @tables;
473 0 0         if (!$SQL) {
474 0           undef $code;
475 0           return $cb->(undef, $dbh);
476             }
477 0 0 0       if ($SQL->{Where} eq '1' && !$P->{__force}) {
478 0           undef $code;
479 0           return $cb->($dbh->set_err($DBI::stderr, "empty WHERE require {__force=>1}\n", undef, 'Delete'), $dbh);
480             }
481 0 0 0       my $sql = sprintf 'DELETE FROM %s WHERE %s' . ($SQL->{Limit} ? ' LIMIT %s' : q{}),
482             $dbh->quote_identifier($SQL->{Table}), $SQL->{Where}, $SQL->{Limit} || ();
483             $dbh->do($sql, sub {
484 0           my ($res, $dbh) = @_; ## no critic (ProhibitReusedNames)
485 0 0 0       if ($res && @tables) {
486 0           return $dbh->GetSQL($tables[0], $P, $code);
487             }
488 0           undef $code;
489 0           return $cb->($res, $dbh);
490 0           });
491 0           };
492 0           return $dbh->GetSQL($tables[0], $P, $code);
493             }
494              
495             sub DBI::db::ID {
496 0     0     my ($dbh, $table, $P, $cb) = @_;
497 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
498              
499 0           my $sql = sprintf 'SELECT %s.%s FROM %s WHERE %s'
500             . ($SQL->{Order} ? ' ORDER BY %s' : q{})
501             . ($SQL->{SelectLimit} ? ' LIMIT %s' : q{}),
502 0 0 0       (map { $dbh->quote_identifier($_) } $SQL->{Table}, $SQL->{ID}),
    0 0        
503             $SQL->{From}, $SQL->{Where}, $SQL->{Order} || (), $SQL->{SelectLimit} || ();
504 0   0       return $dbh->Col($sql, $cb // ());
505             }
506              
507             sub DBI::db::Count {
508 0     0     my ($dbh, $table, $P, $cb) = @_;
509 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
510              
511 0           my $sql = sprintf 'SELECT count(*) __count FROM %s WHERE %s',
512             $SQL->{From}, $SQL->{Where};
513 0   0       return $dbh->Col($sql, $cb // ());
514             }
515              
516             sub DBI::db::Select {
517 0     0     my ($dbh, $table, $P, $cb) = @_;
518 0 0         my $SQL = $dbh->GetSQL($table, $P) or return _ret1($cb, undef, $dbh);
519              
520 0 0 0       my $sql = sprintf 'SELECT %s'
    0 0        
    0 0        
    0          
521             . ($SQL->{Group} ? ', count(*) __count' : q{})
522             . ' FROM %s WHERE %s'
523             . ($SQL->{Group} ? ' GROUP BY %s' : q{})
524             . ($SQL->{Order} ? ' ORDER BY %s' : q{})
525             . ($SQL->{SelectLimit} ? ' LIMIT %s' : q{}),
526             $SQL->{Select}, $SQL->{From}, $SQL->{Where},
527             $SQL->{Group} || (), $SQL->{Order} || (), $SQL->{SelectLimit} || ();
528 0 0         if (!$cb) {
529 0 0         return wantarray ? $dbh->All($sql) : $dbh->Row($sql);
530             }
531 0           return $dbh->All($sql, $cb);
532             }
533              
534             sub _is_cb {
535 0     0     my $cb = shift;
536 0           my $ref = ref $cb;
537 0   0       return $ref eq 'CODE' || $ref eq 'AnyEvent::CondVar';
538             }
539              
540             sub DBI::db::All {
541 0     0     my ($dbh, $sql, @bind) = @_;
542 0 0 0       my $cb = @bind && _is_cb($bind[-1]) ? pop @bind : undef;
543 0 0         if (!$cb) {
544 0 0         (my $sth = $dbh->prepare($sql, {async=>0}))->execute(@bind) or return;
545 0           return @{ $sth->fetchall_arrayref({}) };
  0            
546             }
547             return $dbh->prepare($sql)->execute(@bind, sub {
548 0     0     my ($rv, $sth) = @_;
549 0 0         return $cb->(!$rv ? () : @{ $sth->fetchall_arrayref({}) });
  0            
550 0           });
551             }
552              
553             sub DBI::db::Row {
554 0     0     my ($dbh, $sql, @bind) = @_;
555 0           return $dbh->selectrow_hashref($sql, undef, @bind);
556             }
557              
558             sub DBI::db::Col {
559 0     0     my ($dbh, $sql, @bind) = @_;
560 0 0 0       my $cb = @bind && _is_cb($bind[-1]) ? pop @bind : undef;
561 0 0         if (!$cb) {
562 0 0         my @res = @{ $dbh->selectcol_arrayref($sql, undef, @bind) || [] };
  0            
563 0 0         return wantarray ? @res : $res[0];
564             }
565             return $dbh->selectcol_arrayref($sql, undef, @bind, sub {
566 0     0     my ($ary_ref) = @_;
567 0 0         return $cb->($ary_ref ? @{ $ary_ref } : ());
  0            
568 0           });
569             }
570              
571              
572             1; # Magic true value required at end of module
573             __END__
574              
575             =encoding utf8
576              
577             =head1 NAME
578              
579             DBIx::SecureCGI - Secure conversion of CGI params hash to SQL
580              
581              
582             =head1 SYNOPSIS
583              
584             #--- sync
585              
586             use DBIx::SecureCGI;
587              
588             $row = $dbh->Select('Table', \%Q);
589             @rows = $dbh->Select(['Table1','Table2'], {%Q, id_user=>$id});
590             $count = $dbh->Count('Table', {age__gt=>25});
591             $id = $dbh->ID('Table', {login=>$login, pass=>$pass});
592             @id = $dbh->ID('Table', {age__gt=>25});
593             $newid = $dbh->Insert('Table', \%Q);
594             $rv = $dbh->InsertIgnore('Table', \%Q);
595             $rv = $dbh->Update('Table', \%Q);
596             $rv = $dbh->Replace('Table', \%Q);
597             $rv = $dbh->Delete('Table', \%Q);
598             $rv = $dbh->Delete(undef, {id_user=>$id});
599              
600             @rows = $dbh->All('SELECT * FROM Table WHERE id_user=?', $id);
601             $row = $dbh->Row('SELECT * FROM Table WHERE id_user=?', $id);
602             @col = $dbh->Col('SELECT id_user FROM Table');
603              
604             $SQL = $dbh->GetSQL(['Table1','Table2'], \%Q);
605             $cache = $dbh->TableInfo(['Table1','Table2']);
606             $desc = $dbh->ColumnInfo('Table');
607              
608              
609             #--- async
610              
611             use AnyEvent::DBI::MySQL;
612             use DBIx::SecureCGI;
613              
614             $dbh->Select(…, sub { my (@rows) = @_; … });
615             $dbh->Count(…, sub { my ($count) = @_; … });
616             $dbh->ID(…, sub { my (@id) = @_; … });
617             $dbh->Insert(…, sub { my ($newid, $dbh) = @_; … });
618             $dbh->InsertIgnore(…, sub { my ($rv, $dbh) = @_; … });
619             $dbh->Update(…, sub { my ($rv, $dbh) = @_; … });
620             $dbh->Replace(…, sub { my ($rv, $dbh) = @_; … });
621             $dbh->Delete(…, sub { my ($rv, $dbh) = @_; … });
622              
623             $dbh->All(…, sub { my (@rows) = @_; … });
624             $dbh->Row(…, sub { my ($row) = @_; … });
625             $dbh->Col(…, sub { my (@col) = @_; … });
626              
627             $dbh->GetSQL(…, sub { my ($SQL) = @_; … });
628             $dbh->TableInfo(…, sub { my ($cache) = @_; … });
629             $dbh->ColumnInfo(…, sub { my ($desc) = @_; … });
630              
631              
632             #--- setup
633              
634             DBIx::SecureCGI::DefineFunc( $name, '%s op %s' )
635             DBIx::SecureCGI::DefineFunc( $name, [ qr/regexp/, '%s op %s' ] )
636             DBIx::SecureCGI::DefineFunc( $name, sub { … } )
637              
638             $cache = $dbh->SecureCGICache();
639             $dbh->SecureCGICache($new_cache);
640              
641              
642             =head1 DESCRIPTION
643              
644             This module let you use B<hash with CGI params> to make (or just generate)
645             SQL queries to MySQL database in B<easy and secure> way. To make this
646             magic possible there are some limitations and requirements:
647              
648             =over
649              
650             =item * Your app and db scheme must conform to these L</"CONVENTIONS">
651              
652             =item * Small speed penalty/extra queries to load scheme from db
653              
654             =item * No support for advanced SQL, only basic queries
655              
656             =back
657              
658             Example: if all CGI params (including unrelated to db table 'Table') are
659             in C<%Q>, then:
660              
661             @rows = $dbh->Select('Table', \%Q);
662              
663             will execute any simple C<SELECT> query from the table C<Table> (defined
664             by user-supplied parameters in C<%Q>); and this:
665              
666             @user_rows = $dbh->Select('Table', {%Q, id_user=>$id});
667              
668             will make any similar query limited to records with C<id_user> column
669             value C<$id> (thus allowing user to fetch any or B<his own> records).
670              
671             The module is intended for use only with a fairly simple tables and simple
672             SQL queries. More advanced queries usually can be generated manually with
673             help of L</GetSQL> or you can just use plain L<DBI> methods.
674              
675             Also it support B<non-blocking SQL queries> using L<AnyEvent::DBI::MySQL>
676             and thus can be effectively used with event-based CGI frameworks like
677             L<Mojolicious> or with event-based FastCGI servers like L<FCGI::EV>.
678              
679             Finally, it can be used in non-CGI environment, as simplified interface to
680             L<DBI>.
681              
682             =head2 SECURITY OVERVIEW
683              
684             At a glance, generating SQL queries based on untrusted parameters sent by
685             user to your CGI looks very unsafe. But interface of this module designed
686             to make it safe - while you conform to some L</CONVENTIONS> and follow
687             some simple guidelines.
688              
689             =over
690              
691             =item * B<User have no control over query type (SELECT/INSERT/…)>
692              
693             It's defined by method name you call.
694              
695             =item * B<User have no control over tables involved in SQL query>
696              
697             It's defined by separate (first) parameter in all methods, unrelated to
698             hash with CGI parameters.
699              
700             =item * B<User have no direct control over SQL query>
701              
702             All values from hash are either quoted before inserting into SQL, or
703             checked using very strict regular expressions if it's impossible to quote
704             them (like for date/time C<INTERVAL> values).
705              
706             =item * B<You can block/control access to "secure" fields in all tables>
707              
708             Name all such fields in some special way (like beginning with "C<_>") and
709             when receiving CGI parameters immediately B<delete all keys> in hash which
710             match these fields (i.e. all keys beginning with "C<_>"). Later you can
711             analyse user's request and manually add to hash keys for these fields
712             before call method to execute SQL query.
713              
714             =item * B<You can limit user's access to some subset of records>
715              
716             Just instead of using plain C<\%Q> as parameter for methods use
717             something like C<< { %Q, id_user => $id } >> - this way user will be
718             limited to records with C<$id> value in C<id_user> column.
719              
720             =back
721              
722             Within these security limitations user can do anything - select records
723             with custom C<WHERE>, C<GROUP BY>, C<ORDER BY>, C<LIMIT>; set any values
724             (allowed by table scheme, of course) for any fields on C<INSERT> or
725             C<UPDATE>; etc. without any single line of your code - exclusively by
726             using different CGI parameters.
727              
728              
729             =head1 HOW IT WORKS
730              
731             Each CGI parameter belongs to one of three categories:
732              
733             =over
734              
735             =item * B<related to some table's field in db:> C<fieldname>,
736             C<fieldname__funcname>
737              
738             =item * B<control command:> C<__commandname>
739              
740             =item * B<your app's parameter>
741              
742             =back
743              
744             It's recommended to name fields in db beginning with B<lowercase> letter
745             or B<underscore>, and name your app's parameters beginning with
746             B<Uppercase> letter to avoid occasional clash with field name.
747              
748             To protect some fields (like "C<balance>" or "C<privileges>") from
749             uncontrolled access you can use simple convention: name these fields in db
750             beginning with "C<_>"; when receiving CGI params just
751             B<delete all with names beginning with> "C<_>" - thus it won't be possible
752             to access these fields from CGI params. This module doesn't know about
753             these protected fields and handle them just as usual fields. So, you
754             should later add needed keys for these fields into hash before calling
755             methods to execute SQL query. This way all operations on these fields will
756             be controlled by your app.
757              
758             You can use any other similar naming scheme which won't conflict with
759             L</CONVENTIONS> below - DBIx::SecureCGI will analyse db scheme (and
760             cache it for speed) to detect which keys match field names.
761              
762             CGI params may have several values. In hash, keys for such params must
763             have C<ARRAYREF> value. DBIx::SecureCGI support this only for keys which
764             contain "C<__>" (double underscore). Depending on used CGI framework you
765             may need to convert existing CGI parameters into this format.
766              
767             Error handling: all unknown keys will be silently ignored, all other
768             errors (unable to detect key for joining table, field without
769             "C<__funcname>" have C<ARRAYREF> value, unknown "C<__funcname>" function, etc.)
770             will return usual DBI errors (or throw exceptions when C<< {RaiseError=>1} >>.
771              
772             =head2 CONVENTIONS
773              
774             =over
775              
776             =item *
777              
778             Each table's B<first field> must be a C<PRIMARY KEY>.
779              
780             =over
781              
782             MOTIVATION: This module use simplified analyse of db scheme and suppose
783             first field in every table is a C<PRIMARY KEY>. To add support for complex
784             primary keys or tables without primary keys we should first define how
785             L</ID> should handle them and how to automatically join such tables.
786              
787             =back
788              
789             =item *
790              
791             Two tables are always C<JOIN>ed using field which must be C<PRIMARY KEY>
792             at least in one of them and have B<same name in both tables>.
793              
794             =over
795              
796             So, don't name your primary key "C<id>" if you plan to join this table with
797             another - name it like "C<id_thistable>" or "C<thistableId>".
798              
799             =back
800              
801             If both tables have field corresponding to C<PRIMARY KEY> in other table,
802             then key field of B<right table> (in order defined when you make array of
803             tables in first param of method) will be used.
804              
805             If more than two tables C<JOIN>ed, then each table starting from second
806             one will try to join to each of the previous tables (starting at first
807             table) until it find table with suitable field. If it wasn't found
808             DBI error will be returned.
809              
810             =over
811              
812             MOTIVATION: Let this module automatically join tables.
813              
814             =back
815              
816             =item *
817              
818             Field names must not contain "C<__>" (two adjoined underscore).
819              
820             =over
821              
822             MOTIVATION: Distinguish special commands for this module from field names.
823             Also, some methods sometimes create aliases for fields and their names
824             begins with "C<__>".
825              
826             =back
827              
828             =item *
829              
830             Hash with CGI params may contain several values (as C<ARRAYREF>) only for key
831             names containing "C<__>" (keys unrelated to fields may have any values).
832              
833             =over
834              
835             MOTIVATION: Allowing C<< { field => \@values } >> introduce many
836             ambiguities and in fact same as C<< { field__eq => \@values } >>,
837             so it's safer to deny it.
838              
839             =back
840              
841             =back
842              
843             =head2 Hash to SQL convertion rules
844              
845             =head3 __commandname
846              
847             Keys beginning with "C<__>" are control commands. Supported commands are:
848              
849             =over
850              
851             =item B<__order>
852              
853             Define value for C<ORDER BY>. Valid values are:
854              
855             'field_name'
856             'field_name ASC'
857             'field_name DESC'
858              
859             Multiple values can be given as C<ARRAYREF>.
860              
861             =item B<__group>
862              
863             Define value for C<GROUP BY>. Valid values are same as for B<__order>.
864              
865             =item B<__limit>
866              
867             Can have up to two numeric values (when it's C<ARRAYREF>), set C<LIMIT>.
868              
869             =item B<__force>
870              
871             If the value of B<__force> key is true, then it's allowed to run
872             L</Update> and L</Delete> with an empty C<WHERE>. (This isn't a security
873             feature, it's just for convenience to protect against occasional damage on
874             database while playing with CGI parameters.)
875              
876             =back
877              
878             Examples:
879              
880             my @rows = $dbh->Select('Table', {
881             age__ge => 20,
882             age__lt => 30,
883             __group => 'age',
884             __order => ['age DESC', 'fname'],
885             __limit => 5,
886             });
887             $dbh->Delete('Table', { __force => 1 });
888              
889             =head3 fieldname__funcname
890              
891             If the key contains a "C<__>" then it is treated as applying function
892             "C<funcname>" to field "C<fieldname>".
893             If the there is no field with such name in database, this key is ignored.
894             A valid key value - string/number or a reference to an array of
895             strings/numbers.
896             A list of available functions in this version is shown below.
897              
898             Unless special behavior mentioned functions handle C<ARRAYREF> value by
899             applying itself to each value in array and joining with C<AND>.
900              
901             Example:
902              
903             { html__like => ['%<P>%', '%<BR>%'] }
904              
905             will be transformed in SQL to
906              
907             html LIKE '%<P>%' AND html LIKE '%<BR>%'
908              
909             Typically, such keys are used in C<WHERE>, except when "C<funcname>" begins
910             with "C<set_>" - such keys will be used in C<SET>.
911              
912             =head3 fieldname
913              
914             Other keys are treated as names of fields in database.
915             If there is no field with such name, then key is ignored.
916             A valid value for these keys - scalar.
917              
918             Example:
919              
920             { name => 'Alex' }
921            
922             will be transformed in SQL to
923              
924             name = 'Alex'
925              
926             Typically, such keys are used in part C<SET>, except for C<PRIMARY KEY>
927             field in L</Update> - it will be used in C<WHERE>.
928              
929              
930             =head1 INTERFACE
931              
932             =head2 Functions
933              
934             =head3 DefineFunc
935              
936             DBIx::SecureCGI::DefineFunc( $name, '%s op %s' );
937             DBIx::SecureCGI::DefineFunc( $name, [ qr/regexp/, '%s op %s' ] );
938             DBIx::SecureCGI::DefineFunc( $name, sub { … } );
939              
940             Define new or replace existing function applied to fields after "C<__>"
941             delimiter.
942              
943             SQL expression for that function will be generated in different ways,
944             depending on how you defined that function - using string, regexp+string
945             or code:
946              
947             $expr = sprintf '%s op %s', $field, $dbh->quote($value);
948             $expr = $value =~ /regexp/ && sprintf '%s op %s', $field, $value;
949             $expr = $code->($dbh, $field, $value);
950              
951             If C<$expr> will be false DBI error will be returned.
952             Here is example of code implementation:
953              
954             sub {
955             my ($dbh, $f, $v) = @_;
956             if (… value ok …) {
957             return sprintf '…', $f, $dbh->quote($v);
958             }
959             return; # wrong value
960             }
961              
962              
963             =head2 Methods injected into DBI
964              
965             =head3 GetSQL
966              
967             $SQL = $dbh->GetSQL( $table, \%Q );
968             $dbh->GetSQL( $table, \%Q, sub { my ($SQL) = @_; … } );
969             $SQL = $dbh->GetSQL( \@tables, \%Q );
970             $dbh->GetSQL( \@tables, \%Q, sub { my ($SQL) = @_; … } );
971              
972             This is helper function which will analyse (cached) database scheme for
973             given tables and generate elements of SQL query for given keys in C<%Q>.
974             You may use it to write own methods like L</Select> or L</Insert>.
975              
976             In C<%Q> keys which doesn't match field names in C<$table> / C<@tables>
977             are ignored.
978              
979             Names of tables and fields in all keys (except C<{Table}> and C<{ID}>)
980             are already quoted, field names qualified with table name (so they're
981             ready for inserting into SQL query). Values of C<{Table}> and C<{ID}>
982             should be escaped with C<< $dbh->quote_identifier() >> before using in SQL
983             query.
984              
985             Returns C<HASHREF> with keys:
986              
987             {Table} first of the used tables
988             {ID} name of PRIMARY KEY field in {Table}
989             {Select} list of all field names which should be returned by
990             'SELECT *' excluding duplicated fields (when field with
991             same name exist in many tables only field from first table
992             will be returned); field names in {Select} are joined with ","
993             {From} all tables joined using chosen JOIN type (INNER by default)
994             {Set} string like "field=value, field2=value2" for all simple
995             "fieldname" keys in %Q
996             {Where} a-la {Set}, except fields joined using "AND" and added
997             "field__function" fields; if there are no fields it will
998             be set to string "1"
999             {UpdateWhere} a-la {Where}, except it uses only "field__function" keys
1000             plus one PRIMARY KEY "fieldname" key (if it exists in %Q)
1001             {Order} string like "field1 ASC, field2 DESC" or empty string
1002             {Group} a-la {Order}
1003             {Limit} set to value of __limit if it contain one number
1004             {SelectLimit} set to value of __limit if it contain one number,
1005             or to values of __limit joined with "," if it contain
1006             two numbers
1007              
1008             Example :
1009              
1010             CREATE TABLE A (
1011             id_a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
1012             i INT NOT NULL
1013             );
1014             CREATE TABLE B (
1015             id_b INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
1016             id_a INT NOT NULL,
1017             s VARCHAR(255) NOT NULL
1018             );
1019              
1020             $SQL = $dbh->GetSQL(['A', 'B LEFT'], {
1021             id_a => 3,
1022             i => 10,
1023             s => 'str',
1024             id_b__gt => 5,
1025             __group => 'i',
1026             __order => ['s DESC', 'i'],
1027             __limit => [50,10],
1028             });
1029              
1030             # now %$SQL have these values:
1031             # (backticks added by $dbh->quote_identifier() around all table/field
1032             # names omitted for readability)
1033             Table => 'A'
1034             ID => 'id_a'
1035             Select => 'A.id_a, A.i, B.id_b, B.s'
1036             From => 'A LEFT JOIN B ON (B.id_a = A.id_a)'
1037             Set => 'B.s = "str", A.id_a = 3, A.i = 10'
1038             Where => 'B.s = "str" AND A.id_a = 3 AND A.i = 10 AND B.id_b > 5'
1039             UpdateWhere => ' A.id_a = 3 AND B.id_b > 5'
1040             Group => 'A.i'
1041             Order => 'B.s DESC, A.i'
1042             Limit => ''
1043             SelectLimit => '50,10'
1044              
1045              
1046             =head3 Insert
1047              
1048             $newid = $dbh->Insert( $table, \%Q );
1049             $dbh->Insert( $table, \%Q, sub { my ($newid, $dbh) = @_; … } );
1050              
1051             Execute SQL query:
1052              
1053             INSERT INTO {Table} SET {Set}
1054              
1055             Return C<< $dbh->{mysql_insertid} >> on success or C<undef> on error.
1056              
1057             It's B<strongly recommended> to always use
1058              
1059             $dbh->Insert( …, { %Q, …, primary_key_name=>undef }, … )
1060              
1061             because if you didn't force C<primary_key> field to be C<NULL> in SQL (and
1062             thus use C<AUTO_INCREMENT> value) then user may send CGI parameter to set
1063             it to C<-1> or C<4294967295> and this will result in B<DoS> because no
1064             more records can be added using C<AUTO_INCREMENT> into this table.
1065              
1066              
1067             =head3 InsertIgnore
1068              
1069             $rv = $dbh->InsertIgnore( $table, \%Q );
1070             $dbh->InsertIgnore( $table, \%Q, sub { my ($rv, $dbh) = @_; … } );
1071              
1072             Execute SQL query:
1073              
1074             INSERT IGNORE INTO {Table} SET {Set}
1075              
1076             Return C<$rv> (true on success or C<undef> on error).
1077              
1078              
1079             =head3 Update
1080              
1081             $rv = $dbh->Update( $table, \%Q );
1082             $dbh->Update( $table, \%Q, sub { my ($rv, $dbh) = @_; … } );
1083              
1084             Execute SQL query:
1085              
1086             UPDATE {Table} SET {Set} WHERE {UpdateWhere} [LIMIT {Limit}]
1087              
1088             Uses in C<SET> part all fields given as "C<fieldname>", in C<WHERE> part all
1089             fields given as "C<fieldname__funcname>" plus C<PRIMARY KEY> field if it was
1090             given as "C<fieldname>".
1091              
1092             Return C<$rv> (amount of modified records on success or C<undef> on error).
1093              
1094             To use with empty C<WHERE> part require C<< {__force=>1} >> in C<%Q>.
1095              
1096              
1097             =head3 Replace
1098              
1099             $rv = $dbh->Replace( $table, \%Q );
1100             $dbh->Replace( $table, \%Q, sub { my ($rv, $dbh) = @_; … } );
1101              
1102             Execute SQL query:
1103              
1104             REPLACE INTO {Table} SET {Set}
1105              
1106             Uses in C<SET> part all fields given as "C<fieldname>".
1107              
1108             Return C<$rv> (true on success or C<undef> on error).
1109              
1110              
1111             =head3 Delete
1112              
1113             $rv = $dbh->Delete( $table, \%Q );
1114             $dbh->Delete( $table, \%Q, sub { my ($rv, $dbh) = @_; … } );
1115             $rv = $dbh->Delete( \@tables, \%Q );
1116             $dbh->Delete( \@tables, \%Q, sub { my ($rv, $dbh) = @_; … } );
1117             $rv = $dbh->Delete( undef, \%Q );
1118             $dbh->Delete( undef, \%Q, sub { my ($rv, $dbh) = @_; … } );
1119              
1120             Execute SQL query:
1121              
1122             DELETE FROM {Table} WHERE {Where} [LIMIT {Limit}]
1123              
1124             Delete records from C<$table> or (one-by-one) from each table in
1125             C<@tables>. If C<undef> given, then delete records from B<ALL> tables
1126             (except C<TEMPORARY>) which have B<ALL> fields mentioned in C<%Q>.
1127              
1128             To use with empty C<WHERE> part require C<< {__force=>1} >> in C<%Q>.
1129              
1130             Return C<$rv> (amount of deleted records or C<undef> on error).
1131             If used to delete records from more than one table - return C<$rv>
1132             for last table. If error happens it will be immediately returned,
1133             so some tables may not be processed in this case.
1134              
1135              
1136             =head3 ID
1137              
1138             $id = $dbh->ID( $table, \%Q );
1139             @id = $dbh->ID( $table, \%Q );
1140             $dbh->ID( $table, \%Q, sub { my (@id) = @_; … } );
1141             $id = $dbh->ID( \@tables, \%Q );
1142             @id = $dbh->ID( \@tables, \%Q );
1143             $dbh->ID( \@tables, \%Q, sub { my (@id) = @_; … } );
1144              
1145             Return result of executing this SQL query using L</Col>:
1146              
1147             SELECT {ID} FROM {From} WHERE {Where}
1148             [ORDER BY {Order}] [LIMIT {SelectLimit}]
1149              
1150              
1151             =head3 Count
1152              
1153             $count = $dbh->Count( $table, \%Q );
1154             $dbh->Count( $table, \%Q, sub { my ($count) = @_; … } );
1155             $count = $dbh->Count( \@tables, \%Q );
1156             $dbh->Count( \@tables, \%Q, sub { my ($count) = @_; … } );
1157              
1158             Return result of executing this SQL query using L</Col>:
1159              
1160             SELECT count(*) __count FROM {From} WHERE {Where}
1161              
1162              
1163             =head3 Select
1164              
1165             $row = $dbh->Select( $table, \%Q );
1166             @rows = $dbh->Select( $table, \%Q );
1167             $dbh->Select( $table, \%Q, sub { my (@rows) = @_; … } );
1168             $row = $dbh->Select( \@tables, \%Q );
1169             @rows = $dbh->Select( \@tables, \%Q );
1170             $dbh->Select( \@tables, \%Q, sub { my (@rows) = @_; … } );
1171              
1172             Execute one of these SQL queries (depending on using C<__group> command):
1173              
1174             SELECT * FROM {From} WHERE {Where}
1175             [ORDER BY {Order}] [LIMIT {SelectLimit}]
1176             SELECT *, count(*) __count FROM {From} WHERE {Where} GROUP BY {Group}
1177             [ORDER BY {Order}] [LIMIT {SelectLimit}]
1178              
1179             Instead of C<SELECT *> it uses enumeration of all fields qualified using
1180             table name; if same field found in several tables it's included only
1181             one - from first table having that field.
1182              
1183             In C<@tables> you can append C<' LEFT'> or C<' INNER'> to table name to
1184             choose C<JOIN> variant (by default C<INNER JOIN> will be used):
1185              
1186             $dbh->Select(['TableA', 'TableB LEFT', 'TableC'], …)
1187              
1188             Return result of executing SQL query using L</All> when called in list
1189             context or L</Row> when called in scalar context.
1190              
1191              
1192             =head3 All
1193              
1194             @rows = $dbh->All( $sql, @bind )
1195             $dbh->All( $sql, @bind, sub { my (@rows) = @_; … } );
1196              
1197             Shortcut for this ugly but very useful snippet:
1198              
1199             @{ $dbh->selectall_arrayref($sql, {Slice=>{}}, @bind) }
1200              
1201              
1202             =head3 Row
1203              
1204             $row = $dbh->Row( $sql, @bind );
1205             $dbh->Row( $sql, @bind, sub { my ($row) = @_; … } );
1206              
1207             Shortcut for:
1208              
1209             $dbh->selectrow_hashref($sql, undef, @bind)
1210              
1211             If you wonder why it exists, the answer is simple: it was added circa
1212             2002, when there was no C<< $dbh->selectrow_hashref() >> and now it
1213             continue to exists for compatibility and to complement L</All>
1214             and L</Col>.
1215              
1216              
1217             =head3 Col
1218              
1219             $col = $dbh->Col( $sql, @bind );
1220             @col = $dbh->Col( $sql, @bind );
1221             $dbh->Col( $sql, @bind, sub { my (@col) = @_; … } );
1222              
1223             Shortcut for:
1224              
1225             $col = $dbh->selectcol_arrayref($sql, undef, @bind)->[0];
1226             @col = @{ $dbh->selectcol_arrayref($sql, undef, @bind) };
1227              
1228              
1229             =head3 SecureCGICache
1230              
1231             $cache = $dbh->SecureCGICache();
1232             $cache = $dbh->SecureCGICache( $new_cache );
1233              
1234             Fetch (or set when C<$new_cache> given) C<HASHREF> with cached results of
1235             "C<DESC tablename>" SQL queries for all tables used previous in any methods.
1236              
1237             You may need to reset cache (by using C<{}> as C<$new_cache> value) if
1238             you've changed scheme for tables already accessed by any method or if you
1239             changed current database.
1240              
1241             Also in some environments when many different C<$dbh> used simultaneously,
1242             connected to same database (like in event-based environments) it may make
1243             sense to share same cache for all C<$dbh>.
1244              
1245              
1246             =head3 TableInfo
1247              
1248             $cache = $dbh->TableInfo( $table );
1249             $dbh->TableInfo( $table, sub { my ($cache) = @_; … } );
1250             $cache = $dbh->TableInfo( \@tables );
1251             $dbh->TableInfo( \@tables, sub { my ($cache) = @_; … } );
1252              
1253             Ensure "C<DESC tablename>" for all C<$table> / C<@tables> is cached.
1254              
1255             Return same as L</SecureCGICache> on success or C<undef> on error.
1256              
1257              
1258             =head3 ColumnInfo
1259              
1260             $desc = $dbh->ColumnInfo( $table );
1261             $dbh->ColumnInfo( $table, sub { my ($desc) = @_; … } );
1262              
1263             Ensure "C<DESC $table>" is cached.
1264              
1265             Return result of C<< $dbh->All("DESC $table") >> on success or C<undef> on
1266             error.
1267              
1268              
1269             =head2 __funcname functions for fields
1270              
1271             These functions can be added and replaced using L</DefineFunc>.
1272              
1273             Functions which can be used in C<%Q> as "C<fieldname_funcname>":
1274              
1275             =head3 eq, ne, lt, gt, le, ge
1276              
1277             field = value field IS NULL
1278             field != value field IS NOT NULL
1279             field < value
1280             field > value
1281             field <= value
1282             field >= value
1283              
1284             For functions B<eq> or B<ne>:
1285              
1286             eq [] - NOT 1
1287             ne [] - NOT 0
1288             eq only undef - name IS NULL
1289             ne only undef - name IS NOT NULL
1290             eq without undef - name IN (...)
1291             ne without undef - (name IS NULL OR name NOT IN (...))
1292             eq with undef - (name IS NULL OR name IN (...))
1293             ne with undef - name NOT IN (...)
1294              
1295             where
1296              
1297             "[]" : name__func=>[]
1298             "only undef": name__func=>undef or name__func=>[undef]
1299             "without undef": name__func=>$defined or name__func=>[@defined]
1300             "with undef": name__func=>[@defined_and_not_defined]
1301              
1302             =head3 like, not_like
1303              
1304             field LIKE value
1305             field NOT LIKE value
1306              
1307             =head3 date_eq, date_ne, date_lt, date_gt, date_le, date_ge
1308              
1309             field = DATE_ADD(NOW(), INTERVAL value)
1310             field != DATE_ADD(NOW(), INTERVAL value)
1311             field < DATE_ADD(NOW(), INTERVAL value)
1312             field > DATE_ADD(NOW(), INTERVAL value)
1313             field <= DATE_ADD(NOW(), INTERVAL value)
1314             field >= DATE_ADD(NOW(), INTERVAL value)
1315              
1316             value must match:
1317              
1318             /^-?\d+ (?:SECOND|MINUTE|HOUR|DAY|MONTH|YEAR)$/
1319              
1320             =head3 set_add
1321              
1322             field = field + value
1323              
1324             When used in L</Update> it will be in C<SET> instead of C<WHERE>.
1325             It doesn't make sense to use this function with L</Insert>,
1326             L</InsertIgnore> or L</Replace>.
1327              
1328             =head3 set_date
1329              
1330             field = NOW()
1331             field = DATE_ADD(NOW(), INTERVAL value)
1332              
1333             If it's value is (case-insensitive) string C<'NOW'> then it'll use
1334             C<NOW()> else it will use C<DATE_ADD(…)>.
1335              
1336             When used in L</Insert>, L</InsertIgnore>, L</Update> and L</Replace> it
1337             will be in C<SET>.
1338              
1339              
1340             =head1 BUGS AND LIMITATIONS
1341              
1342             No bugs have been reported.
1343              
1344             Only MySQL supported.
1345              
1346             It's impossible to change C<PRIMARY KEY> using L</Update> with:
1347              
1348             { id => $new_id, id__eq => $old_id }
1349              
1350             because both "C<id>" and "C<id__eq>" will be in C<WHERE> part:
1351              
1352             SET id = $new_id WHERE id = $new_id AND id = $old_id
1353              
1354             and if we won't add C<< 'id => $new_id' >> in C<WHERE> part if we have
1355             C< 'id__eq' >, then we'll have do use this
1356              
1357             $dbh->Func($table, {%Q, id_user=>$S{id_user}, id_user__eq=>$S{id_user})
1358              
1359             in B<all> CGI requests to protect against attempt to read someone else's
1360             records or change own records's id_user field by using C<'id_user'>
1361             or C<'id_user__eq'> CGI params.
1362              
1363              
1364             =head1 SUPPORT
1365              
1366             Please report any bugs or feature requests through the web interface at
1367             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DBIx-SecureCGI>.
1368             I will be notified, and then you'll automatically be notified of progress
1369             on your bug as I make changes.
1370              
1371             You can also look for information at:
1372              
1373             =over
1374              
1375             =item * RT: CPAN's request tracker
1376              
1377             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=DBIx-SecureCGI>
1378              
1379             =item * AnnoCPAN: Annotated CPAN documentation
1380              
1381             L<http://annocpan.org/dist/DBIx-SecureCGI>
1382              
1383             =item * CPAN Ratings
1384              
1385             L<http://cpanratings.perl.org/d/DBIx-SecureCGI>
1386              
1387             =item * Search CPAN
1388              
1389             L<http://search.cpan.org/dist/DBIx-SecureCGI/>
1390              
1391             =back
1392              
1393              
1394             =head1 AUTHORS
1395              
1396             Alex Efros C<< <powerman@cpan.org> >>
1397              
1398             Nikita Savin C<< <nikita@asdfGroup.com> >>
1399              
1400              
1401             =head1 LICENSE AND COPYRIGHT
1402              
1403             Copyright 2002-2014 Alex Efros <powerman@cpan.org>.
1404              
1405             This program is distributed under the MIT (X11) License:
1406             L<http://www.opensource.org/licenses/mit-license.php>
1407              
1408             Permission is hereby granted, free of charge, to any person
1409             obtaining a copy of this software and associated documentation
1410             files (the "Software"), to deal in the Software without
1411             restriction, including without limitation the rights to use,
1412             copy, modify, merge, publish, distribute, sublicense, and/or sell
1413             copies of the Software, and to permit persons to whom the
1414             Software is furnished to do so, subject to the following
1415             conditions:
1416              
1417             The above copyright notice and this permission notice shall be
1418             included in all copies or substantial portions of the Software.
1419              
1420             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1421             EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1422             OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1423             NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1424             HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1425             WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1426             FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1427             OTHER DEALINGS IN THE SOFTWARE.
1428