File Coverage

blib/lib/DBIx/MyParsePP/Lexer.pm
Criterion Covered Total %
statement 416 638 65.2
branch 125 284 44.0
condition 50 150 33.3
subroutine 80 88 90.9
pod 0 28 0.0
total 671 1188 56.4


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 10     10   72 use strict;
  10         27  
  10         382  
23              
24 7     7   18717 use DBIx::MyParsePP::Symbols;
  7         30  
  7         614  
25 6     6   5000 use DBIx::MyParsePP::Charsets;
  6         24  
  6         252  
26 6     6   3693 use DBIx::MyParsePP::Token;
  6         13  
  6         180  
27              
28 6     6   36 use constant CTYPE_U => 01; # Uppercase
  6         13  
  6         334  
29 6     6   30 use constant CTYPE_L => 02; # Lowercase
  6         11  
  6         274  
30 6     6   29 use constant CTYPE_NMR => 04; # Numeral (digit)
  6         11  
  6         237  
31 6     6   27 use constant CTYPE_SPC => 010; # Spacing character
  6         9  
  6         240  
32 6     6   26 use constant CTYPE_PNT => 020; # Punctuation
  6         18  
  6         1614  
33 6     6   28 use constant CTYPE_CTR => 040; # Control character
  6         9  
  6         221  
34 6     6   28 use constant CTYPE_B => 0100; # Blank
  6         10  
  6         221  
35 6     6   27 use constant CTYPE_X => 0200; # heXadecimal digit
  6         11  
  6         227  
36              
37 6     6   28 use constant LEXER_STRING => 0;
  6         9  
  6         222  
38 6     6   27 use constant LEXER_CHARSET => 1;
  6         10  
  6         289  
39 6     6   29 use constant LEXER_VERSION => 2;
  6         10  
  6         226  
40 6     6   30 use constant LEXER_SQL_MODE => 3;
  6         9  
  6         228  
41 6     6   29 use constant LEXER_OPTIONS => 4;
  6         11  
  6         349  
42 6     6   28 use constant LEXER_CLIENT_CAPABILITIES => 5;
  6         8  
  6         227  
43 6     6   29 use constant LEXER_STMT_PREPARE_MODE => 6;
  6         8  
  6         242  
44              
45 6     6   28 use constant LEXER_PTR => 7;
  6         8  
  6         216  
46 6     6   27 use constant LEXER_TOK_START => 8;
  6         9  
  6         232  
47              
48 6     6   27 use constant LEXER_TOKENS => 9;
  6         8  
  6         206  
49              
50 6     6   84 use constant LEXER_YYLINENO => 10;
  6         13  
  6         224  
51 6     6   26 use constant LEXER_NEXT_STATE => 11;
  6         7  
  6         231  
52 6     6   28 use constant LEXER_IN_COMMENT => 12;
  6         8  
  6         247  
53 6     6   26 use constant LEXER_FOUND_SEMICOLON => 13;
  6         9  
  6         205  
54 6     6   43 use constant LEXER_SAFE_TO_CACHE_QUERY => 14;
  6         8  
  6         231  
55 6     6   40 use constant LEXER_SERVER_STATUS => 15;
  6         17  
  6         259  
56 6     6   28 use constant LEXER_CTYPE => 16;
  6         9  
  6         239  
57              
58              
59 6     6   138 use constant OPTION_FOUND_COMMENT => 1 << 15;
  6         8  
  6         292  
60 6     6   27 use constant CLIENT_MULTI_STATEMENTS => 1 << 16;
  6         10  
  6         226  
61 6     6   28 use constant SERVER_MORE_RESULTS_EXISTS => 8;
  6         6  
  6         228  
62 6     6   26 use constant NAMES_SEP_CHAR => '\377';
  6         9  
  6         452  
63              
64              
65 6     6   29 use constant MODE_PIPES_AS_CONCAT => 2; # USE ME!
  6         10  
  6         294  
66 6     6   28 use constant MODE_ANSI_QUOTES => 4;
  6         9  
  6         305  
67 6     6   28 use constant MODE_IGNORE_SPACE => 8;
  6         9  
  6         243  
68 6     6   26 use constant MODE_MYSQL323 => 65536;
  6         9  
  6         297  
69 6     6   29 use constant MODE_MYSQL40 => MODE_MYSQL323 * 2;
  6         10  
  6         322  
70 6     6   26 use constant MODE_ANSI => MODE_MYSQL40 * 2;
  6         7  
  6         292  
