1 /*
2 * Copyright 2015-2018 HuntLabs.cn
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 module hunt.sql.parser.SQLExprParser;
17
18 import hunt.collection;
19
20 import hunt.sql.SQLUtils;
21 import hunt.sql.ast;
22 import hunt.sql.ast.expr;
23 import hunt.sql.ast.statement;
24 // import hunt.sql.dialect.oracle.ast.expr.OracleArgumentExpr;
25 import hunt.sql.dialect.postgresql.ast.expr.PGTypeCastExpr;
26 import hunt.sql.util.FnvHash;
27 import hunt.sql.util.DBType;
28 import hunt.sql.parser.SQLParser;
29 import hunt.sql.parser.Lexer;
30 import hunt.sql.parser.SQLSelectParser;
31 import hunt.sql.parser.Token;
32 import hunt.sql.ast.SQLObject;
33 import hunt.sql.util.Utils;
34 import hunt.Number;
35 import hunt.Integer;
36 import hunt.text;
37 import hunt.Boolean;
38 import hunt.Long;
39 import hunt.sql.parser.ParserException;
40 import hunt.String;
41 import std.algorithm.searching;
42 import hunt.sql.parser.SQLParserFeature;
43 import hunt.Exceptions;
44 import hunt.math;
45
46 import hunt.logging;
47
48 import std.concurrency : initOnce;
49
50 public class SQLExprParser : SQLParser {
51
52 private enum string[] strings = [ "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM" ];
53
54 static string[] AGGREGATE_FUNCTIONS() {
55 __gshared string[] inst;
56 return initOnce!inst({
57 long[] codes = AGGREGATE_FUNCTIONS_CODES();
58 string[] r = new string[codes.length];
59
60 foreach(string str ; strings) {
61 long hash = FnvHash.fnv1a_64_lower(str);
62 int index = search(codes, hash);
63 r[index] = str;
64 }
65 return r;
66 }());
67 }
68
69 static long[] AGGREGATE_FUNCTIONS_CODES() {
70 __gshared long[] inst;
71 return initOnce!inst({
72 return FnvHash.fnv1a_64_lower(strings, true);
73 }());
74 }
75
76
77 // public static string[] AGGREGATE_FUNCTIONS =[];
78
79 // public static long[] AGGREGATE_FUNCTIONS_CODES = [];
80
81 // static this(){
82 // string[] strings = [ "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM" ];
83 // AGGREGATE_FUNCTIONS_CODES = FnvHash.fnv1a_64_lower(strings, true);
84 // AGGREGATE_FUNCTIONS = new string[AGGREGATE_FUNCTIONS_CODES.length];
85 // foreach(string str ; strings) {
86 // long hash = FnvHash.fnv1a_64_lower(str);
87 // int index = search(AGGREGATE_FUNCTIONS_CODES, hash);
88 // AGGREGATE_FUNCTIONS[index] = str;
89 // }
90 // }
91
92 protected string[] aggregateFunctions;
93
94 protected long[] aggregateFunctionHashCodes;
95
96 public this(string sql){
97 import std.stdio;
98 aggregateFunctions = AGGREGATE_FUNCTIONS;
99 aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;
100 super(sql);
101 }
102
103 public this(string sql, string dbType){
104 aggregateFunctions = AGGREGATE_FUNCTIONS;
105 aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;
106 super(sql, dbType);
107 }
108
109 public this(Lexer lexer){
110 aggregateFunctions = AGGREGATE_FUNCTIONS;
111 aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;
112 super(lexer);
113 }
114
115 public this(Lexer lexer, string dbType){
116 aggregateFunctions = AGGREGATE_FUNCTIONS;
117 aggregateFunctionHashCodes = AGGREGATE_FUNCTIONS_CODES;
118 super(lexer, dbType);
119 }
120
121 public SQLExpr expr() {
122 if (lexer.token == Token.STAR) {
123 lexer.nextToken();
124
125 SQLExpr expr = new SQLAllColumnExpr();
126
127 if (lexer.token == Token.DOT) {
128 lexer.nextToken();
129 accept(Token.STAR);
130 return new SQLPropertyExpr(expr, "*");
131 }
132
133 return expr;
134 }
135
136 SQLExpr expr = primary();
137
138 Token token = lexer.token;
139 if (token == Token.COMMA) {
140 return expr;
141 } else if (token == Token.EQ) {
142 expr = relationalRest(expr);
143 expr = andRest(expr);
144 expr = xorRest(expr);
145 expr = orRest(expr);
146 return expr;
147 } else {
148 return exprRest(expr);
149 }
150 }
151
152 public SQLExpr exprRest(SQLExpr expr) {
153 expr = bitXorRest(expr);
154 expr = multiplicativeRest(expr);
155 expr = additiveRest(expr);
156 expr = shiftRest(expr);
157 expr = bitAndRest(expr);
158 expr = bitOrRest(expr);
159 expr = inRest(expr);
160 expr = relationalRest(expr);
161 // expr = equalityRest(expr);
162 expr = andRest(expr);
163 expr = xorRest(expr);
164 expr = orRest(expr);
165
166 return expr;
167 }
168
169 public SQLExpr bitXor() {
170 SQLExpr expr = primary();
171 return bitXorRest(expr);
172 }
173
174 public SQLExpr bitXorRest(SQLExpr expr) {
175 Token token = lexer.token;
176 switch (token) {
177 case Token.CARET: {
178 lexer.nextToken();
179 SQLBinaryOperator op;
180 if (lexer.token == Token.EQ) {
181 lexer.nextToken();
182 op = SQLBinaryOperator.BitwiseXorEQ;
183 } else {
184 op = SQLBinaryOperator.BitwiseXor;
185 }
186 SQLExpr rightExp = primary();
187 expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);
188 expr = bitXorRest(expr);
189 break;
190 }
191 case Token.SUBGT:{
192 lexer.nextToken();
193 SQLExpr rightExp = primary();
194 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, dbType);
195 expr = bitXorRest(expr);
196 break;
197 }
198 case Token.LT_SUB_GT: {
199 lexer.nextToken();
200 SQLExpr rightExp = primary();
201 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PG_ST_DISTANCE, rightExp, dbType);
202 expr = bitXorRest(expr);
203 break;
204 }
205 case Token.SUBGTGT:{
206 lexer.nextToken();
207 SQLExpr rightExp = primary();
208 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, dbType);
209 expr = bitXorRest(expr);
210 break;
211 }
212 case Token.POUNDGT: {
213 lexer.nextToken();
214 SQLExpr rightExp = primary();
215 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, dbType);
216 expr = bitXorRest(expr);
217 break;
218 }
219 case Token.POUNDGTGT: {
220 lexer.nextToken();
221 SQLExpr rightExp = primary();
222 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, dbType);
223 expr = bitXorRest(expr);
224 break;
225 }
226 case Token.QUESQUES: {
227 lexer.nextToken();
228 SQLExpr rightExp = primary();
229 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, dbType);
230 expr = bitXorRest(expr);
231 break;
232 }
233 case Token.QUESBAR: {
234 lexer.nextToken();
235 SQLExpr rightExp = primary();
236 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, dbType);
237 expr = bitXorRest(expr);
238 break;
239 }
240 case Token.QUESAMP: {
241 lexer.nextToken();
242 SQLExpr rightExp = primary();
243 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, dbType);
244 expr = bitXorRest(expr);
245 break;
246 }
247
248 default:
249 break;
250 }
251
252
253 return expr;
254 }
255
256 public SQLExpr multiplicative() {
257 SQLExpr expr = bitXor();
258 return multiplicativeRest(expr);
259 }
260
261 public SQLExpr multiplicativeRest(SQLExpr expr) {
262 Token token = lexer.token;
263 if (token == Token.STAR) {
264 lexer.nextToken();
265 SQLExpr rightExp = bitXor();
266 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Multiply, rightExp, getDbType());
267 expr = multiplicativeRest(expr);
268 } else if (token == Token.SLASH) {
269 lexer.nextToken();
270 SQLExpr rightExp = bitXor();
271 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Divide, rightExp, getDbType());
272 expr = multiplicativeRest(expr);
273 } else if (token == Token.PERCENT) {
274 lexer.nextToken();
275 SQLExpr rightExp = bitXor();
276 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, getDbType());
277 expr = multiplicativeRest(expr);
278 } else if (token == Token.DIV) {
279 lexer.nextToken();
280 SQLExpr rightExp = bitXor();
281 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.DIV, rightExp, getDbType());
282 expr = multiplicativeRest(expr);
283 } else if (lexer.identifierEquals(FnvHash.Constants.MOD) || lexer.token == Token.MOD) {
284 Lexer.SavePoint savePoint = lexer.mark();
285 lexer.nextToken();
286
287 if (lexer.token == Token.COMMA || lexer.token == Token.EOF) {
288 lexer.reset(savePoint);
289 return expr;
290 }
291
292 SQLExpr rightExp = bitXor();
293
294 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Modulus, rightExp, dbType);
295
296 expr = multiplicativeRest(expr);
297 }
298 return expr;
299 }
300
301 public SQLIntegerExpr integerExpr() {
302 SQLIntegerExpr intExpr = new SQLIntegerExpr(lexer.integerValue());
303 accept(Token.LITERAL_INT);
304 return intExpr;
305 }
306
307 public int parseIntValue() {
308 if (lexer.token == Token.LITERAL_INT) {
309 Number number = this.lexer.integerValue();
310 int intVal = (cast(Integer) number).intValue();
311 lexer.nextToken();
312 return intVal;
313 } else {
314 throw new ParserException("not int. " ~ lexer.info());
315 }
316 }
317
318 public SQLExpr primary() {
319 List!(string) beforeComments = null;
320 if (lexer.isKeepComments() && lexer.hasComment()) {
321 beforeComments = lexer.readAndResetComments();
322 }
323
324 SQLExpr sqlExpr = null;
325
326 Token tok = lexer.token;
327
328 switch (tok) {
329 case Token.LPAREN:
330 lexer.nextToken();
331
332 sqlExpr = this.expr();
333 if (lexer.token == Token.COMMA) {
334 SQLListExpr listExpr = new SQLListExpr();
335 listExpr.addItem(sqlExpr);
336 do {
337 lexer.nextToken();
338 listExpr.addItem(this.expr());
339 } while (lexer.token == Token.COMMA);
340
341 sqlExpr = listExpr;
342 }
343
344 if (cast(SQLBinaryOpExpr)(sqlExpr) !is null) {
345 (cast(SQLBinaryOpExpr) sqlExpr).setBracket(true);
346 }
347
348 accept(Token.RPAREN);
349
350 if (lexer.token == Token.UNION && cast(SQLQueryExpr)(sqlExpr) !is null) {
351 SQLQueryExpr queryExpr = cast(SQLQueryExpr) sqlExpr;
352
353 SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery());
354 queryExpr.getSubQuery().setQuery(query);
355 }
356 break;
357 case Token.INSERT:
358 lexer.nextToken();
359 if (lexer.token != Token.LPAREN) {
360 throw new ParserException("syntax error. " ~ lexer.info());
361 }
362 sqlExpr = new SQLIdentifierExpr("INSERT");
363 break;
364 case Token.IDENTIFIER:
365 string ident = lexer.stringVal();
366 long hash_lower = lexer.hash_lower;
367 lexer.nextToken();
368
369 if (hash_lower == FnvHash.Constants.DATE
370 && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)
371 && (DBType.ORACLE.name == (dbType)
372 || DBType.POSTGRESQL.name == (dbType)
373 || DBType.MYSQL.name == (dbType))) {
374 SQLExpr literal = this.primary();
375 SQLDateExpr dateExpr = new SQLDateExpr();
376 dateExpr.setLiteral(literal);
377 sqlExpr = dateExpr;
378 } else if (hash_lower == FnvHash.Constants.TIMESTAMP
379 && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)
380 && !(DBType.ORACLE.name == (dbType))) {
381 SQLTimestampExpr dateExpr = new SQLTimestampExpr(lexer.stringVal());
382 lexer.nextToken();
383 sqlExpr = dateExpr;
384 } else if (equalsIgnoreCase(DBType.MYSQL.name, dbType) && ident.startsWith("0x") && (ident.length % 2) == 0) {
385 sqlExpr = new SQLHexExpr(ident.substring(2));
386 } else {
387 sqlExpr = new SQLIdentifierExpr(ident, hash_lower);
388 }
389 break;
390 case Token.NEW:
391 throw new ParserException("TODO " ~ lexer.info());
392 case Token.LITERAL_INT:
393 sqlExpr = new SQLIntegerExpr(lexer.integerValue());
394 lexer.nextToken();
395 break;
396 case Token.LITERAL_FLOAT:
397 sqlExpr = lexer.numberExpr();
398 lexer.nextToken();
399 break;
400 case Token.LITERAL_CHARS: {
401 sqlExpr = new SQLCharExpr(lexer.stringVal());
402
403 if (DBType.MYSQL.name == (dbType)) {
404 lexer.nextTokenValue();
405
406 for (; ; ) {
407 if (lexer.token == Token.LITERAL_ALIAS) {
408 string concat = (cast(SQLCharExpr) sqlExpr).getText().value();
409 concat ~= lexer.stringVal();
410 lexer.nextTokenValue();
411 sqlExpr = new SQLCharExpr(concat);
412 } else if (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.LITERAL_NCHARS) {
413 string concat = (cast(SQLCharExpr) sqlExpr).getText().value();
414 concat ~= lexer.stringVal();
415 lexer.nextTokenValue();
416 sqlExpr = new SQLCharExpr(concat);
417 } else {
418 break;
419 }
420 }
421 } else {
422 lexer.nextToken();
423 }
424 break;
425 } case Token.LITERAL_NCHARS:
426 sqlExpr = new SQLNCharExpr(lexer.stringVal());
427 lexer.nextToken();
428
429 if (DBType.MYSQL.name == (dbType)) {
430 SQLMethodInvokeExpr concat = null;
431 for (; ; ) {
432 if (lexer.token == Token.LITERAL_ALIAS) {
433 if (concat is null) {
434 concat = new SQLMethodInvokeExpr("CONCAT");
435 concat.addParameter(sqlExpr);
436 sqlExpr = concat;
437 }
438 string _alias = lexer.stringVal();
439 lexer.nextToken();
440 SQLCharExpr concat_right = new SQLCharExpr(_alias.substring(1, cast(int)(_alias.length - 1)));
441 concat.addParameter(concat_right);
442 } else if (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.LITERAL_NCHARS) {
443 if (concat is null) {
444 concat = new SQLMethodInvokeExpr("CONCAT");
445 concat.addParameter(sqlExpr);
446 sqlExpr = concat;
447 }
448
449 string chars = lexer.stringVal();
450 lexer.nextToken();
451 SQLCharExpr concat_right = new SQLCharExpr(chars);
452 concat.addParameter(concat_right);
453 } else {
454 break;
455 }
456 }
457 }
458 break;
459 case Token.VARIANT: {
460 string varName = lexer.stringVal();
461 lexer.nextToken();
462
463 if (varName == (":") && lexer.token == Token.IDENTIFIER && DBType.ORACLE.name == (dbType)) {
464 string part2 = lexer.stringVal();
465 lexer.nextToken();
466 varName ~= part2;
467 }
468
469 SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(varName);
470 if (varName.startsWith(":")) {
471 varRefExpr.setIndex(lexer.nextVarIndex());
472 }
473 if (varRefExpr.getName() == ("@") && lexer.token == Token.LITERAL_CHARS) {
474 varRefExpr.setName("@'" ~ lexer.stringVal() ~ "'");
475 lexer.nextToken();
476 } else if (varRefExpr.getName() == ("@@") && lexer.token == Token.LITERAL_CHARS) {
477 varRefExpr.setName("@@'" ~ lexer.stringVal() ~ "'");
478 lexer.nextToken();
479 }
480 sqlExpr = varRefExpr;
481 }
482 break;
483 case Token.DEFAULT:
484 sqlExpr = new SQLDefaultExpr();
485 lexer.nextToken();
486 break;
487 case Token.DUAL:
488 case Token.KEY:
489 case Token.DISTINCT:
490 case Token.LIMIT:
491 case Token.SCHEMA:
492 case Token.COLUMN:
493 case Token.IF:
494 case Token.END:
495 case Token.COMMENT:
496 case Token.COMPUTE:
497 case Token.ENABLE:
498 case Token.DISABLE:
499 case Token.INITIALLY:
500 case Token.SEQUENCE:
501 case Token.USER:
502 case Token.EXPLAIN:
503 case Token.WITH:
504 case Token.GRANT:
505 case Token.REPLACE:
506 case Token.INDEX:
507 case Token.MODEL:
508 case Token.PCTFREE:
509 case Token.INITRANS:
510 case Token.MAXTRANS:
511 case Token.SEGMENT:
512 case Token.CREATION:
513 case Token.IMMEDIATE:
514 case Token.DEFERRED:
515 case Token.STORAGE:
516 case Token.NEXT:
517 case Token.MINEXTENTS:
518 case Token.MAXEXTENTS:
519 case Token.MAXSIZE:
520 case Token.PCTINCREASE:
521 case Token.FLASH_CACHE:
522 case Token.CELL_FLASH_CACHE:
523 case Token.NONE:
524 case Token.LOB:
525 case Token.STORE:
526 case Token.ROW:
527 case Token.CHUNK:
528 case Token.CACHE:
529 case Token.NOCACHE:
530 case Token.LOGGING:
531 case Token.NOCOMPRESS:
532 case Token.KEEP_DUPLICATES:
533 case Token.EXCEPTIONS:
534 case Token.PURGE:
535 case Token.FULL:
536 case Token.TO:
537 case Token.IDENTIFIED:
538 case Token.PASSWORD:
539 case Token.BINARY:
540 case Token.WINDOW:
541 case Token.OFFSET:
542 case Token.SHARE:
543 case Token.START:
544 case Token.CONNECT:
545 case Token.MATCHED:
546 case Token.ERRORS:
547 case Token.REJECT:
548 case Token.UNLIMITED:
549 case Token.BEGIN:
550 case Token.EXCLUSIVE:
551 case Token.MODE:
552 case Token.ADVISE:
553 case Token.VIEW:
554 case Token.ESCAPE:
555 case Token.OVER:
556 case Token.ORDER:
557 case Token.CONSTRAINT:
558 case Token.TYPE:
559 case Token.OPEN:
560 case Token.REPEAT:
561 case Token.TABLE:
562 case Token.TRUNCATE:
563 case Token.EXCEPTION:
564 case Token.FUNCTION:
565 case Token.IDENTITY:
566 case Token.EXTRACT:
567 case Token.DESC:
568 case Token.DO:
569 case Token.GROUP:
570 case Token.MOD:
571 case Token.CONCAT:
572 sqlExpr = new SQLIdentifierExpr(lexer.stringVal());
573 lexer.nextToken();
574 break;
575 case Token.CASE:
576 SQLCaseExpr caseExpr = new SQLCaseExpr();
577 lexer.nextToken();
578 if (lexer.token != Token.WHEN) {
579 caseExpr.setValueExpr(this.expr());
580 }
581
582 accept(Token.WHEN);
583 SQLExpr testExpr = this.expr();
584 accept(Token.THEN);
585 SQLExpr valueExpr = this.expr();
586 SQLCaseExpr.Item caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);
587 caseExpr.addItem(caseItem);
588
589 while (lexer.token == Token.WHEN) {
590 lexer.nextToken();
591 testExpr = this.expr();
592 accept(Token.THEN);
593 valueExpr = this.expr();
594 caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);
595 caseExpr.addItem(caseItem);
596 }
597
598 if (lexer.token == Token.ELSE) {
599 lexer.nextToken();
600 caseExpr.setElseExpr(this.expr());
601 }
602
603 accept(Token.END);
604
605 sqlExpr = caseExpr;
606 break;
607 case Token.EXISTS:
608 lexer.nextToken();
609 accept(Token.LPAREN);
610 sqlExpr = new SQLExistsExpr(createSelectParser().select());
611 accept(Token.RPAREN);
612 break;
613 case Token.NOT:
614 lexer.nextToken();
615 if (lexer.token == Token.EXISTS) {
616 lexer.nextToken();
617 accept(Token.LPAREN);
618 sqlExpr = new SQLExistsExpr(createSelectParser().select(), true);
619 accept(Token.RPAREN);
620 } else if (lexer.token == Token.LPAREN) {
621 lexer.nextToken();
622
623 SQLExpr notTarget = this.expr();
624
625 accept(Token.RPAREN);
626 notTarget = relationalRest(notTarget);
627 sqlExpr = new SQLNotExpr(notTarget);
628
629 return primaryRest(sqlExpr);
630 } else {
631 SQLExpr restExpr = relational();
632 sqlExpr = new SQLNotExpr(restExpr);
633 }
634 break;
635 case Token.SELECT:
636 SQLQueryExpr queryExpr = new SQLQueryExpr(
637 createSelectParser()
638 .select());
639 sqlExpr = queryExpr;
640 break;
641 case Token.CAST:
642 lexer.nextToken();
643 accept(Token.LPAREN);
644 SQLCastExpr _cast = new SQLCastExpr();
645 _cast.setExpr(this.expr());
646 accept(Token.AS);
647 _cast.setDataType(parseDataType(false));
648 accept(Token.RPAREN);
649
650 sqlExpr = _cast;
651 break;
652 case Token.SUB:
653 lexer.nextToken();
654 switch (lexer.token) {
655 case Token.LITERAL_INT:
656 Number integerValue = lexer.integerValue();
657 if (cast(Integer)(integerValue) !is null) {
658 int intVal = (cast(Integer) integerValue).intValue();
659 if (intVal == Integer.MIN_VALUE) {
660 integerValue = Long.valueOf((cast(long) intVal) * -1);
661 } else {
662 integerValue = Integer.valueOf(intVal * -1);
663 }
664 } else if (cast(Long)(integerValue) !is null) {
665 long longVal = (cast(Long) integerValue).longValue();
666 if (longVal == 2147483648L) {
667 integerValue = Integer.valueOf(cast(int) ((cast(long) longVal) * -1));
668 } else {
669 integerValue = Long.valueOf(longVal * -1);
670 }
671 } else {
672 integerValue = (cast(BigInteger) integerValue).negate();
673 }
674 sqlExpr = new SQLIntegerExpr(integerValue);
675 lexer.nextToken();
676 break;
677 case Token.LITERAL_FLOAT:
678 sqlExpr = lexer.numberExpr(true);
679 lexer.nextToken();
680 break;
681 case Token.IDENTIFIER: // 当负号后面为字段的情况
682 sqlExpr = new SQLIdentifierExpr(lexer.stringVal());
683 lexer.nextToken();
684
685 if (lexer.token == Token.LPAREN || lexer.token == Token.LBRACKET) {
686 sqlExpr = primaryRest(sqlExpr);
687 }
688 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);
689
690 break;
691 case Token.QUES: {
692 SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr("?");
693 variantRefExpr.setIndex(lexer.nextVarIndex());
694 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, variantRefExpr);
695 lexer.nextToken();
696 break;
697 }
698 case Token.LPAREN:
699 lexer.nextToken();
700 sqlExpr = this.expr();
701 accept(Token.RPAREN);
702 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);
703 break;
704 case Token.BANG:
705 sqlExpr = this.expr();
706 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);
707 break;
708 default:
709 throw new ParserException("TODO : " ~ lexer.info());
710 }
711 break;
712 case Token.PLUS:
713 lexer.nextToken();
714 switch (lexer.token) {
715 case Token.LITERAL_INT:
716 sqlExpr = new SQLIntegerExpr(lexer.integerValue());
717 lexer.nextToken();
718 break;
719 case Token.LITERAL_FLOAT:
720 sqlExpr = lexer.numberExpr();
721 lexer.nextToken();
722 break;
723 case Token.IDENTIFIER: // 当~号后面为字段的情况
724 sqlExpr = new SQLIdentifierExpr(lexer.stringVal());
725 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);
726 lexer.nextToken();
727 break;
728 case Token.LPAREN:
729 lexer.nextToken();
730 sqlExpr = this.expr();
731 accept(Token.RPAREN);
732 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);
733 break;
734 case Token.SUB:
735 sqlExpr = this.expr();
736 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);
737 break;
738 default:
739 throw new ParserException("TODO " ~ lexer.info());
740 }
741 break;
742 case Token.TILDE:
743 lexer.nextToken();
744 SQLExpr unaryValueExpr = primary();
745 SQLUnaryExpr unary = new SQLUnaryExpr(SQLUnaryOperator.Compl, unaryValueExpr);
746 sqlExpr = unary;
747 break;
748 case Token.QUES:
749 if (DBType.MYSQL.name == (dbType)) {
750 lexer.nextTokenValue();
751 } else {
752 lexer.nextToken();
753 }
754 SQLVariantRefExpr quesVarRefExpr = new SQLVariantRefExpr("?");
755 quesVarRefExpr.setIndex(lexer.nextVarIndex());
756 sqlExpr = quesVarRefExpr;
757 break;
758 case Token.LEFT:
759 sqlExpr = new SQLIdentifierExpr("LEFT");
760 lexer.nextToken();
761 break;
762 case Token.RIGHT:
763 sqlExpr = new SQLIdentifierExpr("RIGHT");
764 lexer.nextToken();
765 break;
766 case Token.DATABASE:
767 sqlExpr = new SQLIdentifierExpr("DATABASE");
768 lexer.nextToken();
769 break;
770 case Token.LOCK:
771 sqlExpr = new SQLIdentifierExpr("LOCK");
772 lexer.nextToken();
773 break;
774 case Token.NULL:
775 sqlExpr = new SQLNullExpr();
776 lexer.nextToken();
777 break;
778 case Token.BANG:
779 lexer.nextToken();
780 SQLExpr bangExpr = primary();
781 sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Not, bangExpr);
782 break;
783 case Token.LITERAL_HEX:
784 string hex = lexer.hexString();
785 sqlExpr = new SQLHexExpr(hex);
786 lexer.nextToken();
787 break;
788 case Token.INTERVAL:
789 sqlExpr = parseInterval();
790 break;
791 case Token.COLON:
792 lexer.nextToken();
793 if (lexer.token == Token.LITERAL_ALIAS) {
794 sqlExpr = new SQLVariantRefExpr(":\"" ~ lexer.stringVal() ~ "\"");
795 lexer.nextToken();
796 }
797 break;
798 case Token.ANY:
799 sqlExpr = parseAny();
800 break;
801 case Token.SOME:
802 sqlExpr = parseSome();
803 break;
804 case Token.ALL:
805 sqlExpr = parseAll();
806 break;
807 case Token.LITERAL_ALIAS:
808 sqlExpr = parseAliasExpr(lexer.stringVal());
809 lexer.nextToken();
810 break;
811 case Token.EOF:
812 throw new ParserException("EOF");
813 case Token.TRUE:
814 lexer.nextToken();
815 sqlExpr = new SQLBooleanExpr(true);
816 break;
817 case Token.FALSE:
818 lexer.nextToken();
819 sqlExpr = new SQLBooleanExpr(false);
820 break;
821 case Token.BITS: {
822 string strVal = lexer.stringVal();
823 lexer.nextToken();
824 sqlExpr = new SQLBinaryExpr(strVal);
825 break;
826 }
827 case Token.CONTAINS:
828 sqlExpr = inRest(null);
829 break;
830 case Token.SET: {
831 Lexer.SavePoint savePoint = lexer.mark();
832 lexer.nextToken();
833 if (lexer.token() == Token.LPAREN) {
834 sqlExpr = new SQLIdentifierExpr("SET");
835 } else {
836 lexer.reset(savePoint);
837 throw new ParserException("ERROR. " ~ lexer.info());
838 }
839 break;
840 }
841
842 default:
843 throw new ParserException("ERROR. " ~ lexer.info());
844 }
845
846 SQLExpr expr = primaryRest(sqlExpr);
847
848 if (beforeComments !is null) {
849 expr.addBeforeComment(beforeComments);
850 }
851
852 return expr;
853 }
854
855 protected SQLExpr parseAll() {
856 SQLExpr sqlExpr;
857 lexer.nextToken();
858 SQLAllExpr allExpr = new SQLAllExpr();
859
860 accept(Token.LPAREN);
861 SQLSelect allSubQuery = createSelectParser().select();
862 allExpr.setSubQuery(allSubQuery);
863 accept(Token.RPAREN);
864
865 allSubQuery.setParent(allExpr);
866
867 sqlExpr = allExpr;
868 return sqlExpr;
869 }
870
871 protected SQLExpr parseSome() {
872 SQLExpr sqlExpr;
873 lexer.nextToken();
874 SQLSomeExpr someExpr = new SQLSomeExpr();
875
876 accept(Token.LPAREN);
877 SQLSelect someSubQuery = createSelectParser().select();
878 someExpr.setSubQuery(someSubQuery);
879 accept(Token.RPAREN);
880
881 someSubQuery.setParent(someExpr);
882
883 sqlExpr = someExpr;
884 return sqlExpr;
885 }
886
887 protected SQLExpr parseAny() {
888 SQLExpr sqlExpr;
889 lexer.nextToken();
890 if (lexer.token == Token.LPAREN) {
891 accept(Token.LPAREN);
892
893 if (lexer.token == Token.ARRAY || lexer.token == Token.IDENTIFIER) {
894 SQLExpr expr = this.expr();
895 SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr("ANY");
896 methodInvokeExpr.addParameter(expr);
897 accept(Token.RPAREN);
898 return methodInvokeExpr;
899 }
900
901 SQLSelect anySubQuery = createSelectParser().select();
902 SQLAnyExpr anyExpr = new SQLAnyExpr(anySubQuery);
903 accept(Token.RPAREN);
904
905 sqlExpr = anyExpr;
906 } else {
907 sqlExpr = new SQLIdentifierExpr("ANY");
908 }
909 return sqlExpr;
910 }
911
912 protected SQLExpr parseAliasExpr(string _alias) {
913 return new SQLIdentifierExpr(_alias);
914 }
915
916 protected SQLExpr parseInterval() {
917 throw new ParserException("TODO. " ~ lexer.info());
918 }
919
920 public SQLSelectParser createSelectParser() {
921 return new SQLSelectParser(this);
922 }
923
924 public SQLExpr primaryRest(SQLExpr expr) {
925 if (expr is null) {
926 throw new Exception("expr");
927 }
928
929 Token token = lexer.token;
930 if (token == Token.OF) {
931 if (cast(SQLIdentifierExpr)(expr) !is null) {
932 long hashCode64 = (cast(SQLIdentifierExpr) expr).hashCode64();
933 if (hashCode64 == FnvHash.Constants.CURRENT) {
934 lexer.nextToken();
935 SQLName cursorName = this.name();
936 return new SQLCurrentOfCursorExpr(cursorName);
937 }
938 }
939 } else if (token == Token.FOR) {
940 if (cast(SQLIdentifierExpr)(expr) !is null) {
941 SQLIdentifierExpr idenExpr = cast(SQLIdentifierExpr) expr;
942 if (idenExpr.hashCode64() == FnvHash.Constants.NEXTVAL) {
943 lexer.nextToken();
944 SQLName seqName = this.name();
945 SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.NextVal);
946 return seqExpr;
947 } else if (idenExpr.hashCode64() == FnvHash.Constants.CURRVAL) {
948 lexer.nextToken();
949 SQLName seqName = this.name();
950 SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.CurrVal);
951 return seqExpr;
952 } else if (idenExpr.hashCode64() == FnvHash.Constants.PREVVAL) {
953 lexer.nextToken();
954 SQLName seqName = this.name();
955 SQLSequenceExpr seqExpr = new SQLSequenceExpr(seqName, SQLSequenceExpr.Function.PrevVal);
956 return seqExpr;
957 }
958 }
959 }
960
961 if (token == Token.DOT) {
962 lexer.nextToken();
963
964 if (cast(SQLCharExpr)(expr) !is null) {
965 string text = (cast(SQLCharExpr) expr).getText().value();
966 expr = new SQLIdentifierExpr(text);
967 }
968
969 expr = dotRest(expr);
970 return primaryRest(expr);
971 } else if (lexer.identifierEquals(FnvHash.Constants.SETS) //
972 && typeid(expr) == typeid(SQLIdentifierExpr) //
973 && "GROUPING".equalsIgnoreCase((cast(SQLIdentifierExpr) expr).getName())) {
974 SQLGroupingSetExpr groupingSets = new SQLGroupingSetExpr();
975 lexer.nextToken();
976
977 accept(Token.LPAREN);
978
979 for (; ; ) {
980 SQLExpr item;
981 if (lexer.token == Token.LPAREN) {
982 lexer.nextToken();
983
984 SQLListExpr listExpr = new SQLListExpr();
985 this.exprList(listExpr.getItems(), listExpr);
986 item = listExpr;
987
988 accept(Token.RPAREN);
989 } else {
990 item = this.expr();
991 }
992
993 item.setParent(groupingSets);
994 groupingSets.addParameter(item);
995
996 if (lexer.token == Token.RPAREN) {
997 break;
998 }
999
1000 accept(Token.COMMA);
1001 }
1002
1003 this.exprList(groupingSets.getParameters(), groupingSets);
1004
1005 accept(Token.RPAREN);
1006
1007 return groupingSets;
1008 } else {
1009 if (lexer.token == Token.LPAREN) {
1010 return methodRest(expr, true);
1011 }
1012 }
1013
1014 return expr;
1015 }
1016
1017 protected SQLExpr parseExtract() {
1018 throw new ParserException("not supported.");
1019 }
1020
1021 protected SQLExpr parsePosition() {
1022 throw new ParserException("not supported.");
1023 }
1024
1025 protected SQLExpr parseMatch() {
1026 throw new ParserException("not supported.");
1027 }
1028
1029 protected SQLExpr methodRest(SQLExpr expr, bool acceptLPAREN) {
1030 if (acceptLPAREN) {
1031 accept(Token.LPAREN);
1032 }
1033
1034 bool distinct = false;
1035 if (lexer.token == Token.DISTINCT) {
1036 lexer.nextToken();
1037 distinct = true;
1038 }
1039
1040 string methodName = null;
1041 string aggMethodName = null;
1042 SQLMethodInvokeExpr methodInvokeExpr;
1043 SQLExpr owner = null;
1044 string trimOption = null;
1045
1046 long hash_lower = 0L;
1047 if (cast(SQLIdentifierExpr)(expr) !is null) {
1048 SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr) expr;
1049 methodName = identifierExpr.getName();
1050 hash_lower = identifierExpr.nameHashCode64();
1051
1052 if (hash_lower == FnvHash.Constants.TRIM) {
1053 if (lexer.identifierEquals(FnvHash.Constants.LEADING)) {
1054 trimOption = lexer.stringVal();
1055 lexer.nextToken();
1056 } else if (lexer.identifierEquals(FnvHash.Constants.BOTH)) {
1057 trimOption = lexer.stringVal();
1058 lexer.nextToken();
1059 } else if (lexer.identifierEquals(FnvHash.Constants.TRAILING)) {
1060 trimOption = lexer.stringVal();
1061 lexer.nextToken();
1062 }
1063 } else if (hash_lower == FnvHash.Constants.MATCH
1064 && DBType.MYSQL.name == (dbType)) {
1065 return parseMatch();
1066 } else if (hash_lower == FnvHash.Constants.EXTRACT
1067 && DBType.MYSQL.name == (dbType)) {
1068 return parseExtract();
1069 } else if (hash_lower == FnvHash.Constants.POSITION
1070 && DBType.MYSQL.name == (dbType)) {
1071 return parsePosition();
1072 } else if (hash_lower == FnvHash.Constants.INT4 && DBType.POSTGRESQL.name == (dbType)) {
1073 PGTypeCastExpr castExpr = new PGTypeCastExpr();
1074 castExpr.setExpr(this.expr());
1075 castExpr.setDataType(new SQLDataTypeImpl(methodName));
1076 accept(Token.RPAREN);
1077 return castExpr;
1078 } else if (hash_lower == FnvHash.Constants.VARBIT && DBType.POSTGRESQL.name == (dbType)) {
1079 PGTypeCastExpr castExpr = new PGTypeCastExpr();
1080 SQLExpr len = this.primary();
1081 castExpr.setDataType(new SQLDataTypeImpl(methodName, len));
1082 accept(Token.RPAREN);
1083 castExpr.setExpr(this.expr());
1084 return castExpr;
1085 }
1086 aggMethodName = getAggreateFunction(hash_lower);
1087 } else if (cast(SQLPropertyExpr)(expr) !is null) {
1088 methodName = (cast(Object)(expr)).toString();
1089 aggMethodName = SQLUtils.normalize(methodName);
1090 hash_lower = FnvHash.fnv1a_64_lower(aggMethodName);
1091 aggMethodName = getAggreateFunction(hash_lower);
1092
1093 owner = (cast(SQLPropertyExpr) expr).getOwner();
1094 } else if (cast(SQLDefaultExpr)(expr) !is null) {
1095 methodName = "DEFAULT";
1096 } else if (cast(SQLCharExpr)(expr) !is null) {
1097 methodName = (cast(SQLCharExpr) expr).getText().value();
1098 }
1099
1100 if (aggMethodName !is null) {
1101 SQLAggregateExpr aggregateExpr = parseAggregateExpr(aggMethodName);
1102 if (distinct) {
1103 aggregateExpr.setOption(SQLAggregateOption.DISTINCT);
1104 }
1105
1106
1107 return aggregateExpr;
1108 }
1109
1110 methodInvokeExpr = new SQLMethodInvokeExpr(methodName, hash_lower);
1111 if (owner !is null) {
1112 methodInvokeExpr.setOwner(owner);
1113 }
1114 if (trimOption !is null) {
1115 methodInvokeExpr.setTrimOption(trimOption);
1116 }
1117
1118 Token token = lexer.token;
1119 if (token != Token.RPAREN && token != Token.FROM) {
1120 exprList(methodInvokeExpr.getParameters(), methodInvokeExpr);
1121 }
1122
1123 if (hash_lower == FnvHash.Constants.EXIST
1124 && methodInvokeExpr.getParameters().size() == 1
1125 && methodInvokeExpr.getParameters().get(0) !is null) {
1126 throw new ParserException("exists syntax error.");
1127 }
1128
1129 if (lexer.token == Token.FROM) {
1130 lexer.nextToken();
1131 SQLExpr from = this.expr();
1132 methodInvokeExpr.setFrom(from);
1133
1134 if (lexer.token == Token.FOR) {
1135 lexer.nextToken();
1136 SQLExpr forExpr = this.expr();
1137 methodInvokeExpr.setFor(forExpr);
1138 }
1139 }
1140
1141 if (lexer.token == Token.USING || lexer.identifierEquals(FnvHash.Constants.USING)) {
1142 lexer.nextToken();
1143 SQLExpr using;
1144 if (lexer.token == Token.STAR) {
1145 lexer.nextToken();
1146 using = new SQLAllColumnExpr();
1147 } else if (lexer.token == Token.BINARY) {
1148 using = new SQLIdentifierExpr(lexer.stringVal());
1149 lexer.nextToken();
1150 } else {
1151 using = this.primary();
1152 }
1153 methodInvokeExpr.setUsing(using);
1154 }
1155
1156 SQLAggregateExpr aggregateExpr = null;
1157 if (lexer.token == Token.ORDER) {
1158 lexer.nextToken();
1159 accept(Token.BY);
1160
1161 aggregateExpr = new SQLAggregateExpr(methodName);
1162 aggregateExpr.getArguments().addAll(methodInvokeExpr.getParameters());
1163
1164 SQLOrderBy orderBy = new SQLOrderBy();
1165 this.orderBy(orderBy.getItems(), orderBy);
1166 aggregateExpr.setWithinGroup(orderBy);
1167 }
1168
1169 accept(Token.RPAREN);
1170
1171 if (lexer.token == Token.OVER) {
1172 if (aggregateExpr is null) {
1173 aggregateExpr = new SQLAggregateExpr(methodName);
1174 aggregateExpr.getArguments().addAll(methodInvokeExpr.getParameters());
1175 }
1176 over(aggregateExpr);
1177 }
1178
1179 if (aggregateExpr !is null) {
1180 return primaryRest(aggregateExpr);
1181 }
1182
1183 return primaryRest(methodInvokeExpr);
1184
1185 //throw new ParserException("not support token:" ~ lexer.token ~ ", " ~ lexer.info());
1186 }
1187
1188 protected SQLExpr dotRest(SQLExpr expr) {
1189 if (lexer.token == Token.STAR) {
1190 lexer.nextToken();
1191 expr = new SQLPropertyExpr(expr, "*");
1192 } else {
1193 string name;
1194 long hash_lower = 0L;
1195
1196 if (lexer.token == Token.IDENTIFIER) {
1197 name = lexer.stringVal();
1198 hash_lower = lexer.hash_lower;
1199 lexer.nextToken();
1200 } else if (lexer.token == Token.LITERAL_CHARS
1201 || lexer.token == Token.LITERAL_ALIAS) {
1202 name = lexer.stringVal();
1203 lexer.nextToken();
1204 } else if (lexer.getKeywods().containsValue(lexer.token)) {
1205 name = lexer.stringVal();
1206 lexer.nextToken();
1207 } else {
1208 throw new ParserException("error : " ~ lexer.info());
1209 }
1210
1211 if (lexer.token == Token.LPAREN) {
1212 bool aggregate = hash_lower == FnvHash.Constants.WM_CONCAT
1213 && cast(SQLIdentifierExpr)(expr) !is null
1214 && (cast(SQLIdentifierExpr) expr).nameHashCode64() == FnvHash.Constants.WMSYS;
1215 expr = methodRest(expr, name, aggregate);
1216 } else {
1217 expr = new SQLPropertyExpr(expr, name, hash_lower);
1218 }
1219 }
1220
1221 expr = primaryRest(expr);
1222 return expr;
1223 }
1224
1225 private SQLExpr methodRest(SQLExpr expr, string name, bool aggregate) {
1226 lexer.nextToken();
1227
1228 if (lexer.token == Token.DISTINCT) {
1229 lexer.nextToken();
1230
1231 string aggreateMethodName = (cast(Object)(expr)).toString() ~ "." ~ name;
1232 SQLAggregateExpr aggregateExpr = new SQLAggregateExpr(aggreateMethodName, SQLAggregateOption.DISTINCT);
1233
1234 if (lexer.token == Token.RPAREN) {
1235 lexer.nextToken();
1236 } else {
1237 if (lexer.token == Token.PLUS) {
1238 aggregateExpr.getArguments().add(new SQLIdentifierExpr("~"));
1239 lexer.nextToken();
1240 } else {
1241 exprList(aggregateExpr.getArguments(), aggregateExpr);
1242 }
1243 accept(Token.RPAREN);
1244 }
1245 expr = aggregateExpr;
1246 } else if (aggregate) {
1247 SQLAggregateExpr methodInvokeExpr = new SQLAggregateExpr(name);
1248 methodInvokeExpr.setMethodName((cast(Object)(expr)).toString() ~ "." ~ name);
1249 if (lexer.token == Token.RPAREN) {
1250 lexer.nextToken();
1251 } else {
1252 if (lexer.token == Token.PLUS) {
1253 methodInvokeExpr.addArgument(new SQLIdentifierExpr("~"));
1254 lexer.nextToken();
1255 } else {
1256 exprList(methodInvokeExpr.getArguments(), methodInvokeExpr);
1257 }
1258 accept(Token.RPAREN);
1259 }
1260
1261 if (lexer.token == Token.OVER) {
1262 over(methodInvokeExpr);
1263 }
1264
1265 expr = methodInvokeExpr;
1266 } else {
1267 SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(name);
1268 methodInvokeExpr.setOwner(expr);
1269 if (lexer.token == Token.RPAREN) {
1270 lexer.nextToken();
1271 } else {
1272 if (lexer.token == Token.PLUS) {
1273 methodInvokeExpr.addParameter(new SQLIdentifierExpr("~"));
1274 lexer.nextToken();
1275 } else {
1276 exprList(methodInvokeExpr.getParameters(), methodInvokeExpr);
1277 }
1278 accept(Token.RPAREN);
1279 }
1280 expr = methodInvokeExpr;
1281 }
1282 return expr;
1283 }
1284
1285 public SQLExpr groupComparisionRest(SQLExpr expr) {
1286 return expr;
1287 }
1288
1289 public void names(Collection!(SQLName) exprCol) {
1290 names(exprCol, null);
1291 }
1292
1293 public void names(Collection!(SQLName) exprCol, SQLObject parent) {
1294 if (lexer.token == Token.RBRACE) {
1295 return;
1296 }
1297
1298 if (lexer.token == Token.EOF) {
1299 return;
1300 }
1301
1302 SQLName name = name();
1303 name.setParent(parent);
1304 exprCol.add(name);
1305
1306 while (lexer.token == Token.COMMA) {
1307 lexer.nextToken();
1308
1309 name = this.name();
1310 name.setParent(parent);
1311 exprCol.add(name);
1312 }
1313 }
1314
1315 //@Deprecated
1316 public void exprList(Collection!(SQLExpr) exprCol) {
1317 exprList(exprCol, null);
1318 }
1319
1320 public void exprList(Collection!(SQLExpr) exprCol, SQLObject parent) {
1321 if (lexer.token == Token.RPAREN || lexer.token == Token.RBRACKET) {
1322 return;
1323 }
1324
1325 if (lexer.token == Token.EOF) {
1326 return;
1327 }
1328
1329 SQLExpr expr = expr();
1330 expr.setParent(parent);
1331 exprCol.add(expr);
1332
1333 while (lexer.token == Token.COMMA) {
1334 lexer.nextToken();
1335 expr = this.expr();
1336 expr.setParent(parent);
1337 exprCol.add(expr);
1338 }
1339 }
1340
1341 public SQLName name() {
1342 string identName;
1343 long hash = 0;
1344 if (lexer.token == Token.LITERAL_ALIAS) {
1345 identName = lexer.stringVal();
1346 lexer.nextToken();
1347 } else if (lexer.token == Token.IDENTIFIER) {
1348 identName = lexer.stringVal();
1349
1350 char c0 = charAt(identName, 0);
1351 if (c0 != '[') {
1352 hash = lexer.hash_lower();
1353 }
1354 lexer.nextToken();
1355 } else if (lexer.token == Token.LITERAL_CHARS) {
1356 identName = '\'' ~ lexer.stringVal() ~ '\'';
1357 lexer.nextToken();
1358 } else if (lexer.token == Token.VARIANT) {
1359 identName = lexer.stringVal();
1360 lexer.nextToken();
1361 } else {
1362 switch (lexer.token) {
1363 case Token.MODEL:
1364 case Token.PCTFREE:
1365 case Token.INITRANS:
1366 case Token.MAXTRANS:
1367 case Token.SEGMENT:
1368 case Token.CREATION:
1369 case Token.IMMEDIATE:
1370 case Token.DEFERRED:
1371 case Token.STORAGE:
1372 case Token.NEXT:
1373 case Token.MINEXTENTS:
1374 case Token.MAXEXTENTS:
1375 case Token.MAXSIZE:
1376 case Token.PCTINCREASE:
1377 case Token.FLASH_CACHE:
1378 case Token.CELL_FLASH_CACHE:
1379 case Token.NONE:
1380 case Token.LOB:
1381 case Token.STORE:
1382 case Token.ROW:
1383 case Token.CHUNK:
1384 case Token.CACHE:
1385 case Token.NOCACHE:
1386 case Token.LOGGING:
1387 case Token.NOCOMPRESS:
1388 case Token.KEEP_DUPLICATES:
1389 case Token.EXCEPTIONS:
1390 case Token.PURGE:
1391 case Token.INITIALLY:
1392 case Token.END:
1393 case Token.COMMENT:
1394 case Token.ENABLE:
1395 case Token.DISABLE:
1396 case Token.SEQUENCE:
1397 case Token.USER:
1398 case Token.ANALYZE:
1399 case Token.OPTIMIZE:
1400 case Token.GRANT:
1401 case Token.REVOKE:
1402 // binary有很多含义,lexer识别了这个token,实际上应该当做普通IDENTIFIER
1403 case Token.BINARY:
1404 case Token.OVER:
1405 case Token.ORDER:
1406 case Token.DO:
1407 case Token.JOIN:
1408 case Token.TYPE:
1409 case Token.FUNCTION:
1410 case Token.KEY:
1411 case Token.SCHEMA:
1412 case Token.INTERVAL:
1413 case Token.EXPLAIN:
1414 case Token.PARTITION:
1415 case Token.SET:
1416 identName = lexer.stringVal();
1417 lexer.nextToken();
1418 break;
1419 default:
1420 throw new ParserException("error " ~ lexer.info());
1421 }
1422 }
1423
1424 SQLName name = new SQLIdentifierExpr(identName, hash);
1425
1426 name = nameRest(name);
1427
1428 return name;
1429 }
1430
1431 public SQLName nameRest(SQLName name) {
1432 if (lexer.token == Token.DOT) {
1433 lexer.nextToken();
1434
1435 if (lexer.token == Token.KEY) {
1436 name = new SQLPropertyExpr(name, "KEY");
1437 lexer.nextToken();
1438 return name;
1439 }
1440
1441 if (lexer.token != Token.LITERAL_ALIAS && lexer.token != Token.IDENTIFIER
1442 && (!lexer.getKeywods().containsValue(lexer.token))) {
1443 throw new ParserException("error, " ~ lexer.info());
1444 }
1445
1446 if (lexer.token == Token.LITERAL_ALIAS) {
1447 name = new SQLPropertyExpr(name, lexer.stringVal());
1448 } else {
1449 name = new SQLPropertyExpr(name, lexer.stringVal());
1450 }
1451 lexer.nextToken();
1452 name = nameRest(name);
1453 }
1454
1455 return name;
1456 }
1457
1458 public bool isAggreateFunction(string word) {
1459 long hash_lower = FnvHash.fnv1a_64_lower(word);
1460 return isAggreateFunction(hash_lower);
1461 }
1462
1463 protected bool isAggreateFunction(long hash_lower) {
1464 return search(aggregateFunctionHashCodes, hash_lower) >= 0;
1465 }
1466
1467 protected string getAggreateFunction(long hash_lower) {
1468 int index = search(aggregateFunctionHashCodes, hash_lower);
1469 if (index < 0) {
1470 return null;
1471 }
1472 return aggregateFunctions[index];
1473 }
1474
1475 protected SQLAggregateExpr parseAggregateExpr(string methodName) {
1476 SQLAggregateExpr aggregateExpr;
1477 if (lexer.token == Token.ALL) {
1478 aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.ALL);
1479 lexer.nextToken();
1480 } else if (lexer.token == Token.DISTINCT) {
1481 aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DISTINCT);
1482 lexer.nextToken();
1483 } else if (lexer.identifierEquals(FnvHash.Constants.DEDUPLICATION)) { // just for nut
1484 aggregateExpr = new SQLAggregateExpr(methodName, SQLAggregateOption.DEDUPLICATION);
1485 lexer.nextToken();
1486 } else {
1487 aggregateExpr = new SQLAggregateExpr(methodName);
1488 }
1489
1490 exprList(aggregateExpr.getArguments(), aggregateExpr);
1491
1492 if (lexer.token != Token.RPAREN) {
1493 parseAggregateExprRest(aggregateExpr);
1494 }
1495
1496 accept(Token.RPAREN);
1497
1498 if (lexer.identifierEquals(FnvHash.Constants.FILTER)) {
1499 filter(aggregateExpr);
1500 }
1501
1502 if (lexer.token == Token.OVER) {
1503 over(aggregateExpr);
1504 }
1505
1506 return aggregateExpr;
1507 }
1508
1509 protected void filter(SQLAggregateExpr aggregateExpr) {
1510
1511 }
1512
1513 public void over(SQLAggregateExpr aggregateExpr) {
1514 lexer.nextToken();
1515
1516 if (lexer.token != Token.LPAREN) {
1517 SQLName overRef = this.name();
1518 aggregateExpr.setOverRef(overRef);
1519 return;
1520 }
1521
1522 SQLOver Sover = new SQLOver();
1523 over(Sover);
1524 aggregateExpr.setOver(Sover);
1525 }
1526
1527 public void over(SQLOver over) {
1528 lexer.nextToken();
1529
1530 if (lexer.token == Token.PARTITION || lexer.identifierEquals("PARTITION")) {
1531 lexer.nextToken();
1532 accept(Token.BY);
1533
1534 if (lexer.token == (Token.LPAREN)) {
1535 lexer.nextToken();
1536 exprList(over.getPartitionBy(), over);
1537 accept(Token.RPAREN);
1538 } else {
1539 exprList(over.getPartitionBy(), over);
1540 }
1541 }
1542
1543 over.setOrderBy(parseOrderBy());
1544
1545 if (lexer.token == Token.OF) {
1546 lexer.nextToken();
1547 SQLName of = this.name();
1548 over.setOf(of);
1549 }
1550
1551 SQLOver.WindowingType windowingType;
1552 bool is_set =false;
1553 if (lexer.identifierEquals(FnvHash.Constants.ROWS) || lexer.token == Token.ROWS) {
1554 windowingType = SQLOver.WindowingType.ROWS;
1555 is_set =true;
1556
1557 } else if (lexer.identifierEquals(FnvHash.Constants.RANGE)) {
1558 windowingType = SQLOver.WindowingType.RANGE;
1559 is_set =true;
1560 }
1561
1562 if (is_set) {
1563 over.setWindowingType(windowingType);
1564 lexer.nextToken();
1565
1566 if (lexer.token == Token.BETWEEN) {
1567 lexer.nextToken();
1568 SQLExpr rowsBegin = this.primary();
1569 over.setWindowingBetweenBegin(rowsBegin);
1570
1571 if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {
1572 over.setWindowingBetweenBeginPreceding(true);
1573 lexer.nextToken();
1574 } else if (lexer.identifierEquals(FnvHash.Constants.FOLLOWING)) {
1575 over.setWindowingBetweenBeginFollowing(true);
1576 lexer.nextToken();
1577 }
1578
1579 accept(Token.AND);
1580
1581 SQLExpr betweenEnd;
1582 if (lexer.identifierEquals(FnvHash.Constants.CURRENT) || lexer.token == Token.CURRENT) {
1583 lexer.nextToken();
1584 if (lexer.identifierEquals(FnvHash.Constants.ROW)) {
1585 lexer.nextToken();
1586 } else {
1587 accept(Token.ROW);
1588 }
1589 betweenEnd = new SQLIdentifierExpr("CURRENT ROW");
1590 } else {
1591 betweenEnd = this.primary();
1592 }
1593 over.setWindowingBetweenEnd(betweenEnd);
1594
1595 if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {
1596 over.setWindowingBetweenEndPreceding(true);
1597 lexer.nextToken();
1598 } else if (lexer.identifierEquals(FnvHash.Constants.FOLLOWING)) {
1599 over.setWindowingBetweenEndFollowing(true);
1600 lexer.nextToken();
1601 }
1602
1603 } else {
1604
1605 if (lexer.identifierEquals(FnvHash.Constants.CURRENT)) {
1606 lexer.nextToken();
1607 if (lexer.identifierEquals(FnvHash.Constants.ROW)) {
1608 lexer.nextToken();
1609 } else {
1610 accept(Token.ROW);
1611 }
1612 over.setWindowing(new SQLIdentifierExpr("CURRENT ROW"));
1613 } else if (lexer.identifierEquals(FnvHash.Constants.UNBOUNDED)) {
1614 lexer.nextToken();
1615 over.setWindowing(new SQLIdentifierExpr("UNBOUNDED"));
1616
1617 if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {
1618 over.setWindowingPreceding(true);
1619 lexer.nextToken();
1620 } else if (lexer.identifierEquals("FOLLOWING")) {
1621 over.setWindowingFollowing(true);
1622 lexer.nextToken();
1623 }
1624 } else {
1625 SQLIntegerExpr rowsExpr = cast(SQLIntegerExpr) this.primary();
1626 over.setWindowing(rowsExpr);
1627
1628 if (lexer.identifierEquals(FnvHash.Constants.PRECEDING)) {
1629 over.setWindowingPreceding(true);
1630 lexer.nextToken();
1631 } else if (lexer.identifierEquals(FnvHash.Constants.FOLLOWING)) {
1632 over.setWindowingFollowing(true);
1633 lexer.nextToken();
1634 }
1635 }
1636 }
1637 }
1638
1639 accept(Token.RPAREN);
1640 }
1641
1642 protected SQLAggregateExpr parseAggregateExprRest(SQLAggregateExpr aggregateExpr) {
1643 return aggregateExpr;
1644 }
1645
1646 public SQLOrderBy parseOrderBy() {
1647 if (lexer.token == Token.ORDER) {
1648 SQLOrderBy SorderBy = new SQLOrderBy();
1649
1650 lexer.nextToken();
1651
1652 if (lexer.identifierEquals(FnvHash.Constants.SIBLINGS)) {
1653 lexer.nextToken();
1654 SorderBy.setSibings(true);
1655 }
1656
1657 accept(Token.BY);
1658
1659 orderBy(SorderBy.getItems(), SorderBy);
1660
1661 return SorderBy;
1662 }
1663
1664 return null;
1665 }
1666
1667 public void orderBy(List!(SQLSelectOrderByItem) items, SQLObject parent) {
1668 SQLSelectOrderByItem item = parseSelectOrderByItem();
1669 item.setParent(parent);
1670 items.add(item);
1671 while (lexer.token == Token.COMMA) {
1672 lexer.nextToken();
1673 item = parseSelectOrderByItem();
1674 item.setParent(parent);
1675 items.add(item);
1676 }
1677 }
1678
1679 public SQLSelectOrderByItem parseSelectOrderByItem() {
1680 SQLSelectOrderByItem item = new SQLSelectOrderByItem();
1681
1682 item.setExpr(this.expr());
1683
1684 if (lexer.token == Token.ASC) {
1685 lexer.nextToken();
1686 item.setType(SQLOrderingSpecification.ASC);
1687 } else if (lexer.token == Token.DESC) {
1688 lexer.nextToken();
1689 item.setType(SQLOrderingSpecification.DESC);
1690 }
1691
1692 if (lexer.identifierEquals(FnvHash.Constants.NULLS)) {
1693 lexer.nextToken();
1694 if (lexer.identifierEquals(FnvHash.Constants.FIRST)) {
1695 lexer.nextToken();
1696 item.setNullsOrderType(SQLSelectOrderByItem.NullsOrderType.NullsFirst);
1697 } else if (lexer.identifierEquals(FnvHash.Constants.LAST)) {
1698 lexer.nextToken();
1699 item.setNullsOrderType(SQLSelectOrderByItem.NullsOrderType.NullsLast);
1700 } else {
1701 throw new ParserException("TODO " ~ lexer.info());
1702 }
1703 }
1704
1705 return item;
1706 }
1707
1708 public SQLUpdateSetItem parseUpdateSetItem() {
1709 SQLUpdateSetItem item = new SQLUpdateSetItem();
1710
1711 if (lexer.token == (Token.LPAREN)) {
1712 lexer.nextToken();
1713 SQLListExpr list = new SQLListExpr();
1714 this.exprList(list.getItems(), list);
1715 accept(Token.RPAREN);
1716 item.setColumn(list);
1717 } else {
1718 string identName;
1719 long hash;
1720
1721 Token token = lexer.token();
1722 if (token == Token.IDENTIFIER) {
1723 identName = lexer.stringVal();
1724 hash = lexer.hash_lower();
1725 } else if (token == Token.LITERAL_CHARS) {
1726 identName = '\'' ~ lexer.stringVal() ~ '\'';
1727 hash = 0;
1728 } else {
1729 identName = lexer.stringVal();
1730 hash = 0;
1731 }
1732 lexer.nextTokenEq();
1733 SQLExpr expr = new SQLIdentifierExpr(identName, hash);
1734 while (lexer.token() == Token.DOT) {
1735 lexer.nextToken();
1736 string propertyName = lexer.stringVal();
1737 lexer.nextTokenEq();
1738 expr = new SQLPropertyExpr(expr, propertyName);
1739 }
1740
1741 item.setColumn(expr);
1742 }
1743 if (lexer.token == Token.COLONEQ) {
1744 lexer.nextTokenValue();
1745 } else if (lexer.token == Token.EQ) {
1746 lexer.nextTokenValue();
1747 } else {
1748 throw new ParserException("syntax error, expect EQ, actual " ~ lexer.token ~ " "
1749 ~ lexer.info());
1750 }
1751
1752 item.setValue(this.expr());
1753 return item;
1754 }
1755
1756 public SQLExpr bitAnd() {
1757 SQLExpr expr = shift();
1758 return bitAndRest(expr);
1759 }
1760
1761 public SQLExpr bitAndRest(SQLExpr expr) {
1762 while (lexer.token == Token.AMP) {
1763 lexer.nextToken();
1764 SQLExpr rightExp = shift();
1765 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseAnd, rightExp, getDbType());
1766 }
1767 return expr;
1768 }
1769
1770 public SQLExpr bitOr() {
1771 SQLExpr expr = bitAnd();
1772 return bitOrRest(expr);
1773 }
1774
1775 public SQLExpr bitOrRest(SQLExpr expr) {
1776 while (lexer.token == Token.BAR) {
1777 lexer.nextToken();
1778 SQLBinaryOperator op = SQLBinaryOperator.BitwiseOr;
1779 if (lexer.token == Token.BAR) {
1780 lexer.nextToken();
1781 op = SQLBinaryOperator.Concat;
1782 }
1783 SQLExpr rightExp = bitAnd();
1784 expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());
1785 expr = bitAndRest(expr);
1786 }
1787 return expr;
1788 }
1789
1790 public SQLExpr inRest(SQLExpr expr) {
1791 if (lexer.token == Token.IN) {
1792 lexer.nextTokenLParen();
1793
1794 SQLInListExpr inListExpr = new SQLInListExpr(expr);
1795 List!(SQLExpr) targetList = inListExpr.getTargetList();
1796 if (lexer.token == Token.LPAREN) {
1797 lexer.nextTokenValue();
1798
1799 if (lexer.token == Token.WITH) {
1800 SQLSelect select = this.createSelectParser().select();
1801 SQLInSubQueryExpr queryExpr = new SQLInSubQueryExpr(select);
1802 queryExpr.setExpr(expr);
1803 accept(Token.RPAREN);
1804 return queryExpr;
1805 }
1806
1807 for (;;) {
1808 SQLExpr item;
1809 if (lexer.token == Token.LITERAL_INT) {
1810 item = new SQLIntegerExpr(lexer.integerValue());
1811 lexer.nextToken();
1812 if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
1813 item = this.primaryRest(item);
1814 item = this.exprRest(item);
1815 }
1816 } else {
1817 item = this.expr();
1818 }
1819
1820 item.setParent(inListExpr);
1821 targetList.add(item);
1822 if (lexer.token == Token.COMMA) {
1823 lexer.nextTokenValue();
1824 continue;
1825 }
1826 break;
1827 }
1828
1829 accept(Token.RPAREN);
1830 } else {
1831 SQLExpr itemExpr = primary();
1832 itemExpr.setParent(inListExpr);
1833 targetList.add(itemExpr);
1834 }
1835
1836 expr = inListExpr;
1837
1838 if (targetList.size() == 1) {
1839 SQLExpr targetExpr = targetList.get(0);
1840 if (cast(SQLQueryExpr)(targetExpr) !is null) {
1841 SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();
1842 inSubQueryExpr.setExpr(inListExpr.getExpr());
1843 inSubQueryExpr.setSubQuery((cast(SQLQueryExpr) targetExpr).getSubQuery());
1844 expr = inSubQueryExpr;
1845 }
1846 }
1847 } else if (lexer.token == Token.CONTAINS) {
1848 lexer.nextTokenLParen();
1849
1850 SQLContainsExpr containsExpr = new SQLContainsExpr(expr);
1851 List!(SQLExpr) targetList = containsExpr.getTargetList();
1852 if (lexer.token == Token.LPAREN) {
1853 lexer.nextTokenValue();
1854
1855 if (lexer.token == Token.WITH) {
1856 SQLSelect select = this.createSelectParser().select();
1857 SQLInSubQueryExpr queryExpr = new SQLInSubQueryExpr(select);
1858 queryExpr.setExpr(expr);
1859 accept(Token.RPAREN);
1860 return queryExpr;
1861 }
1862
1863 for (;;) {
1864 SQLExpr item;
1865 if (lexer.token == Token.LITERAL_INT) {
1866 item = new SQLIntegerExpr(lexer.integerValue());
1867 lexer.nextToken();
1868 if (lexer.token != Token.COMMA && lexer.token != Token.RPAREN) {
1869 item = this.primaryRest(item);
1870 item = this.exprRest(item);
1871 }
1872 } else {
1873 item = this.expr();
1874 }
1875
1876 item.setParent(containsExpr);
1877 targetList.add(item);
1878 if (lexer.token == Token.COMMA) {
1879 lexer.nextTokenValue();
1880 continue;
1881 }
1882 break;
1883 }
1884
1885 accept(Token.RPAREN);
1886 } else {
1887 SQLExpr itemExpr = primary();
1888 itemExpr.setParent(containsExpr);
1889 targetList.add(itemExpr);
1890 }
1891
1892 expr = containsExpr;
1893 }
1894
1895 return expr;
1896 }
1897
1898 public SQLExpr additive() {
1899 SQLExpr expr = multiplicative();
1900
1901 if (lexer.token == Token.PLUS
1902 || lexer.token == Token.BARBAR
1903 || lexer.token == Token.CONCAT
1904 || lexer.token == Token.SUB) {
1905 expr = additiveRest(expr);
1906 }
1907
1908 return expr;
1909 }
1910
1911 public SQLExpr additiveRest(SQLExpr expr) {
1912 Token token = lexer.token;
1913 if (token == Token.PLUS) {
1914 lexer.nextToken();
1915 SQLExpr rightExp = multiplicative();
1916
1917 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Add, rightExp, dbType);
1918 expr = additiveRest(expr);
1919 } else if ((token == Token.BARBAR || token == Token.CONCAT)
1920 && (isEnabled(SQLParserFeature.PipesAsConcat) || !(DBType.MYSQL.name == (dbType)))) {
1921 lexer.nextToken();
1922 SQLExpr rightExp = multiplicative();
1923 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Concat, rightExp, dbType);
1924 expr = additiveRest(expr);
1925 } else if (token == Token.SUB) {
1926 lexer.nextToken();
1927 SQLExpr rightExp = multiplicative();
1928
1929 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Subtract, rightExp, dbType);
1930 expr = additiveRest(expr);
1931 }
1932
1933 return expr;
1934 }
1935
1936 public SQLExpr shift() {
1937 SQLExpr expr = additive();
1938 return shiftRest(expr);
1939 }
1940
1941 public SQLExpr shiftRest(SQLExpr expr) {
1942 if (lexer.token == Token.LTLT) {
1943 lexer.nextToken();
1944 SQLExpr rightExp = additive();
1945
1946 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LeftShift, rightExp, dbType);
1947 expr = shiftRest(expr);
1948 } else if (lexer.token == Token.GTGT) {
1949 lexer.nextToken();
1950 SQLExpr rightExp = additive();
1951
1952 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RightShift, rightExp, dbType);
1953 expr = shiftRest(expr);
1954 }
1955
1956 return expr;
1957 }
1958
1959 public SQLExpr and() {
1960 SQLExpr expr = relational();
1961 if (lexer.token == Token.AND || lexer.token == Token.AMPAMP) {
1962 expr = andRest(expr);
1963 }
1964 return expr;
1965 }
1966
1967 public SQLExpr andRest(SQLExpr expr) {
1968 for (;;) {
1969 Token token = lexer.token;
1970 if (token == Token.AND) {
1971 if (lexer.isKeepComments() && lexer.hasComment()) {
1972 expr.addAfterComment(lexer.readAndResetComments());
1973 }
1974
1975 lexer.nextToken();
1976
1977 SQLExpr rightExp = relational();
1978
1979 if (lexer.token == Token.AND
1980 && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) {
1981
1982 SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanAnd, dbType);
1983 group.add(expr);
1984 group.add(rightExp);
1985
1986 if (lexer.isKeepComments() && lexer.hasComment()) {
1987 rightExp.addAfterComment(lexer.readAndResetComments());
1988 }
1989
1990 for (;;) {
1991 lexer.nextToken();
1992 SQLExpr more = relational();
1993 group.add(more);
1994
1995 if (lexer.token == Token.AND) {
1996 if (lexer.isKeepComments() && lexer.hasComment()) {
1997 more.addAfterComment(lexer.readAndResetComments());
1998 }
1999
2000 continue;
2001 }
2002 break;
2003 }
2004
2005 expr = group;
2006 } else {
2007 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanAnd, rightExp, dbType);
2008 }
2009 } else if (token == Token.AMPAMP) {
2010 if (lexer.isKeepComments() && lexer.hasComment()) {
2011 expr.addAfterComment(lexer.readAndResetComments());
2012 }
2013
2014 lexer.nextToken();
2015
2016 SQLExpr rightExp = relational();
2017
2018 SQLBinaryOperator operator = DBType.POSTGRESQL.name == (dbType)
2019 ? SQLBinaryOperator.PG_And
2020 : SQLBinaryOperator.BooleanAnd;
2021
2022 expr = new SQLBinaryOpExpr(expr, operator, rightExp, dbType);
2023 } else {
2024 break;
2025 }
2026 }
2027
2028 return expr;
2029 }
2030
2031
2032 public SQLExpr xor() {
2033 SQLExpr expr = and();
2034 if (lexer.token == Token.XOR) {
2035 expr = xorRest(expr);
2036 }
2037 return expr;
2038 }
2039
2040 public SQLExpr xorRest(SQLExpr expr) {
2041 for (;;) {
2042 if (lexer.token == Token.XOR) {
2043 lexer.nextToken();
2044 SQLExpr rightExp = and();
2045
2046 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanXor, rightExp, dbType);
2047 } else {
2048 break;
2049 }
2050 }
2051
2052 return expr;
2053 }
2054
2055 public SQLExpr or() {
2056 SQLExpr expr = xor();
2057 if (lexer.token == Token.OR || lexer.token == Token.BARBAR) {
2058 expr = orRest(expr);
2059 }
2060 return expr;
2061 }
2062
2063 public SQLExpr orRest(SQLExpr expr) {
2064 for (;;) {
2065 if (lexer.token == Token.OR) {
2066 lexer.nextToken();
2067 SQLExpr rightExp = xor();
2068
2069 if (lexer.token == Token.OR
2070 && lexer.isEnabled(SQLParserFeature.EnableSQLBinaryOpExprGroup)) {
2071
2072 SQLBinaryOpExprGroup group = new SQLBinaryOpExprGroup(SQLBinaryOperator.BooleanOr, dbType);
2073 group.add(expr);
2074 group.add(rightExp);
2075
2076 if (lexer.isKeepComments() && lexer.hasComment()) {
2077 rightExp.addAfterComment(lexer.readAndResetComments());
2078 }
2079
2080 for (;;) {
2081 lexer.nextToken();
2082 SQLExpr more = xor();
2083 group.add(more);
2084 if (lexer.token == Token.OR) {
2085 if (lexer.isKeepComments() && lexer.hasComment()) {
2086 more.addAfterComment(lexer.readAndResetComments());
2087 }
2088
2089 continue;
2090 }
2091 break;
2092 }
2093
2094 expr = group;
2095 } else {
2096 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BooleanOr, rightExp, dbType);
2097 }
2098 } else if (lexer.token == Token.BARBAR) {
2099 lexer.nextToken();
2100 SQLExpr rightExp = xor();
2101
2102 SQLBinaryOperator op = DBType.MYSQL.name == (dbType) && !isEnabled(SQLParserFeature.PipesAsConcat)
2103 ? SQLBinaryOperator.BooleanOr
2104 : SQLBinaryOperator.Concat;
2105
2106 expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);
2107 } else {
2108 break;
2109 }
2110 }
2111
2112 return expr;
2113 }
2114
2115 public SQLExpr relational() {
2116 SQLExpr expr = bitOr();
2117
2118 return relationalRest(expr);
2119 }
2120
2121 public SQLExpr relationalRest(SQLExpr expr) {
2122 SQLExpr rightExp;
2123
2124 Token token = lexer.token;
2125
2126 switch (token) {
2127 case Token.EQ:{
2128 lexer.nextToken();
2129 try {
2130 rightExp = bitOr();
2131 } catch (ParserException e) {
2132 throw new ParserException("EOF, " ~ expr.stringof ~ "=", e);
2133 }
2134
2135 if (lexer.token == Token.COLONEQ) {
2136 lexer.nextToken();
2137 SQLExpr colonExpr = this.expr();
2138 rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);
2139 }
2140
2141 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
2142 }
2143 break;
2144 case Token.IS: {
2145 lexer.nextTokenNotOrNull();
2146
2147 SQLBinaryOperator op;
2148 if (lexer.token == Token.NOT) {
2149 op = SQLBinaryOperator.IsNot;
2150 lexer.nextTokenNotOrNull();
2151 } else {
2152 op = SQLBinaryOperator.Is;
2153 }
2154 rightExp = primary();
2155 expr = new SQLBinaryOpExpr(expr, op, rightExp, dbType);
2156 }
2157 break;
2158 case Token.EQGT: {
2159 lexer.nextToken();
2160 rightExp = this.expr();
2161 string argumentName = (cast(SQLIdentifierExpr) expr).getName();
2162 // expr = new OracleArgumentExpr(argumentName, rightExp);
2163 implementationMissing(false);
2164 }
2165 break;
2166 case Token.BANGEQ:
2167 case Token.CARETEQ: {
2168 lexer.nextToken();
2169 rightExp = bitOr();
2170 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, dbType);
2171 }
2172 break;
2173 case Token.COLONEQ:{
2174 lexer.nextToken();
2175 rightExp = this.expr();
2176 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, dbType);
2177 }
2178 break;
2179 case Token.LT:{
2180 SQLBinaryOperator op = SQLBinaryOperator.LessThan;
2181
2182 lexer.nextToken();
2183 if (lexer.token == Token.EQ) {
2184 lexer.nextToken();
2185 op = SQLBinaryOperator.LessThanOrEqual;
2186 }
2187
2188 rightExp = bitOr();
2189 expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());
2190 }
2191 break;
2192 case Token.LTEQ: {
2193 lexer.nextToken();
2194 rightExp = bitOr();
2195
2196 // rightExp = relationalRest(rightExp);
2197
2198 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqual, rightExp, getDbType());
2199 }
2200 break;
2201 case Token.LTEQGT: {
2202 lexer.nextToken();
2203 rightExp = bitOr();
2204
2205 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqualOrGreaterThan, rightExp, getDbType());
2206 }
2207 break;
2208 case Token.GT: {
2209 SQLBinaryOperator op = SQLBinaryOperator.GreaterThan;
2210
2211 lexer.nextToken();
2212
2213 if (lexer.token == Token.EQ) {
2214 lexer.nextToken();
2215 op = SQLBinaryOperator.GreaterThanOrEqual;
2216 }
2217
2218 rightExp = bitOr();
2219
2220 expr = new SQLBinaryOpExpr(expr, op, rightExp, getDbType());
2221 }
2222 break;
2223 case Token.GTEQ:{
2224 lexer.nextToken();
2225 rightExp = bitOr();
2226
2227 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThanOrEqual, rightExp, getDbType());
2228 }
2229 break;
2230 case Token.BANGLT:{
2231 lexer.nextToken();
2232 rightExp = bitOr();
2233
2234 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLessThan, rightExp, getDbType());
2235 }
2236 break;
2237 case Token.BANGGT:
2238 lexer.nextToken();
2239 rightExp = bitOr();
2240
2241 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotGreaterThan, rightExp, getDbType());
2242 break;
2243 case Token.LTGT:
2244 lexer.nextToken();
2245 rightExp = bitOr();
2246 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrGreater, rightExp, getDbType());
2247 break;
2248 case Token.LIKE:
2249 lexer.nextTokenValue();
2250 rightExp = bitOr();
2251
2252 if (typeid(rightExp) == typeid(SQLIdentifierExpr)) {
2253 string name = (cast(SQLIdentifierExpr) rightExp).getName();
2254 int length = cast(int)(name.length);
2255 if(length > 1 && charAt(name, 0) == charAt(name, length -1 )) {
2256 rightExp = new SQLCharExpr(name.substring(1, length - 1));
2257 }
2258 }
2259
2260 // rightExp = relationalRest(rightExp);
2261
2262 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Like, rightExp, getDbType());
2263
2264 if (lexer.token == Token.ESCAPE) {
2265 lexer.nextToken();
2266 rightExp = primary();
2267 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, getDbType());
2268 }
2269 break;
2270 case Token.ILIKE:
2271 lexer.nextToken();
2272 rightExp = bitOr();
2273
2274 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.ILike, rightExp, getDbType());
2275 break;
2276 case Token.MONKEYS_AT_AT:
2277 lexer.nextToken();
2278 rightExp = bitOr();
2279
2280 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.AT_AT, rightExp, getDbType());
2281 break;
2282 case Token.MONKEYS_AT_GT:
2283 lexer.nextToken();
2284 rightExp = bitOr();
2285
2286 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Array_Contains, rightExp, getDbType());
2287 break;
2288 case Token.LT_MONKEYS_AT:
2289 lexer.nextToken();
2290 rightExp = bitOr();
2291
2292 rightExp = relationalRest(rightExp);
2293
2294 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Array_ContainedBy, rightExp, getDbType());
2295 break;
2296 case Token.NOT:
2297 lexer.nextToken();
2298 expr = notRationalRest(expr);
2299 break;
2300 case Token.BETWEEN:
2301 lexer.nextToken();
2302 SQLExpr beginExpr = relational();
2303 accept(Token.AND);
2304 SQLExpr endExpr = relational();
2305 expr = new SQLBetweenExpr(expr, beginExpr, endExpr);
2306 break;
2307 case Token.IN:
2308 case Token.CONTAINS:
2309 expr = inRest(expr);
2310 break;
2311 case Token.EQEQ:
2312 /* if (DBType.ODPS.name == (dbType)) {
2313 lexer.nextToken();
2314 try {
2315 rightExp = bitOr();
2316 } catch (ParserException e) {
2317 throw new ParserException("EOF, " ~ expr.stringof ~ "=", e);
2318 }
2319
2320 if (lexer.token == Token.COLONEQ) {
2321 lexer.nextToken();
2322 SQLExpr colonExpr = this.expr();
2323 rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType);
2324 }
2325
2326 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType);
2327 } else */ {
2328 return expr;
2329 }
2330 case Token.TILDE:
2331 if (DBType.POSTGRESQL == (lexer.dbType)) {
2332 lexer.nextToken();
2333
2334 rightExp = relational();
2335
2336 rightExp = relationalRest(rightExp);
2337
2338 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match, rightExp, getDbType());
2339 } else {
2340 return expr;
2341 }
2342 break;
2343 case Token.TILDE_STAR:
2344 if (DBType.POSTGRESQL.name == (lexer.dbType)) {
2345 lexer.nextToken();
2346 rightExp = relational();
2347 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match_Insensitive, rightExp, getDbType());
2348 } else {
2349 return expr;
2350 }
2351 break;
2352 case Token.BANG_TILDE:
2353 if (DBType.POSTGRESQL.name == (lexer.dbType)) {
2354 lexer.nextToken();
2355 rightExp = relational();
2356 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match, rightExp, getDbType());
2357 } else {
2358 return expr;
2359 }
2360 break;
2361 case Token.BANG_TILDE_STAR:
2362 if (DBType.POSTGRESQL.name == (lexer.dbType)) {
2363 lexer.nextToken();
2364 rightExp = relational();
2365 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive, rightExp, getDbType());
2366 } else {
2367 return expr;
2368 }
2369 break;
2370 case Token.TILDE_EQ:
2371 if (DBType.POSTGRESQL.name == (lexer.dbType)) {
2372 lexer.nextToken();
2373 rightExp = relational();
2374 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SAME_AS, rightExp, getDbType());
2375 } else {
2376 return expr;
2377 }
2378 break;
2379 case Token.RLIKE:
2380 lexer.nextToken();
2381 rightExp = relational();
2382 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.RLike, rightExp, getDbType());
2383 break;
2384 case Token.IDENTIFIER:
2385 long hash = lexer.hash_lower;
2386 if (hash == FnvHash.Constants.SOUNDS) {
2387 lexer.nextToken();
2388 accept(Token.LIKE);
2389
2390 rightExp = relational();
2391
2392 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SoudsLike, rightExp, getDbType());
2393 } else if (hash == FnvHash.Constants.REGEXP) {
2394 lexer.nextToken();
2395 rightExp = relational();
2396
2397 return new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp, DBType.MYSQL.name);
2398
2399 } else if (hash == FnvHash.Constants.SIMILAR && DBType.POSTGRESQL.name == (lexer.dbType)) {
2400 lexer.nextToken();
2401 accept(Token.TO);
2402
2403 rightExp = relational();
2404
2405 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SIMILAR_TO, rightExp, getDbType());
2406 } else {
2407 return expr;
2408 }
2409 break;
2410 default:
2411 break;
2412 }
2413
2414 switch (lexer.token) {
2415 case Token.BETWEEN:
2416 case Token.IS:
2417 case Token.EQ:
2418 case Token.IN:
2419 case Token.CONTAINS:
2420 case Token.BANG_TILDE_STAR:
2421 case Token.TILDE_EQ:
2422 case Token.LT:
2423 case Token.LTEQ:
2424 case Token.LTEQGT:
2425 case Token.GT:
2426 case Token.GTEQ:
2427 case Token.LTGT:
2428 case Token.BANGEQ:
2429 case Token.LIKE:
2430 case Token.NOT:
2431 expr = relationalRest(expr);
2432 break;
2433 default:
2434 break;
2435 }
2436
2437 return expr;
2438 }
2439
2440 public SQLExpr notRationalRest(SQLExpr expr) {
2441 SQLExpr rightExp;
2442 switch (lexer.token) {
2443 case Token.LIKE:
2444 lexer.nextTokenValue();
2445 rightExp = bitOr();
2446
2447 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLike, rightExp, getDbType());
2448
2449 if (lexer.token == Token.ESCAPE) {
2450 lexer.nextToken();
2451 rightExp = bitOr();
2452 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Escape, rightExp, getDbType());
2453 }
2454 break;
2455 case Token.IN:
2456 lexer.nextToken();
2457
2458 SQLInListExpr inListExpr = new SQLInListExpr(expr, true);
2459 if (lexer.token == Token.LPAREN) {
2460 lexer.nextToken();
2461
2462 exprList(inListExpr.getTargetList(), inListExpr);
2463 expr = inListExpr;
2464
2465 accept(Token.RPAREN);
2466 } else {
2467 SQLExpr valueExpr = this.primary();
2468 valueExpr.setParent(inListExpr);
2469 inListExpr.getTargetList().add(valueExpr);
2470 expr = inListExpr;
2471 }
2472
2473 if (inListExpr.getTargetList().size() == 1) {
2474 SQLExpr targetExpr = inListExpr.getTargetList().get(0);
2475 if (cast(SQLQueryExpr)(targetExpr) !is null) {
2476 SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();
2477 inSubQueryExpr.setNot(true);
2478 inSubQueryExpr.setExpr(inListExpr.getExpr());
2479 inSubQueryExpr.setSubQuery((cast(SQLQueryExpr) targetExpr).getSubQuery());
2480 expr = inSubQueryExpr;
2481 }
2482 }
2483
2484 break;
2485 case Token.CONTAINS:
2486 lexer.nextToken();
2487
2488 SQLContainsExpr containsExpr = new SQLContainsExpr(expr, true);
2489 if (lexer.token == Token.LPAREN) {
2490 lexer.nextToken();
2491
2492 exprList(containsExpr.getTargetList(), containsExpr);
2493 expr = containsExpr;
2494
2495 accept(Token.RPAREN);
2496 } else {
2497 SQLExpr valueExpr = this.primary();
2498 valueExpr.setParent(containsExpr);
2499 containsExpr.getTargetList().add(valueExpr);
2500 expr = containsExpr;
2501 }
2502
2503 if (containsExpr.getTargetList().size() == 1) {
2504 SQLExpr targetExpr = containsExpr.getTargetList().get(0);
2505 if (cast(SQLQueryExpr)(targetExpr) !is null) {
2506 SQLInSubQueryExpr inSubQueryExpr = new SQLInSubQueryExpr();
2507 inSubQueryExpr.setNot(true);
2508 inSubQueryExpr.setExpr(containsExpr.getExpr());
2509 inSubQueryExpr.setSubQuery((cast(SQLQueryExpr) targetExpr).getSubQuery());
2510 expr = inSubQueryExpr;
2511 }
2512 }
2513
2514 break;
2515 case Token.BETWEEN:
2516 lexer.nextToken();
2517 SQLExpr beginExpr = relational();
2518 accept(Token.AND);
2519 SQLExpr endExpr = relational();
2520
2521 expr = new SQLBetweenExpr(expr, true, beginExpr, endExpr);
2522 break;
2523 case Token.ILIKE:
2524 lexer.nextToken();
2525 rightExp = bitOr();
2526
2527 return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotILike, rightExp, getDbType());
2528 case Token.LPAREN:
2529 expr = this.primary();
2530 break;
2531 case Token.RLIKE:
2532 lexer.nextToken();
2533 rightExp = bitOr();
2534 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRLike, rightExp, getDbType());
2535 break;
2536 case Token.IDENTIFIER:
2537 long hash = lexer.hash_lower;
2538 if (hash == FnvHash.Constants.REGEXP) {
2539 lexer.nextToken();
2540 rightExp = bitOr();
2541 expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRegExp, rightExp, getDbType());
2542 }
2543 break;
2544 default:
2545 throw new ParserException("TODO " ~ lexer.info());
2546 }
2547
2548 return expr;
2549 }
2550
2551 public SQLDataType parseDataType() {
2552 return parseDataType(true);
2553 }
2554
2555 public SQLDataType parseDataType(bool restrict) {
2556 Token token = lexer.token;
2557 if (token == Token.DEFAULT || token == Token.NOT || token == Token.NULL) {
2558 return null;
2559 }
2560
2561 SQLName typeExpr = name();
2562 string typeName = (cast(Object)(typeExpr)).toString();
2563
2564 version(HUNT_SQL_PARSER_DEBUG) warningf("typename: %s", typeName);
2565
2566 if ("long".equalsIgnoreCase(typeName) //
2567 && lexer.identifierEquals("byte") //
2568 && DBType.MYSQL.name == (getDbType()) //
2569 ) {
2570 typeName ~= (' ' ~ lexer.stringVal());
2571 lexer.nextToken();
2572 } else if ("double".equalsIgnoreCase(typeName)
2573 && DBType.POSTGRESQL.name == (getDbType()) //
2574 ) {
2575 typeName ~= (' ' ~ lexer.stringVal());
2576 lexer.nextToken();
2577 }
2578
2579 if (isCharType(typeName)) {
2580 SQLCharacterDataType charType = new SQLCharacterDataType(typeName);
2581
2582 if (lexer.token == Token.LPAREN) {
2583 lexer.nextToken();
2584 SQLExpr arg = this.expr();
2585 arg.setParent(charType);
2586 charType.addArgument(arg);
2587 accept(Token.RPAREN);
2588 }
2589
2590 charType = cast(SQLCharacterDataType) parseCharTypeRest(charType);
2591
2592 if (lexer.token == Token.HINT) {
2593 List!(SQLCommentHint) hints = this.parseHints();
2594 charType.setHints(hints);
2595 }
2596
2597 return charType;
2598 }
2599
2600 if ("character".equalsIgnoreCase(typeName) && "varying".equalsIgnoreCase(lexer.stringVal())) {
2601 typeName ~= ' ' ~ lexer.stringVal();
2602 lexer.nextToken();
2603 }
2604
2605 SQLDataTypeImpl dataType = new SQLDataTypeImpl(typeName);
2606 dataType.setDbType(dbType);
2607
2608 version(HUNT_SQL_PARSER_DEBUG) infof("token: %s, value: %s", lexer.token, cast(string)lexer.token);
2609
2610 // FIXME: Needing refactor or cleanup -@zhangxueping at 2020-08-05T18:03:58+08:00
2611 //
2612 // if (lexer.token == Token.LPAREN) {
2613 // lexer.nextToken();
2614 // SQLExpr arg = this.expr();
2615 // arg.setParent(dataType);
2616 // dataType.addArgument(arg);
2617 // accept(Token.RPAREN);
2618 // }
2619
2620 return parseDataTypeRest(dataType);
2621 }
2622
2623 protected SQLDataType parseDataTypeRest(SQLDataType dataType) {
2624 if (lexer.token == Token.LPAREN) {
2625 lexer.nextToken();
2626 exprList(dataType.getArguments(), dataType);
2627 accept(Token.RPAREN);
2628 }
2629
2630 if (lexer.identifierEquals(FnvHash.Constants.PRECISION)
2631 && dataType.nameHashCode64() == FnvHash.Constants.DOUBLE) {
2632 lexer.nextToken();
2633 dataType.setName("DOUBLE PRECISION");
2634 }
2635
2636 if (FnvHash.Constants.TIMESTAMP == dataType.nameHashCode64()) {
2637 if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {
2638 lexer.nextToken();
2639 acceptIdentifier("TIME");
2640 acceptIdentifier("ZONE");
2641 dataType.setWithTimeZone(Boolean.FALSE);
2642 } else if (lexer.token == Token.WITH) {
2643 lexer.nextToken();
2644 acceptIdentifier("TIME");
2645 acceptIdentifier("ZONE");
2646 dataType.setWithTimeZone(Boolean.TRUE);
2647 }
2648 }
2649
2650 return dataType;
2651 }
2652
2653 protected bool isCharType(string dataTypeName) {
2654 long hash = FnvHash.hashCode64(dataTypeName);
2655 return isCharType(hash);
2656 }
2657
2658
2659 protected bool isCharType(long hash) {
2660 return hash == FnvHash.Constants.CHAR
2661 || hash == FnvHash.Constants.VARCHAR
2662 || hash == FnvHash.Constants.NCHAR
2663 || hash == FnvHash.Constants.NVARCHAR
2664 || hash == FnvHash.Constants.TINYTEXT
2665 || hash == FnvHash.Constants.TEXT
2666 || hash == FnvHash.Constants.MEDIUMTEXT
2667 || hash == FnvHash.Constants.LONGTEXT
2668 ;
2669 }
2670
2671 protected SQLDataType parseCharTypeRest(SQLCharacterDataType charType) {
2672 if (lexer.token == Token.BINARY) {
2673 charType.setHasBinary(true);
2674 lexer.nextToken();
2675 }
2676
2677 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) {
2678 lexer.nextToken();
2679
2680 accept(Token.SET);
2681
2682 if (lexer.token != Token.IDENTIFIER
2683 && lexer.token != Token.LITERAL_CHARS
2684 && lexer.token != Token.BINARY) {
2685 throw new ParserException(lexer.info());
2686 }
2687 charType.setCharSetName(lexer.stringVal());
2688 lexer.nextToken();
2689 } else if (lexer.identifierEquals(FnvHash.Constants.CHARSET)) {
2690 lexer.nextToken();
2691
2692 if (lexer.token != Token.IDENTIFIER
2693 && lexer.token != Token.LITERAL_CHARS
2694 && lexer.token != Token.BINARY) {
2695 throw new ParserException(lexer.info());
2696 }
2697 charType.setCharSetName(lexer.stringVal());
2698 lexer.nextToken();
2699 }
2700
2701 if (lexer.token == Token.BINARY) {
2702 charType.setHasBinary(true);
2703 lexer.nextToken();
2704 }
2705
2706 if (lexer.identifierEquals(FnvHash.Constants.COLLATE)) {
2707 lexer.nextToken();
2708
2709 if (lexer.token == Token.LITERAL_ALIAS) {
2710 charType.setCollate(lexer.stringVal());
2711 } else if (lexer.token == Token.IDENTIFIER) {
2712 charType.setCollate(lexer.stringVal());
2713 } else {
2714 throw new ParserException();
2715 }
2716
2717 lexer.nextToken();
2718 }
2719
2720 return charType;
2721 }
2722
2723 override public void accept(Token token) {
2724 if (lexer.token == token) {
2725 lexer.nextToken();
2726 } else {
2727 throw new ParserException("syntax error, expect:{" ~ token ~ "}, actual:{" ~ lexer.token ~ "}, "
2728 ~ lexer.info());
2729 }
2730 }
2731
2732 public SQLColumnDefinition parseColumn() {
2733 SQLColumnDefinition column = createColumnDefinition();
2734 column.setName(name());
2735
2736 Token token = lexer.token;
2737 if (token != Token.SET //
2738 && token != Token.DROP
2739 && token != Token.PRIMARY
2740 && token != Token.RPAREN) {
2741 column.setDataType(parseDataType());
2742 }
2743 return parseColumnRest(column);
2744 }
2745
2746 public SQLColumnDefinition createColumnDefinition() {
2747 SQLColumnDefinition column = new SQLColumnDefinition();
2748 column.setDbType(dbType);
2749 return column;
2750 }
2751
2752 public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {
2753 if (lexer.token == Token.DEFAULT) {
2754 lexer.nextToken();
2755 column.setDefaultExpr(bitOr());
2756 return parseColumnRest(column);
2757 }
2758
2759 if (lexer.token == Token.NOT) {
2760 lexer.nextToken();
2761 accept(Token.NULL);
2762 SQLNotNullConstraint notNull = new SQLNotNullConstraint();
2763 if (lexer.token == Token.HINT) {
2764 List!(SQLCommentHint) hints = this.parseHints();
2765 notNull.setHints(hints);
2766 }
2767 column.addConstraint(notNull);
2768 return parseColumnRest(column);
2769 }
2770
2771 if (lexer.token == Token.NULL) {
2772 lexer.nextToken();
2773 column.getConstraints().add(new SQLNullConstraint());
2774 return parseColumnRest(column);
2775 }
2776
2777 if (lexer.token == Token.PRIMARY) {
2778 lexer.nextToken();
2779 accept(Token.KEY);
2780 column.addConstraint(new SQLColumnPrimaryKey());
2781 return parseColumnRest(column);
2782 }
2783
2784 if (lexer.token == Token.UNIQUE) {
2785 lexer.nextToken();
2786 if (lexer.token == Token.KEY) {
2787 lexer.nextToken();
2788 }
2789 column.addConstraint(new SQLColumnUniqueKey());
2790 return parseColumnRest(column);
2791 }
2792
2793 if (lexer.token == Token.KEY) {
2794 lexer.nextToken();
2795 column.addConstraint(new SQLColumnUniqueKey());
2796 return parseColumnRest(column);
2797 }
2798
2799 if (lexer.token == Token.REFERENCES) {
2800 SQLColumnReference _ref = parseReference();
2801 column.addConstraint(_ref);
2802 return parseColumnRest(column);
2803 }
2804
2805 if (lexer.token == Token.CONSTRAINT) {
2806 lexer.nextToken();
2807
2808 SQLName name = this.name();
2809
2810 if (lexer.token == Token.PRIMARY) {
2811 lexer.nextToken();
2812 accept(Token.KEY);
2813 SQLColumnPrimaryKey pk = new SQLColumnPrimaryKey();
2814 pk.setName(name);
2815 column.addConstraint(pk);
2816 return parseColumnRest(column);
2817 }
2818
2819 if (lexer.token == Token.UNIQUE) {
2820 lexer.nextToken();
2821 SQLColumnUniqueKey uk = new SQLColumnUniqueKey();
2822 uk.setName(name);
2823
2824 column.addConstraint(uk);
2825 return parseColumnRest(column);
2826 }
2827
2828 if (lexer.token == Token.REFERENCES) {
2829 SQLColumnReference _ref = parseReference();
2830 _ref.setName(name);
2831 column.addConstraint(_ref);
2832 return parseColumnRest(column);
2833 }
2834
2835 if (lexer.token == Token.NOT) {
2836 lexer.nextToken();
2837 accept(Token.NULL);
2838 SQLNotNullConstraint notNull = new SQLNotNullConstraint();
2839 notNull.setName(name);
2840 column.addConstraint(notNull);
2841 return parseColumnRest(column);
2842 }
2843
2844 if (lexer.token == Token.CHECK) {
2845 SQLColumnCheck check = parseColumnCheck();
2846 check.setName(name);
2847 check.setParent(column);
2848 column.addConstraint(check);
2849 return parseColumnRest(column);
2850 }
2851
2852 if (lexer.token == Token.DEFAULT) {
2853 lexer.nextToken();
2854 SQLExpr expr = this.expr();
2855 column.setDefaultExpr(expr);
2856 return parseColumnRest(column);
2857 }
2858
2859 throw new ParserException("TODO : " ~ lexer.info());
2860 }
2861
2862 if (lexer.token == Token.CHECK) {
2863 SQLColumnCheck check = parseColumnCheck();
2864 column.addConstraint(check);
2865 return parseColumnRest(column);
2866 }
2867
2868 if (lexer.token == Token.COMMENT) {
2869 lexer.nextToken();
2870
2871 if (lexer.token == Token.LITERAL_ALIAS) {
2872 string _alias = lexer.stringVal();
2873 if (_alias.length > 2 && charAt(_alias, 0) == '"' && charAt(_alias, _alias.length - 1) == '"') {
2874 _alias = _alias.substring(1, cast(int)(_alias.length - 1));
2875 }
2876 column.setComment(_alias);
2877 lexer.nextToken();
2878 } else {
2879 column.setComment(primary());
2880 }
2881 return parseColumnRest(column);
2882 }
2883
2884 if (lexer.identifierEquals(FnvHash.Constants.AUTO_INCREMENT)) {
2885 lexer.nextToken();
2886 column.setAutoIncrement(true);
2887 return parseColumnRest(column);
2888 }
2889
2890 return column;
2891 }
2892
2893 private SQLColumnReference parseReference() {
2894 SQLColumnReference fk = new SQLColumnReference();
2895
2896 lexer.nextToken();
2897 fk.setTable(this.name());
2898 accept(Token.LPAREN);
2899 this.names(fk.getColumns(), fk);
2900 accept(Token.RPAREN);
2901
2902 if (lexer.identifierEquals(FnvHash.Constants.MATCH)) {
2903 lexer.nextToken();
2904 if (lexer.identifierEquals("FULL") || lexer.token() == Token.FULL) {
2905 fk.setReferenceMatch(SQLForeignKeyImpl.Match.FULL);
2906 lexer.nextToken();
2907 } else if (lexer.identifierEquals(FnvHash.Constants.PARTIAL)) {
2908 fk.setReferenceMatch(SQLForeignKeyImpl.Match.PARTIAL);
2909 lexer.nextToken();
2910 } else if (lexer.identifierEquals(FnvHash.Constants.SIMPLE)) {
2911 fk.setReferenceMatch(SQLForeignKeyImpl.Match.SIMPLE);
2912 lexer.nextToken();
2913 } else {
2914 throw new ParserException("TODO : " ~ lexer.info());
2915 }
2916 }
2917
2918 while (lexer.token() == Token.ON) {
2919 lexer.nextToken();
2920
2921 if (lexer.token() == Token.DELETE) {
2922 lexer.nextToken();
2923
2924 SQLForeignKeyImpl.Option option = parseReferenceOption();
2925 fk.setOnDelete(option);
2926 } else if (lexer.token() == Token.UPDATE) {
2927 lexer.nextToken();
2928
2929 SQLForeignKeyImpl.Option option = parseReferenceOption();
2930 fk.setOnUpdate(option);
2931 } else {
2932 throw new ParserException("syntax error, expect DELETE or UPDATE, actual " ~ lexer.token() ~ " "
2933 ~ lexer.info());
2934 }
2935 }
2936
2937 return fk;
2938 }
2939
2940 protected SQLForeignKeyImpl.Option parseReferenceOption() {
2941 SQLForeignKeyImpl.Option option;
2942 if (lexer.token() == Token.RESTRICT || lexer.identifierEquals(FnvHash.Constants.RESTRICT)) {
2943 option = SQLForeignKeyImpl.Option.RESTRICT;
2944 lexer.nextToken();
2945 } else if (lexer.identifierEquals(FnvHash.Constants.CASCADE)) {
2946 option = SQLForeignKeyImpl.Option.CASCADE;
2947 lexer.nextToken();
2948 } else if (lexer.token() == Token.SET) {
2949 lexer.nextToken();
2950 accept(Token.NULL);
2951 option = SQLForeignKeyImpl.Option.SET_NULL;
2952 } else if (lexer.identifierEquals(FnvHash.Constants.NO)) {
2953 lexer.nextToken();
2954 if (lexer.identifierEquals(FnvHash.Constants.ACTION)) {
2955 option = SQLForeignKeyImpl.Option.NO_ACTION;
2956 lexer.nextToken();
2957 } else {
2958 throw new ParserException("syntax error, expect ACTION, actual " ~ lexer.token() ~ " "
2959 ~ lexer.info());
2960 }
2961 } else {
2962 throw new ParserException("syntax error, expect ACTION, actual " ~ lexer.token() ~ " "
2963 ~ lexer.info());
2964 }
2965
2966 return option;
2967 }
2968
2969 protected SQLColumnCheck parseColumnCheck() {
2970 lexer.nextToken();
2971 SQLExpr expr = this.expr();
2972 SQLColumnCheck check = new SQLColumnCheck(expr);
2973
2974 if (lexer.token == Token.DISABLE) {
2975 lexer.nextToken();
2976 check.setEnable(Boolean.FALSE);
2977 } else if (lexer.token == Token.ENABLE) {
2978 lexer.nextToken();
2979 check.setEnable(Boolean.TRUE);
2980 } else if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {
2981 lexer.nextToken();
2982 check.setValidate(Boolean.TRUE);
2983 } else if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {
2984 lexer.nextToken();
2985 check.setValidate(Boolean.FALSE);
2986 } else if (lexer.identifierEquals(FnvHash.Constants.RELY)) {
2987 lexer.nextToken();
2988 check.setRely(Boolean.TRUE);
2989 } else if (lexer.identifierEquals(FnvHash.Constants.NORELY)) {
2990 lexer.nextToken();
2991 check.setRely(Boolean.FALSE);
2992 }
2993 return check;
2994 }
2995
2996 public SQLPrimaryKey parsePrimaryKey() {
2997 accept(Token.PRIMARY);
2998 accept(Token.KEY);
2999
3000 SQLPrimaryKeyImpl pk = new SQLPrimaryKeyImpl();
3001
3002 if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {
3003 lexer.nextToken();
3004 pk.setClustered(true);
3005 }
3006
3007 accept(Token.LPAREN);
3008 orderBy(pk.getColumns(), pk);
3009 accept(Token.RPAREN);
3010
3011 return pk;
3012 }
3013
3014 public SQLUnique parseUnique() {
3015 accept(Token.UNIQUE);
3016
3017 SQLUnique unique = new SQLUnique();
3018 accept(Token.LPAREN);
3019 orderBy(unique.getColumns(), unique);
3020 accept(Token.RPAREN);
3021
3022 if (lexer.token == Token.DISABLE) {
3023 lexer.nextToken();
3024 unique.setEnable(Boolean.FALSE);
3025 } else if (lexer.token == Token.ENABLE) {
3026 lexer.nextToken();
3027 unique.setEnable(Boolean.TRUE);
3028 } else if (lexer.identifierEquals(FnvHash.Constants.VALIDATE)) {
3029 lexer.nextToken();
3030 unique.setValidate(Boolean.TRUE);
3031 } else if (lexer.identifierEquals(FnvHash.Constants.NOVALIDATE)) {
3032 lexer.nextToken();
3033 unique.setValidate(Boolean.FALSE);
3034 } else if (lexer.identifierEquals(FnvHash.Constants.RELY)) {
3035 lexer.nextToken();
3036 unique.setRely(Boolean.TRUE);
3037 } else if (lexer.identifierEquals(FnvHash.Constants.NORELY)) {
3038 lexer.nextToken();
3039 unique.setRely(Boolean.FALSE);
3040 }
3041
3042 return unique;
3043 }
3044
3045 public SQLAssignItem parseAssignItem() {
3046 SQLAssignItem item = new SQLAssignItem();
3047
3048 SQLExpr var = primary();
3049
3050 if (cast(SQLIdentifierExpr)(var) !is null) {
3051 var = new SQLVariantRefExpr((cast(SQLIdentifierExpr) var).getName());
3052 }
3053 item.setTarget(var);
3054 if (lexer.token == Token.COLONEQ) {
3055 lexer.nextToken();
3056 } else if (lexer.token == Token.TRUE || lexer.identifierEquals(FnvHash.Constants.TRUE)) {
3057 lexer.nextToken();
3058 item.setValue(new SQLBooleanExpr(true));
3059 return item;
3060 } else if (lexer.token == Token.ON) {
3061 lexer.nextToken();
3062 item.setValue(new SQLIdentifierExpr("ON"));
3063 return item;
3064 } else {
3065 if (lexer.token == Token.EQ) {
3066 lexer.nextToken();
3067 } else {
3068 accept(Token.EQ);
3069 }
3070 }
3071
3072 if (lexer.token == Token.ON) {
3073 item.setValue(new SQLIdentifierExpr(lexer.stringVal()));
3074 lexer.nextToken();
3075 } else {
3076 if (lexer.token == Token.ALL) {
3077 item.setValue(new SQLIdentifierExpr(lexer.stringVal()));
3078 lexer.nextToken();
3079 } else {
3080 SQLExpr expr = this.expr();
3081
3082 if (lexer.token == Token.COMMA && DBType.POSTGRESQL.name == (dbType)) {
3083 SQLListExpr listExpr = new SQLListExpr();
3084 listExpr.addItem(expr);
3085 expr.setParent(listExpr);
3086 do {
3087 lexer.nextToken();
3088 SQLExpr listItem = this.expr();
3089 listItem.setParent(listExpr);
3090 listExpr.addItem(listItem);
3091 } while (lexer.token == Token.COMMA);
3092 item.setValue(listExpr);
3093 } else {
3094 item.setValue(expr);
3095 }
3096 }
3097 }
3098
3099 return item;
3100 }
3101
3102 public List!(SQLCommentHint) parseHints() {
3103 List!(SQLCommentHint) hints = new ArrayList!(SQLCommentHint)();
3104 parseHints!(SQLCommentHint)((hints));
3105 return hints;
3106 }
3107
3108 //@SuppressWarnings({ "unchecked", "rawtypes" })
3109 public void parseHints(T)(List!(T) hints) {
3110 if (lexer.token == Token.HINT) {
3111 SQLCommentHint hint = new SQLCommentHint(lexer.stringVal());
3112
3113 if (lexer.commentCount > 0) {
3114 hint.addBeforeComment(lexer.comments);
3115 }
3116
3117 hints.add(hint);
3118 lexer.nextToken();
3119 }
3120 }
3121
3122 public SQLConstraint parseConstaint() {
3123 SQLName name = null;
3124
3125 if (lexer.token == Token.CONSTRAINT) {
3126 lexer.nextToken();
3127 name = this.name();
3128 }
3129
3130 SQLConstraint constraint;
3131 if (lexer.token == Token.PRIMARY) {
3132 constraint = parsePrimaryKey();
3133 } else if (lexer.token == Token.UNIQUE) {
3134 constraint = parseUnique();
3135 } else if (lexer.token == Token.KEY) {
3136 constraint = parseUnique();
3137 } else if (lexer.token == Token.FOREIGN) {
3138 constraint = parseForeignKey();
3139 } else if (lexer.token == Token.CHECK) {
3140 constraint = parseCheck();
3141 } else {
3142 throw new ParserException("TODO : " ~ lexer.info());
3143 }
3144
3145 constraint.setName(name);
3146
3147 return constraint;
3148 }
3149
3150 public SQLCheck parseCheck() {
3151 accept(Token.CHECK);
3152 SQLCheck check = createCheck();
3153 accept(Token.LPAREN);
3154 check.setExpr(this.expr());
3155 accept(Token.RPAREN);
3156 return check;
3157 }
3158
3159 protected SQLCheck createCheck() {
3160 return new SQLCheck();
3161 }
3162
3163 public SQLForeignKeyConstraint parseForeignKey() {
3164 accept(Token.FOREIGN);
3165 accept(Token.KEY);
3166
3167 SQLForeignKeyImpl fk = createForeignKey();
3168
3169 accept(Token.LPAREN);
3170 this.names(fk.getReferencingColumns(), fk);
3171 accept(Token.RPAREN);
3172
3173 accept(Token.REFERENCES);
3174
3175 fk.setReferencedTableName(this.name());
3176
3177 if (lexer.token == Token.LPAREN) {
3178 lexer.nextToken();
3179 this.names(fk.getReferencedColumns(), fk);
3180 accept(Token.RPAREN);
3181 }
3182
3183 if (lexer.token == Token.ON) {
3184 lexer.nextToken();
3185 accept(Token.DELETE);
3186 if (lexer.identifierEquals(FnvHash.Constants.CASCADE)) {
3187 lexer.nextToken();
3188 fk.setOnDeleteCascade(true);
3189 } else {
3190 accept(Token.SET);
3191 accept(Token.NULL);
3192 fk.setOnDeleteSetNull(true);
3193 }
3194 }
3195
3196 return fk;
3197 }
3198
3199 protected SQLForeignKeyImpl createForeignKey() {
3200 return new SQLForeignKeyImpl();
3201 }
3202
3203 public SQLSelectItem parseSelectItem() {
3204 SQLExpr expr;
3205 bool connectByRoot = false;
3206 Token token = lexer.token;
3207 if (token == Token.IDENTIFIER) {
3208 string ident = lexer.stringVal();
3209 long hash_lower = lexer.hash_lower();
3210 lexer.nextTokenComma();
3211
3212 if (hash_lower == FnvHash.Constants.CONNECT_BY_ROOT) {
3213 connectByRoot = lexer.token != Token.LPAREN;
3214 if (connectByRoot) {
3215 expr = new SQLIdentifierExpr(lexer.stringVal());
3216 lexer.nextToken();
3217 } else {
3218 expr = new SQLIdentifierExpr(ident);
3219 }
3220 } else if (FnvHash.Constants.DATE == hash_lower
3221 && lexer.token == Token.LITERAL_CHARS
3222 && (DBType.ORACLE.name == (getDbType())
3223 || DBType.POSTGRESQL.name == (getDbType()))) {
3224 string literal = lexer.stringVal();
3225 lexer.nextToken();
3226
3227 SQLDateExpr dateExpr = new SQLDateExpr();
3228 dateExpr.setLiteral(new String(literal));
3229
3230 expr = dateExpr;
3231 } else {
3232 expr = new SQLIdentifierExpr(ident, hash_lower);
3233 }
3234
3235 token = lexer.token;
3236
3237 if (token == Token.DOT) {
3238 lexer.nextTokenIdent();
3239 string name;
3240 long name_hash_lower;
3241
3242 if (lexer.token == Token.STAR) {
3243 name = "*";
3244 name_hash_lower = FnvHash.Constants.STAR;
3245 } else {
3246 name = lexer.stringVal();
3247 name_hash_lower = lexer.hash_lower();
3248 }
3249
3250 lexer.nextTokenComma();
3251
3252 token = lexer.token;
3253 if (token == Token.LPAREN) {
3254 bool aggregate = hash_lower == FnvHash.Constants.WMSYS && name_hash_lower == FnvHash.Constants.WM_CONCAT;
3255 expr = methodRest(expr, name, aggregate);
3256 token = lexer.token;
3257 } else {
3258 if (name_hash_lower == FnvHash.Constants.NEXTVAL) {
3259 expr = new SQLSequenceExpr(cast(SQLIdentifierExpr) expr, SQLSequenceExpr.Function.NextVal);
3260 } else if (name_hash_lower == FnvHash.Constants.CURRVAL) {
3261 expr = new SQLSequenceExpr(cast(SQLIdentifierExpr) expr, SQLSequenceExpr.Function.CurrVal);
3262 } else if (name_hash_lower == FnvHash.Constants.PREVVAL) {
3263 expr = new SQLSequenceExpr(cast(SQLIdentifierExpr) expr, SQLSequenceExpr.Function.PrevVal);
3264 } else {
3265 expr = new SQLPropertyExpr(expr, name, name_hash_lower);
3266 }
3267 }
3268 }
3269
3270 if (token == Token.COMMA) {
3271 return new SQLSelectItem(expr, null, connectByRoot);
3272 }
3273
3274 if (token == Token.AS) {
3275 lexer.nextToken();
3276 string as = null;
3277 if (lexer.token != Token.COMMA && lexer.token != Token.FROM) {
3278 as = lexer.stringVal();
3279
3280 lexer.nextTokenComma();
3281
3282 if (lexer.token == Token.DOT) {
3283 lexer.nextToken();
3284 as ~= '.' ~ lexer.stringVal();
3285 lexer.nextToken();
3286 }
3287 }
3288
3289 return new SQLSelectItem(expr, as, connectByRoot);
3290 }
3291
3292 if (token == Token.LITERAL_ALIAS) {
3293 string as = lexer.stringVal();
3294 lexer.nextTokenComma();
3295 return new SQLSelectItem(expr, as, connectByRoot);
3296 }
3297
3298 if ((token == Token.IDENTIFIER && hash_lower != FnvHash.Constants.CURRENT)
3299 || token == Token.MODEL) {
3300 string as;
3301 if (lexer.hash_lower == FnvHash.Constants.FORCE && DBType.MYSQL.name == (dbType)) {
3302 string force = lexer.stringVal();
3303
3304 Lexer.SavePoint savePoint = lexer.mark();
3305 lexer.nextToken();
3306
3307 if (lexer.token == Token.PARTITION) {
3308 lexer.reset(savePoint);
3309 as = null;
3310 } else {
3311 as = force;
3312 lexer.nextTokenComma();
3313 }
3314 } else {
3315 as = lexer.stringVal();
3316 lexer.nextTokenComma();
3317 }
3318 return new SQLSelectItem(expr, as, connectByRoot);
3319 }
3320
3321 if (token == Token.LPAREN) {
3322 lexer.nextToken();
3323 expr = this.methodRest(expr, false);
3324 } else {
3325 expr = this.primaryRest(expr);
3326 }
3327 expr = this.exprRest(expr);
3328 } else if (token == Token.STAR) {
3329 expr = new SQLAllColumnExpr();
3330 lexer.nextToken();
3331 return new SQLSelectItem(expr, null, connectByRoot);
3332 } else if (token == Token.DO || token == Token.JOIN) {
3333 expr = this.name();
3334 expr = this.exprRest(expr);
3335 } else {
3336 expr = this.expr();
3337 }
3338
3339 string _alias;
3340 switch (lexer.token) {
3341 case Token.FULL:
3342 case Token.MODEL:
3343 case Token.TABLESPACE:
3344 _alias = lexer.stringVal();
3345 lexer.nextToken();
3346 break;
3347 default:
3348 _alias = as();
3349 break;
3350 }
3351
3352 SQLSelectItem selectItem = new SQLSelectItem(expr, _alias, connectByRoot);
3353 if (lexer.token == Token.HINT && !lexer.isEnabled(SQLParserFeature.StrictForWall)) {
3354 string comment = "/*" ~ lexer.stringVal() ~ "*/";
3355 selectItem.addAfterComment(comment);
3356 lexer.nextToken();
3357 }
3358
3359 return selectItem;
3360 }
3361
3362 public SQLExpr parseGroupingSet() {
3363 string tmp = lexer.stringVal();
3364 acceptIdentifier("GROUPING");
3365
3366 SQLGroupingSetExpr expr = new SQLGroupingSetExpr();
3367
3368 if (lexer.token == Token.SET || lexer.identifierEquals(FnvHash.Constants.SET)) {
3369 lexer.nextToken();
3370 } else {
3371 return new SQLIdentifierExpr(tmp);
3372 }
3373
3374 accept(Token.LPAREN);
3375
3376 this.exprList(expr.getParameters(), expr);
3377
3378 accept(Token.RPAREN);
3379
3380 return expr;
3381 }
3382
3383 protected SQLPartition parsePartition() {
3384 throw new ParserException("TODO");
3385 }
3386
3387 public SQLPartitionBy parsePartitionBy() {
3388 throw new ParserException("TODO");
3389 }
3390
3391 public SQLPartitionValue parsePartitionValues() {
3392 if (lexer.token != Token.VALUES) {
3393 return null;
3394 }
3395 lexer.nextToken();
3396
3397 SQLPartitionValue values = null;
3398
3399 if (lexer.token == Token.IN) {
3400 lexer.nextToken();
3401 values = new SQLPartitionValue(SQLPartitionValue.Operator.In);
3402
3403 accept(Token.LPAREN);
3404 this.exprList(values.getItems(), values);
3405 accept(Token.RPAREN);
3406 } else if (lexer.identifierEquals(FnvHash.Constants.LESS)) {
3407 lexer.nextToken();
3408 acceptIdentifier("THAN");
3409
3410 values = new SQLPartitionValue(SQLPartitionValue.Operator.LessThan);
3411
3412 if (lexer.identifierEquals(FnvHash.Constants.MAXVALUE)) {
3413 SQLIdentifierExpr maxValue = new SQLIdentifierExpr(lexer.stringVal());
3414 lexer.nextToken();
3415 maxValue.setParent(values);
3416 values.addItem(maxValue);
3417 } else {
3418 accept(Token.LPAREN);
3419 this.exprList(values.getItems(), values);
3420 accept(Token.RPAREN);
3421 }
3422 } else if (lexer.token == Token.LPAREN) {
3423 values = new SQLPartitionValue(SQLPartitionValue.Operator.List);
3424 lexer.nextToken();
3425 this.exprList(values.getItems(), values);
3426 accept(Token.RPAREN);
3427 }
3428
3429 return values;
3430 }
3431
3432 protected static bool isIdent(SQLExpr expr, string name) {
3433 if (cast(SQLIdentifierExpr)(expr) !is null) {
3434 SQLIdentifierExpr identExpr = cast(SQLIdentifierExpr) expr;
3435 return identExpr.getName().equalsIgnoreCase(name);
3436 }
3437 return false;
3438 }
3439
3440 public SQLLimit parseLimit() {
3441 if (lexer.token == Token.LIMIT) {
3442 lexer.nextTokenValue();
3443
3444 SQLLimit limit = new SQLLimit();
3445
3446 SQLExpr temp;
3447 if (lexer.token == Token.LITERAL_INT) {
3448 temp = new SQLIntegerExpr(lexer.integerValue());
3449 lexer.nextTokenComma();
3450 if (lexer.token != Token.COMMA && lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {
3451 temp = this.primaryRest(temp);
3452 temp = this.exprRest(temp);
3453 }
3454 } else {
3455 temp = this.expr();
3456 }
3457
3458 if (lexer.token == (Token.COMMA)) {
3459 limit.setOffset(temp);
3460 lexer.nextTokenValue();
3461
3462 SQLExpr rowCount;
3463 if (lexer.token == Token.LITERAL_INT) {
3464 rowCount = new SQLIntegerExpr(lexer.integerValue());
3465 lexer.nextToken();
3466 if (lexer.token != Token.EOF && lexer.token != Token.IDENTIFIER) {
3467 rowCount = this.primaryRest(rowCount);
3468 rowCount = this.exprRest(rowCount);
3469 }
3470 } else {
3471 rowCount = this.expr();
3472 }
3473
3474 limit.setRowCount(rowCount);
3475 } else if (lexer.identifierEquals(FnvHash.Constants.OFFSET)) {
3476 limit.setRowCount(temp);
3477 lexer.nextToken();
3478 limit.setOffset(this.expr());
3479 } else {
3480 limit.setRowCount(temp);
3481 }
3482 return limit;
3483 }
3484
3485 return null;
3486 }
3487 }