File Coverage

blib/lib/SQL/Parser.pm
Criterion Covered Total %
statement 1229 1380 89.0
branch 544 752 72.3
condition 175 245 71.4
subroutine 80 86 93.0
pod 30 67 44.7
total 2058 2530 81.3


line stmt bran cond sub pod time code
1             package SQL::Parser;
2              
3             ######################################################################
4             #
5             # This module is copyright (c), 2001,2005 by Jeff Zucker.
6             # This module is copyright (c), 2007-2020 by Jens Rehsack.
7             # All rights reserved.
8             #
9             # It may be freely distributed under the same terms as Perl itself.
10             # See below for help and copyright information (search for SYNOPSIS).
11             #
12             ######################################################################
13              
14 17     17   1017 use strict;
  17         28  
  17         515  
15 17     17   77 use warnings FATAL => "all";
  17         29  
  17         553  
16 17     17   96 use vars qw($VERSION);
  17         26  
  17         905  
17 17     17   97 use constant FUNCTION_NAMES => join( '|', qw(TRIM SUBSTRING) );
  17         31  
  17         2022  
18 17         902 use constant BAREWORD_FUNCTIONS =>
19 17     17   111 join( '|', qw(TRIM SUBSTRING CURRENT_DATE CURDATE CURRENT_TIME CURTIME CURRENT_TIMESTAMP NOW UNIX_TIMESTAMP PI DBNAME) );
  17         29  
20 17     17   94 use Carp qw(carp croak);
  17         43  
  17         1089  
21 17     17   3677 use Params::Util qw(_ARRAY0 _ARRAY _HASH);
  17         42232  
  17         1110  
22 17     17   108 use Scalar::Util qw(looks_like_number);
  17         47  
  17         781  
23 17     17   10620 use Text::Balanced qw(extract_bracketed extract_multiple);
  17         262942  
  17         1829  
