File Coverage

blib/lib/DBIx/MyParsePP/Lexer.pm
Criterion Covered Total %
statement 437 639 68.3
branch 138 286 48.2
condition 51 147 34.6
subroutine 81 88 92.0
pod 0 28 0.0
total 707 1188 59.5


line stmt bran cond sub pod time code
1             # This program is free software; you can redistribute it and/or modify
2             # it under the terms of the GNU General Public License as published by
3             # the Free Software Foundation; version 2 of the License.
4              
5             # This program is distributed in the hope that it will be useful,
6             # but WITHOUT ANY WARRANTY; without even the implied warranty of
7             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8             # GNU General Public License for more details.
9             #
10             # You should have received a copy of the GNU General Public License
11             # along with this program; if not, write to the Free Software
12             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13              
14             # Based on code Copyright (C) 2000-2006 MySQL AB
15              
16             package DBIx::MyParsePP::Lexer;
17             require Exporter;
18             @ISA = qw(Exporter);
19             @EXPORT = qw(MODE_PIPES_AS_CONCAT MODE_ANSI_QUOTES MODE_IGNORE_SPACE MODE_NO_BACKSLASH_ESCAPES
20             CLIENT_MULTI_STATEMENTS MODE_HIGH_NOT_PRECEDENCE);
21              
22 13     13   83 use strict;
  13         20  
  13         339  
23              
24 9     9   13398 use DBIx::MyParsePP::Symbols;
  9         33  
  9         398  
25 8     8   3670 use DBIx::MyParsePP::Charsets;
  8         23  
  8         220  
26 8     8   2397 use DBIx::MyParsePP::Token;
  8         14  
  8         183  
27              
28 8     8   54 use constant CTYPE_U => 01; # Uppercase
  8         10  
  8         355  
29 8     8   33 use constant CTYPE_L => 02; # Lowercase
  8         11  
  8         283  
30 8     8   32 use constant CTYPE_NMR => 04; # Numeral (digit)
  8         13  
  8         251  
31 8     8   32 use constant CTYPE_SPC => 010; # Spacing character
  8         10  
  8         232  
32 8     8   28 use constant CTYPE_PNT => 020; # Punctuation
  8         14  
  8         232  
33 8     8   31 use constant CTYPE_CTR => 040; # Control character
  8         10  
  8         240  
34 8     8   30 use constant CTYPE_B => 0100; # Blank
  8         10  
  8         237  
35 8     8   29 use constant CTYPE_X => 0200; # heXadecimal digit
  8         11  
  8         229  
36              
37 8     8   29 use constant LEXER_STRING => 0;
  8         12  
  8         300  
38 8     8   40 use constant LEXER_CHARSET => 1;
  8         114  
  8         271  
39 8     8   49 use constant LEXER_VERSION => 2;
  8         12  
  8         238  
40 8     8   31 use constant LEXER_SQL_MODE => 3;
  8         11  
  8         338  
41 8     8   47 use constant LEXER_OPTIONS => 4;
  8         13  
  8         293  
42 8     8   36 use constant LEXER_CLIENT_CAPABILITIES => 5;
  8         9  
  8         270  
43 8     8   39 use constant LEXER_STMT_PREPARE_MODE => 6;
  8         12  
  8         302  
44              
45 8     8   38 use constant LEXER_PTR => 7;
  8         22  
  8         298  
46 8     8   34 use constant LEXER_TOK_START => 8;
  8         10  
  8         246  
47              
48 8     8   32 use constant LEXER_TOKENS => 9;
  8         10  
  8         292  
49              
50 8     8   50 use constant LEXER_YYLINENO => 10;
  8         12  
  8         332  
51 8     8   38 use constant LEXER_NEXT_STATE => 11;
  8         13  
  8         1403  
52 8     8   42 use constant LEXER_IN_COMMENT => 12;
  8         12  
  8         299  
53 8     8   36 use constant LEXER_FOUND_SEMICOLON => 13;
  8         13  
  8         287  
54 8     8   39 use constant LEXER_SAFE_TO_CACHE_QUERY => 14;
  8         12  
  8         959  
55 8     8   60 use constant LEXER_SERVER_STATUS => 15;
  8         15  
  8         338  
56 8     8   40 use constant LEXER_CTYPE => 16;
  8         12  
  8         303  
57              
58              
59 8     8   47 use constant OPTION_FOUND_COMMENT => 1 << 15;
  8         13  
  8         329  
60 8     8   39 use constant CLIENT_MULTI_STATEMENTS => 1 << 16;
  8         14  
  8         271  
61 8     8   33 use constant SERVER_MORE_RESULTS_EXISTS => 8;
  8         13  
  8         320  
62 8     8   39 use constant NAMES_SEP_CHAR => '\377';
  8         9  
  8         292  
63              
64              
65 8     8   35 use constant MODE_PIPES_AS_CONCAT => 2; # USE ME!
  8         10  
  8         310  
66 8     8   40 use constant MODE_ANSI_QUOTES => 4;
  8         12  
  8         307  
67 8     8   35 use constant MODE_IGNORE_SPACE => 8;
  8         11  
  8         305  
68 8     8   36 use constant MODE_MYSQL323 => 65536;
  8         11  
  8         351  
69 8     8   39 use constant MODE_MYSQL40 => MODE_MYSQL323 * 2;
  8         12  
  8         316  
70 8     8   38 use constant MODE_ANSI => MODE_MYSQL40 * 2;
  8         11  
  8         407  
71 8     8   41 use constant MODE_NO_AUTO_VALUE_ON_ZERO => MODE_ANSI * 2;
  8         14  
  8         339  
72 8     8   41 use constant MODE_NO_BACKSLASH_ESCAPES => MODE_NO_AUTO_VALUE_ON_ZERO * 2;
  8         12  
  8         305  
73 8     8   38 use constant MODE_STRICT_TRANS_TABLES => MODE_NO_BACKSLASH_ESCAPES * 2;
  8         9  
  8         366  