71 6     6   29 use constant MODE_NO_AUTO_VALUE_ON_ZERO => MODE_ANSI * 2;
  6         9  
  6         309  
72 6     6   27 use constant MODE_NO_BACKSLASH_ESCAPES => MODE_NO_AUTO_VALUE_ON_ZERO * 2;
  6         11  
  6         303  
73 6     6   29 use constant MODE_STRICT_TRANS_TABLES => MODE_NO_BACKSLASH_ESCAPES * 2;
  6         8  
  6         304  
74 6     6   28 use constant MODE_STRICT_ALL_TABLES => MODE_STRICT_TRANS_TABLES * 2;
  6         11  
  6         305  
75 6     6   28 use constant MODE_NO_ZERO_IN_DATE => MODE_STRICT_ALL_TABLES * 2;
  6         10  
  6         312  
76 6     6   27 use constant MODE_NO_ZERO_DATE => MODE_NO_ZERO_IN_DATE * 2;
  6         10  
  6         295  
77 6     6   27 use constant MODE_INVALID_DATES => MODE_NO_ZERO_DATE * 2;
  6         11  
  6         353  
78 6     6   52 use constant MODE_ERROR_FOR_DIVISION_BY_ZERO => MODE_INVALID_DATES * 2;
  6         19  
  6         314  
79 6     6   31 use constant MODE_TRADITIONAL => MODE_ERROR_FOR_DIVISION_BY_ZERO * 2;
  6         10  
  6         297  
80 6     6   28 use constant MODE_NO_AUTO_CREATE_USER => MODE_TRADITIONAL * 2;
  6         10  
  6         442  