24              
25             $VERSION = '1.414';
26              
27             BEGIN
28             {
29 17 50   17   12648 if ( $ENV{SQL_USER_DEFS} ) { require SQL::UserDefs; }
  0         0  
30             }
31              
32             #############################
33             # PUBLIC METHODS
34             #############################
35              
36             sub new
37             {
38 17     17 1 76250 my $class = shift;
39 17   100     104 my $dialect = shift || 'ANSI';
40 17 50       94 $dialect = 'ANSI' if ( uc $dialect eq 'ANSI' );
41 17 50 33     143 $dialect = 'AnyData' if ( ( uc $dialect eq 'ANYDATA' ) or ( uc $dialect eq 'CSV' ) );
42 17 50       69 $dialect = 'AnyData' if ( $dialect eq 'SQL::Eval' );
43              
44 17   100     390 my $flags = shift || {};
45 17         62 $flags->{dialect} = $dialect;
46 17 100       79 $flags->{PrintError} = 1 unless ( defined( $flags->{PrintError} ) );
47              
48 17         44 my $self = bless( $flags, $class );
49 17         181 $self->dialect( $self->{dialect} );
50 17         170 $self->set_feature_flags( $self->{select}, $self->{create} );
51              
52 17         117 $self->LOAD('LOAD SQL::Statement::Functions');
53              
54 17         108 return $self;
55             }
56              
57             sub parse
58             {
59 872     872 1 1534 my ( $self, $sql ) = @_;
60 872 50       2037 $self->dialect( $self->{dialect} ) unless ( $self->{dialect_set} );
61 872         3262 $sql =~ s/^\s+//;
62 872         3129 $sql =~ s/\s+$//;
63 872         1595 $sql =~ s/\s*;$//;
64 872         7317 $self->{struct} = { dialect => $self->{dialect} };
65 872         2135 $self->{tmp} = {};
66 872         1527 $self->{original_string} = $sql;
67 872         1572 $self->{struct}->{original_string} = $sql;
68              
69             ################################################################
70             #
71             # COMMENTS
72              
73             # C-STYLE
74             #
75 872   100     2024 my $comment_re = $self->{comment_re} || '(\/\*.*?\*\/)';
76 872         1302 $self->{comment_re} = $comment_re;
77 872         1141 my $starts_with_comment;
78 872 100       4406 if ( $sql =~ /^\s*$comment_re(.*)$/s )
79             {
80 36         108 $self->{comment} = $1;
81 36         66 $sql = $2;
82 36         58 $starts_with_comment = 1;
83             }
84              
85             # SQL STYLE
86             #
87             # SQL-style comment can not begin inside quotes.
88 872 50       2110 if ( $sql =~ s/^([^']*?(?:'[^']*'[^'])*?)(--.*)(\n|$)/$1$3/ )
89             {
90 0         0 $self->{comment} = $2;
91             }
92             ################################################################
93              
94 872         2151 $sql = $self->clean_sql($sql);
95 872         3013 my ($com) = $sql =~ m/^\s*(\S+)\s+/s;
96 872 100       1927 if ( !$com )
97             {
98 38 100       125 return 1 if ($starts_with_comment);
99 2         12 return $self->do_err("Incomplete statement!");
100             }
101 834         1520 $com = uc $com;
102 834         1749 $self->{opts}->{valid_commands}->{CALL} = 1;
103 834         1391 $self->{opts}->{valid_commands}->{LOAD} = 1;
104 834 50       1990 if ( $self->{opts}->{valid_commands}->{$com} )
105             {
106 834         2772 my $rv = $self->$com($sql);
107 828         1915 delete $self->{struct}->{literals};
108              
109 828 50       1773 return $self->do_err("No command found!") unless ( $self->{struct}->{command} );
110              
111 828         2133 $self->replace_quoted_ids();
112              
113 620         1654 my @tables = @{ $self->{struct}->{table_names} }
114 828 100       2965 if ( defined( _ARRAY0( $self->{struct}->{table_names} ) ) );
115 828         1363 push( @{ $self->{struct}->{org_table_names} }, @tables );
  828         2258  
116             # REMOVE schema.table info if present
117 828 100       1531 @tables = map { s/^.*\.([^\.]+)$/$1/; ( -1 == index( $_, '"' ) ) ? lc $_ : $_ } @tables;
  706         1271  
  706         2820  
118              
119 828 100 100     3782 if ( exists( $self->{struct}->{join} ) && !defined( _HASH( $self->{struct}->{join} ) ) )
120             {
121 464         966 delete $self->{struct}->{join};
122             }
123             else
124             {
125             $self->{struct}->{join}->{table_order} = $self->{struct}->{table_names}
126             if ( defined( $self->{struct}->{join}->{table_order} )
127 364 50 66     1341 && !defined( _ARRAY0( $self->{struct}->{join}->{table_order} ) ) );
128 58         139 @{ $self->{struct}->{join}->{keycols} } =
129 144         255 map { lc $_ } @{ $self->{struct}->{join}->{keycols} }
  58         150  
130 364 100       841 if ( $self->{struct}->{join}->{keycols} );
131 0         0 @{ $self->{struct}->{join}->{shared_cols} } =
132 0         0 map { lc $_ } @{ $self->{struct}->{join}->{shared_cols} }
  0         0  
133 364 50       897 if ( $self->{struct}->{join}->{shared_cols} );
134             }
135              
136 828 100 66     3462 if ( defined( $self->{struct}->{column_defs} )
137             && defined( _ARRAY( $self->{struct}->{column_defs} ) ) )
138             {
139 792         1101 my $colname;
140             # FIXME SUBSTR('*')
141             my @fine_defs =
142 792 100       991 grep { defined( $_->{fullorg} ) && ( -1 == index( $_->{fullorg}, '*' ) ) } @{ $self->{struct}->{column_defs} };
  1013         3860  
  792         1558  
143 792         1652 foreach my $col (@fine_defs)
144             {
145 596         974 my $colname = $col->{fullorg};
146             #$cn = lc $cn unless ( $cn =~ m/^(?:\w+\.)?"/ );
147 596   66     801 push( @{ $self->{struct}->{org_col_names} }, $self->{struct}->{ORG_NAME}->{$colname} || $colname );
  596         2359  
148             }
149              
150 792 100       1797 unless ( $com eq 'CREATE' )
151             {
152 733         1526 $self->{struct}->{table_names} = \@tables;
153             # For RR aliases, added quoted id protection from upper casing
154 733         1229 foreach my $col (@fine_defs)
155             {
156             # defined( $col->{fullorg} ) && ( -1 == index( $col->{fullorg}, '*' ) ) or next;
157 465         820 my $orgname = $colname = $col->{fullorg};
158 17 50   17   10741 $colname =~ m/^(?:\p{Word}+\.)?"/ or $colname = lc $colname;
  17         240  
  17         257  
  465         1231  
159 465 100       1021 defined( $self->{struct}->{ORG_NAME}->{$colname} ) and next;
160             $self->{struct}->{ORG_NAME}->{$colname} =
161 454         1309 $self->{struct}->{ORG_NAME}->{$orgname};
162             }
163             #my @uCols = map { ( $_ =~ /^(\w+\.)?"/ ) ? $_ : lc $_ } @{ $self->{struct}->{column_names} };
164             #$self->{struct}->{column_names} = \@uCols;
165             }
166             }
167              
168 828         3004 return $rv;
169             }
170             else
171             {
172 0         0 $self->{struct} = {};
173 0 0       0 if ( $ENV{SQL_USER_DEFS} )
174             {
175 0         0 return SQL::UserDefs::user_parse( $self, $sql );
176             }
177 0         0 return $self->do_err("Command '$com' not recognized or not supported!");
178             }
179             }
180              
181             sub replace_quoted_commas
182             {
183 9     9 1 12 my ( $self, $id ) = @_;
184 9         20 $id =~ s/\?COMMA\?/,/gs;
185 9         49 return $id;
186             }
187              
188             sub replace_quoted_ids
189             {
190 1881     1881 1 3348 my ( $self, $id ) = @_;
191 1881 100 100     7306 $self->{struct}->{quoted_ids} or $self->{struct}->{literals} or return;
192 1081 100       2026 if ($id)
193             {
194 1053 100       2645 if ( $id =~ /^\?QI(\d+)\?$/ )
    50          
195             {
196 44         164 return '"' . $self->{struct}->{quoted_ids}->[$1] . '"';
197             }
198             elsif ( $id =~ /^\?(\d+)\?$/ )
199             {
200 0         0 return $self->{struct}->{literals}->[$1];
201             }
202             else
203             {
204 1009         2126 return $id;
205             }
206             }
207 28 100       76 return unless defined $self->{struct}->{table_names};
208 26         41 my @tables = @{ $self->{struct}->{table_names} };
  26         77  
209 26         54 for my $t (@tables)
210             {
211 28 100       129 if ( $t =~ /^\?QI(.+)\?$/ )
    50          
212             {
213 6         28 $t = '"' . $self->{struct}->{quoted_ids}->[$1] . '"';
214             }
215             elsif( $t =~ /^\?(\d+)\?$/ )
216             {
217 0         0 $t = $self->{struct}->{literals}->[$1];
218             }
219             }
220 26         69 $self->{struct}->{table_names} = \@tables;
221 26         99 delete $self->{struct}->{quoted_ids};
222             }
223              
224 31     31 1 3311 sub structure { $_[0]->{struct} }
225 1   50 1 1 11 sub command { my $x = $_[0]->{struct}->{command} || '' }
226              
227             sub feature
228             {
229 9     9 1 26 my ( $self, $opt_class, $opt_name, $opt_value ) = @_;
230 9 50       25 if ( defined $opt_value )
231             {
232 9 50       26 if ( $opt_class eq 'select' )
    50          
233             {
234 0         0 $self->set_feature_flags( { "join" => $opt_value } );
235             }
236             elsif ( $opt_class eq 'create' )
237             {
238 0         0 $self->set_feature_flags( undef, { $opt_name => $opt_value } );
239             }
240             else
241             {
242              
243             # patch from chromatic
244 9         40 $self->{opts}->{$opt_class}->{$opt_name} = $opt_value;
245              
246             # $self->{$opt_class}->{$opt_name} = $opt_value;
247             }
248             }
249             else
250             {
251 0         0 return $self->{opts}->{$opt_class}->{$opt_name};
252             }
253             }
254              
255 10     10 1 48 sub errstr { $_[0]->{struct}->{errstr} }
256              
257             sub list
258             {
259 0     0 1 0 my $self = shift;
260 0         0 my $com = uc shift;
261 0 0       0 return () if $com !~ /COMMANDS|RESERVED|TYPES|OPS|OPTIONS|DIALECTS/i;
262 0 0       0 $com = 'valid_commands' if $com eq 'COMMANDS';
263 0 0       0 $com = 'valid_comparison_operators' if $com eq 'OPS';
264 0 0       0 $com = 'valid_data_types' if $com eq 'TYPES';
265 0 0       0 $com = 'valid_options' if $com eq 'OPTIONS';
266 0 0       0 $com = 'reserved_words' if $com eq 'RESERVED';
267 0 0       0 $self->dialect( $self->{dialect} ) unless $self->{dialect_set};
268              
269 0 0       0 return sort keys %{ $self->{opts}->{$com} } unless $com eq 'DIALECTS';
  0         0  
270 0         0 my $dDir = "SQL/Dialects";
271 0         0 my @dialects;
272 0         0 for my $dir (@INC)
273             {
274 0         0 local *D;
275              
276 0 0       0 if ( opendir( D, "$dir/$dDir" ) )
277             {
278 0         0 @dialects = grep /.*\.pm$/, readdir(D);
279 0         0 last;
280             }
281             }
282 0         0 @dialects = map { s/\.pm$//; $_ } @dialects;
  0         0  
  0         0  
283 0         0 return @dialects;
284             }
285              
286             sub dialect
287             {
288 18     18 1 72 my ( $self, $dialect ) = @_;
289 18 50       63 return $self->{dialect} unless ($dialect);
290 18 100       70 return $self->{dialect} if ( $self->{dialect_set} );
291 17         54 $self->{opts} = {};
292 17         62 my $mod_class = "SQL::Dialects::$dialect";
293              
294 17 100       217 $self->_load_class($mod_class) unless $mod_class->can("get_config");
295              
296             # This is here for backwards compatibility with existing dialects
297             # before the had the role to add new methods.
298 17 50       204 $self->_inject_role( "SQL::Dialects::Role", $mod_class )
299             unless ( $mod_class->can("get_config_as_hash") );
300              
301 17         79 $self->{opts} = $mod_class->get_config_as_hash();
302              
303 17         127 $self->create_op_regexen();
304 17         50 $self->{dialect} = $dialect;
305 17         52 $self->{dialect_set}++;
306              
307 17         49 return $self->{dialect};
308             }
309              
310             sub _load_class
311             {
312 34     34   86 my ( $self, $class ) = @_;
313              
314 34         69 my $mod = $class;
315 34         169 $mod =~ s{::}{/}g;
316 34         77 $mod .= ".pm";
317              
318 34         203 local ( $!, $@ );
319 34 50       88 eval { require "$mod"; } or return $self->do_err($@);
  34         9454  
320              
321 34         146 return 1;
322             }
323              
324             sub _inject_role
325             {
326 0     0   0 my ( $self, $role, $dest ) = @_;
327              
328 0 0       0 eval qq{
329             package $dest;
330             use $role;
331             1;
332             } or croak "Can't inject $role into $dest: $@";
333             }
334              
335             sub create_op_regexen
336             {
337 20     20 1 68 my ($self) = @_;
338              
339             #
340             # DAA precompute the predicate operator regex's
341             #
342             # JZ moved this into a sub so it can be called from both
343             # dialect() and from CREATE_OPERATOR and DROP_OPERATOR
344             # since those also modify the available operators
345             #
346 20         41 my @allops = keys %{ $self->{opts}->{valid_comparison_operators} };
  20         164  
347              
348             #
349             # complement operators
350             #
351 20         58 my @notops;
352 20         55 for (@allops)
353             {
354 285 100       641 push( @notops, $_ )
355             if /NOT/i;
356             }
357 20 50       193 $self->{opts}->{valid_comparison_NOT_ops_regex} = '^\s*(.+)\s+(' . join( '|', @notops ) . ')\s+(.*)\s*$'
358             if scalar @notops;
359              
360             #
361             # <>, <=, >= operators
362             #
363 20         53 my @compops;
364 20         55 for (@allops)
365             {
366 285 100       1025 push( @compops, $_ )
367             if /<=|>=|<>/;
368             }
369 20 50       133 $self->{opts}->{valid_comparison_twochar_ops_regex} = '^\s*(.+)\s+(' . join( '|', @compops ) . ')\s+(.*)\s*$'
370             if scalar @compops;
371              
372             #
373             # everything
374             #
375 20 50       201 $self->{opts}->{valid_comparison_ops_regex} = '^\s*(.+)\s+(' . join( '|', @allops ) . ')\s+(.*)\s*$'
376             if scalar @allops;
377              
378             #
379             # end DAA
380             #
381             }
382              
383             ##################################################################
384             # SQL COMMANDS
385             ##################################################################
386              
387             ####################################################
388             # DROP TABLE
389             ####################################################
390             sub DROP
391             {
392 19     19 0 51 my ( $self, $stmt ) = @_;
393 19         43 my $features = 'TYPE|KEYWORD|FUNCTION|OPERATOR|PREDICATE';
394 19 100       513 if ( $stmt =~ /^\s*DROP\s+($features)\s+(.+)$/si )
395             {
396 3         13 my ( $sub, $arg ) = ( $1, $2 );
397 3         7 $sub = 'DROP_' . $sub;
398 3         14 return $self->$sub($arg);
399             }
400 16         43 my $table_name;
401 16         47 $self->{struct}->{command} = 'DROP';
402 16 100       79 if ( $stmt =~ /^\s*DROP\s+TABLE\s+IF\s+EXISTS\s+(.*)$/si )
403             {
404 9         33 $stmt = "DROP TABLE $1";
405 9         28 $self->{struct}->{ignore_missing_table} = 1;
406             }
407 16 50       83 if ( $stmt =~ /^\s*DROP\s+(\S+)\s+(.+)$/si )
408             {
409 16   50     67 my $com2 = $1 || '';
410 16         35 $table_name = $2;
411 16 50       59 if ( $com2 !~ /^TABLE$/i )
412             {
413 0         0 return $self->do_err("The command 'DROP $com2' is not recognized or not supported!");
414             }
415 16         46 $table_name =~ s/^\s+//;
416 16         36 $table_name =~ s/\s+$//;
417 16 100       168 if ( $table_name =~ /(\S+) (RESTRICT|CASCADE)/i )
418             {
419 2         5 $table_name = $1;
420 2         5 $self->{struct}->{drop_behavior} = uc $2;
421             }
422             }
423             else
424             {
425 0         0 return $self->do_err("Incomplete DROP statement!");
426              
427             }
428 16 50       56 return undef unless $self->TABLE_NAME($table_name);
429 16         133 $table_name = $self->replace_quoted_ids($table_name);
430 16         65 $self->{tmp}->{is_table_name} = { $table_name => 1 };
431 16         46 $self->{struct}->{table_names} = [$table_name];
432 16         41 return 1;
433             }
434              
435             ####################################################
436             # DELETE FROM WHERE
437             ####################################################
438             sub DELETE
439             {
440 9     9   25 my ( $self, $str ) = @_;
441 9         26 $self->{struct}->{command} = 'DELETE';
442 9         41 $str =~ s/^DELETE\s+FROM\s+/DELETE /i; # Make FROM optional
443 9         50 my ( $table_name, $where_clause ) = $str =~ /^DELETE (\S+)(.*)$/i;
444 9 50       36 return $self->do_err('Incomplete DELETE statement!') if !$table_name;
445 9 50       29 return undef unless $self->TABLE_NAME($table_name);
446 9         37 $self->{tmp}->{is_table_name} = { $table_name => 1 };
447 9         30 $self->{struct}->{table_names} = [$table_name];
448             $self->{struct}->{column_defs} = [
449             {
450 9         36 type => 'column',
451             value => '*'
452             }
453             ];
454 9         33 $where_clause =~ s/^\s+//;
455 9         27 $where_clause =~ s/\s+$//;
456              
457 9 100       34 if ($where_clause)
458             {
459 6         31 $where_clause =~ s/^WHERE\s*(.*)$/$1/i;
460 6 50       25 return undef unless $self->SEARCH_CONDITION($where_clause);
461             }
462 9         23 return 1;
463             }
464              
465             ##############################################################
466             # SELECT
467             ##############################################################
468             # SELECT []
469             # |
470             # FROM
471             # [WHERE ]
472             # [ORDER BY ]
473             # [LIMIT ]
474             ##############################################################
475              
476             sub SELECT
477             {
478 549     549 0 1062 my ( $self, $str ) = @_;
479 549         1171 $self->{struct}->{command} = 'SELECT';
480 549         872 my ( $from_clause, $where_clause, $order_clause, $groupby_clause, $limit_clause );
481 549         2665 $str =~ s/^SELECT (.+)$/$1/i;
482 549 100       2314 if ( $str =~ s/^(.+) LIMIT (.+)$/$1/i ) { $limit_clause = $2; }
  9         22  
483 549 100       1636 if ( $str =~ s/^(.+) ORDER BY (.+)$/$1/i ) { $order_clause = $2; }
  20         49  
484 549 100       1545 if ( $str =~ s/^(.+) GROUP BY (.+)$/$1/i ) { $groupby_clause = $2; }
  8         21  
485 549 100       1969 if ( $str =~ s/^(.+?) WHERE (.+)$/$1/i ) { $where_clause = $2; }
  219         459  
486 549 100       2220 if ( $str =~ s/^(.+?) FROM (.+)$/$1/i ) { $from_clause = $2; }
  359         688  
487              
488             # else {
489             # return $self->do_err("Couldn't find FROM clause in SELECT!");
490             # }
491             # return undef unless $self->FROM_CLAUSE($from_clause);
492 549 100       1647 my $has_from_clause = $self->FROM_CLAUSE($from_clause) if ($from_clause);
493              
494 547 100       1304 return undef unless ( $self->SELECT_CLAUSE($str) );
495              
496 540 100       1063 if ($where_clause)
497             {
498 219 50       513 return undef unless ( $self->SEARCH_CONDITION($where_clause) );
499             }
500 538 100       972 if ($groupby_clause)
501             {
502 7 50       24 return undef unless ( $self->GROUPBY_LIST($groupby_clause) );
503             }
504 538 100       992 if ($order_clause)
505             {
506 20 50       106 return undef unless ( $self->SORT_SPEC_LIST($order_clause) );
507             }
508 538 100       998 if ($limit_clause)
509             {
510 9 50       35 return undef unless ( $self->LIMIT_CLAUSE($limit_clause) );
511             }
512 538 100 100     2493 if (
      100        
      100        
513             ( $self->{struct}->{join}->{clause} and $self->{struct}->{join}->{clause} eq 'ON' )
514             or ( $self->{struct}->{multiple_tables}
515 47         283 and !( scalar keys %{ $self->{struct}->{join} } ) )
516             )
517             {
518 39 50       110 return undef unless ( $self->IMPLICIT_JOIN() );
519             }
520              
521 538 50 100     1201 if ( $self->{struct}->{set_quantifier}
      100        
      66        
522             && ( 'DISTINCT' eq $self->{struct}->{set_quantifier} )
523             && $self->{struct}->{has_set_functions}
524             && !defined( _ARRAY( $self->{struct}->{group_by} ) ) )
525             {
526 0         0 delete $self->{struct}->{set_quantifier};
527             carp "Specifying DISTINCT when using aggregate functions isn't reasonable - ignored."
528 0 0       0 if ( $self->{PrintError} );
529             }
530              
531 538         1033 return 1;
532             }
533              
534             sub GROUPBY_LIST
535             {
536 7     7 0 21 my ( $self, $gclause ) = @_;
537 7 50       19 return 1 unless ($gclause);
538 7         33 my $cols = $self->ROW_VALUE_LIST($gclause);
539 7 50       23 return undef if ( $self->{struct}->{errstr} );
540 7         14 @{ $self->{struct}->{group_by} } = map { $_->{fullorg} } @{$cols};
  7         27  
  8         22  
  7         18  
541 7         32 return 1;
542             }
543              
544             sub IMPLICIT_JOIN
545             {
546 39     39 0 58 my $self = $_[0];
547 39         81 delete $self->{struct}->{multiple_tables};
548 39 100 66     166 if ( !$self->{struct}->{join}->{clause}
549             or $self->{struct}->{join}->{clause} ne 'ON' )
550             {
551 12         29 $self->{struct}->{join}->{type} = 'INNER';
552 12         196 $self->{struct}->{join}->{clause} = 'IMPLICIT';
553             }
554 39 50       95 if ( defined $self->{struct}->{keycols} )
555             {
556 39         67 my @keys;
557 39         57 my @keys2 = @keys = @{ $self->{struct}->{keycols} };
  39         135  
558 39         231 $self->{struct}->{join}->{table_order} = $self->order_joins( \@keys2 );
559 39         74 @{ $self->{struct}->{join}->{keycols} } = @keys;
  39         114  
560 39         144 delete $self->{struct}->{keycols};
561             }
562             else
563             {
564 0         0 return $self->do_err("No equijoin condition in WHERE or ON clause");
565             }
566 39         97 return 1;
567             }
568              
569             sub EXPLICIT_JOIN
570             {
571 64     64 0 117 my ( $self, $remainder ) = @_;
572 64 50       125 return undef unless ($remainder);
573 64         98 my ( $tableA, $tableB, $keycols, $jtype, $natural );
574 64 50       317 if ( $remainder =~ m/^(.+?) (NATURAL|INNER|LEFT|RIGHT|FULL|CROSS|UNION|JOIN)(.+)$/is )
575             {
576 64         123 $tableA = $1;
577 64         172 $remainder = $2 . $3;
578             }
579             else
580             {
581 0         0 ( $tableA, $remainder ) = $remainder =~ m/^(\S+) (.*)/i;
582             }
583 64 100       203 if ( $remainder =~ m/^NATURAL (.+)/ )
584             {
585 15         49 $self->{struct}->{join}->{clause} = 'NATURAL';
586 15         23 $natural++;
587 15         29 $remainder = $1;
588             }
589 64 100       224 if ( $remainder =~ m/^(INNER|LEFT|RIGHT|FULL|CROSS|UNION) JOIN (.+)/i )
590             {
591 43         143 $jtype = $self->{struct}->{join}->{clause} = uc($1);
592 43         77 $remainder = $2;
593 43 100       143 $jtype = "$jtype OUTER" if $jtype !~ /INNER|UNION/i;
594             }
595 64 50       169 if ( $remainder =~ m/^(LEFT|RIGHT|FULL|CROSS) OUTER JOIN (.+)/i )
596             {
597 0         0 $jtype = $self->{struct}->{join}->{clause} = uc($1) . " OUTER";
598 0         0 $remainder = $2;
599             }
600 64 100       169 if ( $remainder =~ m/^JOIN (.+)/i )
601             {
602 21         41 $jtype = 'INNER';
603 21         51 $self->{struct}->{join}->{clause} = 'DEFAULT INNER';
604 21         52 $remainder = $1;
605             }
606 64 50       163 if ( $self->{struct}->{join} )
607             {
608 64 100 66     319 if ( $remainder && $remainder =~ m/^(.+?) USING \(([^\)]+)\)(.*)/i )
609             {
610 20         50 $self->{struct}->{join}->{clause} = 'USING';
611 20         38 $tableB = $1;
612 20         39 my $keycolstr = $2;
613 20         34 $remainder = $3;
614 20         65 @$keycols = split( /,/, $keycolstr );
615             }
616 64 100 100     302 if ( $remainder && $remainder =~ m/^(.+?) ON (.+)/i )
    100          
617             {
618 27         57 $self->{struct}->{join}->{clause} = 'ON';
619 27         50 $tableB = $1;
620 27         51 my $keycolstr = $2;
621 27         44 $remainder = $3;
622 27         173 @$keycols = split(/ AND|OR /i, $keycolstr);
623              
624             return undef
625 27 50       101 unless $self->TABLE_NAME_LIST( $tableA . ',' . $tableB );
626              
627             # $self->{tmp}->{is_table_name}->{"$tableA"} = 1;
628             # $self->{tmp}->{is_table_name}->{"$tableB"} = 1;
629 27         62 for my $keycol (@$keycols)
630             {
631 48         68 my %is_done;
632 48         171 $keycol =~ s/\)|\(//g;
633 48         195 my ( $arg1, $arg2 ) = split( m/ [>=<] /, $keycol );
634 48         99 my ( $c1, $c2 ) = ( $arg1, $arg2 );
635 48         167 $c1 =~ s/^.*\.([^\.]+)$/$1/;
636 48         134 $c2 =~ s/^.*\.([^\.]+)$/$1/;
637 48 100       110 if ( $c1 eq $c2 )
638             {
639 9 50       29 return undef unless ( $arg1 = $self->ROW_VALUE($c1) );
640 9 50 33     53 if ( $arg1->{type} eq 'column' and !$is_done{$c1} )
641             {
642 9         20 push( @{ $self->{struct}->{keycols} }, $arg1->{value} );
  9         33  
643 9         44 $is_done{$c1} = 1;
644             }
645             }
646             else
647             {
648 39 50       79 return undef unless ( $arg1 = $self->ROW_VALUE($arg1) );
649 39 50       77 return undef unless ( $arg2 = $self->ROW_VALUE($arg2) );
650 39 100 66     160 if ( $arg1->{type} eq 'column'
651             and $arg2->{type} eq 'column' )
652             {
653 34         42 push( @{ $self->{struct}->{keycols} }, $arg1->{value} );
  34         85  
654 34         49 push( @{ $self->{struct}->{keycols} }, $arg2->{value} );
  34         125  
655              
656             # delete $self->{struct}->{where_clause};
657             }
658             }
659             }
660             }
661             elsif ( $remainder =~ /^(.+?)$/i )
662             {
663 18         38 $tableB = $1;
664 18         27 $remainder = $2;
665             }
666 64 50       126 $remainder =~ s/^\s+// if ($remainder);
667             }
668              
669 64 50       125 if ($jtype)
670             {
671 64 100       153 $jtype = "NATURAL $jtype" if ($natural);
672 64 50 66     158 if ( $natural and $keycols )
673             {
674 0         0 return $self->do_err(qq{Can't use NATURAL with a USING or ON clause!});
675             }
676 64 100       207 return undef unless ( $self->TABLE_NAME_LIST("$tableA,$tableB") );
677 62         141 $self->{struct}->{join}->{type} = $jtype;
678 62 100       151 $self->{struct}->{join}->{keycols} = $keycols if ($keycols);
679 62         187 return 1;
680             }
681 0         0 return $self->do_err("Couldn't parse explicit JOIN!");
682             }
683              
684             sub SELECT_CLAUSE
685             {
686 547     547 0 1030 my ( $self, $str ) = @_;
687 547 50       1007 return undef unless ($str);
688 547 100       1408 if ( $str =~ s/^(DISTINCT|ALL) (.+)$/$2/i )
689             {
690 8         35 $self->{struct}->{set_quantifier} = uc($1);
691             }
692 547 100       1296 return undef unless ( $self->SELECT_LIST($str) );
693             }
694              
695             sub FROM_CLAUSE
696             {
697 359     359 0 672 my ( $self, $str ) = @_;
698 359 50       673 return undef unless $str;
699 359 100       799 if ( $str =~ m/ JOIN /i )
700             {
701 64 100       169 return undef unless $self->EXPLICIT_JOIN($str);
702             }
703             else
704             {
705 295 100       744 return undef unless $self->TABLE_NAME_LIST($str);
706             }
707             }
708              
709             sub INSERT
710             {
711 174     174 0 364 my ( $self, $str ) = @_;
712 174         262 my $col_str;
713 174         675 $str =~ s/^INSERT\s+INTO\s+/INSERT /i; # allow INTO to be optional
714 174         1112 my ( $table_name, $val_str ) = $str =~ m/^INSERT\s+(.+?)\s+VALUES\s+(\(.+\))$/i;
715 174 100 66     891 if ( $table_name and $table_name =~ m/[()]/ )
716             {
717 7         41 ( $table_name, $col_str, $val_str ) = $str =~ m/^INSERT\s+(.+?)\s+\((.+?)\)\s+VALUES\s+(\(.+\))$/i;
718             }
719 174 50       419 return $self->do_err('No table name specified!') unless ($table_name);
720 174 50       354 return $self->do_err('Missing values list!') unless ( defined $val_str );
721 174 50       433 return undef unless ( $self->TABLE_NAME($table_name) );
722 174         432 $self->{struct}->{command} = 'INSERT';
723 174         455 $self->{struct}->{table_names} = [$table_name];
724 174 100       418 if ($col_str)
725             {
726 7 50       25 return undef unless ( $self->{struct}->{column_defs} = $self->ROW_VALUE_LIST($col_str) );
727             }
728             else
729             {
730             $self->{struct}->{column_defs} = [
731             {
732 167         575 type => 'column',
733             value => '*'
734             }
735             ];
736             }
737 174         363 $self->{struct}->{values} = [];
738 174   33     850 for (my ($v,$line_str) = $val_str;
739             (($line_str,$v)=extract_bracketed($v,"('",'')) && defined $line_str;
740             ) {
741 180 50       31949 return undef unless ( $self->LITERAL_LIST(substr($line_str,1,-1)) );
742 180 100       561 last unless $v =~ s/\A\s*,\s*//;
743             }
744              
745 174         408 return 1;
746             }
747              
748             ###################################################################
749             # UPDATE ::=
750             #
751             # UPDATE SET [ WHERE ]
752             #
753             ###################################################################
754             sub UPDATE
755             {
756 12     12 0 31 my ( $self, $str ) = @_;
757 12         34 $self->{struct}->{command} = 'UPDATE';
758 12         73 my ( $table_name, $remainder ) = $str =~ m/^UPDATE (.+?) SET (.+)$/i;
759 12 50 33     102 return $self->do_err('Incomplete UPDATE clause') unless ( $table_name && $remainder );
760 12 50       51 return undef unless ( $self->TABLE_NAME($table_name) );
761 12         47 $self->{tmp}->{is_table_name} = { $table_name => 1 };
762 12         37 $self->{struct}->{table_names} = [$table_name];
763 12         65 my ( $set_clause, $where_clause ) = $remainder =~ m/(.*?) WHERE (.*)$/i;
764 12 100       44 $set_clause = $remainder if ( !$set_clause );
765 12 50       51 return undef unless ( $self->SET_CLAUSE_LIST($set_clause) );
766              
767 12 100       35 if ($where_clause)
768             {
769 6 50       22 return undef unless ( $self->SEARCH_CONDITION($where_clause) );
770             }
771              
772 12         20 my @vals = @{ $self->{struct}->{values}->[0] };
  12         35  
773 12         22 my $num_val_placeholders = 0;
774 12         32 for my $v (@vals)
775             {
776 22 100       54 ++$num_val_placeholders if ( $v->{type} eq 'placeholder' );
777             }
778 12         24 $self->{struct}->{num_val_placeholders} = $num_val_placeholders;
779              
780 12         28 return 1;
781             }
782              
783             ############
784             # FUNCTIONS
785             ############
786             sub LOAD
787             {
788 18     18 0 74 my ( $self, $str ) = @_;
789 18         103 $self->{struct}->{command} = 'LOAD';
790 18         54 $self->{struct}->{no_execute} = 1;
791 18         130 my ($package) = $str =~ /^LOAD\s+(.+)$/;
792 18         49 $str = $package;
793 18         57 $package =~ s/\?(\d+)\?/$self->{struct}->{literals}->[$1]/g;
794              
795 18         78 $self->_load_class($package);
796              
797 18         1183 my %subs = eval '%' . $package . '::';
798              
799 18         439 for my $sub ( keys %subs )
800             {
801 2992 100       6273 next unless ( $sub =~ m/^SQL_FUNCTION_([A-Z_0-9]+)$/ );
802 1854         2917 my $funcName = uc $1;
803 1854         3355 my $subname = $package . '::' . 'SQL_FUNCTION_' . $funcName;
804 1854         3632 $self->{opts}->{function_names}->{$funcName} = $subname;
805 1854         2585 delete $self->{opts}->{_udf_function_names};
806             }
807 18         747 1;
808             }
809              
810             sub CREATE_RAM_TABLE
811             {
812 0     0 0 0 my ( $self, $stmt ) = @_;
813 0         0 $self->{struct}->{is_ram_table} = 1;
814 0         0 $self->{struct}->{command} = 'CREATE_RAM_TABLE';
815 0         0 my ( $table_name, $table_element_def, %is_col_name );
816 0 0       0 if ( $stmt =~ /^(\S+)\s+LIKE\s*(.+)$/si )
817             {
818 0         0 $table_name = $1;
819 0         0 $table_element_def = $2;
820 0 0       0 if ( $table_element_def =~ /^(.*)\s+KEEP CONNECTION\s*$/i )
821             {
822 0         0 $table_element_def = $1;
823 0         0 $self->{struct}->{ram_table_keep_connection} = 1;
824             }
825             }
826             else
827             {
828 0         0 return $self->CREATE("CREATE TABLE $stmt");
829             }
830 0 0       0 return undef unless $self->TABLE_NAME($table_name);
831 0         0 for my $col ( split ',', $table_element_def )
832             {
833 0         0 push( @{ $self->{struct}->{column_defs} }, $self->ROW_VALUE($col) );
  0         0  
834             }
835 0         0 $self->{struct}->{table_names} = [$table_name];
836 0         0 return 1;
837             }
838              
839             sub CREATE_FUNCTION
840             {
841 3     3 0 7 my ( $self, $stmt ) = @_;
842 3         8 $self->{struct}->{command} = 'CREATE_FUNCTION';
843 3         6 $self->{struct}->{no_execute} = 1;
844 3         4 my ( $func, $subname );
845 3         8 $stmt =~ s/\s*EXTERNAL//i;
846 3 100       12 if ( $stmt =~ /^(\S+)\s+NAME\s+(.*)$/smi )
847             {
848 2         8 $func = trim($1);
849 2         4 $subname = trim($2);
850             }
851 3   66     10 $func ||= $stmt;
852 3   66     8 $subname ||= $func;
853 3 50       8 if ( $func =~ /^\?QI(\d+)\?$/ )
854             {
855 0         0 $func = $self->{struct}->{quoted_ids}->[$1];
856             }
857 3 100       10 if ( $subname =~ /^\?QI(\d+)\?$/ )
858             {
859 2         6 $subname = $self->{struct}->{quoted_ids}->[$1];
860             }
861 3         9 $self->{opts}->{function_names}->{ uc $func } = $subname;
862 3         6 delete $self->{opts}->{_udf_function_names};
863              
864 3         9 return 1;
865             }
866              
867             sub CALL
868             {
869 0     0 0 0 my ( $self, $stmt ) = @_;
870 0         0 $stmt =~ s/^CALL\s+(.*)/$1/i;
871 0         0 $self->{struct}->{command} = 'CALL';
872 0         0 $self->{struct}->{procedure} = $self->ROW_VALUE($stmt);
873 0         0 return 1;
874             }
875              
876             sub CREATE_TYPE
877             {
878 3     3 0 9 my ( $self, $type ) = @_;
879 3         8 $self->{struct}->{command} = 'CREATE_TYPE';
880 3         6 $self->{struct}->{no_execute} = 1;
881 3         15 $self->feature( 'valid_data_types', uc $type, 1 );
882             }
883              
884             sub DROP_TYPE
885             {
886 1     1 0 3 my ( $self, $type ) = @_;
887 1         3 $self->{struct}->{command} = 'DROP_TYPE';
888 1         3 $self->{struct}->{no_execute} = 1;
889 1         4 $self->feature( 'valid_data_types', uc $type, 0 );
890             }
891              
892             sub CREATE_KEYWORD
893             {
894 1     1 0 3 my ( $self, $type ) = @_;
895 1         3 $self->{struct}->{command} = 'CREATE_KEYWORD';
896 1         3 $self->{struct}->{no_execute} = 1;
897 1         5 $self->feature( 'reserved_words', uc $type, 1 );
898             }
899              
900             sub DROP_KEYWORD
901             {
902 1     1 0 4 my ( $self, $type ) = @_;
903 1         3 $self->{struct}->{command} = 'DROP_KEYWORD';
904 1         3 $self->{struct}->{no_execute} = 1;
905 1         4 $self->feature( 'reserved_words', uc $type, 0 );
906             }
907              
908             sub CREATE_OPERATOR
909             {
910 2     2 0 7 my ( $self, $stmt ) = @_;
911 2         5 $self->{struct}->{command} = 'CREATE_OPERATOR';
912 2         5 $self->{struct}->{no_execute} = 1;
913              
914 2         4 my ( $func, $subname );
915 2         3 $stmt =~ s/\s*EXTERNAL//i;
916 2 50       8 if ( $stmt =~ /^(\S+)\s+NAME\s+(.*)$/smi )
917             {
918 0         0 $func = trim($1);
919 0         0 $subname = trim($2);
920             }
921 2   33     11 $func ||= $stmt;
922 2   33     9 $subname ||= $func;
923 2 50       5 if ( $func =~ /^\?QI(\d+)\?$/ )
924             {
925 0         0 $func = $self->{struct}->{quoted_ids}->[$1];
926             }
927 2 50       6 if ( $subname =~ /^\?QI(\d+)\?$/ )
928             {
929 0         0 $subname = $self->{struct}->{quoted_ids}->[$1];
930             }
931 2         7 $self->{opts}->{function_names}->{ uc $func } = $subname;
932 2         5 delete $self->{opts}->{_udf_function_names};
933              
934 2         9 $self->feature( 'valid_comparison_operators', uc $func, 1 );
935 2         8 return $self->create_op_regexen();
936             }
937              
938             sub DROP_OPERATOR
939             {
940 1     1 0 4 my ( $self, $type ) = @_;
941 1         3 $self->{struct}->{command} = 'DROP_OPERATOR';
942 1         3 $self->{struct}->{no_execute} = 1;
943 1         36 $self->feature( 'valid_comparison_operators', uc $type, 0 );
944 1         3 return $self->create_op_regexen();
945             }
946              
947             sub replace_quoted($)
948             {
949 9     9 1 13 my ( $self, $str ) = @_;
950 9         18 my @l = map { $self->replace_quoted_ids($_) } split( ',', $self->replace_quoted_commas($str) );
  18         28  
951 9         25 return @l;
952             }
953              
954             #########
955             # CREATE
956             #########
957             sub CREATE
958             {
959 70     70 0 158 my ( $self, $stmt ) = @_;
960 70         131 my $features = 'TYPE|KEYWORD|FUNCTION|OPERATOR|PREDICATE';
961 70 100       1066 if ( $stmt =~ m/^\s*CREATE\s+($features)\s+(.+)$/si )
962             {
963 9         38 my ( $sub, $arg ) = ( $1, $2 );
964 9         22 $sub = 'CREATE_' . uc $sub;
965 9         36 return $self->$sub($arg);
966             }
967              
968 61         210 $stmt =~ s/^CREATE (LOCAL|GLOBAL) /CREATE /si;
969 61 100       310 if ( $stmt =~ m/^\s*CREATE\s+(?:TEMP|TEMPORARY)\s+TABLE\s+(.+)$/si )
970             {
971 43         156 $stmt = "CREATE TABLE $1";
972 43         130 $self->{struct}->{is_ram_table} = 1;
973             }
974 61         142 $self->{struct}->{command} = 'CREATE';
975 61         126 my ( $table_name, $table_element_def, %is_col_name );
976              
977 61 100       267 if ( $stmt =~ m/^(.*) ON COMMIT (DELETE|PRESERVE) ROWS\s*$/si )
978             {
979 4         9 $stmt = $1;
980 4         8 $self->{struct}->{commit_behaviour} = $2;
981              
982             # return $self->do_err(
983             # "Can't specify commit behaviour for permanent tables."
984             # )
985             # if !defined $self->{struct}->{table_type}
986             # or $self->{struct}->{table_type} !~ /TEMPORARY/;
987             }
988 61 50       260 if ( $stmt =~ m/^CREATE TABLE (\S+) \((.*)\)$/si )
    0          
989             {
990 61         143 $table_name = $1;
991 61         134 $table_element_def = $2;
992             }
993             elsif ( $stmt =~ m/^CREATE TABLE (\S+) AS (.*)$/si )
994             {
995 0         0 $table_name = $1;
996 0         0 my $subquery = $2;
997 0 0       0 return undef unless $self->TABLE_NAME($table_name);
998 0         0 $self->{struct}->{table_names} = [$table_name];
999              
1000             # undo subquery replaces
1001 0         0 $subquery =~ s/\?(\d+)\?/'$self->{struct}{literals}[$1]'/g;
1002 0         0 $subquery =~ s/\?QI(\d+)\?/"$self->{struct}->{quoted_ids}->[$1]"/g;
1003 0         0 $subquery =~ s/\?COMMA\?/,/gs;
1004 0         0 $self->{struct}->{subquery} = $subquery;
1005 0 0       0 if ( -1 != index( $subquery, '?' ) )
1006             {
1007 0         0 ++$self->{struct}->{num_placeholders};
1008             }
1009 0         0 return 1;
1010             }
1011             else
1012             {
1013 0         0 return $self->do_err("Can't find column definitions!");
1014             }
1015 61 50       174 return undef unless ( $self->TABLE_NAME($table_name) );
1016 61         212 $table_element_def =~ s/\s+\(/(/g;
1017 61         109 my $primary_defined;
1018 61         255 while (
1019             $table_element_def =~ s/( # start of grouping 1
1020             \( # match a bracket; vi compatible bracket -> \)(
1021             [^)]+ # everything up to but not including the comma, no nesting of brackets is required
1022             ) # end of grouping 1
1023             , # the comma to be removed to allow splitting on commas
1024             ( # start of grouping 2; vi compatible bracket -> \(
1025             .*?\) # everything up to and including the end bracket
1026             )/$1?COMMA?$2/sgx
1027             )
1028             {
1029             }
1030              
1031 61         253 for my $col ( split( ',', $table_element_def ) )
1032             {
1033 139 100       501 if (
    100          
1034             $col =~ m/^\s*(?:CONSTRAINT\s+(\S+)\s*)? # optional name of foreign key
1035             FOREIGN\s+KEY\s*\(\s* # start of list of; vi compatibile bracket -> (
1036             (\s*[^)]+\s*) # field names in this table
1037             \s*\)\s* # end of field names in this table
1038             REFERENCES # key word
1039             \s*(\S+)\s* # table name being referenced in foreign key
1040             \(\s* # start of list of; vi compatible bracket -> (
1041             (\s*[^)]+\s*) # field names in foreign table
1042             \s*\)\s* # end of field names in foreign table
1043             $/x
1044             )
1045             {
1046 3         12 my ( $name, $local_cols, $referenced_table, $referenced_cols ) = ( $1, $2, $3, $4 );
1047 3         8 my @local_cols = $self->replace_quoted($local_cols);
1048 3         5 $referenced_table = $self->replace_quoted_ids($referenced_table);
1049 3         6 my @referenced_cols = $self->replace_quoted($referenced_cols);
1050              
1051 3 100       10 if ( defined $name )
1052             {
1053 2         4 $name = $self->replace_quoted_ids($name);
1054             }
1055             else
1056             {
1057 1         4 $name = $self->replace_quoted_ids($table_name);
1058 1         3 my ($quote_char) = '';
1059 1 50       5 if ( $name =~ s/(\W)$// )
1060             {
1061 0         0 $quote_char = ($1);
1062             }
1063 1         3 foreach my $local_col (@local_cols)
1064             {
1065 2         2 my $col_name = $local_col;
1066 2         5 $col_name =~ s/^\W//;
1067 2         7 $col_name =~ s/\W$//;
1068 2         4 $name .= '_' . $col_name;
1069             }
1070 1         2 $name .= '_fkey' . $quote_char;
1071             }
1072              
1073 3         9 $self->{struct}->{table_defs}->{$name}->{type} = 'FOREIGN';
1074 3         6 $self->{struct}->{table_defs}->{$name}->{local_cols} = \@local_cols;
1075 3         6 $self->{struct}->{table_defs}->{$name}->{referenced_table} = $referenced_table;
1076 3         5 $self->{struct}->{table_defs}->{$name}->{referenced_cols} = \@referenced_cols;
1077 3         7 next;
1078             }
1079             elsif (
1080             $col =~ m/^\s*(?:CONSTRAINT\s+(\S+)\s*)? # optional name of foreign key
1081             PRIMARY\s+KEY\s*\(\s* # start of list of; vi compatibile bracket -> (
1082             (\s*[^)]+\s*) # field names in this table
1083             \s*\)\s* # end of field names in this table
1084             $/x
1085             )
1086             {
1087 3         10 my ( $name, $local_cols ) = ( $1, $2 );
1088 3         8 my @local_cols = $self->replace_quoted($local_cols);
1089 3 100       6 if ( defined $name )
1090             {
1091 2         5 $name = $self->replace_quoted_ids($name);
1092             }
1093             else
1094             {
1095 1         2 $name = $table_name;
1096 1 50       5 if ( $name =~ s/(\W)$// )
1097             {
1098 0         0 $name .= '_pkey' . $1;
1099             }
1100             else
1101             {
1102 1         2 $name .= '_pkey';
1103             }
1104             }
1105 3         12 $self->{struct}->{table_defs}->{$name}->{type} = 'PRIMARY';
1106 3         4 $self->{struct}->{table_defs}->{$name}->{local_cols} = \@local_cols;
1107 3         7 next;
1108             }
1109              
1110             # it seems, perl 5.6 isn't greedy enough .. let's help a bit
1111 133         205 my ($data_types_regex) = join( '|', sort { length($b) <=> length($a) } keys %{ $self->{opts}->{valid_data_types} } );
  13110         15904  
  133         1007  
1112 133         1056 $data_types_regex =~ s/ /\\ /g; # backslash spaces to allow the /x modifier below
1113 133         3282 my ( $name, $type, $suffix ) = (
1114             $col =~ m/\s*(\S+)\s+ # capture the column name
1115             ((?:$data_types_regex|\S+) # check for all allowed data types OR anything that looks like a bad data type to give a good error
1116             (?:\s*\(\d+(?:\?COMMA\?\d+)?\))?) # allow the data type to have a precision specifier such as NUMERIC(4,6) on it
1117             \s*(\W.*|$) # capture the suffix of the column definition, e.g. constraints
1118             /ix
1119             );
1120 133 50       385 return $self->do_err("Column definition is missing a data type!") unless ($type);
1121 133 50       306 return undef unless ( $self->IDENTIFIER($name) );
1122              
1123 133         371 $name = $self->replace_quoted_ids($name);
1124              
1125 133         351 my @possible_constraints = ('PRIMARY KEY', 'NOT NULL', 'UNIQUE');
1126              
1127 133         251 for my $constraint (@possible_constraints)
1128             {
1129 399         2273 my $count = $suffix =~ s/$constraint//gi;
1130 399 100       931 next if $count == 0;
1131              
1132 10 50       17 return $self->do_err(qq~Duplicate column constraint: '$constraint'!~)
1133             if $count > 1;
1134              
1135 10 50 66     24 return $self->do_err(qq{Can't have two PRIMARY KEYs in a table!})
1136             if $constraint eq 'PRIMARY KEY' and $primary_defined++;
1137              
1138 10         13 push @{ $self->{struct}->{table_defs}->{columns}->{$name}->{constraints} }, $constraint;
  10         37  
1139             }
1140              
1141 133         220 $suffix =~ s/^\s+//;
1142 133         181 $suffix =~ s/\s+$//;
1143              
1144 133 50       274 return $self->do_err("Unknown column constraint: '$suffix'!") unless ($suffix eq '');
1145              
1146 133         240 $type = uc $type;
1147 133         190 my $length;
1148 133 100       340 if ( $type =~ m/(.+)\((.+)\)/ )
1149             {
1150 20         50 $type = $1;
1151 20         36 $length = $2;
1152             }
1153 133 100       335 if ( !$self->{opts}->{valid_data_types}->{$type} )
1154             {
1155 2         10 return $self->do_err("'$type' is not a recognized data type!");
1156             }
1157 131         431 $self->{struct}->{table_defs}->{columns}->{$name}->{data_type} = $type;
1158 131         278 $self->{struct}->{table_defs}->{columns}->{$name}->{data_length} = $length;
1159             push(
1160 131         192 @{ $self->{struct}->{column_defs} },
  131         572  
1161             {
1162             type => 'column',
1163             value => $name,
1164             fullorg => $name,
1165             }
1166             );
1167              
1168 131         239 my $tmpname = $name;
1169 131 100       404 $tmpname = lc $tmpname unless ( $tmpname =~ m/^(?:\p{Word}+\.)?"/ );
1170 131 50       544 return $self->do_err("Duplicate column names!") if $is_col_name{$tmpname}++;
1171              
1172             }
1173 59         241 $self->{struct}->{table_names} = [$table_name];
1174 59         186 return 1;
1175             }
1176              
1177             ###############
1178             # SQL SUBRULES
1179             ###############
1180              
1181             sub SET_CLAUSE_LIST
1182             {
1183 12     12 0 33 my ( $self, $set_string ) = @_;
1184             my @sets = extract_multiple($set_string, [
1185 28   100 28   1011 sub { my ($m, $r, $p) = extract_bracketed($_[0], "()", qr/[^,(]*/); (($p||'').($m||''), $r, ''); },
  28   100     2670  
1186 12         123 qr/([^,(]+)/,
1187             ], undef, 1);
1188 12         424 my ( @cols, @vals );
1189 12         33 for my $set (@sets)
1190             {
1191 20         60 my ( $col, $val ) = split( m/ = /, $set );
1192 20 50 33     90 return $self->do_err('Incomplete SET clause!') unless ( defined($col) && defined($val) );
1193 20         34 push( @cols, $col );
1194 20         54 push( @vals, $val );
1195             }
1196             return undef
1197 12 50       57 unless ( $self->{struct}->{column_defs} = $self->ROW_VALUE_LIST( join ',', @cols ) );
1198 12 50       52 return undef unless ( $self->LITERAL_LIST( join ',', @vals ) );
1199 12         42 return 1;
1200             }
1201              
1202             sub SET_QUANTIFIER
1203             {
1204 0     0 0 0 my ( $self, $str ) = @_;
1205 0 0       0 if ( $str =~ /^(DISTINCT|ALL)\s+(.*)$/si )
1206             {
1207 0         0 $self->{struct}->{set_quantifier} = uc $1;
1208 0         0 $str = $2;
1209             }
1210 0         0 return $str;
1211             }
1212              
1213             #
1214             # DAA v1.11
1215             # modify to transform || strings into
1216             # CONCAT(); note that we
1217             # only xform the topmost expressions;
1218             # if a concat is contained within a subfunction,
1219             # it should get handled by ROW_VALUE()
1220             #
1221             sub transform_concat
1222             {
1223 1     1 1 4 my ( $obj, $colstr ) = @_;
1224              
1225 1         3 pos($colstr) = 0;
1226 1         2 my $parens = 0;
1227 1         2 my $spos = 0;
1228 1         4 my @concats = ();
1229 1 50       5 my $alias = ( $colstr =~ s/^(.+)(\s+AS\s+\S+)$/$1/ ) ? $2 : '';
1230              
1231 1         7 while ( $colstr =~ /\G.*?([\(\)\|])/gcs )
1232             {
1233 10 100 33     38 if ( $1 eq '(' )
    100          
    50          
1234             {
1235 3         9 $parens++;
1236             }
1237             elsif ( $1 eq ')' )
1238             {
1239 3         8 $parens--;
1240             }
1241             elsif (( !$parens )
1242             && ( substr( $colstr, $-[1] + 1, 1 ) eq '|' ) )
1243             {
1244              
1245             #
1246             # its a concat outside of parens, push prior string on stack
1247             #
1248 0         0 push @concats, substr( $colstr, $spos, $-[1] - $spos );
1249 0         0 $spos = $+[1] + 1;
1250 0         0 pos($colstr) = $spos;
1251             }
1252             }
1253              
1254             #
1255             # no concats, return original
1256             #
1257 1 50       7 return $colstr unless scalar @concats;
1258              
1259             #
1260             # don't forget the last one!
1261             #
1262 0         0 push @concats, substr( $colstr, $spos );
1263 0         0 return 'CONCAT(' . join( ', ', @concats ) . ")$alias";
1264             }
1265              
1266             #
1267             # DAA v1.10
1268             # improved column list extraction
1269             # original doesn't seem to handle
1270             # commas within function argument lists
1271             #
1272             # DAA v1.11
1273             # modify to transform || strings into
1274             # CONCAT()
1275             #
1276             sub extract_column_list
1277             {
1278 315     315 1 587 my ( $self, $colstr ) = @_;
1279              
1280 315         471 my @collist = ();
1281 315         825 pos($colstr) = 0;
1282 315         624 my $parens = 0;
1283 315         471 my $spos = 0;
1284 315         1380 while ( $colstr =~ m/\G.*?([\(\),])/gcs )
1285             {
1286 711 100       2163 if ( $1 eq '(' )
    100          
    100          
1287             {
1288 242         720 $parens++;
1289             }
1290             elsif ( $1 eq ')' )
1291             {
1292 239         519 $parens--;
1293             }
1294             elsif ( !$parens )
1295             { # its a comma outside of parens
1296 137         478 push( @collist, substr( $colstr, $spos, $-[1] - $spos ) );
1297 137         323 $collist[-1] =~ s/^\s+//;
1298 137         289 $collist[-1] =~ s/\s+$//;
1299 137 50       313 return $self->do_err('Bad column list!') if ( $collist[-1] eq '' );
1300 137         612 $spos = $+[1];
1301             }
1302             }
1303 315 100       734 return $self->do_err('Unbalanced parentheses!') if ($parens);
1304              
1305             # don't forget the last one!
1306 312         776 push( @collist, substr( $colstr, $spos ) );
1307 312         724 $collist[-1] =~ s/^\s+//;
1308 312         720 $collist[-1] =~ s/\s+$//;
1309 312 50       738 return $self->do_err('Bad column list!') if ( $collist[-1] eq '' );
1310              
1311             # scan for and convert string concats to CONCAT()
1312 312         895 foreach ( 0 .. $#collist )
1313             {
1314 449 100       1206 $collist[$_] = $self->transform_concat( $collist[$_] ) if ( $collist[$_] =~ m/\|\|/ );
1315             }
1316              
1317 312         1029 return @collist;
1318             }
1319              
1320             sub SELECT_LIST
1321             {
1322 547     547 0 1060 my ( $self, $col_str ) = @_;
1323 547 100       1688 if ( $col_str =~ m/^\s*\*\s*$/ )
1324             {
1325             $self->{struct}->{column_defs} = [
1326             {
1327 232         790 type => 'column',
1328             value => '*'
1329             }
1330             ];
1331 232         591 $self->{struct}->{column_aliases} = {};
1332              
1333 232         736 return 1;
1334             }
1335 315         783 my @col_list = $self->extract_column_list($col_str);
1336 315 100       691 return undef unless ( scalar(@col_list) );
1337              
1338 312         558 my ( @newcols, %aliases );
1339 312         588 for my $col (@col_list)
1340             {
1341             # DAA:
1342             # need better alias test here, since AS is a common
1343             # keyword that might be used in a function
1344 445 100       2345 my ( $fld, $alias ) =
1345             ( $col =~ m/^(.+?)\s+(?:AS\s+)?([A-Z]\p{Word}*|\?QI\d+\?)$/i )
1346             ? ( $1, $2 )
1347             : ( $col, undef );
1348 445         768 $col = $fld;
1349 445 100       849 if ( $col =~ m/^(\S+)\.\*$/ )
1350             {
1351 2         4 my $table = $1;
1352 2 50       5 if ( defined($alias) )
1353             {
1354 0         0 return $self->do_err("'$table.*' cannot be aliased");
1355             }
1356             $table = $self->{tmp}->{is_table_alias}->{$table}
1357 2 50       5 if ( $self->{tmp}->{is_table_alias}->{$table} );
1358             $table = $self->{tmp}->{is_table_alias}->{"\L$table"}
1359 2 50       6 if ( $self->{tmp}->{is_table_alias}->{"\L$table"} );
1360 2 50       5 return undef unless ( $self->TABLE_NAME($table) );
1361 2         4 $table = $self->replace_quoted_ids($table);
1362 2         7 push(
1363             @newcols,
1364             {
1365             type => 'column',
1366             value => "$table.*",
1367             }
1368             );
1369             }
1370             else
1371             {
1372 443         571 my $newcol;
1373 443         986 $newcol = $self->SET_FUNCTION_SPEC($col);
1374 443 100       1119 return if ( $self->{struct}->{errstr} );
1375 440   66     1556 $newcol ||= $self->ROW_VALUE($col);
1376 440 100       1055 return if ( $self->{struct}->{errstr} );
1377 439 50       1289 return $self->do_err("Invalid SELECT entry '$col'")
1378             unless ( defined( _HASH($newcol) ) );
1379              
1380             # FIXME this might be better done later and only if not 2 functions with the same name are selected
1381 439 100 100     1940 if ( !defined($alias)
      100        
1382             && ( ( 'function' eq $newcol->{type} ) || ( 'setfunc' eq $newcol->{type} ) ) )
1383             {
1384 220         419 $alias = $newcol->{name};
1385             }
1386              
1387 439 100       910 if ( defined($alias) )
1388             {
1389 236         608 $alias = $self->replace_quoted_ids($alias);
1390 236         527 $newcol->{alias} = $alias;
1391 236         671 $aliases{ $newcol->{fullorg} } = $alias;
1392 236         582 $self->{struct}->{ORG_NAME}->{ $newcol->{fullorg} } = $alias;
1393 236         653 $self->{struct}->{ALIASES}->{$alias} = $newcol->{fullorg};
1394             }
1395 439         1139 push( @newcols, $newcol );
1396             }
1397             }
1398 308         898 $self->{struct}->{column_aliases} = \%aliases;
1399 308         653 $self->{struct}->{column_defs} = \@newcols;
1400 308         1242 return 1;
1401             }
1402              
1403             sub SET_FUNCTION_SPEC
1404             {
1405 443     443 0 776 my ( $self, $col_str ) = @_;
1406              
1407 443 100       1062 if ( $col_str =~ m/^(COUNT|AVG|SUM|MAX|MIN) \((.*)\)\s*$/i )
1408             {
1409 34         93 my $set_function_name = uc $1;
1410 34         63 my $set_function_arg_str = $2;
1411 34         49 my $distinct = 'ALL';
1412 34 100       117 if ( $set_function_arg_str =~ s/(DISTINCT|ALL) (.+)$/$2/i )
1413             {
1414 5         12 $distinct = uc $1;
1415             }
1416 34   100     115 my $count_star = ( $set_function_name eq 'COUNT' ) && ( $set_function_arg_str eq '*' );
1417              
1418 34         49 my $set_function_arg;
1419 34 100       70 if ($count_star)
1420             {
1421 8 100       27 return $self->do_err("Keyword DISTINCT is not allowed for COUNT(*)")
1422             if ( 'DISTINCT' eq $distinct );
1423 7         37 $set_function_arg = {
1424             type => 'column',
1425             value => '*'
1426             };
1427             }
1428             else
1429             {
1430 26         67 $set_function_arg = $self->ROW_VALUE($set_function_arg_str);
1431 26 50       73 return if ( $self->{struct}->{errstr} );
1432 26 50       97 return unless ( defined( _HASH($set_function_arg) ) );
1433             }
1434              
1435 33         95 $self->{struct}->{has_set_functions} = 1;
1436              
1437 33         171 my $value = {
1438             name => $set_function_name,
1439             arg => $set_function_arg,
1440             argstr => lc($set_function_arg_str),
1441             distinct => $distinct,
1442             type => 'setfunc',
1443             fullorg => $col_str,
1444             };
1445 33         84 return $value;
1446             }
1447             else
1448             {
1449 409         872 return undef;
1450             }
1451             }
1452              
1453             sub LIMIT_CLAUSE
1454             {
1455 9     9 0 29 my ( $self, $limit_clause ) = @_;
1456              
1457             # $limit_clause = trim($limit_clause);
1458 9         23 $limit_clause =~ s/^\s+//;
1459 9         19 $limit_clause =~ s/\s+$//;
1460              
1461 9 50       22 return 1 if !$limit_clause;
1462 9         24 my $offset;
1463             my $limit;
1464 9         0 my $junk;
1465 9         39 ($offset, $limit, $junk ) = split /,|OFFSET/i, $limit_clause;
1466 9 100       27 if ($limit_clause =~ m/(\d+)\s+OFFSET\s+(\d+)/) {
1467 1         2 $limit = $1;
1468 1         3 $offset = $2;
1469             } else {
1470 8         24 ( $offset, $limit, $junk ) = split /,/i, $limit_clause;
1471             }
1472 9 50 66     88 return $self->do_err('Bad limit clause!:'.$limit_clause)
      33        
      33        
      33        
1473             if ( defined $limit and $limit =~ /[^\d]/ )
1474             or ( defined $offset and $offset =~ /[^\d]/ )
1475             or defined $junk;
1476 9 100 66     54 if ( defined $offset and !defined $limit )
1477             {
1478 2         8 $limit = $offset;
1479 2         4 undef $offset;
1480             }
1481             $self->{struct}->{limit_clause} = {
1482 9         32 limit => $limit,
1483             offset => $offset,
1484             };
1485 9         27 return 1;
1486             }
1487              
1488             sub SORT_SPEC_LIST
1489             {
1490 20     20 0 60 my ( $self, $order_clause ) = @_;
1491 20 50       70 return 1 if !$order_clause;
1492 20         34 my @ocols;
1493 20         71 my @order_columns = split ',', $order_clause;
1494 20         52 for my $col (@order_columns)
1495             {
1496 26         46 my $newcol;
1497             my $newarg;
1498 26 100       166 if ( $col =~ /\s*(\S+)\s+(ASC|DESC)/si )
    50          
1499             {
1500 9         25 $newcol = $1;
1501 9         26 $newarg = uc $2;
1502             }
1503             elsif ( $col =~ /^\s*(\S+)\s*$/si )
1504             {
1505 17         48 $newcol = $1;
1506 17         30 $newarg = 'ASC';
1507             }
1508             else
1509             {
1510 0         0 return $self->do_err('Junk after column name in ORDER BY clause!');
1511             }
1512 26 50       70 $newcol = $self->COLUMN_NAME($newcol) or return;
1513 26 100       81 if ( $newcol =~ /^(.+)\..+$/s )
1514             {
1515 3         31 my $table = $1;
1516 3         13 $self->_verify_tablename( $table, "ORDER BY" );
1517             }
1518 26         97 push( @ocols, { $newcol => $newarg } );
1519             }
1520 20         62 $self->{struct}->{sort_spec_list} = \@ocols;
1521 20         65 return 1;
1522             }
1523              
1524             sub SEARCH_CONDITION
1525             {
1526 231     231 0 439 my ( $self, $str ) = @_;
1527 231         470 $str =~ s/^\s*WHERE (.+)/$1/;
1528 231         472 $str =~ s/^\s+//;
1529 231         564 $str =~ s/\s+$//;
1530 231 50       456 return $self->do_err("Couldn't find WHERE clause!") unless $str;
1531              
1532             #
1533             # DAA
1534             # make these OO so subclasses can override them
1535             #
1536 231         508 $str = $self->repl_btwin($str);
1537              
1538             #
1539             # DAA
1540             # add another abstract method so subclasses
1541             # can inject their own syntax transforms
1542             #
1543 231         520 $str = $self->transform_syntax($str);
1544              
1545 231         464 my $open_parens = $str =~ tr/\(//;
1546 231         312 my $close_parens = $str =~ tr/\)//;
1547 231 50       498 if ( $open_parens != $close_parens )
1548             {
1549 0         0 return $self->do_err("Mismatched parentheses in WHERE clause!");
1550             }
1551 231         517 $str = nongroup_numeric( $self->nongroup_string($str) );
1552 231 100       772 my $pred =
1553             $open_parens
1554             ? $self->parens_search( $str, [] )
1555             : $self->non_parens_search( $str, [] );
1556 229 50       537 return $self->do_err("Couldn't find predicate!") unless $pred;
1557 229         386 $self->{struct}->{where_clause} = $pred;
1558 229         547 return 1;
1559             }
1560              
1561             ############################################################
1562             # UTILITY FUNCTIONS CALLED TO PARSE PARENS IN WHERE CLAUSE
1563             ############################################################
1564              
1565             sub repl_btwin
1566             {
1567 231     231 1 384 my ( $self, $str ) = @_; # DAA make OO for subclassing
1568 231         298 my @lids;
1569              
1570 231         308 my $i = -1;
1571 231         875 while ( $str =~ m/\G.*(?:IN|BETWEEN)\s+\(/g )
1572             {
1573 32         59 my $start = pos($str) - 1;
1574 32         44 my $lparens = 1;
1575 32         46 my $rparens = 0;
1576 32         109 while ( $str =~ m/\G.*?([\(\)])/gcs )
1577             {
1578 36 100       101 ++$lparens if ( '(' eq $1 );
1579 36 100       78 ++$rparens if ( ')' eq $1 );
1580 36 100       85 last if ( $lparens == $rparens );
1581             }
1582 32         45 my $now = pos($str);
1583 32         41 ++$i;
1584 32         65 my $subst = "?LI$i?";
1585 32         92 my $term = substr( $str, $start, $now - $start, $subst );
1586 32         57 $term = substr( $term, 1, length($term) - 2 );
1587 32         60 push( @lids, $term );
1588 32         116 pos($str) = $start + length($subst);
1589             }
1590              
1591 231         437 $self->{struct}->{list_ids} = \@lids;
1592 231         456 return $str;
1593             }
1594              
1595             # groups clauses by nested parens
1596             #
1597             # DAA
1598             # rewrite to correct paren scan
1599             # and optimize code, and remove
1600             # recursion
1601             #
1602             sub parens_search
1603             {
1604 135     135 1 255 my ( $self, $str, $predicates ) = @_;
1605 135         151 my $index = scalar( @{$predicates} );
  135         191  
1606              
1607             # to handle WHERE (a=b) AND (c=d)
1608             # but needs escape space to not foul up AND/OR
1609              
1610             # locate all open parens
1611             # locate all close parens
1612             # apply non_paren_search to contents of
1613             # inner parens
1614              
1615 135         203 my $lparens = ( $str =~ tr/\(// );
1616 135         159 my $rparens = ( $str =~ tr/\)// );
1617 135 0       263 return $self->do_err( 'Unmatched ' . ( ( $lparens > $rparens ) ? 'left' : 'right' ) . " parentheses in '$str'!" )
    50          
1618             unless ( $lparens == $rparens );
1619              
1620 135 100       354 return $self->non_parens_search( $str, $predicates )
1621             unless $lparens;
1622              
1623 8         16 my @lparens = ();
1624 8         35 while ( $str =~ m/\G.*?([\(\)])/gcs )
1625             {
1626 20 100       88 push( @lparens, $-[1] ), next
1627             if ( $1 eq '(' );
1628              
1629             #
1630             # got a close paren, so pop the position of matching
1631             # left paren and extract the expression, removing the
1632             # parens
1633             #
1634 10         29 my $pos = pop @lparens;
1635 10         29 my $predlen = $+[1] - $pos;
1636 10         31 my $pred = substr( $str, $pos + 1, $predlen - 2 );
1637              
1638             #
1639             # note that this will pass thru any prior ^$index^ xlation,
1640             # so we don't need to recurse to recover the predicate
1641             #
1642 10 100       63 substr( $str, $pos, $predlen ) = $pred, pos($str) = $pos + length($pred), next
1643             unless ( $pred =~ / (AND|OR) /i );
1644              
1645             #
1646             # handle AND/OR
1647             #
1648 3         13 push( @$predicates, substr( $str, $pos + 1, $predlen - 2 ) );
1649 3         11 my $replacement = "^$#$predicates^";
1650 3         11 substr( $str, $pos, $predlen ) = $replacement;
1651 3         14 pos($str) = $pos + length($replacement);
1652             }
1653              
1654 8         22 return $self->non_parens_search( $str, $predicates );
1655             }
1656              
1657             # creates predicates from clauses that either have no parens
1658             # or ANDs or have been previously grouped by parens and ANDs
1659             #
1660             # DAA
1661             # rewrite to fix paren scanning
1662             #
1663             sub non_parens_search
1664             {
1665 311     311 1 549 my ( $self, $str, $predicates ) = @_;
1666 311         405 my $neg = 0;
1667 311         405 my $nots = {};
1668              
1669 311 50       687 $neg = 1, $nots = { pred => 1 }
1670             if ( $str =~ s/^NOT (\^.+)$/$1/i );
1671              
1672 311         422 my ( $pred1, $pred2, $op );
1673 311         439 my $and_preds = [];
1674 311         629 ( $str, $and_preds ) = group_ands($str);
1675 311 50       664 $str = $and_preds->[$1]
1676             if $str =~ /^\s*~(\d+)~\s*$/;
1677              
1678 311 100       689 return $self->non_parens_search( $$predicates[$1], $predicates )
1679             if ( $str =~ /^\s*\^(\d+)\^\s*$/ );
1680              
1681 309 100       1520 if ( $str =~ /\G(.*?)\s+(AND|OR)\s+(.*)$/igcs )
1682             {
1683 39         146 ( $pred1, $op, $pred2 ) = ( $1, $2, $3 );
1684              
1685 39 100       102 if ( $pred1 =~ /^\s*\^(\d+)\^\s*$/ )
1686             {
1687 1         13 $pred1 = $self->non_parens_search( $$predicates[$1], $predicates );
1688             }
1689             else
1690             {
1691 38         92 $pred1 =~ s/\~(\d+)\~$/$and_preds->[$1]/g;
1692 38         140 $pred1 = $self->non_parens_search( $pred1, $predicates );
1693             }
1694              
1695             #
1696             # handle pred2 as a full predicate
1697             #
1698 39         97 $pred2 =~ s/\~(\d+)\~$/$and_preds->[$1]/g;
1699 39         100 $pred2 = $self->non_parens_search( $pred2, $predicates );
1700              
1701             return {
1702 39         202 neg => $neg,
1703             nots => $nots,
1704             arg1 => $pred1,
1705             op => uc $op,
1706             arg2 => $pred2,
1707             };
1708             }
1709              
1710             #
1711             # terminal predicate
1712             # need to check for singleton functions here
1713             #
1714 270         444 my $xstr = $str;
1715 270         378 my ( $k, $v );
1716 270 100       800 if ( $str =~ /^\s*([A-Z]\p{Word}*)\s*\[/gcs )
1717             {
1718              
1719             #
1720             # we've got a function, check if its a singleton
1721             #
1722 120         154 my $parens = 1;
1723 120         218 my $spos = $-[1];
1724 120         174 my $epos = 0;
1725 120 100 66     805 $epos = $-[1], $parens += ( $1 eq '[' ) ? 1 : -1 while ( ( $parens > 0 ) && ( $str =~ /\G.*?([\[\]])/gcs ) );
1726 120         244 $k = substr( $str, $spos, $epos - $spos + 1 );
1727 120         201 $k =~ s/\?(\d+)\?/$self->{struct}{literals}[$1]/g;
1728              
1729             #
1730             # for now we assume our parens are balanced
1731             # now look for a predicate operator and a right operand
1732             #
1733 120 100       443 $v = $1, $v =~ s/\?(\d+)\?/$self->{struct}{literals}[$1]/g
1734             if ( $str =~ /\G\s+\S+\s*(.+)\s*$/gcs );
1735             }
1736             else
1737             {
1738 150         378 $xstr =~ s/\?(\d+)\?/$self->{struct}{literals}[$1]/g;
1739 150         729 ( $k, $v ) = $xstr =~ /^(\S+?)\s+\S+\s*(.+)\s*$/;
1740             }
1741 270 50       605 push @{ $self->{struct}{where_cols}{$k} }, $v
  270         1036  
1742             if defined $k;
1743 270         689 return $self->PREDICATE($str);
1744             }
1745              
1746             # groups AND clauses that aren't already grouped by parens
1747             #
1748             sub group_ands
1749             {
1750 315     315 1 458 my $str = shift;
1751 315   100     848 my $and_preds = shift || [];
1752 315 100 100     1283 return ( $str, $and_preds )
1753             unless $str =~ / AND / and $str =~ / OR /;
1754              
1755 4 50       23 return $str, $and_preds
1756             unless ( $str =~ /^(.*?) AND (.*)$/i );
1757              
1758 4         15 my ( $front, $back ) = ( $1, $2 );
1759 4         9 my $index = scalar @$and_preds;
1760 4 50       15 $front = $1
1761             if ( $front =~ /^.* OR (.*)$/i );
1762              
1763 4 50       24 $back = $1
1764             if ( $back =~ /^(.*?) (OR|AND) .*$/i );
1765              
1766 4         12 my $newpred = "$front AND $back";
1767 4         8 push @$and_preds, $newpred;
1768 4         53 $str =~ s/\Q$newpred/~$index~/i;
1769 4         16 return group_ands( $str, $and_preds );
1770             }
1771              
1772             # replaces string function parens with square brackets
1773             # e.g TRIM (foo) -> TRIM[foo]
1774             #
1775             # DAA update to support UDFs
1776             # and remove recursion
1777             #
1778             sub nongroup_string
1779             {
1780 231     231 1 426 my ( $self, $str ) = @_;
1781              
1782             #
1783             # add in any user defined functions
1784             #
1785 231         552 my $f = join( '|', FUNCTION_NAMES, $self->_udf_function_names );
1786              
1787             #
1788             # we need a scan here to permit arbitrarily nested paren
1789             # arguments to functions
1790             #
1791 231         355 my $parens = 0;
1792 231         262 my $pos;
1793 231         301 my @lparens = ();
1794 231         9453 while ( $str =~ /\G.*?((\b($f)\s*\()|[\(\)])/igcs )
1795             {
1796 298 100       776 if ( $1 eq ')' )
    100          
1797             {
1798             #
1799             # close paren, see if any pending function open
1800             # paren matches it
1801             #
1802 149         185 --$parens;
1803 149 100 66     1282 $pos = $+[0], substr( $str, $+[0] - 1, 1 ) = ']', pos($str) = $pos, pop(@lparens)
1804             if ( @lparens && ( $lparens[-1] == $parens ) );
1805             }
1806             elsif ( $1 eq '(' )
1807             {
1808              
1809             #
1810             # just an open paren, count it and go on
1811             #
1812 15         112 ++$parens;
1813             }
1814             else
1815             {
1816              
1817             #
1818             # new function definition, capture its open paren
1819             # also uppercase the function name
1820             #
1821 134         291 $pos = $+[0];
1822 134         477 substr( $str, $-[3], length($3) ) = uc $3;
1823 134         302 substr( $str, $+[0] - 1, 1 ) = '[';
1824 134         243 pos($str) = $pos;
1825 134         206 push @lparens, $parens;
1826 134         780 ++$parens;
1827             }
1828             }
1829              
1830             # return $self->do_err('Unmatched ' .
1831             # (($parens > 0) ? 'left' : 'right') . ' parentheses!')
1832             # if $parens;
1833             #
1834             # DAA
1835             # remove scoped recursion
1836             #
1837             # return ( $str =~ /($f)\s*\(/i ) ?
1838             # nongroup_string($str) : $str;
1839 231         811 return $str;
1840             }
1841              
1842             # replaces math parens with square brackets
1843             # e.g (4-(6+7)*9) -> MATH[4-MATH[6+7]*9]
1844             #
1845             sub nongroup_numeric
1846             {
1847 233     233 1 346 my $str = $_[0];
1848 233         292 my $has_op;
1849              
1850             #
1851             # DAA
1852             # optimize regex
1853             #
1854 233 100       536 if ( $str =~ m/\(([\p{Word} \*\/\+\-\[\]\?]+)\)/ )
1855             {
1856 7         17 my $match = $1;
1857 7 100       39 if ( $match !~ m/(LIKE |IS|BETWEEN|IN)/i )
1858             {
1859 5         12 my $re = quotemeta($match);
1860 5         81 $str =~ s/\($re\)/MATH\[$match\]/;
1861             }
1862             else
1863             {
1864 2         4 $has_op++;
1865             }
1866             }
1867              
1868             #
1869             # DAA
1870             # remove scoped recursion
1871             #
1872 233 100 100     977 return ( !$has_op and $str =~ /\(([\p{Word} \*\/\+\-\[\]\?]+)\)/ )
1873             ? nongroup_numeric($str)
1874             : $str;
1875             }
1876             ############################################################
1877              
1878             #########################################################
1879             # LITERAL_LIST ::= [,]
1880             #########################################################
1881             sub LITERAL_LIST
1882             {
1883 192     192 0 621 my ( $self, $str ) = @_;
1884             my @tokens = extract_multiple($str, [
1885 1036   100 1036   38146 sub { my ($m, $r, $p) = extract_bracketed($_[0], "()", qr/[^,(]*/); (($p||'').($m||''), $r, ''); },
  1036   100     69659  
1886 192         1653 qr/([^,(]+)/,
1887             ], undef, 1);
1888 192         7149 my @values;
1889 192         462 for my $tok (@tokens)
1890             {
1891 614         1247 my $val = $self->ROW_VALUE($tok);
1892 614 50       1393 return $self->do_err(qq('$tok' is not a valid value or is not quoted!))
1893             unless $val;
1894 614         1338 push @values, $val;
1895             }
1896 192         255 push( @{ $self->{struct}->{values} }, \@values );
  192         545  
1897 192         659 return 1;
1898             }
1899              
1900             #############################################################################
1901             # LITERAL ::= | | | NULL/TRUE/FALSE
1902             #############################################################################
1903             sub LITERAL
1904             {
1905 1899     1899 0 3073 my ( $self, $str ) = @_;
1906              
1907             #
1908             # DAA
1909             # strip parens (if any)
1910             #
1911 1899         3515 $str = $1 while ( $str =~ m/^\s*\(\s*(.+)\s*\)\s*$/ );
1912              
1913 1899 100       3467 return 'null' if $str =~ m/^NULL$/i; # NULL
1914 1872 100       3345 return 'boolean' if $str =~ m/^(?:TRUE|FALSE)$/i; # TRUE/FALSE
1915              
1916             # return 'empty_string' if $str =~ /^~E~$/i; # NULL
1917 1859 100       3661 if ( $str eq '?' )
1918             {
1919 36         78 $self->{struct}->{num_placeholders}++;
1920 36         100 return 'placeholder';
1921             }
1922              
1923             # return 'placeholder' if $str eq '?'; # placeholder question mark
1924 1823 100       3157 return 'string' if $str =~ m/^'.*'$/s; # quoted string
1925             # return 'number' if $str =~ m/^[+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/; # number
1926 1822 100       6112 return 'number' if ( looks_like_number($str) ); # number
1927              
1928 1126         2303 return undef;
1929             }
1930             ###################################################################
1931             # PREDICATE
1932             ###################################################################
1933             sub PREDICATE
1934             {
1935 270     270 0 467 my ( $self, $str ) = @_;
1936              
1937 270         354 my ( $arg1, $op, $arg2, $opexp );
1938              
1939             $opexp = $self->{opts}{valid_comparison_NOT_ops_regex}, ( $arg1, $op, $arg2 ) = $str =~ /$opexp/i
1940 270 50       2090 if $self->{opts}{valid_comparison_NOT_ops_regex};
1941              
1942             $opexp = $self->{opts}{valid_comparison_twochar_ops_regex}, ( $arg1, $op, $arg2 ) = $str =~ /$opexp/i
1943             if ( !defined($op)
1944 270 50 66     2041 && $self->{opts}{valid_comparison_twochar_ops_regex} );
1945              
1946             $opexp = $self->{opts}{valid_comparison_ops_regex}, ( $arg1, $op, $arg2 ) = $str =~ /$opexp/i
1947 270 50 66     2500 if ( !defined($op) && $self->{opts}{valid_comparison_ops_regex} );
1948              
1949             #
1950             ### USER-DEFINED PREDICATE
1951             #
1952 269 50 66     1164 unless ( defined $arg1 && defined $op && defined $arg2 )
      66        
1953             {
1954 57         88 $arg1 = $str;
1955 57         67 $op = 'USER_DEFINED';
1956 57         65 $arg2 = '';
1957             }
1958              
1959 269         444 $op = uc $op;
1960              
1961             # my $uname = $self->is_func($arg1);
1962             # if (!$uname) {
1963             # $arg1 =~ s/^(\S+).*$/$1/;
1964             # return $self->do_err("Bad predicate: '$arg1'!");
1965             # }
1966              
1967 269         342 my $negated = 0; # boolean value showing if predicate is negated
1968 269         322 my %not; # hash showing elements modified by NOT
1969             #
1970             # e.g. "NOT bar = foo" -> %not = (arg1=>1)
1971             # "bar NOT LIKE foo" -> %not = (op=>1)
1972             # "NOT bar NOT LIKE foo" -> %not = (arg1=>1,op=>1);
1973             # "NOT bar IS NOT NULL" -> %not = (arg1=>1,op=>1);
1974             # "bar = foo" -> %not = undef;
1975             #
1976 269 100       651 $not{arg1}++
1977             if ( $arg1 =~ s/^NOT (.+)$/$1/i );
1978              
1979 269 100 100     971 $not{op}++
1980             if ( $op =~ s/^(.+) NOT$/$1/i
1981             || $op =~ s/^NOT (.+)$/$1/i );
1982              
1983 269 100 66     595 $negated = 1 if %not and scalar keys %not == 1;
1984              
1985 269 50       570 return undef unless $arg1 = $self->ROW_VALUE($arg1);
1986              
1987 268 100       672 if ( $op ne 'USER_DEFINED' )
1988             { # USER-PREDICATE;
1989 212 50       462 return undef unless $arg2 = $self->ROW_VALUE($arg2);
1990             }
1991             else
1992             {
1993              
1994             # $arg2 = $self->ROW_VALUE($arg2);
1995             }
1996              
1997 268 100 66     2042 if ( defined( _HASH($arg1) )
      50        
      100        
      50        
      100        
      100        
1998             and defined( _HASH($arg2) )
1999             and ( ( $arg1->{type} || '' ) eq 'column' )
2000             and ( ( $arg2->{type} || '' ) eq 'column' )
2001             and ( $op eq '=' ) )
2002             {
2003 27         44 push( @{ $self->{struct}->{keycols} }, $arg1->{value} );
  27         97  
2004 27         47 push( @{ $self->{struct}->{keycols} }, $arg2->{value} );
  27         59  
2005             }
2006              
2007             return {
2008 268         1619 neg => $negated,
2009             nots => \%not,
2010             arg1 => $arg1,
2011             op => $op,
2012             arg2 => $arg2,
2013             };
2014             }
2015              
2016             sub _udf_function_names
2017             {
2018             $_[0]->{opts}->{_udf_function_names}
2019 2540 100   2540   5361 or return $_[0]->{opts}->{_udf_function_names} = join( "|", map { uc $_ } keys %{ $_[0]->{opts}->{function_names} } );
  1971         3147  
  18         385  
2020 2522         6675 $_[0]->{opts}->{_udf_function_names};
2021             }
2022              
2023             sub undo_string_funcs
2024             {
2025 2309     2309 1 3857 my ( $self, $str ) = @_;
2026 2309         4049 my $f = join( '|', FUNCTION_NAMES, $self->_udf_function_names );
2027              
2028             # eliminate recursion:
2029             # we have to scan for closing brackets, since we may
2030             # have intervening MATH elements with brackets
2031 2309         4383 my ( $brackets, $pos, @lbrackets ) = (0);
2032 2309         26045 while ( $str =~ /\G.*?((\b($f)\s*\[)|[\[\]])/igcs )
2033             {
2034 278 100       642 if ( $1 eq ']' )
    100          
2035             {
2036             # close paren, see if any pending function open
2037             # paren matches it
2038 139         173 $brackets--;
2039 139 100 66     1026 $pos = $+[0], substr( $str, $+[0] - 1, 1 ) = ')', pos($str) = $pos, pop @lbrackets
2040             if ( @lbrackets && ( $lbrackets[-1] == $brackets ) );
2041             }
2042             elsif ( $1 eq '[' )
2043             {
2044             # just an open paren, count it and go on
2045 5         35 $brackets++;
2046             }
2047             else
2048             {
2049             # new function definition, capture its open paren
2050             # also uppercase the function name
2051 134         230 $pos = $+[0];
2052 134         403 substr( $str, $-[3], length($3) ) = uc $3;
2053 134         296 substr( $str, $+[0] - 1, 1 ) = '(';
2054 134         237 pos($str) = $pos;
2055 134         213 push @lbrackets, $brackets;
2056 134         669 $brackets++;
2057             }
2058             }
2059              
2060 2309         5490 return $str;
2061             }
2062              
2063             sub undo_math_funcs
2064             {
2065 2309     2309 1 3310 my $str = $_[0];
2066              
2067             # eliminate recursion
2068 2309         4926 while ( $str =~ s/MATH\[([^\]\[]+?)\]/($1)/ )
2069             {
2070             }
2071              
2072 2309         3834 return $str;
2073             }
2074              
2075             #
2076             # DAA
2077             # need better nested function/parens handling
2078             #
2079             sub extract_func_args
2080             {
2081 346     346 1 588 my ( $self, $value ) = @_;
2082              
2083 346         517 my @final_args = ();
2084 346         643 my ( $spos, $parens, $epos, $delim ) = ( 0, 0, 0, 0 );
2085 346         1129 while ( $value =~ m/\G.*?([\(\),])/gcs )
2086             {
2087 201         475 $epos = $+[0];
2088 201         389 $delim = $1;
2089 201 100 100     689 unless ( $parens or ( $delim ne ',' ) )
2090             {
2091 149         490 push( @final_args, $self->ROW_VALUE( substr( $value, $spos, $epos - $spos - 1 ) ) );
2092 149         323 $spos = $epos;
2093 149         526 next;
2094             }
2095              
2096 52 100       137 unless ( $delim eq ',' )
2097             {
2098 38 100       133 $parens += ( $delim eq '(' ) ? 1 : -1;
2099             }
2100             }
2101              
2102             # don't forget the last argument
2103 346 100       744 if ( $spos != length($value) )
2104             {
2105 312         456 $epos = length($value);
2106 312         956 push( @final_args, $self->ROW_VALUE( substr( $value, $spos, $epos - $spos ) ) ); # XXX
2107             }
2108              
2109 346         1062 return @final_args;
2110             }
2111              
2112             ###################################################################
2113             # ROW_VALUE ::= |
2114             ###################################################################
2115             sub ROW_VALUE
2116             {
2117 2309     2309 0 4965 my ( $self, $str ) = @_;
2118              
2119 2309         4506 $str =~ s/^\s+//;
2120 2309         4005 $str =~ s/\s+$//;
2121 2309         4673 $str = $self->undo_string_funcs($str);
2122 2309         4399 $str = undo_math_funcs($str);
2123 2309         4498 my ( $orgstr, $f, $bf ) = ( $str, FUNCTION_NAMES, BAREWORD_FUNCTIONS );
2124              
2125             # USER-DEFINED FUNCTION
2126 2309         3114 my ( $user_func_name, $user_func_args, $is_func );
2127              
2128             # DAA
2129             # need better paren check here
2130 2309 100       7916 if ( $str =~ m/^([^\s\(]+)\s*(.*)\s*$/ )
2131             {
2132 2303         4494 $user_func_name = $1;
2133 2303         4005 $user_func_args = $2;
2134              
2135             # convert operator-like function to parenthetical format
2136 2303 100 100     4296 if ( ( $is_func = $self->is_func($user_func_name) )
      100        
2137             && ( $user_func_args !~ m/^\(.*\)$/ )
2138             && ( $is_func =~ /^(?:$bf)$/i ) )
2139             {
2140 8         33 $orgstr = $str = "$user_func_name ($user_func_args)";
2141             }
2142             }
2143             else
2144             {
2145 6         12 $user_func_name = $str;
2146 6         25 $user_func_name =~ s/^(\S+).*$/$1/;
2147 6         12 $user_func_args = '';
2148 6         16 $is_func = $self->is_func($user_func_name);
2149             }
2150              
2151             # BLKB
2152             # Limiting the parens convert shortcut, so that "SELECT LOG(1), PI" works as a
2153             # two functions, and "SELECT x FROM log" works as a table
2154 2309 100 100     7718 undef $is_func if ( $is_func && $is_func !~ /^(?:$bf)$/i && $str !~ m/^\S+\s*\(.*\)\s*$/ );
      100        
2155              
2156 2309 100 66     5504 if ( $is_func && ( uc($is_func) !~ m/^($f)$/ ) )
2157             {
2158 346         730 my ( $name, $value ) = ( $user_func_name, '' );
2159 346 50       1184 if ( $str =~ m/^(\S+)\s*\((.*)\)\s*$/ )
2160             {
2161 346         654 $name = $1;
2162 346         579 $value = $2;
2163 346         697 $is_func = $self->is_func($name);
2164             }
2165              
2166 346 50       829 if ($is_func)
2167             {
2168             #
2169             # DAA
2170             # need a better argument extractor, since it can
2171             # contain arbitrary (possibly parenthesized)
2172             # expressions/functions
2173             #
2174             # if ($value =~ /\(/ ) {
2175             # $value = $self->ROW_VALUE($value);
2176             # }
2177             # my @args = split ',',$value;
2178              
2179 346         695 my @final_args = $self->extract_func_args($value);
2180 346         768 my $usr_sub = $self->{opts}->{function_names}->{$is_func};
2181 346         685 $self->{struct}->{procedure} = {};
2182 346 50       664 if ($usr_sub)
2183             {
2184 346         1487 $value = {
2185             type => 'function',
2186             name => lc $name,
2187             subname => $usr_sub,
2188             value => \@final_args,
2189             fullorg => $orgstr,
2190             };
2191              
2192 346         1443 return $value;
2193             }
2194             }
2195             }
2196              
2197 1963         2456 my $type;
2198             # MATH
2199             #
2200 1963 100       4317 if ( $str =~ m/[\*\+\-\/\%]/ )
2201             {
2202 45         80 my @vals;
2203 45         84 my $i = -1;
2204 45         117 my $open_parens = $str =~ tr/\(//;
2205 45         87 my $close_parens = $str =~ tr/\)//;
2206 45 50       116 if ( $open_parens != $close_parens )
2207             {
2208 0         0 return $self->do_err("Mismatched parentheses in term '$str'!");
2209             }
2210              
2211             # $str =~ s/([^\s\*\+\-\/\%\)\(]+)/push @vals,$1;++$i;"?$i?"/ge;
2212 45         191 while ( $str =~ m/\G.*?([^\s\*\+\-\/\%\)\(]+)/g )
2213             {
2214 74         157 my $term = $1;
2215 74         129 my $start = pos($str) - length($term);
2216 74 100       150 if ( $self->is_func($term) )
2217             {
2218 5         9 my $lparens = 0;
2219 5         9 my $rparens = 0;
2220 5         20 while ( $str =~ m/\G.*?([\(\)])/gcs )
2221             {
2222 4 100       12 ++$lparens if ( '(' eq $1 );
2223 4 100       8 ++$rparens if ( ')' eq $1 );
2224 4 100       13 last if ( $lparens == $rparens );
2225             }
2226 5         9 my $now = pos($str);
2227 5         9 ++$i;
2228 5         18 $term = substr( $str, $start, $now - $start, "?$i?" );
2229 5         9 push( @vals, $term );
2230 5         25 pos($str) = $start + length("?$i?");
2231             }
2232             else
2233             {
2234 69         125 push( @vals, $term );
2235 69         97 ++$i;
2236 69         244 substr( $str, $start, length($term), "?$i?" );
2237 69         367 pos($str) = $start + length("?$i?");
2238             }
2239             }
2240              
2241 45         82 my @newvalues;
2242 45         91 foreach my $val (@vals)
2243             {
2244 74         161 my $newval = $self->ROW_VALUE($val);
2245 74 50 66     515 if ( $newval && $newval->{type} !~ m/number|column|placeholder|function/ )
2246             {
2247 0         0 return $self->do_err(qq[String '$val' not allowed in Numeric expression!]);
2248             }
2249 74         190 push( @newvalues, $newval );
2250             }
2251              
2252             return {
2253 45         287 type => 'function',
2254             name => 'numeric_exp',
2255             str => $str,
2256             value => \@newvalues,
2257             fullorg => $orgstr,
2258             };
2259             }
2260              
2261             # SUBSTRING (value FROM start [FOR length])
2262             #
2263 1918 100       3274 if ( $str =~ m/^SUBSTRING \((.+?) FROM (.+)\)\s*$/i )
2264             {
2265 5         9 my $name = 'SUBSTRING';
2266 5         11 my $start = $2;
2267 5         16 my $value = $self->ROW_VALUE($1);
2268 5         12 my $length;
2269 5 100       25 if ( $start =~ /^(.+?) FOR (.+)$/i )
2270             {
2271 4         10 $start = $1;
2272 4         10 $length = $2;
2273 4         10 $length = $self->ROW_VALUE($length);
2274             }
2275 5         15 $start = $self->ROW_VALUE($start);
2276 5         12 $str =~ s/\?(\d+)\?/$self->{struct}->{literals}->[$1]/g;
2277 5 50 33     35 if ( ( $start->{type} eq 'string' )
      33        
2278             or ( $start->{length} && ( $start->{length}->{type} eq 'string' ) ) )
2279             {
2280 0         0 return $self->do_err("Can't use a string as a SUBSTRING position: '$str'!");
2281             }
2282 5 50       12 return undef unless ($value);
2283             return $self->do_err("Can't use a number in SUBSTRING: '$str'!")
2284 5 50       16 if $value->{type} eq 'number';
2285             return {
2286 5         35 type => 'function',
2287             name => $name,
2288             value => [$value],
2289             start => $start,
2290             length => $length,
2291             fullorg => $orgstr,
2292             };
2293             }
2294              
2295             # TRIM ( [ [TRAILING|LEADING|BOTH] ['char'] FROM ] value )
2296             #
2297 1913 100       3258 if ( $str =~ m/^(TRIM) \((.+)\)\s*$/i )
2298             {
2299 11         28 my $name = uc $1;
2300 11         18 my $value = $2;
2301 11         21 my ( $trim_spec, $trim_char );
2302 11 100       36 if ( $value =~ m/^(.+) FROM ([^\(\)]+)$/i )
2303             {
2304 5         10 my $front = $1;
2305 5         8 $value = $2;
2306 5 50       22 if ( $front =~ m/^\s*(TRAILING|LEADING|BOTH)(.*)$/i )
2307             {
2308 5         11 $trim_spec = uc $1;
2309 5         10 $trim_char = $2;
2310 5         10 $trim_char =~ s/^\s+//;
2311 5         10 $trim_char =~ s/\s+$//;
2312 5 100       16 undef $trim_char if ( length($trim_char) == 0 );
2313             }
2314             else
2315             {
2316 0         0 $trim_char = $front;
2317 0         0 $trim_char =~ s/^\s+//;
2318 0         0 $trim_char =~ s/\s+$//;
2319             }
2320             }
2321              
2322 11   100     40 $trim_char ||= '';
2323 11         26 $trim_char =~ s/\?(\d+)\?/$self->{struct}->{literals}->[$1]/g;
2324 11         46 $value = $self->ROW_VALUE($value);
2325 11 50       30 return undef unless ($value);
2326 11         42 $str =~ s/\?(\d+)\?/$self->{struct}->{literals}->[$1]/g;
2327 11 50       37 my $value_type = $value->{type} if ref $value eq 'HASH';
2328 11 50       37 $value_type = $value->[0] if ( defined( _ARRAY($value) ) );
2329 11 50 33     44 return $self->do_err("Can't use a number in TRIM: '$str'!")
2330             if ( $value_type and $value_type eq 'number' );
2331              
2332             return {
2333 11         71 type => 'function',
2334             name => $name,
2335             value => [$value],
2336             trim_spec => $trim_spec,
2337             trim_char => $trim_char,
2338             fullorg => $orgstr,
2339             };
2340             }
2341              
2342             # UNKNOWN FUNCTION
2343 1902 100       3394 if ( $str =~ m/^(\S+) \(/ )
2344             {
2345 2         10 return $self->do_err("Unknown function '$1'");
2346             }
2347              
2348             # STRING CONCATENATION
2349             #
2350 1900 100       3380 if ( $str =~ m/\|\|/ )
2351             {
2352 1         6 my @vals = split( m/ \|\| /, $str );
2353 1         3 my @newvals;
2354 1         3 for my $val (@vals)
2355             {
2356 3         9 my $newval = $self->ROW_VALUE($val);
2357 3 50       10 return undef unless ($newval);
2358             return $self->do_err("Can't use a number in string concatenation: '$str'!")
2359 3 50       9 if ( $newval->{type} eq 'number' );
2360 3         7 push @newvals, $newval;
2361             }
2362             return {
2363 1         5 type => 'function',
2364             name => 'str_concat',
2365             value => \@newvals,
2366             fullorg => $orgstr,
2367             };
2368             }
2369              
2370             # NULL, BOOLEAN, PLACEHOLDER, NUMBER
2371             #
2372 1899 100       3928 if ( $type = $self->LITERAL($str) )
2373             {
2374 773 100       1464 undef $str if ( $type eq 'null' );
2375 773 100 66     1665 $str = 1 if ( $type eq 'boolean' and $str =~ /^TRUE$/i );
2376 773 50 66     1453 $str = 0 if ( $type eq 'boolean' and $str =~ /^FALSE$/i );
2377              
2378             # if ($type eq 'empty_string') {
2379             # $str = '';
2380             # $type = 'string';
2381             # }
2382 773 100 100     2480 $str = '' if ( $str and $str eq q('') );
2383             return {
2384 773         3340 type => $type,
2385             value => $str,
2386             fullorg => $orgstr,
2387             };
2388             }
2389              
2390             # QUOTED STRING LITERAL
2391             #
2392 1126 100       3375 if ( $str =~ m/\?(\d+)\?/ )
    100          
2393             {
2394             return {
2395             type => 'string',
2396             value => $self->{struct}->{literals}->[$1],
2397 429         2516 fullorg => $self->{struct}->{literals}->[$1],
2398             };
2399             }
2400             elsif ( $str =~ /^\?LI(\d+)\?$/ )
2401             {
2402 30         110 return $self->ROW_VALUE_LIST( $self->{struct}->{list_ids}->[$1] );
2403             }
2404              
2405             # COLUMN NAME
2406             #
2407 667 100       1407 return undef unless ( $str = $self->COLUMN_NAME($str) );
2408              
2409 665 100       1502 if ( $str =~ m/^(.*)\./ )
2410             {
2411 119         229 my $table_name = $1;
2412 119         227 $self->_verify_tablename( $table_name, "WHERE" );
2413             }
2414              
2415             # push @{ $self->{struct}->{where_cols}},$str
2416             # unless $self->{tmp}->{where_cols}->{"$str"};
2417 665         1569 ++$self->{tmp}->{where_cols}->{$str};
2418             return {
2419 665         3058 type => 'column',
2420             value => $str,
2421             fullorg => $orgstr,
2422             };
2423             }
2424              
2425             #########################################################
2426             # ROW_VALUE_LIST ::= [,...]
2427             #########################################################
2428             sub ROW_VALUE_LIST
2429             {
2430 56     56 0 115 my ( $self, $row_str ) = @_;
2431 56         176 my @row_list = split ',', $row_str;
2432 56 50       135 if ( !( scalar @row_list ) )
2433             {
2434 0         0 return $self->do_err('Missing row value list!');
2435             }
2436 56         105 my @newvals;
2437             my $newval;
2438 56         102 for my $row_val (@row_list)
2439             {
2440 129         269 $row_val =~ s/^\s+//;
2441 129         226 $row_val =~ s/\s+$//;
2442              
2443 129 50       257 return undef if !( $newval = $self->ROW_VALUE($row_val) );
2444 129         275 push @newvals, $newval;
2445             }
2446 56         231 return \@newvals;
2447             }
2448              
2449             ###############################################
2450             # COLUMN NAME ::= [.]
2451             ###############################################
2452              
2453             sub COLUMN_NAME
2454             {
2455 693     693 0 1154 my ( $self, $str ) = @_;
2456 693         919 my ( $table_name, $col_name );
2457 693 100       1399 if ( $str =~ m/^\s*(\S+)\.(\S+)$/s )
2458             {
2459 122         326 ( $table_name, $col_name ) = ( $1, $2 );
2460 122 50       300 if ( !$self->{opts}->{valid_options}->{SELECT_MULTIPLE_TABLES} )
2461             {
2462 0         0 return $self->do_err('Dialect does not support multiple tables!');
2463             }
2464 122 50       235 return undef unless ( $table_name = $self->TABLE_NAME($table_name) );
2465 122         300 $table_name = $self->replace_quoted_ids($table_name);
2466 122         261 $self->_verify_tablename($table_name);
2467             }
2468             else
2469             {
2470 571         770 $col_name = $str;
2471             }
2472              
2473 693         1280 $col_name =~ s/^\s+//;
2474 693         1183 $col_name =~ s/\s+$//;
2475              
2476 693         1021 my $user_func = $col_name;
2477 693         2149 $user_func =~ s/^(\S+).*$/$1/;
2478 693 50       1753 if ( $col_name !~ m/^(TRIM|SUBSTRING)$/i )
2479             {
2480 693 100       1845 undef $user_func unless ( $self->{opts}->{function_names}->{ uc $user_func } );
2481             }
2482 693 100       1140 if ( !$user_func )
2483             {
2484 690 100 66     1983 return undef unless ( ( $col_name eq '*' ) || $self->IDENTIFIER($col_name) );
2485             }
2486              
2487             #
2488             # MAKE COL NAMES ALL UPPER CASE UNLESS IS DELIMITED IDENTIFIER
2489 691         1163 my $orgcol = $col_name;
2490              
2491 691 100       1234 if ( $col_name =~ m/^\?QI(\d+)\?$/ )
2492             {
2493 10         42 $col_name = '"' . $self->{struct}->{quoted_ids}->[$1] . '"';
2494             }
2495             else
2496             {
2497             $col_name = lc $col_name
2498             unless (
2499 681 50 33     2836 ( $self->{struct}->{command} eq 'CREATE' )
2500             ##############################################
2501             #
2502             # JZ addition to RR's alias patch
2503             #
2504             or ( $col_name =~ m/^(?:\p{Word}+\.)?"/ )
2505             );
2506              
2507             }
2508              
2509             #
2510             $col_name = $self->{struct}->{column_aliases}->{$col_name}
2511 691 50       1673 if ( $self->{struct}->{column_aliases}->{$col_name} );
2512              
2513             # $orgcol = $self->replace_quoted_ids($orgcol);
2514             ##############################################
2515              
2516 691 100       1182 if ($table_name)
2517             {
2518 122         277 my $alias = $self->{tmp}->{is_table_alias}->{"\L$table_name"};
2519 122 100       218 $table_name = $alias if ( defined($alias) );
2520 122 100       256 $table_name = lc $table_name unless ( $table_name =~ m/^"/ );
2521 122 50       394 $col_name = "$table_name.$col_name" if ( -1 == index( $col_name, '.' ) );
2522             }
2523 691         1658 return $col_name;
2524             }
2525              
2526             #########################################################
2527             # COLUMN NAME_LIST ::= [,...]
2528             #########################################################
2529             sub COLUMN_NAME_LIST
2530             {
2531 0     0 0 0 my ( $self, $col_str ) = @_;
2532              
2533 0         0 my @col_list = split( ',', $col_str );
2534 0 0       0 return $self->do_err('Missing column name list!') unless ( scalar(@col_list) );
2535              
2536 0         0 my @newcols;
2537 0         0 for my $col (@col_list)
2538             {
2539 0         0 $col =~ s/^\s+//;
2540 0         0 $col =~ s/\s+$//;
2541              
2542 0         0 my $newcol;
2543 0 0       0 return undef unless ( $newcol = $self->COLUMN_NAME($col) );
2544 0         0 push( @newcols, $newcol );
2545             }
2546              
2547 0         0 return \@newcols;
2548             }
2549              
2550             #####################################################
2551             # TABLE_NAME_LIST := [,...]
2552             #####################################################
2553             sub TABLE_NAME_LIST
2554             {
2555 386     386 0 703 my ( $self, $table_name_str ) = @_;
2556 386         616 my %aliases = ();
2557 386         481 my @tables;
2558 386         648 $table_name_str =~ s/(\?\d+\?),/$1:/g; # fudge commas in functions
2559 386         1044 my @table_names = split ',', $table_name_str;
2560 386 50 66     1148 if ( scalar @table_names > 1
2561             and !$self->{opts}->{valid_options}->{SELECT_MULTIPLE_TABLES} )
2562             {
2563 0         0 return $self->do_err('Dialect does not support multiple tables!');
2564             }
2565              
2566 386         645 my $bf = BAREWORD_FUNCTIONS;
2567 386         498 my %is_table_alias;
2568 386         667 for my $table_str (@table_names)
2569             {
2570 501         780 $table_str =~ s/(\?\d+\?):/$1,/g; # unfudge commas in functions
2571 501         816 $table_str =~ s/\s+\(/\(/g; # fudge spaces in functions
2572 501         695 my ( $table, $alias );
2573 501         1142 my (@tstr) = split( m/\s+/, $table_str );
2574 501 100       1033 if ( @tstr == 1 )
    100          
    100          
2575             {
2576 475         723 $table = $tstr[0];
2577             }
2578             elsif ( @tstr == 2 )
2579             {
2580 11         22 $table = $tstr[0];
2581 11         15 $alias = $tstr[1];
2582             }
2583             elsif ( @tstr == 3 )
2584             {
2585 13 50       41 return $self->do_err("Can't find alias in FROM clause!")
2586             unless ( uc( $tstr[1] ) eq 'AS' );
2587 13         20 $table = $tstr[0];
2588 13         23 $alias = $tstr[2];
2589             }
2590             else
2591             {
2592 2         8 return $self->do_err("Can't find table names in FROM clause!");
2593             }
2594              
2595 499         790 $table =~ s/\(/ \(/g; # unfudge spaces in functions
2596 499         648 my $u_name = $table;
2597 499         1790 $u_name =~ s/^(\S+)\s*(.*$)/$1/;
2598 499         913 my $u_args = $2;
2599              
2600 499 100 66     1092 if ( ( $u_name = $self->is_func($u_name) )
      100        
2601             && ( $u_name =~ /^(?:$bf)$/i || $table =~ /^$u_name\s*\(/i ) )
2602             {
2603 2 50       7 $u_args = " $u_args" if ($u_args);
2604 2         9 my $u_func = $self->ROW_VALUE( $u_name . $u_args );
2605 2         5 $self->{struct}->{table_func}->{$u_name} = $u_func;
2606 2         6 $self->{struct}->{temp_table} = 1;
2607 2         3 $table = $u_name;
2608             }
2609             else
2610             {
2611 497 100       1053 return undef unless ( $self->TABLE_NAME($table) );
2612             }
2613              
2614 494         1226 $table = $self->replace_quoted_ids($table);
2615 494 100       1283 push( @tables, $table =~ m/^"/ ? $table : $table );
2616              
2617 494 100       1324 if ($alias)
2618             {
2619 24 50       47 return unless ( $self->TABLE_NAME($alias) );
2620 24         56 $alias = $self->replace_quoted_ids($alias);
2621 24 50       53 if ( $alias =~ m/^"/ )
2622             {
2623 0         0 push( @{ $aliases{$table} }, $alias );
  0         0  
2624 0         0 $is_table_alias{$alias} = $table;
2625             }
2626             else
2627             {
2628 24         36 push( @{ $aliases{$table} }, "\L$alias" );
  24         74  
2629 24         88 $is_table_alias{"\L$alias"} = $table;
2630             }
2631             }
2632             }
2633 379         669 my %is_table_name = map { $_ => 1 } @tables;
  492         1626  
2634 379         941 $self->{tmp}->{is_table_alias} = \%is_table_alias;
2635 379         686 $self->{tmp}->{is_table_name} = \%is_table_name;
2636 379         702 $self->{struct}->{table_names} = \@tables;
2637 379         606 $self->{struct}->{table_alias} = \%aliases;
2638 379 100       880 $self->{struct}->{multiple_tables} = 1 if ( @tables > 1 );
2639 379         1343 return 1;
2640             }
2641              
2642             sub is_func($)
2643             {
2644 3228     3228 1 5050 my ( $self, $name ) = @_;
2645 3228         9737 $name =~ s/^(\S+).*$/$1/;
2646 3228 100       10879 return $name if ( $self->{opts}->{function_names}->{$name} );
2647 2548 100       6017 return uc $name if ( $self->{opts}->{function_names}->{ uc $name } );
2648 2516         6221 undef;
2649             }
2650              
2651             #############################
2652             # TABLE_NAME :=
2653             #############################
2654             sub TABLE_NAME
2655             {
2656 917     917 0 1659 my ( $self, $table_name ) = @_;
2657 917 50       1868 if ( $table_name =~ m/^(.+?)\.([^\.]+)$/ )
2658             {
2659 0         0 my $schema = $1; # ignored
2660 0         0 $table_name = $2;
2661             }
2662 917 50       3372 if ( $table_name =~ m/\s*(\S+)\s+\S+/s )
2663             {
2664 0         0 return $self->do_err("Junk after table name '$1'!");
2665             }
2666 917         1483 $table_name =~ s/\s+//s;
2667 917 50       1592 if ( !$table_name )
2668             {
2669 0         0 return $self->do_err('No table name specified!');
2670             }
2671 917 100       1909 return $table_name if ( $self->IDENTIFIER($table_name) );
2672              
2673             # return undef if !($self->IDENTIFIER($table_name));
2674             # return 1;
2675             }
2676              
2677             sub _verify_tablename
2678             {
2679 244     244   446 my ( $self, $table_name, $location ) = @_;
2680 244 100       415 if ( defined($location) )
2681             {
2682 122         259 $location = " in $location";
2683             }
2684             else
2685             {
2686 122         188 $location = "";
2687             }
2688              
2689 244 100       432 if ( $table_name =~ m/^"/ )
2690             {
2691 4 0 33     16 if ( !$self->{tmp}->{is_table_name}->{$table_name}
2692             and !$self->{tmp}->{is_table_alias}->{$table_name} )
2693             {
2694 0         0 return $self->do_err("Table '$table_name' referenced$location but not found in FROM list!");
2695             }
2696             }
2697             else
2698             {
2699 240         297 my @tblnamelist = ( keys( %{ $self->{tmp}->{is_table_name} } ), keys( %{ $self->{tmp}->{is_table_alias} } ) );
  240         633  
  240         491  
2700 240         509 my $tblnames = join( "|", @tblnamelist );
2701 240 50       2087 unless ( $table_name =~ m/^(?:$tblnames)$/i )
2702             {
2703 0         0 return $self->do_err(
2704             "Table '$table_name' referenced$location but not found in FROM list (" . join( ",", @tblnamelist ) . ")!" );
2705             }
2706             }
2707              
2708 244         438 return 1;
2709             }
2710              
2711             ###################################################################
2712             # IDENTIFIER ::= { | _ }...
2713             #
2714             # and must not be a reserved word or over 128 chars in length
2715             ###################################################################
2716             sub IDENTIFIER
2717             {
2718 1740     1740 0 2811 my ( $self, $id ) = @_;
2719 1740 100 66     6098 if ( $id =~ m/^\?QI(.+)\?$/ or $id =~ m/^\?(.+)\?$/ )
2720             {
2721 31         125 return 1;
2722             }
2723 1709 100       3041 if ( $id =~ m/^[`](.+)[`]$/ )
2724             {
2725 21 50       115 $id = $1 and return 1;
2726             }
2727 1688 50       2966 if ( $id =~ m/^(.+)\.([^\.]+)$/ )
2728             {
2729 0         0 my $schema = $1; # ignored
2730 0         0 $id = $2;
2731             }
2732 1688         3813 $id =~ s/\(|\)//g;
2733 1688 50       2986 return 1 if $id =~ m/^".+?"$/s; # QUOTED IDENTIFIER
2734 1688         3159 my $err = "Bad table or column name: '$id' "; # BAD CHARS
2735 1688 100       3566 if ( $id =~ /\W/ )
2736             {
2737 4         12 $err .= "has chars not alphanumeric or underscore!";
2738 4         14 return $self->do_err($err);
2739             }
2740             # CSV requires optional start with _
2741 1684 50       6273 my $badStartRx = uc( $self->{dialect} ) eq 'ANYDATA' ? qr/^\d/ : qr/^[_\d]/;
2742 1684 50       6500 if ( $id =~ $badStartRx )
2743             { # BAD START
2744 0         0 $err .= "starts with non-alphabetic character!";
2745 0         0 return $self->do_err($err);
2746             }
2747 1684 50       3268 if ( length $id > 128 )
2748             { # BAD LENGTH
2749 0         0 $err .= "contains more than 128 characters!";
2750 0         0 return $self->do_err($err);
2751             }
2752 1684         2455 $id = uc $id;
2753 1684 100       3604 if ( $self->{opts}->{reserved_words}->{$id} )
2754             { # BAD RESERVED WORDS
2755 3         9 $err .= "is a SQL reserved word!";
2756 3         12 return $self->do_err($err);
2757             }
2758 1681         6339 return 1;
2759             }
2760              
2761             ########################################
2762             # PRIVATE METHODS AND UTILITY FUNCTIONS
2763             ########################################
2764             sub order_joins
2765             {
2766 39     39 1 94 my ( $self, $links ) = @_;
2767 39         83 for my $link (@$links)
2768             {
2769 115 100       236 if ( $link !~ /\./ )
2770             {
2771 19         53 return [];
2772             }
2773             }
2774 20         53 @$links = map { s/^(.+)\..*$/$1/; $1; } @$links;
  96         284  
  96         217  
2775 20         67 my @all_tables;
2776             my %relations;
2777 20         0 my %is_table;
2778 20         51 while (@$links)
2779             {
2780 48         82 my $t1 = shift @$links;
2781 48         72 my $t2 = shift @$links;
2782 48 50 33     165 return undef unless defined $t1 and defined $t2;
2783 48 100       133 push @all_tables, $t1 unless $is_table{$t1}++;
2784 48 100       108 push @all_tables, $t2 unless $is_table{$t2}++;
2785 48         111 $relations{$t1}{$t2}++;
2786 48         113 $relations{$t2}{$t1}++;
2787             }
2788 20         48 my @tables = @all_tables;
2789 20         47 my @order = shift @tables;
2790 20         53 my %is_ordered = ( $order[0] => 1 );
2791 20         27 my %visited;
2792 20         45 while (@tables)
2793             {
2794 32         81 my $t = shift @tables;
2795 32         50 my @rels = keys %{ $relations{$t} };
  32         91  
2796 32         63 for my $t2 (@rels)
2797             {
2798 36 100       80 next unless $is_ordered{$t2};
2799 32         57 push @order, $t;
2800 32         52 $is_ordered{$t}++;
2801 32         42 last;
2802             }
2803 32 50       106 if ( !$is_ordered{$t} )
2804             {
2805 0 0       0 push @tables, $t if $visited{$t}++ < @all_tables;
2806             }
2807             }
2808 20 50       57 return $self->do_err("Unconnected tables in equijoin statement!")
2809             if @order < @all_tables;
2810 20         123 return \@order;
2811             }
2812              
2813             # PROVIDE BACKWARD COMPATIBILIT FOR JOCHEN'S FEATURE ATTRIBUTES TO NEW
2814             #
2815             #
2816             sub set_feature_flags
2817             {
2818 17     17 1 103 my ( $self, $select, $create ) = @_;
2819 17 50       72 if ( defined $select )
2820             {
2821 0         0 delete $self->{select};
2822             $self->{opts}->{valid_options}->{SELECT_MULTIPLE_TABLES} =
2823 0         0 $self->{opts}->{select}->{join} = $select->{join};
2824             }
2825 17 50       76 if ( defined $create )
2826             {
2827 0         0 delete $self->{create};
2828 0         0 for my $key ( keys %$create )
2829             {
2830 0         0 my $type = $key;
2831 0         0 $type =~ s/type_(.*)/\U$1/;
2832             $self->{opts}->{valid_data_types}->{$type} = $self->{opts}->{create}->{$key} =
2833 0         0 $create->{$key};
2834             }
2835             }
2836             }
2837              
2838             sub clean_sql
2839             {
2840 872     872 1 1597 my ( $self, $sql ) = @_;
2841 872         1117 my $fields;
2842 872         1230 my $i = -1;
2843 872         1264 my $e = '\\';
2844 872         1459 $e = quotemeta($e);
2845              
2846             #
2847             # patch from cpan@goess.org, adds support for col2=''
2848             #
2849             # $sql =~ s~'(([^'$e]|$e.|'')+)'~push(@$fields,$1);$i++;"?$i?"~ge;
2850 872         4384 $sql =~ s~(?
  442         1396  
  442         647  
  442         2087  
2851              
2852             #
2853 872         2033 foreach (@$fields) { $_ =~ s/''/\\'/g; }
  442         818  
2854 872         1959 my @a = $sql =~ m/((?
2855 872 50       2253 if ( ( scalar(@a) % 2 ) == 1 )
2856             {
2857 0         0 $sql =~ s/^.*\?(.+)$/$1/;
2858 0         0 $self->do_err("Mismatched single quote before: <$sql>");
2859             }
2860 872 50       1965 if ( $sql =~ m/\?\?(\d)\?/ )
2861             {
2862 0         0 $sql = $fields->[$1];
2863 0         0 $self->do_err("Mismatched single quote: <$sql>");
2864             }
2865 872         1503 foreach (@$fields) { $_ =~ s/$e'/'/g; s/^'(.*)'$/$1/; }
  442         1050  
  442         882  
2866              
2867             #
2868             # From Steffen G. to correctly return newlines from $dbh->quote;
2869             #
2870 872         1279 foreach (@$fields) { $_ =~ s/([^\\])\\r/$1\r/g; }
  442         686  
2871 872         1357 foreach (@$fields) { $_ =~ s/([^\\])\\n/$1\n/g; }
  442         697  
2872              
2873 872         1560 $self->{struct}->{literals} = $fields;
2874              
2875 872         1250 my $qids;
2876 872         1192 $i = -1;
2877 872         1242 $e = q/""/;
2878              
2879             # $sql =~ s~"(([^"$e]|$e.)+)"~push(@$qids,$1);$i++;"?QI$i?"~ge;
2880 872         1796 $sql =~ s/"(([^"]|"")+)"/push(@$qids,$1);$i++;"?QI$i?"/ge;
  62         174  
  62         120  
  62         244  
2881              
2882             #@$qids = map { s/$e'/'/g; s/^'(.*)'$/$1/; $_} @$qids;
2883 872 100       1644 $self->{struct}->{quoted_ids} = $qids if ($qids);
2884              
2885             # $sql =~ s~'(([^'\\]|\\.)+)'~push(@$fields,$1);$i++;"?$i?"~ge;
2886             # @$fields = map { s/\\'/'/g; s/^'(.*)'$/$1/; $_} @$fields;
2887             #print "$sql [@$fields]\n";# if $sql =~ /SELECT/;
2888              
2889             ## before line 1511
2890 872         1368 my $comment_re = $self->{comment_re};
2891              
2892             # if ( $sql =~ s/($comment_re)//gs) {
2893             # $self->{comment} = $1;
2894             # }
2895 872 50       2687 if ( $sql =~ m/(.*)$comment_re$/s )
2896             {
2897 0         0 $sql = $1;
2898 0         0 $self->{comment} = $2;
2899             }
2900 872 100       1828 if ( $sql =~ m/^(.*)--(.*)(\n|$)/ )
2901             {
2902 2         7 $sql = $1;
2903 2         6 $self->{comment} = $2;
2904             }
2905              
2906 872         1365 $sql =~ s/\n/ /g;
2907 872         5170 $sql =~ s/\s+/ /g;
2908 872         3568 $sql =~ s/(\S)\(/$1 (/g; # ensure whitespace before (
2909 872         1725 $sql =~ s/\)(\S)/) $1/g; # ensure whitespace after )
2910 872         2571 $sql =~ s/\(\s*/(/g; # trim whitespace after (
2911 872         3481 $sql =~ s/\s*\)/)/g; # trim whitespace before )
2912             #
2913             # $sql =~ s/\s*\(/(/g; # trim whitespace before (
2914             # $sql =~ s/\)\s*/)/g; # trim whitespace after )
2915             # for my $op (qw(= <> < > <= >= \|\|))
2916             # {
2917             # $sql =~ s/(\S)$op/$1 $op/g;
2918             # $sql =~ s/$op(\S)/$op $1/g;
2919             # }
2920 872         7521 $sql =~ s/(\S)([<>]?=|<>|<|>|\|\|)/$1 $2/g;
2921 872         6025 $sql =~ s/([<>]?=|<>|<|>|\|\|)(\S)/$1 $2/g;
2922 872         1400 $sql =~ s/< >/<>/g;
2923 872         1265 $sql =~ s/< =/<=/g;
2924 872         1257 $sql =~ s/> =/>=/g;
2925 872         2532 $sql =~ s/\s*,/,/g;
2926 872         2628 $sql =~ s/,\s*/,/g;
2927 872         1551 $sql =~ s/^\s+//;
2928 872         2208 $sql =~ s/\s+$//;
2929              
2930 872         2581 return $sql;
2931             }
2932              
2933             sub trim
2934             {
2935 4 50   4 1 11 my $str = $_[0] or return ('');
2936 4         5 $str =~ s/^\s+//;
2937 4         9 $str =~ s/\s+$//;
2938 4         7 return $str;
2939             }
2940              
2941             sub do_err
2942             {
2943 19     19 1 51 my ( $self, $err, $errstr ) = @_;
2944              
2945             # $err = $errtype ? "DIALECT ERROR: $err" : "SQL ERROR: $err";
2946 19         46 $self->{struct}->{errstr} = $err;
2947              
2948 19 50       50 carp $err if ( $self->{PrintError} );
2949 19 100       800 croak $err if ( $self->{RaiseError} );
2950 13         66 return;
2951             }
2952              
2953             #
2954             # DAA
2955             # abstract method so subclasses can provide
2956             # their own syntax transformations
2957             #
2958             sub transform_syntax
2959             {
2960 231     231 1 397 my ( $self, $str ) = @_;
2961 231         360 return $str;
2962             }
2963              
2964             sub DESTROY
2965             {
2966 12     12   5452 my $self = $_[0];
2967              
2968 12         383 undef $self->{opts};
2969 12         76 undef $self->{struct};
2970 12         40 undef $self->{tmp};
2971 12         30 undef $self->{dialect};
2972 12         412 undef $self->{dialect_set};
2973             }
2974              
2975             1;
2976              
2977             __END__