74 8     8   40 use constant MODE_STRICT_ALL_TABLES => MODE_STRICT_TRANS_TABLES * 2;
  8         14  
  8         299  
75 8     8   36 use constant MODE_NO_ZERO_IN_DATE => MODE_STRICT_ALL_TABLES * 2;
  8         12  
  8         387  
76 8     8   38 use constant MODE_NO_ZERO_DATE => MODE_NO_ZERO_IN_DATE * 2;
  8         16  
  8         345  
77 8     8   36 use constant MODE_INVALID_DATES => MODE_NO_ZERO_DATE * 2;
  8         15  
  8         323  
78 8     8   34 use constant MODE_ERROR_FOR_DIVISION_BY_ZERO => MODE_INVALID_DATES * 2;
  8         14  
  8         329  
79 8     8   38 use constant MODE_TRADITIONAL => MODE_ERROR_FOR_DIVISION_BY_ZERO * 2;
  8         14  
  8         324  
80 8     8   46 use constant MODE_NO_AUTO_CREATE_USER => MODE_TRADITIONAL * 2;
  8         13  
  8         346  
81 8     8   39 use constant MODE_HIGH_NOT_PRECEDENCE => MODE_NO_AUTO_CREATE_USER * 2;
  8         11  
  8         33232  
82              
83             my %state_maps;
84             my %ident_maps;
85              
86             my %args = (
87             string => LEXER_STRING,
88             charset => LEXER_CHARSET,
89             client_capabilities => LEXER_CLIENT_CAPABILITIES,
90             stmt_prepare_mode => LEXER_STMT_PREPARE_MODE,
91             sql_mode => LEXER_SQL_MODE,
92             version => LEXER_VERSION
93             );
94              
95             1;
96              
97             sub new {
98 14     14 0 37 my $class = shift;
99 14         41 my $lexer = bless([], $class);
100              
101 14         66 my $max_arg = (scalar(@_) / 2) - 1;
102              
103 14         51 foreach my $i (0..$max_arg) {
104 84 50       210 if (exists $args{$_[$i * 2]}) {
105 84         266 $lexer->[$args{$_[$i * 2]}] = $_[$i * 2 + 1];
106             } else {
107 0         0 warn("Unkown argument '$_[$i * 2]' to DBIx::MyParsePP::Lexer->new()");
108             }
109             }
110              
111 14         67 $lexer->[LEXER_STRING] = $lexer->[LEXER_STRING]."\0";
112 14         43 $lexer->[LEXER_YYLINENO] = 1;
113 14         36 $lexer->[LEXER_TOK_START] = 0;
114 14         28 $lexer->[LEXER_PTR] = 0;
115 14         33 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
116              
117 14 50       61 $lexer->[LEXER_CLIENT_CAPABILITIES] = CLIENT_MULTI_STATEMENTS if not defined $lexer->[LEXER_CLIENT_CAPABILITIES];
118 14 50       56 $lexer->[LEXER_STMT_PREPARE_MODE] = 0 if not defined $lexer->[LEXER_STMT_PREPARE_MODE];
119 14 100       53 $lexer->[LEXER_SQL_MODE] = 0 if not defined $lexer->[LEXER_SQL_MODE]; # CHECKME
120              
121 14 100       48 $lexer->[LEXER_VERSION] = '50045' if not defined $lexer->[LEXER_VERSION];
122 14 50       47 $lexer->[LEXER_CHARSET] = 'ascii' if not defined $lexer->[LEXER_CHARSET]; # FIXME
123              
124 14         49 my $charset_uc = ucfirst($lexer->[LEXER_CHARSET]);
125 8     8   4595 eval('
  8         29  
  8         262  
  14         1133  
126             use DBIx::MyParsePP::'.$charset_uc.';
127             $lexer->[LEXER_CTYPE] = $DBIx::MyParsePP::'.$charset_uc.'::ctype;
128             ');
129              
130 14 50       75 if ($@) {
131 0         0 print STDERR "DBIx::MyParsePP::Lexer->new() failed: $@\n";
132 0         0 return undef;
133             }
134              
135 14         37 $lexer->[LEXER_TOKENS] = [];
136              
137 14         71 $lexer->init_state_maps($lexer->[LEXER_CHARSET]);
138              
139 14         47 return $lexer;
140            
141             }
142              
143             sub getLine {
144 1     1 0 3 return $_[0]->[LEXER_YYLINENO];
145             }
146              
147             sub line {
148 0     0 0 0 return $_[0]->[LEXER_YYLINENO];
149             }
150              
151             sub pos {
152 0     0 0 0 return $_[0]->[LEXER_PTR];
153             }
154              
155             sub getPos {
156 1     1 0 4 return $_[0]->[LEXER_PTR];
157             }
158              
159             sub getTokens {
160 1     1 0 3 return $_[0]->[LEXER_TOKENS];
161             }
162              
163             sub tokens {
164 0     0 0 0 return $_[0]->[LEXER_TOKENS];
165             }
166              
167 4359     4359 0 8915 sub yyGet { return ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR]++, 1)) };
168 19     19 0 33 sub yyGetLast { ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR] - 1, 1)) };
169 388     388 0 1046 sub yyPeek { ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR], 1)) };
170 0     0 0 0 sub yyPeek2 { ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR] + 1, 1)) };
171 554     554 0 659 sub yyUnget { $_[0]->[LEXER_PTR]-- };
172 109     109 0 161 sub yySkip { $_[0]->[LEXER_PTR]++ };
173 135     135 0 267 sub yyLength { ($_[0]->[LEXER_PTR] - $_[0]->[LEXER_TOK_START]) - 1 };
174              
175             sub yylex {
176 781     781 0 952 my $lexer = shift;
177 781         1083 my @res = $lexer->MYSQLlex();
178 781 100 66     1733 if (($res[0] eq '0') && ($res[1] eq '0')) {
179 12         44 return (undef, ''); # EOF
180             } else {
181 769         1738 my $token = DBIx::MyParsePP::Token->new(@res);
182 769         901 push @{$lexer->[LEXER_TOKENS]}, $token;
  769         1294  
183 769         2087 return ($res[0], $token);
184             }
185             }
186              
187             sub MYSQLlex {
188 781     781 0 878 my $lexer = shift;
189              
190 781         968 my $string = $lexer->[LEXER_STRING];
191 781         1070 my $state_map = $state_maps{$lexer->[LEXER_CHARSET]};
192 781         937 my $ident_map = $ident_maps{$lexer->[LEXER_CHARSET]};
193            
194 781         882 my $c = 0;
195 781         1248 my @token;
196             my $result_state;
197 781         0 my $state;
198              
199 781         976 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
200              
201              
202 781         922 $state = $lexer->[LEXER_NEXT_STATE];
203 781         1066 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_OPERATOR_OR_IDENT';
204              
205 781         1097 my $char = substr($string, $lexer->[LEXER_PTR], 1);
206              
207 781         841 for (;;) {
208 834 100 100     2187 if (
209             ($state eq 'MY_LEX_OPERATOR_OR_IDENT') ||
210             ($state eq 'MY_LEX_START')
211             ) {
212 576         886 for ($c = $lexer->yyGet(); $state_map->[$c] eq 'MY_LEX_SKIP'; $c = $lexer->yyGet()) {
213 941 100       1669 $lexer->[LEXER_YYLINENO]++ if $c == ord("\n");
214             }
215 576         735 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR] - 1;
216 576         749 $state = $state_map->[$c];
217             }
218            
219 834 50       1243 if ($state eq 'MY_LEX_ESCAPE') {
220 0 0       0 return ("NULL_SYM","NULL") if $lexer->yyGet() == ord('N');
221             }
222            
223 834 100 66     3343 if (
    100 66        
    50          
    100          
224             ($state eq 'MY_LEX_ESCAPE') ||
225             ($state eq 'MY_LEX_CHAR') ||
226             ($state eq 'MY_LEX_SKIP')
227             ) {
228 112 0 66     256 if (
      0        
      33        
229             ($c == ord('-')) &&
230             ($lexer->yyPeek() == ord('-')) &&
231             (
232             ($lexer->my_isspace($lexer->yyPeek2())) ||
233             ($lexer->my_iscntrl($lexer->yyPeek2()))
234             )
235             ) {
236 0         0 $state = 'MY_LEX_COMMENT';
237 0         0 next;
238             }
239 112         145 $lexer->[LEXER_PTR] = $lexer->[LEXER_TOK_START];
240 112         158 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
241 112         162 $c = $lexer->yyGet();
242            
243 112 100       215 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START' if $c != ord (')');
244              
245 112 100 33     279 if ($c == ord(',')) {
    50          
246 40         61 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
247             } elsif (($c == ord('?')) && (!$ident_map->[$lexer->yyPeek()])) { # CHANGED
248 0         0 return ("PARAM_MARKER","?");
249             }
250 112         348 return (chr($c), $lex_str);
251             } elsif ($state eq 'MY_LEX_IDENT_OR_NCHAR') {
252 4 50       8 if ($lexer->yyPeek() != ord("'")) {
253 4         6 $state = 'MY_LEX_IDENT';
254 4         16 next;
255             }
256 0         0 $lexer->[LEXER_TOK_START]++;
257 0         0 $lexer->yySkip();
258 0         0 my $lex_str;
259 0 0       0 if (!defined ($lex_str = $lexer->get_text())) {
260 0         0 $state = 'MY_LEX_CHAR';
261 0         0 next;
262             }
263 0         0 return ('NCHAR_STRING',$lex_str);
264             } elsif ($state eq 'MY_LEX_IDENT_OR_HEX') {
265 0 0       0 if ($lexer->yyPeek() == ord("'")) {
266 0         0 $state = 'MY_LEX_BIN_NUMBER';
267 0         0 next;
268             }
269             } elsif ($state eq 'MY_LEX_IDENT_OR_BIN') {
270 7 50       23 if ($lexer->yyPeek() == ord("'")) {
271 0         0 $state = 'MY_LEX_BIN_NUMBER';
272 0         0 next;
273             }
274             }
275              
276 718 100 66     2508 if (
    100 100        
    100          
277             ($state eq 'MY_LEX_IDENT_OR_HEX') ||
278             ($state eq 'MY_LEX_IDENT_OR_BIN') ||
279             ($state eq 'MY_LEX_IDENT')
280             ) {
281 329         361 my $start;
282             ## FIXME - multibyte
283              
284 329         586 for ($result_state = $c; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
285            
286 329 50       594 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
287              
288 329         451 my $length = $lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START] - 1;
289 329         376 $start = $lexer->[LEXER_PTR];
290              
291 329 50       534 if ($lexer->[LEXER_SQL_MODE] & MODE_IGNORE_SPACE) {
292 0         0 for(; $state_map->[$c] eq 'MY_LEX_SKIP'; $c = $lexer->yyGet()) {};
293             }
294              
295 329 100 66     1064 if (
      100        
296             ($start == $lexer->[LEXER_PTR]) &&
297             ($c == ord('.')) &&
298             ($ident_map->[$lexer->yyPeek()])
299             ) {
300 103         141 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP';
301             } else {
302 226         475 $lexer->yyUnget();
303 226 100       381 if (@token = $lexer->find_keyword($length, $c == ord('('))) {
304 157         230 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
305 157         404 return @token;
306             }
307 69         139 $lexer->yySkip();
308             }
309 172         319 my $lex_str = $lexer->get_token($length);
310              
311 172 50 33     377 if (
312             (substr($lex_str,0,1) eq '_') &&
313             (exists $DBIx::MyParsePP::Charsets::charsets->{substr($lex_str,1)})
314             ) {
315 0         0 return ('UNDERSCORE_CHARSET', substr($lex_str,1));
316             }
317              
318 172         405 return($result_state, $lex_str);
319             } elsif ($state eq 'MY_LEX_IDENT_SEP') {
320 107         167 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
321 107         168 $c = $lexer->yyGet();
322 107         139 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_START';
323 107 100       193 if (!$ident_map->[$lexer->yyPeek()]) {
324 2         3 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
325             }
326 107         359 return (chr($c), $lex_str);
327             } elsif ($state eq 'MY_LEX_NUMBER_IDENT') {
328 27         48 while ($lexer->my_isdigit($c = $lexer->yyGet())) {} ;
329 27 50       57 if (!$ident_map->[$c]) {
330 27         37 $state = 'MY_LEX_INT_OR_REAL';
331 27         35 next;
332             }
333 0 0 0     0 if (($c == ord('e')) || ($c == ord('E'))) {
    0 0        
    0 0        
      0        
      0        
334 0 0 0     0 if (
      0        
335             ($lexer->my_isdigit($lexer->yyPeek())) ||
336             ($c = $lexer->yyGet() == ord('+')) ||
337             ($c == ord('-'))
338             ) {
339 0 0       0 if ($lexer->my_isdigit($lexer->yyPeek())) {
340 0         0 $lexer->yySkip();
341 0         0 while ($lexer->my_isdigit($lexer->yyGet())) {};
342 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
343 0         0 return ('FLOAT_NUM', $lex_str);
344             }
345             }
346 0         0 $lexer->yyUnget();
347             } elsif (
348             ($c == ord('x')) &&
349             ($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START] == 2) &&
350             (substr($string, $lexer->[LEXER_TOK_START], 1) eq '0')
351             ) {
352 0         0 while($lexer->my_isxdigit($c = $lexer->yyGet())) {};
353 0 0 0     0 if (($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START]) >= 4 && (!$ident_map->[$c])) {
354 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
355 0         0 $lex_str = substr($lex_str, 2);
356 0         0 return ('HEX_NUM', $lex_str);
357             }
358 0         0 $lexer->yyUnget();
359             } elsif (
360             ($c == ord('b')) &&
361             ($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START] == 2) &&
362             (substr($string, $lexer->[LEXER_TOK_START], 1) eq '0')
363             ) {
364 0         0 while($lexer->my_isxdigit($c = $lexer->yyGet())) {};
365 0 0 0     0 if (($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START]) >= 4 && (!$ident_map->[$c])) {
366 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
367 0         0 $lex_str = substr($lex_str, 2);
368 0         0 return ('BIN_NUM', $lex_str);
369             }
370 0         0 $lexer->yyUnget();
371             }
372             }
373              
374 255 100       594 if ($state eq 'MY_LEX_IDENT_START') {
    100          
    100          
375 105         118 $result_state = 'IDENT';
376             # FIXME multibyte
377 105         200 for ($result_state = 0; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
378 105 50       195 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
379              
380 105 100 100     207 if (($c == ord('.')) && ($ident_map->[$lexer->yyPeek()])) {
381 2         4 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP';
382             }
383              
384 105         167 my $lex_str = $lexer->get_token($lexer->yyLength());
385 105         235 return($result_state, $lex_str);
386             } elsif ($state eq 'MY_LEX_USER_VARIABLE_DELIMITER') {
387 3         5 my $double_quotes = 0;
388 3         3 my $quote_char = $c;
389 3         5 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
390 3         5 while ($c = $lexer->yyGet()) {
391 20         28 my $var_length = $lexer->my_mbcharlen($c);
392 20 50       27 if ($var_length == 1) {
393 20 50       30 last if $c == ord(NAMES_SEP_CHAR);
394 20 100       30 if ($c == $quote_char) {
395 3 50       4 last if $lexer->yyPeek() != $quote_char;
396 0         0 $c = $lexer->yyGet();
397 0         0 $double_quotes++;
398 0         0 next;
399             }
400             }
401             }
402             # MULTIBYTE!!
403              
404 3         5 my $lex_str;
405            
406 3 50       5 if ($double_quotes) {
407 0         0 $lex_str = $lexer->get_quoted_token($lexer->yyLength() - $double_quotes, $quote_char);
408             } else {
409 3         6 $lex_str = $lexer->get_token($lexer->yyLength());
410             }
411            
412 3 50       11 $lexer->yySkip() if $c == $quote_char;
413 3         4 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
414 3         7 return ('IDENT_QUOTED', $lex_str);
415             } elsif ($state eq 'MY_LEX_INT_OR_REAL') {
416 27 50       55 if ($c != ord ('.')) {
417 27         45 my $lex_str = $lexer->get_token($lexer->yyLength());
418 27         68 return $lexer->int_token($lex_str);
419             }
420             }
421              
422 120 50 33     642 if (
    50          
    50          
    100          
    50          
    100          
    100          
423             ($state eq 'MY_LEX_INT_OR_REAL') ||
424             ($state eq 'MY_LEX_REAL')
425             ) {
426 0         0 while ($lexer->my_isdigit($c = $lexer->yyGet())) {};
427 0 0 0     0 if (
428             ($c == ord('e')) ||
429             ($c == ord('E'))
430             ) {
431 0         0 $c = $lexer->yyGet();
432 0 0 0     0 if (
433             ($c == ord('+')) ||
434             ($c == ord('-'))
435             ) {
436 0         0 $c = $lexer->yyGet();
437             }
438            
439 0 0       0 if (!$lexer->my_isdigit($c)) {
440 0         0 $state = 'MY_LEX_CHAR';
441 0         0 next;
442             }
443              
444 0         0 while ($lexer->my_isdigit($lexer->yyGet())) {};
445            
446 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
447 0         0 return ('FLOAT_NUM', $lex_str);
448             }
449            
450 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
451 0         0 return ('DECIMAL_NUM', $lex_str);
452             } elsif ($state eq 'MY_LEX_HEX_NUMBER') {
453 0         0 $lexer->yyGet();
454 0         0 while ($lexer->my_isdigit($lexer->yyGet())) {};
455 0         0 my $length = $lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START];
456 0 0 0     0 if (!($length & 1) || ($c != ord ("'"))) {
457 0         0 return ('ABORT_SYM','ABORT_SYM');
458             }
459 0         0 $lexer->yyGet();
460 0         0 my $lex_str = $lexer->get_token($length);
461 0         0 $lex_str = substr($lex_str, 2, length($lex_str) - 3);
462 0         0 return ('HEX_NUM', $lex_str);
463             } elsif ($state eq 'MY_LEX_BIN_NUMBER') {
464 0         0 $lexer->yyGet();
465 0   0     0 while (($c = $lexer->yyGet()) == ord('0') || $c == ord ('1')) {};
466 0         0 my $length = $lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START];
467 0 0       0 if ($c != ord("'")) {
468 0         0 return ('ABORT_SYM','ABORT_SYM');
469             }
470 0         0 $lexer->yyGet();
471 0         0 my $lex_str = $lexer->get_token($length);
472 0         0 $lex_str = substr($lex_str, 2, length($lex_str) - 3);
473 0         0 return ('BIN_NUM', $lex_str);
474             } elsif ($state eq 'MY_LEX_CMP_OP') {
475 50 100 66     94 if (
476             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_CMP_OP') ||
477             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_LONG_CMP_OP')
478             ) {
479 1         4 $lexer->yySkip();
480             }
481 50 50       119 if (@token = $lexer->find_keyword($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START], 0)) {
482 50         65 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
483 50         114 return @token; # ADDED
484             }
485 0         0 $state = 'MY_LEX_CHAR';
486 0         0 next;
487             } elsif ($state eq 'MY_LEX_LONG_CMP_OP') {
488 0 0 0     0 if (
489             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_CMP_OP') ||
490             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_LONG_CMP_OP')
491             ) {
492 0         0 $lexer->yySkip();
493 0 0       0 if ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_CMP_OP') {
494 0         0 $lexer->yySkip();
495             }
496             }
497 0 0       0 if (@token = $lexer->find_keyword($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START], 0)) {
498 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
499 0         0 return @token;
500             }
501 0         0 $state = 'MY_LEX_CHAR';
502 0         0 next;
503             } elsif ($state eq 'MY_LEX_BOOL') {
504 2 50       6 if ($c != $lexer->yyPeek()) {
505 0         0 $state = 'MY_LEX_CHAR';
506 0         0 next;
507             }
508 2         7 $lexer->yySkip();
509 2         5 @token = $lexer->find_keyword(2, 0);
510 2         4 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
511 2         6 return @token;
512             } elsif ($state eq 'MY_LEX_STRING_OR_DELIMITER') {
513 4 50       10 if ($lexer->[LEXER_SQL_MODE] & MODE_ANSI_QUOTES) {
514 0         0 $state = 'MY_LEX_USER_VARIABLE_DELIMITER';
515 0         0 next;
516             }
517             }
518            
519 68 100 100     361 if (
    50          
    100          
    100          
    50          
    100          
520             ($state eq 'MY_LEX_STRING_OR_DELIMITER') ||
521             ($state eq 'MY_LEX_STRING')
522             ) {
523 19         27 my $lex_str;
524 19 50       38 if (!defined ($lex_str = $lexer->get_text())) {
525 0         0 $state = 'MY_LEX_CHAR';
526 0         0 next;
527             }
528 19         48 return ('TEXT_STRING', $lex_str);
529             } elsif ($state eq 'MY_LEX_COMMENT') {
530 0         0 $lexer->[LEXER_OPTIONS] |= OPTION_FOUND_COMMENT;
531 0   0     0 while (($c = $lexer->yyGet()) != ord("\n") && $c) {};
532 0         0 $lexer->yyUnget();
533 0         0 $state = 'MY_LEX_START';
534 0         0 next;
535             } elsif ($state eq 'MY_LEX_LONG_COMMENT') {
536 17 100       41 if ($lexer->yyPeek() != ord('*')) {
537 1         3 $state = 'MY_LEX_CHAR';
538 1         2 next;
539             }
540 16         40 $lexer->yySkip();
541 16         28 $lexer->[LEXER_OPTIONS] |= OPTION_FOUND_COMMENT;
542 16 100       26 if ($lexer->yyPeek() == ord('!')) {
543 2         6 $lexer->yySkip();
544 2         4 my $version = $lexer->[LEXER_VERSION];
545 2         5 $state = 'MY_LEX_START';
546 2 50       5 if ($lexer->my_isdigit($lexer->yyPeek())) {
547 2         5 $version = substr($string, $lexer->[LEXER_PTR], 5);
548 2         4 $lexer->[LEXER_PTR] += 5; # FIXME for version numbers different from 5 characters
549             }
550              
551 2 100       9 if ($version <= $lexer->[LEXER_VERSION]){
552 1         4 $lexer->[LEXER_IN_COMMENT] = 1;
553 1         2 next;
554             }
555             }
556              
557 15   66     65 while (
      33        
558             ($lexer->[LEXER_PTR] != length($string) - 1) &&
559             (
560             ($c = $lexer->yyGet() != ord('*')) ||
561             ($lexer->yyPeek() != ord('/'))
562             )
563             ) {
564 447 50       910 $lexer->[LEXER_YYLINENO]++ if $c == ord("\n");
565             }
566            
567 15 50       44 $lexer->yySkip() if $lexer->[LEXER_PTR] != length($string) - 1;
568              
569 15         23 $state = 'MY_LEX_START';
570 15         18 next;
571             } elsif ($state eq 'MY_LEX_END_LONG_COMMENT') {
572 3 100 66     12 if ($lexer->[LEXER_IN_COMMENT] && $lexer->yyPeek() == ord('/')) {
573 1         4 $lexer->yySkip();
574 1         2 $lexer->[LEXER_IN_COMMENT] = 0;
575 1         2 $state = 'MY_LEX_START';
576             } else {
577 2         2 $state = 'MY_LEX_CHAR';
578             }
579 3         6 next;
580             } elsif ($state eq 'MY_LEX_SET_VAR') {
581 0 0       0 if ($lexer->yyPeek() != ord ('=')) {
582 0         0 $state = 'MY_LEX_CHAR';
583 0         0 next;
584             }
585 0         0 $lexer->yySkip();
586 0         0 return('SET_VAR','SET_VAR');
587             } elsif ($state eq 'MY_LEX_SEMICOLON') {
588 1 50       3 if ($lexer->yyPeek()) {
589 1 50 33     9 if (
590             ($lexer->[LEXER_CLIENT_CAPABILITIES] & CLIENT_MULTI_STATEMENTS) &&
591             (!$lexer->[LEXER_STMT_PREPARE_MODE])
592             ) {
593 1         3 $lexer->[LEXER_SAFE_TO_CACHE_QUERY] = 0;
594 1         2 $lexer->[LEXER_FOUND_SEMICOLON] = $lexer->[LEXER_PTR];
595 1         2 $lexer->[LEXER_SERVER_STATUS] |= SERVER_MORE_RESULTS_EXISTS;
596 1         2 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_END';
597 1         4 return ('END_OF_INPUT','');
598             }
599 0         0 $state = 'MY_LEX_CHAR';
600 0         0 next;
601             }
602             }
603            
604 28 100 66     133 if (
    100          
    100          
    50          
    0          
    0          
    0          
605             ($state eq 'MY_LEX_SEMICOLON') ||
606             ($state eq 'MY_LEX_EOL')
607             ) {
608 13 50       62 if ($lexer->[LEXER_PTR] >= length($string) - 1) {
609 13         22 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_END';
610 13         52 return ('END_OF_INPUT','');
611             }
612 0         0 $state = 'MY_LEX_CHAR';
613 0         0 next;
614             } elsif ($state eq 'MY_LEX_END') {
615 12         24 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_END';
616 12         46 return (0,0);
617             } elsif ($state eq 'MY_LEX_REAL_OR_POINT') {
618 2 50       4 if ($lexer->my_isdigit($lexer->yyPeek())) {
619 0         0 $state = 'MY_LEX_REAL';
620             } else {
621 2         3 $state = 'MY_LEX_IDENT_SEP';
622 2         5 $lexer->yyUnget();
623             }
624 2         3 next;
625             } elsif ($state eq 'MY_LEX_USER_END') {
626 1 50 33     3 if (
    50          
    50          
627             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_STRING') ||
628             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_STRING_OR_DELIMITER')
629             ) {
630 0         0 next;
631             } elsif ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_USER_END') {
632 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_SYSTEM_VAR';
633             } elsif ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_USER_VARIABLE_DELIMITER') {
634 1         3 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
635             } else {
636 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_HOSTNAME'; # could be replaced by 'MY_LEX_START' for homogeneity
637             }
638 1         3 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
639 1         3 return ('@', $lex_str);
640             } elsif ($state eq 'MY_LEX_HOSTNAME') {
641 0   0     0 for ($c = $lexer->yyGet(); $lexer->my_isalnum($c) || $c == ord('.') || $c == ord('_') || $c == ord('$'); $c = $lexer->yyGet()) {};
      0        
      0        
642 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
643 0         0 return ('LEX_HOSTNAME', $lex_str);
644             } elsif ($state eq 'MY_LEX_SYSTEM_VAR') {
645 0         0 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
646 0         0 $lexer->yySkip();
647 0 0       0 $lexer->[LEXER_NEXT_STATE] = $state_map->[$lexer->yyPeek()] eq 'MY_LEX_USER_VARIABLE_DELIMITER' ? 'MY_LEX_OPERATOR_OR_IDENT' : 'MY_LEX_IDENT_OR_KEYWORD';
648 0         0 return ('@', $lex_str);
649             } elsif ($state eq 'MY_LEX_IDENT_OR_KEYWORD') {
650 0         0 for ($result_state = 0; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
651 0 0       0 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
652              
653 0 0       0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP' if $c == ord('.');
654            
655 0         0 my $length = ($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START]) - 1;
656 0 0       0 return ('ABORT_SYM','ABORT_SYM') if $length == 0;
657 0 0       0 if (@token = $lexer->find_keyword($length, 0)) {
658 0         0 $lexer->yyUnget();
659 0         0 return @token;
660             }
661 0         0 my $lex_str = $lexer->get_token($length);
662 0         0 return ($result_state, $lex_str);
663             }
664             }
665             }
666              
667             sub init_state_maps {
668              
669 14     14 0 33 my $lexer = shift;
670              
671 14 100       57 return if exists $state_maps{$lexer->[LEXER_CHARSET]};
672              
673 8         21 my @state_map;
674             my @ident_map;
675              
676 8         34 for (my $i = 0; $i < 256; $i++) {
677 2048 100       2408 if ($lexer->my_isalpha($i)) {
    100          
    100          
678 416         652 $state_map[$i] = 'MY_LEX_IDENT';
679             } elsif ($lexer->my_isdigit($i)) {
680 80         138 $state_map[$i] = 'MY_LEX_NUMBER_IDENT';
681             # FIXME MULTI-BYTE
682             } elsif ($lexer->my_isspace($i)) {
683 48         108 $state_map[$i] = 'MY_LEX_SKIP';
684             } else {
685 1504         2512 $state_map[$i] = 'MY_LEX_CHAR';
686             }
687             }
688              
689 8         23 $state_map[ord('_')] = $state_map[ord('$')] = 'MY_LEX_IDENT';
690 8         14 $state_map[ord("'")] = 'MY_LEX_STRING';
691 8         18 $state_map[ord('.')] = 'MY_LEX_REAL_OR_POINT';
692              
693 8         18 $state_map[ord('>')] = $state_map[ord('=')] = $state_map[ord('!')] = 'MY_LEX_CMP_OP';
694 8         14 $state_map[ord('<')] = 'MY_LEX_LONG_CMP_OP';
695 8         16 $state_map[ord('&')] = $state_map[ord('|')] = 'MY_LEX_BOOL';
696 8         14 $state_map[ord('#')] = 'MY_LEX_COMMENT';
697 8         14 $state_map[ord(';')] = 'MY_LEX_SEMICOLON';
698 8         13 $state_map[ord(':')] = 'MY_LEX_SET_VAR';
699 8         19 $state_map[0] = 'MY_LEX_EOL';
700 8         13 $state_map[ord("\\")] = 'MY_LEX_ESCAPE';
701 8         12 $state_map[ord('/')] = 'MY_LEX_LONG_COMMENT';
702 8         15 $state_map[ord('*')] = 'MY_LEX_END_LONG_COMMENT';
703 8         12 $state_map[ord('@')] = 'MY_LEX_USER_END';
704 8         16 $state_map[ord('`')] = 'MY_LEX_USER_VARIABLE_DELIMITER';
705 8         15 $state_map[ord('"')] = 'MY_LEX_STRING_OR_DELIMITER';
706              
707 8         27 for (my $i=0; $i < 256 ; $i++) {
708 2048   100     4550 $ident_map[$i] = ($state_map[$i] eq 'MY_LEX_IDENT') || ($state_map[$i] eq 'MY_LEX_NUMBER_IDENT');
709             }
710              
711 8         23 $state_map[ord('x')] = $state_map[ord('X')] = 'MY_LEX_IDENT_OR_HEX';
712 8         17 $state_map[ord('b')] = $state_map[ord('B')] = 'MY_LEX_IDENT_OR_BIN';
713 8         13 $state_map[ord('n')] = $state_map[ord('N')] = 'MY_LEX_IDENT_OR_NCHAR';
714              
715 8         27 $state_maps{$lexer->[LEXER_CHARSET]} = \@state_map;
716 8         27 $ident_maps{$lexer->[LEXER_CHARSET]} = \@ident_map;
717             }
718              
719              
720 20     20 0 20 sub my_mbcharlen { 1 };
721              
722 2048     2048 0 2989 sub my_isalpha { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & (CTYPE_U | CTYPE_L) }
723              
724 0     0 0 0 sub my_isalnum { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & (CTYPE_U | CTYPE_L | CTYPE_NMR) }
725              
726 0     0 0 0 sub my_isxdigit { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_X }
727              
728 1668     1668 0 2448 sub my_isdigit { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_NMR }
729              
730 1552     1552 0 1996 sub my_isspace { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_SPC }
731              
732 0     0 0 0 sub my_iscntrl { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_CTR }
733              
734             sub get_text {
735 19     19 0 28 my $lexer = shift;
736 19         26 my $string = $lexer->[LEXER_STRING];
737 19         37 my $sep = $lexer->yyGetLast();
738 19         26 my $found_escape = 0;
739 19         48 while ($lexer->[LEXER_PTR] != length($lexer->[LEXER_STRING]) - 1) {
740 90         116 my $c = $lexer->yyGet();
741 90 50 33     238 if (
    100          
742             ($c == ord("\\")) &&
743             (!($lexer->[LEXER_SQL_MODE] & MODE_NO_BACKSLASH_ESCAPES))
744             ) {
745 0         0 $found_escape = 1;
746 0 0       0 return undef if $lexer->[LEXER_PTR] == length($lexer->[LEXER_STRING]);
747 0         0 $lexer->yySkip();
748             } elsif ($c == $sep) {
749 19 50       33 if ($c == $lexer->yyGet()) {
750 0         0 $found_escape = 1;
751 0         0 next;
752             } else {
753 19         31 $lexer->yyUnget();
754             }
755            
756 19         26 my ($str, $end, $start);
757              
758 19         29 $str = $lexer->[LEXER_TOK_START] + 1;
759 19         24 $end = $lexer->[LEXER_PTR] - 1;
760              
761 19         21 my $to;
762              
763 19 50       32 if (!$found_escape) {
764 19         26 my $yytoklen = $end - $str; # CHANGED
765 19 50       44 if ($yytoklen > 0) {
766 19         71 return substr($lexer->[LEXER_STRING], $str, $yytoklen);
767             } else {
768 0         0 return '';
769             }
770             } else {
771 0         0 my $new_str = ''; # ADDED
772 0         0 for ($to = $start; $str != $end; $str++) {
773 0 0 0     0 if (
    0 0        
774             (!($lexer->[LEXER_SQL_MODE] & MODE_NO_BACKSLASH_ESCAPES)) &&
775             (substr($string, $str, 1) eq "\\") &&
776             ($str + 1 != $end)
777             ) {
778 0         0 my $prev_str = substr($string, ++$str, 1);
779 0 0 0     0 if ($prev_str eq 'n') {
    0          
    0          
    0          
    0          
    0          
    0          
780 0         0 substr($new_str, $to++, 1) = "\n";
781 0         0 next;
782             } elsif ($prev_str eq 't') {
783 0         0 substr($new_str, $to++, 1) = "\t";
784 0         0 next;
785             } elsif ($prev_str eq 'r') {
786 0         0 substr($new_str, $to++, 1) = "\r";
787 0         0 next;
788             } elsif ($prev_str eq 'b') {
789 0         0 substr($new_str, $to++, 1) = "\b";
790 0         0 next;
791             } elsif ($prev_str eq '0') {
792 0         0 substr($new_str, $to++, 1) = "\0";
793 0         0 next;
794             } elsif ($prev_str eq 'Z') {
795 0         0 substr($new_str, $to++, 1) = "\032";
796 0         0 next;
797             } elsif (
798             ($prev_str eq '_') ||
799             ($prev_str eq '%')
800             ) {
801 0         0 substr($new_str, $to++, 1) = "\\";
802 0         0 substr($new_str, $to++, 1) = $prev_str; # Added
803             } else {
804 0         0 substr($new_str, $to++, 1) = $prev_str;
805             }
806             } elsif (substr($string, $str, 1) eq $sep) {
807 0         0 substr($new_str, $to++, 1) = substr($string, $str++, 1);
808             } else {
809 0         0 substr($new_str, $to++, 1) = substr($string, $str, 1);
810             }
811             }
812 0         0 return $new_str;
813             }
814 0         0 return substr($string, $start, ($to - $start));
815             }
816             }
817 0         0 return undef;
818             }
819              
820             sub get_token {
821 307     307 0 448 my ($lexer, $length) = @_;
822 307         580 $lexer->yyUnget();
823 307         677 return substr($lexer->[LEXER_STRING], $lexer->[LEXER_TOK_START], $length);
824             }
825              
826 8     8   65 use constant LONG_STR => "2147483647";
  8         14  
  8         419  