81 6     6   29 use constant MODE_HIGH_NOT_PRECEDENCE => MODE_NO_AUTO_CREATE_USER * 2;
  6         11  
  6         44551  
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 11     11 0 33 my $class = shift;
99 11         43 my $lexer = bless([], $class);
100              
101 11         52 my $max_arg = (scalar(@_) / 2) - 1;
102              
103 11         39 foreach my $i (0..$max_arg) {
104 66 50       574 if (exists $args{$_[$i * 2]}) {
105 66         5882 $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 11         64 $lexer->[LEXER_STRING] = $lexer->[LEXER_STRING]."\0";
112 11         35 $lexer->[LEXER_YYLINENO] = 1;
113 11         25 $lexer->[LEXER_TOK_START] = 0;
114 11         28 $lexer->[LEXER_PTR] = 0;
115 11         29 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
116              
117 11 50       63 $lexer->[LEXER_CLIENT_CAPABILITIES] = CLIENT_MULTI_STATEMENTS if not defined $lexer->[LEXER_CLIENT_CAPABILITIES];
118 11 50       47 $lexer->[LEXER_STMT_PREPARE_MODE] = 0 if not defined $lexer->[LEXER_STMT_PREPARE_MODE];
119 11 100       40 $lexer->[LEXER_SQL_MODE] = 0 if not defined $lexer->[LEXER_SQL_MODE]; # CHECKME
120              
121 11 100       48 $lexer->[LEXER_VERSION] = '50045' if not defined $lexer->[LEXER_VERSION];
122 11 50       43 $lexer->[LEXER_CHARSET] = 'ascii' if not defined $lexer->[LEXER_CHARSET]; # FIXME
123              
124 11         41 my $charset_uc = ucfirst($lexer->[LEXER_CHARSET]);
125 6     6   5490 eval('
  6         25  
  6         263  
  11         1522  
126             use DBIx::MyParsePP::'.$charset_uc.';
127             $lexer->[LEXER_CTYPE] = $DBIx::MyParsePP::'.$charset_uc.'::ctype;
128             ');
129              
130 11 50       56 if ($@) {
131 0         0 print STDERR "DBIx::MyParsePP::Lexer->new() failed: $@\n";
132 0         0 return undef;
133             }
134              
135 11         37 $lexer->[LEXER_TOKENS] = [];
136              
137 11         115 $lexer->init_state_maps($lexer->[LEXER_CHARSET]);
138              
139 11         49 return $lexer;
140            
141             }
142              
143             sub getLine {
144 1     1 0 7 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 6 return $_[0]->[LEXER_PTR];
157             }
158              
159             sub getTokens {
160 1     1 0 5 return $_[0]->[LEXER_TOKENS];
161             }
162              
163             sub tokens {
164 0     0 0 0 return $_[0]->[LEXER_TOKENS];
165             }
166              
167 4134     4134 0 13806 sub yyGet { return ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR]++, 1)) };
168 19     19 0 56 sub yyGetLast { ord(substr($_[0]->[LEXER_STRING], $_[0]->[LEXER_PTR] - 1, 1)) };
169 374     374 0 1425 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 508     508 0 919 sub yyUnget { $_[0]->[LEXER_PTR]-- };
172 94     94 0 189 sub yySkip { $_[0]->[LEXER_PTR]++ };
173 132     132 0 378 sub yyLength { ($_[0]->[LEXER_PTR] - $_[0]->[LEXER_TOK_START]) - 1 };
174              
175             sub yylex {
176 732     732 0 823 my $lexer = shift;
177 732         1202 my @res = $lexer->MYSQLlex();
178 732 100 66     2151 if (($res[0] eq '0') && ($res[1] eq '0')) {
179 9         49 return (undef, ''); # EOF
180             } else {
181 723         2120 my $token = DBIx::MyParsePP::Token->new(@res);
182 723         794 push @{$lexer->[LEXER_TOKENS]}, $token;
  723         1237  
183 723         2972 return ($res[0], $token);
184             }
185             }
186              
187             sub MYSQLlex {
188 732     732 0 1087 my $lexer = shift;
189              
190 732         1317 my $string = $lexer->[LEXER_STRING];
191 732         1111 my $state_map = $state_maps{$lexer->[LEXER_CHARSET]};
192 732         896 my $ident_map = $ident_maps{$lexer->[LEXER_CHARSET]};
193            
194 732         694 my $c = 0;
195 732         675 my @token;
196             my $result_state;
197 0         0 my $state;
198              
199 732         888 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
200              
201              
202 732         812 $state = $lexer->[LEXER_NEXT_STATE];
203 732         809 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_OPERATOR_OR_IDENT';
204              
205 732         1019 my $char = substr($string, $lexer->[LEXER_PTR], 1);
206              
207 732         701 for (;;) {
208 785 100 100     8124 if (
209             ($state eq 'MY_LEX_OPERATOR_OR_IDENT') ||
210             ($state eq 'MY_LEX_START')
211             ) {
212 530         988 for ($c = $lexer->yyGet(); $state_map->[$c] eq 'MY_LEX_SKIP'; $c = $lexer->yyGet()) {
213 915 100       2232 $lexer->[LEXER_YYLINENO]++ if $c == ord("\n");
214             }
215 530         732 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR] - 1;
216 530         677 $state = $state_map->[$c];
217             }
218            
219 785 50       1388 if ($state eq 'MY_LEX_ESCAPE') {
220 0 0       0 return ("NULL_SYM","NULL") if $lexer->yyGet() == ord('N');
221             }
222            
223 785 100 66     5196 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 106 0 66     270 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 106         130 $lexer->[LEXER_PTR] = $lexer->[LEXER_TOK_START];
240 106         166 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
241 106         194 $c = $lexer->yyGet();
242            
243 106 100       258 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START' if $c != ord (')');
244              
245 106 100 33     345 if ($c == ord(',')) {
    50          
246 38         52 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
247             } elsif (($c == ord('?')) && (!$ident_map->[$lexer->yyPeek()])) { # CHANGED
248 0         0 return ("PARAM_MARKER","?");
249             }
250 106         416 return (chr($c), $lex_str);
251             } elsif ($state eq 'MY_LEX_IDENT_OR_NCHAR') {
252 4 50       11 if ($lexer->yyPeek() != ord("'")) {
253 4         8 $state = 'MY_LEX_IDENT';
254 4         7 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 4 50       16 if ($lexer->yyPeek() == ord("'")) {
271 0         0 $state = 'MY_LEX_BIN_NUMBER';
272 0         0 next;
273             }
274             }
275              
276 675 100 66     4026 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 298         293 my $start;
282             ## FIXME - multibyte
283              
284 298         585 for ($result_state = $c; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
285            
286 298 50       589 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
287              
288 298         422 my $length = $lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START] - 1;
289 298         325 $start = $lexer->[LEXER_PTR];
290              
291 298 50       604 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 298 100 66     5086 if (
      100        
296             ($start == $lexer->[LEXER_PTR]) &&
297             ($c == ord('.')) &&
298             ($ident_map->[$lexer->yyPeek()])
299             ) {
300 103         160 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP';
301             } else {
302 195         342 $lexer->yyUnget();
303 195 100       446 if (@token = $lexer->find_keyword($length, $c == ord('('))) {
304 138         181 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
305 138         534 return @token;
306             }
307 57         128 $lexer->yySkip();
308             }
309 160         298 my $lex_str = $lexer->get_token($length);
310              
311 160 50 33     436 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 160         549 return($result_state, $lex_str);
319             } elsif ($state eq 'MY_LEX_IDENT_SEP') {
320 107         176 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
321 107         181 $c = $lexer->yyGet();
322 107         165 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_START';
323 107 100       204 if (!$ident_map->[$lexer->yyPeek()]) {
324 2         5 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
325             }
326 107         485 return (chr($c), $lex_str);
327             } elsif ($state eq 'MY_LEX_NUMBER_IDENT') {
328 27         96 while ($lexer->my_isdigit($c = $lexer->yyGet())) {} ;
329 27 50       66 if (!$ident_map->[$c]) {
330 27         36 $state = 'MY_LEX_INT_OR_REAL';
331 27         33 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 243 100       674 if ($state eq 'MY_LEX_IDENT_START') {
    50          
    100          
375 105         107 $result_state = 'IDENT';
376             # FIXME multibyte
377 105         209 for ($result_state = 0; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
378 105 50       201 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
379              
380 105 100 100     264 if (($c == ord('.')) && ($ident_map->[$lexer->yyPeek()])) {
381 2         4 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP';
382             }
383              
384 105         186 my $lex_str = $lexer->get_token($lexer->yyLength());
385 105         400 return($result_state, $lex_str);
386             } elsif ($state eq 'MY_LEX_USER_VARIABLE_DELIMITER') {
387 0         0 my $double_quotes = 0;
388 0         0 my $quote_char = $c;
389 0         0 $lexer->[LEXER_TOK_START] = $lexer->[LEXER_PTR];
390 0         0 while ($c = $lexer->yyGet()) {
391 0         0 my $var_length = $lexer->my_mbcharlen($c);
392 0 0       0 if ($var_length == 1) {
393 0 0       0 last if $c == ord(NAMES_SEP_CHAR);
394 0 0       0 if ($c == $quote_char) {
395 0 0       0 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 0         0 my $lex_str;
405            
406 0 0       0 if ($double_quotes) {
407 0         0 $lex_str = $lexer->get_quoted_token($lexer->yyLength() - $double_quotes, $quote_char);
408             } else {
409 0         0 $lex_str = $lexer->get_token($lexer->yyLength());
410             }
411            
412 0 0       0 $lexer->yySkip() if $c == $quote_char;
413 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
414 0         0 return ('IDENT_QUOTED', $lex_str);
415             } elsif ($state eq 'MY_LEX_INT_OR_REAL') {
416 27 50       65 if ($c != ord ('.')) {
417 27         65 my $lex_str = $lexer->get_token($lexer->yyLength());
418 27         87 return $lexer->int_token($lex_str);
419             }
420             }
421              
422 111 50 33     871 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 48 100 66     103 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 48 50       121 if (@token = $lexer->find_keyword($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START], 0)) {
482 48         65 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
483 48         166 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       9 if ($c != $lexer->yyPeek()) {
505 0         0 $state = 'MY_LEX_CHAR';
506 0         0 next;
507             }
508 2         8 $lexer->yySkip();
509 2         6 @token = $lexer->find_keyword(2, 0);
510 2         6 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_START';
511 2         9 return @token;
512             } elsif ($state eq 'MY_LEX_STRING_OR_DELIMITER') {
513 4 50       12 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 61 100 100     462 if (
    50          
    100          
    100          
    50          
    100          
520             ($state eq 'MY_LEX_STRING_OR_DELIMITER') ||
521             ($state eq 'MY_LEX_STRING')
522             ) {
523 19         19 my $lex_str;
524 19 50       60 if (!defined ($lex_str = $lexer->get_text())) {
525 0         0 $state = 'MY_LEX_CHAR';
526 0         0 next;
527             }
528 19         71 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       151 if ($lexer->yyPeek() != ord('*')) {
537 1         2 $state = 'MY_LEX_CHAR';
538 1         3 next;
539             }
540 16         42 $lexer->yySkip();
541 16         40 $lexer->[LEXER_OPTIONS] |= OPTION_FOUND_COMMENT;
542 16 100       34 if ($lexer->yyPeek() == ord('!')) {
543 2         6 $lexer->yySkip();
544 2         5 my $version = $lexer->[LEXER_VERSION];
545 2         6 $state = 'MY_LEX_START';
546 2 50       13 if ($lexer->my_isdigit($lexer->yyPeek())) {
547 2         6 $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       12 if ($version <= $lexer->[LEXER_VERSION]){
552 1         2 $lexer->[LEXER_IN_COMMENT] = 1;
553 1         3 next;
554             }
555             }
556              
557 15   66     79 while (
      33        
558             ($lexer->[LEXER_PTR] != length($string) - 1) &&
559             (
560             ($c = $lexer->yyGet() != ord('*')) ||
561             ($lexer->yyPeek() != ord('/'))
562             )
563             ) {
564 447 50       1562 $lexer->[LEXER_YYLINENO]++ if $c == ord("\n");
565             }
566            
567 15 50       56 $lexer->yySkip() if $lexer->[LEXER_PTR] != length($string) - 1;
568              
569 15         21 $state = 'MY_LEX_START';
570 15         22 next;
571             } elsif ($state eq 'MY_LEX_END_LONG_COMMENT') {
572 3 100 66     19 if ($lexer->[LEXER_IN_COMMENT] && $lexer->yyPeek() == ord('/')) {
573 1         3 $lexer->yySkip();
574 1         3 $lexer->[LEXER_IN_COMMENT] = 0;
575 1         11 $state = 'MY_LEX_START';
576             } else {
577 2         3 $state = 'MY_LEX_CHAR';
578             }
579 3         5 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       11 if ($lexer->yyPeek()) {
589 1 50 33     14 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         3 $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         5 return ('END_OF_INPUT','');
598             }
599 0         0 $state = 'MY_LEX_CHAR';
600 0         0 next;
601             }
602             }
603            
604 21 100 66     151 if (
    100          
    50          
    0          
    0          
    0          
    0          
605             ($state eq 'MY_LEX_SEMICOLON') ||
606             ($state eq 'MY_LEX_EOL')
607             ) {
608 10 50       40 if ($lexer->[LEXER_PTR] >= length($string) - 1) {
609 10         21 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_END';
610 10         41 return ('END_OF_INPUT','');
611             }
612 0         0 $state = 'MY_LEX_CHAR';
613 0         0 next;
614             } elsif ($state eq 'MY_LEX_END') {
615 9         23 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_END';
616 9         37 return (0,0);
617             } elsif ($state eq 'MY_LEX_REAL_OR_POINT') {
618 2 50       6 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         4 $lexer->yyUnget();
623             }
624 2         2 next;
625             } elsif ($state eq 'MY_LEX_USER_END') {
626 0 0 0     0 if (
    0 0        
627             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_STRING') ||
628             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_USER_VARIABLE_DELIMITER') ||
629             ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_STRING_OR_DELIMITER')
630             ) {
631 0         0 next;
632             } elsif ($state_map->[$lexer->yyPeek()] eq 'MY_LEX_USER_END') {
633 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_SYSTEM_VAR';
634             } else {
635 0         0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_HOSTNAME';
636             }
637 0         0 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
638 0         0 return ('@', $lex_str);
639             } elsif ($state eq 'MY_LEX_HOSTNAME') {
640 0   0     0 for ($c = $lexer->yyGet(); $lexer->my_isalnum($c) || $c == ord('.') || $c == ord('_') || $c == ord('$'); $c = $lexer->yyGet()) {};
      0        
      0        
641 0         0 my $lex_str = $lexer->get_token($lexer->yyLength());
642 0         0 return ('LEX_HOSTNAME', $lex_str);
643             } elsif ($state eq 'MY_LEX_SYSTEM_VAR') {
644 0         0 my $lex_str = substr($string, $lexer->[LEXER_PTR], 1);
645 0         0 $lexer->yySkip();
646 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';
647 0         0 return ('@', $lex_str);
648             } elsif ($state eq 'MY_LEX_IDENT_OR_KEYWORD') {
649 0         0 for ($result_state = 0; $ident_map->[$c = $lexer->yyGet()]; $result_state |= $c) {};
650 0 0       0 $result_state = $result_state & 0x80 ? 'IDENT_QUOTED' : 'IDENT';
651              
652 0 0       0 $lexer->[LEXER_NEXT_STATE] = 'MY_LEX_IDENT_SEP' if $c == ord('.');
653            
654 0         0 my $length = ($lexer->[LEXER_PTR] - $lexer->[LEXER_TOK_START]) - 1;
655 0 0       0 return ('ABORT_SYM','ABORT_SYM') if $length == 0;
656 0 0       0 if (@token = $lexer->find_keyword($length, 0)) {
657 0         0 $lexer->yyUnget();
658 0         0 return @token;
659             }
660 0         0 my $lex_str = $lexer->get_token($length);
661 0         0 return ($result_state, $lex_str);
662             }
663             }
664             }
665              
666             sub init_state_maps {
667              
668 11     11 0 25 my $lexer = shift;
669              
670 11 100       58 return if exists $state_maps{$lexer->[LEXER_CHARSET]};
671              
672 6         16 my @state_map;
673             my @ident_map;
674              
675 6         32 for (my $i = 0; $i < 256; $i++) {
676 1536 100       2390 if ($lexer->my_isalpha($i)) {
    100          
    100          
677 312         715 $state_map[$i] = 'MY_LEX_IDENT';
678             } elsif ($lexer->my_isdigit($i)) {
679 60         149 $state_map[$i] = 'MY_LEX_NUMBER_IDENT';
680             # FIXME MULTI-BYTE
681             } elsif ($lexer->my_isspace($i)) {
682 36         97 $state_map[$i] = 'MY_LEX_SKIP';
683             } else {
684 1128         2923 $state_map[$i] = 'MY_LEX_CHAR';
685             }
686             }
687              
688 6         21 $state_map[ord('_')] = $state_map[ord('$')] = 'MY_LEX_IDENT';
689 6         15 $state_map[ord("'")] = 'MY_LEX_STRING';
690 6         14 $state_map[ord('.')] = 'MY_LEX_REAL_OR_POINT';
691              
692 6         15 $state_map[ord('>')] = $state_map[ord('=')] = $state_map[ord('!')] = 'MY_LEX_CMP_OP';
693 6         13 $state_map[ord('<')] = 'MY_LEX_LONG_CMP_OP';
694 6         17 $state_map[ord('&')] = $state_map[ord('|')] = 'MY_LEX_BOOL';
695 6         12 $state_map[ord('#')] = 'MY_LEX_COMMENT';
696 6         16 $state_map[ord(';')] = 'MY_LEX_SEMICOLON';
697 6         12 $state_map[ord(':')] = 'MY_LEX_SET_VAR';
698 6         13 $state_map[0] = 'MY_LEX_EOL';
699 6         22 $state_map[ord("\\")] = 'MY_LEX_ESCAPE';
700 6         13 $state_map[ord('/')] = 'MY_LEX_LONG_COMMENT';
701 6         12 $state_map[ord('*')] = 'MY_LEX_END_LONG_COMMENT';
702 6         12 $state_map[ord('@')] = 'MY_LEX_USER_END';
703 6         10 $state_map[ord('`')] = 'MY_LEX_USER_VARIABLE_DELIMITER';
704 6         15 $state_map[ord('"')] = 'MY_LEX_STRING_OR_DELIMITER';
705              
706 6         29 for (my $i=0; $i < 256 ; $i++) {
707 1536   100     5766 $ident_map[$i] = ($state_map[$i] eq 'MY_LEX_IDENT') || ($state_map[$i] eq 'MY_LEX_NUMBER_IDENT');
708             }
709              
710 6         20 $state_map[ord('x')] = $state_map[ord('X')] = 'MY_LEX_IDENT_OR_HEX';
711 6         16 $state_map[ord('b')] = $state_map[ord('B')] = 'MY_LEX_IDENT_OR_BIN';
712 6         16 $state_map[ord('n')] = $state_map[ord('N')] = 'MY_LEX_IDENT_OR_NCHAR';
713              
714 6         29 $state_maps{$lexer->[LEXER_CHARSET]} = \@state_map;
715 6         30 $ident_maps{$lexer->[LEXER_CHARSET]} = \@ident_map;
716             }
717              
718              
719 0     0 0 0 sub my_mbcharlen { 1 };
720              
721 1536     1536 0 3933 sub my_isalpha { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & (CTYPE_U | CTYPE_L) }
722              
723 0     0 0 0 sub my_isalnum { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & (CTYPE_U | CTYPE_L | CTYPE_NMR) }
724              
725 0     0 0 0 sub my_isxdigit { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_X }
726              
727 1260     1260 0 3294 sub my_isdigit { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_NMR }
728              
729 1164     1164 0 2256 sub my_isspace { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_SPC }
730              
731 0     0 0 0 sub my_iscntrl { $_[0]->[LEXER_CTYPE]->[$_[1] + 1] & CTYPE_CTR }
732              
733             sub get_text {
734 19     19 0 29 my $lexer = shift;
735 19         59 my $string = $lexer->[LEXER_STRING];
736 19         40 my $sep = $lexer->yyGetLast();
737 19         29 my $found_escape = 0;
738 19         71 while ($lexer->[LEXER_PTR] != length($lexer->[LEXER_STRING]) - 1) {
739 90         141 my $c = $lexer->yyGet();
740 90 50 33     349 if (
    100          
741             ($c == ord("\\")) &&
742             (!($lexer->[LEXER_SQL_MODE] & MODE_NO_BACKSLASH_ESCAPES))
743             ) {
744 0         0 $found_escape = 1;
745 0 0       0 return undef if $lexer->[LEXER_PTR] == length($lexer->[LEXER_STRING]);
746 0         0 $lexer->yySkip();
747             } elsif ($c == $sep) {
748 19 50       43 if ($c == $lexer->yyGet()) {
749 0         0 $found_escape = 1;
750 0         0 next;
751             } else {
752 19         37 $lexer->yyUnget();
753             }
754            
755 19         22 my ($str, $end, $start);
756              
757 19         30 $str = $lexer->[LEXER_TOK_START] + 1;
758 19         25 $end = $lexer->[LEXER_PTR] - 1;
759              
760 19         46 my $to;
761              
762 19 50       40 if (!$found_escape) {
763 19         33 my $yytoklen = $end - $str; # CHANGED
764 19 50       43 if ($yytoklen > 0) {
765 19         94 return substr($lexer->[LEXER_STRING], $str, $yytoklen);
766             } else {
767 0         0 return '';
768             }
769             } else {
770 0         0 my $new_str = ''; # ADDED
771 0         0 for ($to = $start; $str != $end; $str++) {
772 0 0 0     0 if (
    0 0        
773             (!($lexer->[LEXER_SQL_MODE] & MODE_NO_BACKSLASH_ESCAPES)) &&
774             (substr($string, $str, 1) eq "\\") &&
775             ($str + 1 != $end)
776             ) {
777 0         0 my $prev_str = substr($string, ++$str, 1);
778 0 0 0     0 if ($prev_str eq 'n') {
    0          
    0          
    0          
    0          
    0          
    0          
779 0         0 substr($new_str, $to++, 1) = "\n";
780 0         0 next;
781             } elsif ($prev_str eq 't') {
782 0         0 substr($new_str, $to++, 1) = "\t";
783 0         0 next;
784             } elsif ($prev_str eq 'r') {
785 0         0 substr($new_str, $to++, 1) = "\r";
786 0         0 next;
787             } elsif ($prev_str eq 'b') {
788 0         0 substr($new_str, $to++, 1) = "\b";
789 0         0 next;
790             } elsif ($prev_str eq '0') {
791 0         0 substr($new_str, $to++, 1) = "\0";
792 0         0 next;
793             } elsif ($prev_str eq 'Z') {
794 0         0 substr($new_str, $to++, 1) = "\032";
795 0         0 next;
796             } elsif (
797             ($prev_str eq '_') ||
798             ($prev_str eq '%')
799             ) {
800 0         0 substr($new_str, $to++, 1) = "\\";
801 0         0 substr($new_str, $to++, 1) = $prev_str; # Added
802             } else {
803 0         0 substr($new_str, $to++, 1) = $prev_str;
804             }
805             } elsif (substr($string, $str, 1) eq $sep) {
806 0         0 substr($new_str, $to++, 1) = substr($string, $str++, 1);
807             } else {
808 0         0 substr($new_str, $to++, 1) = substr($string, $str, 1);
809             }
810             }
811 0         0 return $new_str;
812             }
813 0         0 return substr($string, $start, ($to - $start));
814             }
815             }
816 0         0 return undef;
817             }
818              
819             sub get_token {
820 292     292 0 696 my ($lexer, $length) = @_;
821 292         448 $lexer->yyUnget();
822 292         805 return substr($lexer->[LEXER_STRING], $lexer->[LEXER_TOK_START], $length);
823             }
824              
825 6     6   134 use constant LONG_STR => "2147483647";
  6         15  
  6         582  
826 6     6   34 use constant LONG_LEN => 10;
  6         12  
  6         302  
827 6     6   30 use constant SIGNED_LONG_STR => "-2147483648";
  6         15  
  6         257  
828 6     6   43 use constant LONGLONG_STR => "9223372036854775807";
  6         11  
  6         240  
829 6     6   28 use constant LONGLONG_LEN => 19;
  6         11  
  6         274  
830 6     6   30 use constant SIGNED_LONGLONG_STR => "-9223372036854775808";
  6         10  
  6         290  
831 6     6   29 use constant SIGNED_LONGLONG_LEN => 19;
  6         11  
  6         287  
832 6     6   27 use constant UNSIGNED_LONGLONG_STR => "18446744073709551615";
  6         11  
  6         344  
833 6     6   28 use constant UNSIGNED_LONGLONG_LEN => 20;
  6         14  
  6         4092  
834              
835             sub int_token {
836 27     27 0 46 my ($lexer, $token) = @_;
837            
838 27 50       73 if (length($token) < LONG_LEN) {
839 27         111 return ("NUM", $token);
840             }
841              
842 0         0 my $neg = 0;
843              
844 0 0       0 if (substr($token, 0, 1) eq '+') {
    0          
845 0         0 $token = substr($token, 1);
846             } elsif (substr($token, 0, 1) eq '-') {
847 0         0 $token = substr($token, 1);
848 0         0 $neg = 1;
849             }
850              
851 0   0     0 while (
852             (substr($token, 0, 1) eq '0') &&
853             (length($token) > 0)
854             ) {
855 0         0 $token = substr($token, 1);
856             }
857              
858 0 0       0 if (length($token) < LONG_LEN) {
859 0         0 return ("NUM", $token);
860             }
861              
862 0         0 my ($smaller, $bigger);
863 0         0 my $cmp;
864              
865 0 0       0 if ($neg) {
866 0 0       0 if (length($token) == LONG_LEN) {
    0          
    0          
867 0         0 $cmp = SIGNED_LONG_STR + 1;
868 0         0 $smaller = 'NUM';
869 0         0 $bigger = 'LONG_NUM';
870             } elsif (length($token) < SIGNED_LONGLONG_LEN) {
871 0         0 return ('LONG_NUM', $token);
872             } elsif (length($token) > SIGNED_LONGLONG_LEN) {
873 0         0 return ('DECIMAL_SYM', $token);
874             } else {
875 0         0 $cmp = SIGNED_LONGLONG_STR + 1;
876 0         0 $smaller = 'LONG_NUM';
877 0         0 $bigger = 'DECIMAL_NUM';
878             }
879             } else {
880 0 0       0 if (length($token) == LONGLONG_LEN) {
    0          
    0          
881 0         0 $cmp = LONG_STR;
882 0         0 $smaller = 'NUM';
883 0         0 $bigger = 'LONG_NUM';
884             } elsif (length($token) < LONGLONG_LEN) {
885 0         0 return('LONG_NUM', $token);
886             } elsif (length($token) > LONGLONG_LEN) {
887 0 0       0 if (length($token) > UNSIGNED_LONGLONG_LEN) {
888 0         0 return ('DECIMAL_NUM', $token);
889             }
890 0         0 $cmp = UNSIGNED_LONGLONG_STR;
891 0         0 $smaller = 'ULONGLONG_NUM';
892 0         0 $bigger = 'DECIMAL_NUM';
893             } else {
894 0         0 $cmp = LONGLONG_STR;
895 0         0 $smaller = 'LONG_NUM';
896 0         0 $bigger = 'ULONGLONG_NUM';
897             }
898             }
899            
900 0 0       0 return $token > $cmp ? ($bigger, $token) : ($smaller, $token);
901             }
902              
903             sub find_keyword {
904 245     245 0 343 my ($lexer, $length, $function) = @_;
905 245         578 my $keyword = substr($lexer->[LEXER_STRING], $lexer->[LEXER_TOK_START], $length);
906              
907 245         216 my $symbol;
908 245 100       386 if ($function) {
909 8         26 $symbol = $DBIx::MyParsePP::Symbols::functions->{uc($keyword)};
910 8 100       32 $symbol = $DBIx::MyParsePP::Symbols::symbols->{uc($keyword)} if not defined $symbol;
911             } else {
912 237         699 $symbol = $DBIx::MyParsePP::Symbols::symbols->{uc($keyword)};
913             }
914              
915 245 100       800 return () if not defined $symbol;
916            
917 188 50 66     454 if (
918             ($symbol eq 'NOT_SYM') &&
919             ($lexer->[LEXER_SQL_MODE] & MODE_HIGH_NOT_PRECEDENCE)
920             ) {
921 0         0 $symbol = 'NOT2_SYM';
922             }
923              
924 188 100 100     430 if (
925             ($symbol eq 'OR_OR_SYM') &&
926             ($lexer->[LEXER_SQL_MODE] & MODE_PIPES_AS_CONCAT)
927             ) {
928 1         3 $symbol = 'OR2_SYM';
929             }
930              
931 188         825 return ($symbol, $keyword);
932             }
933              
934             1;
935              
936              
937             __END__