827 8     8   50 use constant LONG_LEN => 10;
  8         24  
  8         383  
828 8     8   45 use constant SIGNED_LONG_STR => "-2147483648";
  8         13  
  8         357  
829 8     8   56 use constant LONGLONG_STR => "9223372036854775807";
  8         15  
  8         352  
830 8     8   42 use constant LONGLONG_LEN => 19;
  8         13  
  8         337  
831 8     8   42 use constant SIGNED_LONGLONG_STR => "-9223372036854775808";
  8         10  
  8         335  
832 8     8   288 use constant SIGNED_LONGLONG_LEN => 19;
  8         21  
  8         318  
833 8     8   46 use constant UNSIGNED_LONGLONG_STR => "18446744073709551615";
  8         11  
  8         392  
834 8     8   44 use constant UNSIGNED_LONGLONG_LEN => 20;
  8         12  
  8         3669  
835              
836             sub int_token {
837 27     27 0 49 my ($lexer, $token) = @_;
838            
839 27 50       51 if (length($token) < LONG_LEN) {
840 27         81 return ("NUM", $token);
841             }
842              
843 0         0 my $neg = 0;
844              
845 0 0       0 if (substr($token, 0, 1) eq '+') {
    0          
846 0         0 $token = substr($token, 1);
847             } elsif (substr($token, 0, 1) eq '-') {
848 0         0 $token = substr($token, 1);
849 0         0 $neg = 1;
850             }
851              
852 0   0     0 while (
853             (substr($token, 0, 1) eq '0') &&
854             (length($token) > 0)
855             ) {
856 0         0 $token = substr($token, 1);
857             }
858              
859 0 0       0 if (length($token) < LONG_LEN) {
860 0         0 return ("NUM", $token);
861             }
862              
863 0         0 my ($smaller, $bigger);
864 0         0 my $cmp;
865              
866 0 0       0 if ($neg) {
867 0 0       0 if (length($token) == LONG_LEN) {
    0          
    0          
868 0         0 $cmp = SIGNED_LONG_STR + 1;
869 0         0 $smaller = 'NUM';
870 0         0 $bigger = 'LONG_NUM';
871             } elsif (length($token) < SIGNED_LONGLONG_LEN) {
872 0         0 return ('LONG_NUM', $token);
873             } elsif (length($token) > SIGNED_LONGLONG_LEN) {
874 0         0 return ('DECIMAL_SYM', $token);
875             } else {
876 0         0 $cmp = SIGNED_LONGLONG_STR + 1;
877 0         0 $smaller = 'LONG_NUM';
878 0         0 $bigger = 'DECIMAL_NUM';
879             }
880             } else {
881 0 0       0 if (length($token) == LONGLONG_LEN) {
    0          
    0          
882 0         0 $cmp = LONG_STR;
883 0         0 $smaller = 'NUM';
884 0         0 $bigger = 'LONG_NUM';
885             } elsif (length($token) < LONGLONG_LEN) {
886 0         0 return('LONG_NUM', $token);
887             } elsif (length($token) > LONGLONG_LEN) {
888 0 0       0 if (length($token) > UNSIGNED_LONGLONG_LEN) {
889 0         0 return ('DECIMAL_NUM', $token);
890             }
891 0         0 $cmp = UNSIGNED_LONGLONG_STR;
892 0         0 $smaller = 'ULONGLONG_NUM';
893 0         0 $bigger = 'DECIMAL_NUM';
894             } else {
895 0         0 $cmp = LONGLONG_STR;
896 0         0 $smaller = 'LONG_NUM';
897 0         0 $bigger = 'ULONGLONG_NUM';
898             }
899             }
900            
901 0 0       0 return $token > $cmp ? ($bigger, $token) : ($smaller, $token);
902             }
903              
904             sub find_keyword {
905 278     278 0 498 my ($lexer, $length, $function) = @_;
906 278         480 my $keyword = substr($lexer->[LEXER_STRING], $lexer->[LEXER_TOK_START], $length);
907              
908 278         301 my $symbol;
909 278 100       459 if ($function) {
910 10         28 $symbol = $DBIx::MyParsePP::Symbols::functions->{uc($keyword)};
911 10 100       32 $symbol = $DBIx::MyParsePP::Symbols::symbols->{uc($keyword)} if not defined $symbol;
912             } else {
913 268         729 $symbol = $DBIx::MyParsePP::Symbols::symbols->{uc($keyword)};
914             }
915              
916 278 100       639 return () if not defined $symbol;
917            
918 209 50 66     418 if (
919             ($symbol eq 'NOT_SYM') &&
920             ($lexer->[LEXER_SQL_MODE] & MODE_HIGH_NOT_PRECEDENCE)
921             ) {
922 0         0 $symbol = 'NOT2_SYM';
923             }
924              
925 209 100 100     360 if (
926             ($symbol eq 'OR_OR_SYM') &&
927             ($lexer->[LEXER_SQL_MODE] & MODE_PIPES_AS_CONCAT)
928             ) {
929 1         2 $symbol = 'OR2_SYM';
930             }
931              
932 209         610 return ($symbol, $keyword);
933             }
934              
935             1;
936              
937              
938             __END__