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.dialect.mysql.parser.MySqlStatementParser; 17 18 import hunt.sql.SQLUtils; 19 import hunt.sql.ast; 20 import hunt.sql.ast.SQLParameter; 21 // import hunt.sql.ast.SQLParameter.ParameterType; 22 import hunt.sql.ast.expr; 23 import hunt.sql.ast.statement; 24 import hunt.sql.dialect.mysql.ast.MysqlForeignKey; 25 import hunt.sql.dialect.mysql.ast.clause.ConditionValue; 26 // import hunt.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType; 27 import hunt.sql.dialect.mysql.ast.clause.MySqlCaseStatement; 28 // import hunt.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement; 29 import hunt.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatement; 30 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareConditionStatement; 31 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareHandlerStatement; 32 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareStatement; 33 import hunt.sql.dialect.mysql.ast.clause.MySqlHandlerType; 34 import hunt.sql.dialect.mysql.ast.clause.MySqlIterateStatement; 35 import hunt.sql.dialect.mysql.ast.clause.MySqlLeaveStatement; 36 import hunt.sql.dialect.mysql.ast.clause.MySqlRepeatStatement; 37 import hunt.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; 38 import hunt.sql.dialect.mysql.ast.statement; 39 // import hunt.sql.dialect.mysql.ast.statement.MySqlLockTableStatement.LockType; 40 import hunt.sql.parser; 41 42 import hunt.sql.visitor.SQLASTOutputVisitor; 43 import hunt.sql.util.FnvHash; 44 import hunt.sql.util.DBType; 45 import hunt.sql.dialect.mysql.parser.MySqlSelectParser; 46 import hunt.sql.dialect.mysql.parser.MySqlExprParser; 47 import hunt.sql.dialect.mysql.parser.MySqlCreateTableParser; 48 import std.algorithm.searching; 49 import hunt.String; 50 import hunt.collection; 51 import std.uni; 52 import hunt.Boolean; 53 54 import hunt.text; 55 import hunt.sql.dialect.mysql.parser.MySqlSelectIntoParser; 56 57 public class MySqlStatementParser : SQLStatementParser { 58 59 private enum string AUTO_INCREMENT = "AUTO_INCREMENT"; 60 private enum string COLLATE2 = "COLLATE"; 61 private enum string CHAIN = "CHAIN"; 62 private enum string ENGINES = "ENGINES"; 63 private enum string ENGINE = "ENGINE"; 64 private enum string BINLOG = "BINLOG"; 65 private enum string EVENTS = "EVENTS"; 66 private enum string SESSION = "SESSION"; 67 private enum string GLOBAL = "GLOBAL"; 68 private enum string VARIABLES = "VARIABLES"; 69 private enum string STATUS = "STATUS"; 70 private enum string RESET = "RESET"; 71 private enum string DESCRIBE = "DESCRIBE"; 72 private enum string WRITE = "WRITE"; 73 private enum string READ = "READ"; 74 private enum string LOCAL = "LOCAL"; 75 private enum string TABLES = "TABLES"; 76 private enum string TEMPORARY = "TEMPORARY"; 77 private enum string SPATIAL = "SPATIAL"; 78 private enum string LOW_PRIORITY = "LOW_PRIORITY"; 79 private enum string CONNECTION = "CONNECTION"; 80 private enum string EXTENDED = "EXTENDED"; 81 private enum string PARTITIONS = "PARTITIONS"; 82 private enum string FORMAT = "FORMAT"; 83 84 private int maxIntoClause = -1; 85 86 public this(string sql) { 87 import std.stdio; 88 super(new MySqlExprParser(sql)); 89 } 90 91 public this(string sql, SQLParserFeature[] features...) { 92 super(new MySqlExprParser(sql, features)); 93 } 94 95 public this(string sql, bool keepComments) { 96 super(new MySqlExprParser(sql, keepComments)); 97 } 98 99 public this(string sql, bool skipComment, bool keepComments) { 100 super(new MySqlExprParser(sql, skipComment, keepComments)); 101 } 102 103 public this(Lexer lexer) { 104 super(new MySqlExprParser(lexer)); 105 } 106 107 public int getMaxIntoClause() { 108 return maxIntoClause; 109 } 110 111 public void setMaxIntoClause(int maxIntoClause) { 112 this.maxIntoClause = maxIntoClause; 113 } 114 115 override public SQLCreateTableStatement parseCreateTable() { 116 MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser); 117 return parser.parseCreateTable(); 118 } 119 120 override public SQLStatement parseSelect() { 121 MySqlSelectParser selectParser = createSQLSelectParser(); 122 123 SQLSelect select = selectParser.select(); 124 125 if (selectParser.returningFlag) { 126 return selectParser.updateStmt; 127 } 128 129 return new SQLSelectStatement(select, DBType.MYSQL.name); 130 } 131 132 override public SQLUpdateStatement parseUpdateStatement() { 133 return new MySqlSelectParser(this.exprParser, selectListCache).parseUpdateStatment(); 134 } 135 136 override protected MySqlUpdateStatement createUpdateStatement() { 137 return new MySqlUpdateStatement(); 138 } 139 140 override public MySqlDeleteStatement parseDeleteStatement() { 141 MySqlDeleteStatement deleteStatement = new MySqlDeleteStatement(); 142 143 if (lexer.token() == Token.DELETE) { 144 lexer.nextToken(); 145 146 if (lexer.token() == Token.COMMENT) { 147 lexer.nextToken(); 148 } 149 150 if (lexer.token() == Token.HINT) { 151 this.getExprParser().parseHints!(SQLCommentHint)((deleteStatement.getHints())); 152 } 153 154 if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { 155 deleteStatement.setLowPriority(true); 156 lexer.nextToken(); 157 } 158 159 if (lexer.identifierEquals("QUICK")) { 160 deleteStatement.setQuick(true); 161 lexer.nextToken(); 162 } 163 164 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 165 deleteStatement.setIgnore(true); 166 lexer.nextToken(); 167 } 168 169 if (lexer.identifierEquals(FnvHash.Constants.FORCE)) { 170 Lexer.SavePoint savePoint = lexer.mark(); 171 lexer.nextToken(); 172 173 if (lexer.token() == Token.ALL) { 174 lexer.nextToken(); 175 acceptIdentifier("PARTITIONS"); 176 deleteStatement.setForceAllPartitions(true); 177 } else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)){ 178 lexer.nextToken(); 179 deleteStatement.setForceAllPartitions(true); 180 } else if (lexer.token() == Token.PARTITION) { 181 lexer.nextToken(); 182 SQLName partition = this.exprParser.name(); 183 deleteStatement.setForcePartition(partition); 184 } else { 185 lexer.reset(savePoint); 186 } 187 } 188 189 if (lexer.token() == Token.IDENTIFIER) { 190 deleteStatement.setTableSource(createSQLSelectParser().parseTableSource()); 191 192 if (lexer.token() == Token.FROM) { 193 lexer.nextToken(); 194 SQLTableSource tableSource = createSQLSelectParser().parseTableSource(); 195 deleteStatement.setFrom(tableSource); 196 } 197 } else if (lexer.token() == Token.FROM) { 198 lexer.nextToken(); 199 deleteStatement.setTableSource(createSQLSelectParser().parseTableSource()); 200 } else { 201 throw new ParserException("syntax error. " ~ lexer.info()); 202 } 203 204 if (lexer.identifierEquals(FnvHash.Constants.USING)) { 205 lexer.nextToken(); 206 207 SQLTableSource tableSource = createSQLSelectParser().parseTableSource(); 208 deleteStatement.setUsing(tableSource); 209 } 210 } 211 212 if (lexer.token() == (Token.WHERE)) { 213 lexer.nextToken(); 214 SQLExpr where = this.exprParser.expr(); 215 deleteStatement.setWhere(where); 216 } 217 218 if (lexer.token() == (Token.ORDER)) { 219 SQLOrderBy orderBy = exprParser.parseOrderBy(); 220 deleteStatement.setOrderBy(orderBy); 221 } 222 223 deleteStatement.setLimit(this.exprParser.parseLimit()); 224 225 return deleteStatement; 226 } 227 228 override public SQLStatement parseCreate() { 229 char markChar = lexer.current(); 230 int markBp = lexer.bp(); 231 232 List!(string) comments = null; 233 if (lexer.isKeepComments() && lexer.hasComment()) { 234 comments = lexer.readAndResetComments(); 235 } 236 237 accept(Token.CREATE); 238 239 bool replace = false; 240 if (lexer.token() == Token.OR) { 241 lexer.nextToken(); 242 accept(Token.REPLACE); 243 replace = true; 244 } 245 246 List!(SQLCommentHint) hints = this.exprParser.parseHints(); 247 248 if (lexer.token() == Token.TABLE || lexer.identifierEquals(TEMPORARY)) { 249 if (replace) { 250 lexer.reset(markBp, markChar, Token.CREATE); 251 } 252 MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser); 253 MySqlCreateTableStatement stmt = parser.parseCreateTable(false); 254 stmt.setHints(hints); 255 256 if (comments !is null) { 257 stmt.addBeforeComment(comments); 258 } 259 260 return stmt; 261 } 262 263 if (lexer.token() == Token.DATABASE 264 || lexer.token() == Token.SCHEMA) { 265 if (replace) { 266 lexer.reset(markBp, markChar, Token.CREATE); 267 } 268 return parseCreateDatabase(); 269 } 270 271 if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || lexer.token() == Token.FULLTEXT 272 || lexer.identifierEquals(SPATIAL)) { 273 if (replace) { 274 lexer.reset(markBp, markChar, Token.CREATE); 275 } 276 return parseCreateIndex(false); 277 } 278 279 if (lexer.token() == Token.USER) { 280 if (replace) { 281 lexer.reset(markBp, markChar, Token.CREATE); 282 } 283 return parseCreateUser(); 284 } 285 286 if (lexer.token() == Token.VIEW 287 || lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) { 288 if (replace) { 289 lexer.reset(markBp, markChar, Token.CREATE); 290 } 291 292 return parseCreateView(); 293 } 294 295 if (lexer.token() == Token.TRIGGER) { 296 lexer.reset(markBp, markChar, Token.CREATE); 297 return parseCreateTrigger(); 298 } 299 300 // parse create procedure 301 if (lexer.token() == Token.PROCEDURE ) { 302 if (replace) { 303 lexer.reset(markBp, markChar, Token.CREATE); 304 } 305 return parseCreateProcedure(); 306 } 307 308 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 309 // Lexer.SavePoint savePoint = lexer.mark(); 310 lexer.nextToken(); 311 accept(Token.EQ); 312 this.getExprParser().userName(); 313 314 if (lexer.identifierEquals(FnvHash.Constants.SQL)) { 315 lexer.nextToken(); 316 acceptIdentifier("SECURITY"); 317 if (lexer.token() == Token.EQ) { 318 lexer.nextToken(); 319 } 320 lexer.nextToken(); 321 } 322 if (lexer.identifierEquals(FnvHash.Constants.EVENT)) { 323 lexer.reset(markBp, markChar, Token.CREATE); 324 return parseCreateEvent(); 325 } else if (lexer.token() == Token.TRIGGER) { 326 lexer.reset(markBp, markChar, Token.CREATE); 327 return parseCreateTrigger(); 328 } else if (lexer.token() == Token.VIEW) { 329 lexer.reset(markBp, markChar, Token.CREATE); 330 return parseCreateView(); 331 } else if (lexer.token() == Token.FUNCTION) { 332 lexer.reset(markBp, markChar, Token.CREATE); 333 return parseCreateFunction(); 334 } else { 335 lexer.reset(markBp, markChar, Token.CREATE); 336 return parseCreateProcedure(); 337 } 338 } 339 340 if (lexer.token() == Token.FUNCTION) { 341 if (replace) { 342 lexer.reset(markBp, markChar, Token.CREATE); 343 } 344 return parseCreateFunction(); 345 } 346 347 if (lexer.identifierEquals(FnvHash.Constants.LOGFILE)) { 348 return parseCreateLogFileGroup(); 349 } 350 351 if (lexer.identifierEquals(FnvHash.Constants.SERVER)) { 352 return parseCreateServer(); 353 } 354 355 if (lexer.token() == Token.TABLESPACE) { 356 return parseCreateTableSpace(); 357 } 358 359 throw new ParserException("TODO " ~ lexer.info()); 360 } 361 362 public SQLStatement parseCreateTableSpace() { 363 if (lexer.token() == Token.CREATE) { 364 accept(Token.CREATE); 365 } 366 367 MySqlCreateTableSpaceStatement stmt = new MySqlCreateTableSpaceStatement(); 368 369 accept(Token.TABLESPACE); 370 stmt.setName(this.exprParser.name()); 371 372 if (lexer.identifierEquals(FnvHash.Constants.ADD)) { 373 lexer.nextToken(); 374 acceptIdentifier("DATAFILE"); 375 SQLExpr file = this.exprParser.primary(); 376 stmt.setAddDataFile(file); 377 } 378 379 for (;;) { 380 if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) { 381 lexer.nextToken(); 382 if (lexer.token() == Token.EQ) { 383 lexer.nextToken(); 384 } 385 SQLExpr initialSize = this.exprParser.expr(); 386 stmt.setInitialSize(initialSize); 387 } else if (lexer.identifierEquals(FnvHash.Constants.FILE_BLOCK_SIZE)) { 388 lexer.nextToken(); 389 if (lexer.token() == Token.EQ) { 390 lexer.nextToken(); 391 } 392 SQLExpr fileBlockSize = this.exprParser.expr(); 393 stmt.setFileBlockSize(fileBlockSize); 394 } else if (lexer.identifierEquals(FnvHash.Constants.EXTENT_SIZE)) { 395 lexer.nextToken(); 396 if (lexer.token() == Token.EQ) { 397 lexer.nextToken(); 398 } 399 SQLExpr extentSize = this.exprParser.expr(); 400 stmt.setExtentSize(extentSize); 401 } else if (lexer.identifierEquals(FnvHash.Constants.AUTOEXTEND_SIZE)) { 402 lexer.nextToken(); 403 if (lexer.token() == Token.EQ) { 404 lexer.nextToken(); 405 } 406 SQLExpr extentSize = this.exprParser.expr(); 407 stmt.setAutoExtentSize(extentSize); 408 } else if (lexer.identifierEquals(FnvHash.Constants.MAX_SIZE)) { 409 lexer.nextToken(); 410 if (lexer.token() == Token.EQ) { 411 lexer.nextToken(); 412 } 413 SQLExpr size = this.exprParser.expr(); 414 stmt.setMaxSize(size); 415 } else if (lexer.identifierEquals(FnvHash.Constants.NODEGROUP)) { 416 lexer.nextToken(); 417 if (lexer.token() == Token.EQ) { 418 lexer.nextToken(); 419 } 420 SQLExpr size = this.exprParser.expr(); 421 stmt.setNodeGroup(size); 422 } else if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { 423 lexer.nextToken(); 424 stmt.setWait(true); 425 } else if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) { 426 lexer.nextToken(); 427 if (lexer.token() == Token.EQ) { 428 lexer.nextToken(); 429 } 430 SQLExpr engine = this.exprParser.expr(); 431 stmt.setEngine(engine); 432 } else if (lexer.token() == Token.COMMENT) { 433 lexer.nextToken(); 434 SQLExpr comment = this.exprParser.expr(); 435 stmt.setComment(comment); 436 } else if (lexer.token() == Token.USE) { 437 lexer.nextToken(); 438 acceptIdentifier("LOGFILE"); 439 accept(Token.GROUP); 440 441 SQLExpr logFileGroup = this.exprParser.expr(); 442 stmt.setFileBlockSize(logFileGroup); 443 } else { 444 break; 445 } 446 } 447 return stmt; 448 } 449 450 public SQLStatement parseCreateServer() { 451 if (lexer.token() == Token.CREATE) { 452 accept(Token.CREATE); 453 } 454 455 MySqlCreateServerStatement stmt = new MySqlCreateServerStatement(); 456 457 acceptIdentifier("SERVER"); 458 stmt.setName(this.exprParser.name()); 459 460 accept(Token.FOREIGN); 461 acceptIdentifier("DATA"); 462 acceptIdentifier("WRAPPER"); 463 stmt.setForeignDataWrapper(this.exprParser.name()); 464 465 acceptIdentifier("OPTIONS"); 466 accept(Token.LPAREN); 467 for (;;) { 468 if (lexer.identifierEquals(FnvHash.Constants.HOST)) { 469 lexer.nextToken(); 470 SQLExpr host = this.exprParser.expr(); 471 stmt.setHost(host); 472 } else if (lexer.token() == Token.USER) { 473 lexer.nextToken(); 474 SQLExpr user = this.exprParser.expr(); 475 stmt.setUser(user); 476 } else if (lexer.token() == Token.DATABASE) { 477 lexer.nextToken(); 478 SQLExpr db = this.exprParser.expr(); 479 stmt.setDatabase(db); 480 } else if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) { 481 lexer.nextToken(); 482 SQLExpr pwd = this.exprParser.expr(); 483 stmt.setPassword(pwd); 484 } else if (lexer.identifierEquals(FnvHash.Constants.SOCKET)) { 485 lexer.nextToken(); 486 SQLExpr sock = this.exprParser.expr(); 487 stmt.setSocket(sock); 488 } else if (lexer.identifierEquals(FnvHash.Constants.OWNER)) { 489 lexer.nextToken(); 490 SQLExpr owner = this.exprParser.expr(); 491 stmt.setOwner(owner); 492 } else if (lexer.identifierEquals(FnvHash.Constants.PORT)) { 493 lexer.nextToken(); 494 SQLExpr port = this.exprParser.expr(); 495 stmt.setPort(port); 496 } 497 498 if (lexer.token() == Token.COMMA) { 499 lexer.nextToken(); 500 } else { 501 break; 502 } 503 } 504 accept(Token.RPAREN); 505 return stmt; 506 } 507 508 override public SQLStatement parseCreateIndex(bool acceptCreate) { 509 if (acceptCreate) { 510 accept(Token.CREATE); 511 } 512 513 SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(); 514 515 if (lexer.token() == Token.UNIQUE) { 516 stmt.setType("UNIQUE"); 517 lexer.nextToken(); 518 } else if (lexer.token() == Token.FULLTEXT) { 519 stmt.setType("FULLTEXT"); 520 lexer.nextToken(); 521 } else if (lexer.identifierEquals(SPATIAL)) { 522 stmt.setType(SPATIAL); 523 lexer.nextToken(); 524 } 525 526 accept(Token.INDEX); 527 528 stmt.setName(this.exprParser.name()); 529 530 parseCreateIndexUsing(stmt); 531 532 accept(Token.ON); 533 534 stmt.setTable(this.exprParser.name()); 535 536 accept(Token.LPAREN); 537 538 for (; ; ) { 539 SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem(); 540 stmt.addItem(item); 541 if (lexer.token() == Token.COMMA) { 542 lexer.nextToken(); 543 continue; 544 } 545 break; 546 } 547 accept(Token.RPAREN); 548 549 for (;;) { 550 if (lexer.identifierEquals(FnvHash.Constants.USING)) { 551 parseCreateIndexUsing(stmt); 552 } else if (lexer.token() == Token.COMMENT) { 553 lexer.nextToken(); 554 SQLExpr comment = this.exprParser.expr(); 555 stmt.setComment(comment); 556 } else { 557 break; 558 } 559 } 560 561 return stmt; 562 } 563 564 private void parseCreateIndexUsing(SQLCreateIndexStatement stmt) { 565 if (lexer.identifierEquals(FnvHash.Constants.USING)) { 566 lexer.nextToken(); 567 568 if (lexer.identifierEquals(FnvHash.Constants.BTREE)) { 569 stmt.setUsing("BTREE"); 570 lexer.nextToken(); 571 } else if (lexer.identifierEquals(FnvHash.Constants.HASH)) { 572 stmt.setUsing("HASH"); 573 lexer.nextToken(); 574 } else { 575 throw new ParserException("TODO " ~ lexer.info()); 576 } 577 } 578 } 579 580 override public SQLStatement parseCreateUser() { 581 if (lexer.token() == Token.CREATE) { 582 lexer.nextToken(); 583 } 584 585 accept(Token.USER); 586 587 MySqlCreateUserStatement stmt = new MySqlCreateUserStatement(); 588 589 for (; ; ) { 590 MySqlCreateUserStatement.UserSpecification userSpec = new MySqlCreateUserStatement.UserSpecification(); 591 592 SQLExpr expr = exprParser.primary(); 593 userSpec.setUser(expr); 594 595 if (lexer.token() == Token.IDENTIFIED) { 596 lexer.nextToken(); 597 if (lexer.token() == Token.BY) { 598 lexer.nextToken(); 599 600 if (lexer.identifierEquals("PASSWORD")) { 601 lexer.nextToken(); 602 userSpec.setPasswordHash(true); 603 } 604 605 SQLCharExpr password = cast(SQLCharExpr) this.exprParser.expr(); 606 userSpec.setPassword(password); 607 } else if (lexer.token() == Token.WITH) { 608 lexer.nextToken(); 609 userSpec.setAuthPlugin(this.exprParser.expr()); 610 } 611 } 612 613 stmt.addUser(userSpec); 614 615 if (lexer.token() == Token.COMMA) { 616 lexer.nextToken(); 617 continue; 618 } 619 620 break; 621 } 622 623 return stmt; 624 } 625 626 override public SQLStatement parseKill() { 627 accept(Token.KILL); 628 629 MySqlKillStatement stmt = new MySqlKillStatement(); 630 631 if (lexer.identifierEquals("CONNECTION")) { 632 stmt.setType(MySqlKillStatement.Type.CONNECTION); 633 lexer.nextToken(); 634 } else if (lexer.identifierEquals("QUERY")) { 635 stmt.setType(MySqlKillStatement.Type.QUERY); 636 lexer.nextToken(); 637 } else if (lexer.token() == Token.LITERAL_INT) { 638 // skip 639 } else { 640 throw new ParserException("not support kill type " ~ lexer.token() ~ ". " ~ lexer.info()); 641 } 642 643 this.exprParser.exprList(stmt.getThreadIds(), stmt); 644 return stmt; 645 } 646 647 public SQLStatement parseBinlog() { 648 acceptIdentifier("binlog"); 649 650 MySqlBinlogStatement stmt = new MySqlBinlogStatement(); 651 652 SQLExpr expr = this.exprParser.expr(); 653 stmt.setExpr(expr); 654 655 return stmt; 656 } 657 658 public MySqlAnalyzeStatement parseAnalyze() { 659 accept(Token.ANALYZE); 660 accept(Token.TABLE); 661 662 MySqlAnalyzeStatement stmt = new MySqlAnalyzeStatement(); 663 List!(SQLName) names = new ArrayList!(SQLName)(); 664 this.exprParser.names(names, stmt); 665 666 foreach(SQLName name ; names) { 667 stmt.addTableSource(new SQLExprTableSource(name)); 668 } 669 return stmt; 670 } 671 672 public MySqlOptimizeStatement parseOptimize() { 673 accept(Token.OPTIMIZE); 674 accept(Token.TABLE); 675 676 MySqlOptimizeStatement stmt = new MySqlOptimizeStatement(); 677 List!(SQLName) names = new ArrayList!(SQLName)(); 678 this.exprParser.names(names, stmt); 679 680 foreach(SQLName name ; names) { 681 stmt.addTableSource(new SQLExprTableSource(name)); 682 } 683 return stmt; 684 } 685 686 public SQLStatement parseReset() { 687 acceptIdentifier(RESET); 688 689 MySqlResetStatement stmt = new MySqlResetStatement(); 690 691 for (; ; ) { 692 if (lexer.token() == Token.IDENTIFIER) { 693 if (lexer.identifierEquals("QUERY")) { 694 lexer.nextToken(); 695 accept(Token.CACHE); 696 stmt.getOptions().add("QUERY CACHE"); 697 } else { 698 stmt.getOptions().add(lexer.stringVal()); 699 lexer.nextToken(); 700 } 701 702 if (lexer.token() == Token.COMMA) { 703 lexer.nextToken(); 704 continue; 705 } 706 } 707 break; 708 } 709 710 return stmt; 711 } 712 713 override public bool parseStatementListDialect(List!(SQLStatement) statementList) { 714 if (lexer.identifierEquals("PREPARE")) { 715 MySqlPrepareStatement stmt = parsePrepare(); 716 statementList.add(stmt); 717 return true; 718 } 719 720 if (lexer.identifierEquals("EXECUTE")) { 721 MySqlExecuteStatement stmt = parseExecute(); 722 statementList.add(stmt); 723 return true; 724 } 725 726 if (lexer.identifierEquals("DEALLOCATE")) { 727 MysqlDeallocatePrepareStatement stmt = parseDeallocatePrepare(); 728 statementList.add(stmt); 729 return true; 730 } 731 732 if (lexer.identifierEquals("LOAD")) { 733 SQLStatement stmt = parseLoad(); 734 statementList.add(stmt); 735 return true; 736 } 737 738 if (lexer.token() == Token.REPLACE) { 739 SQLReplaceStatement stmt = parseReplace(); 740 statementList.add(stmt); 741 return true; 742 } 743 744 if (lexer.identifierEquals("START")) { 745 SQLStartTransactionStatement stmt = parseStart(); 746 statementList.add(stmt); 747 return true; 748 } 749 750 if (lexer.token() == Token.SHOW) { 751 SQLStatement stmt = parseShow(); 752 statementList.add(stmt); 753 return true; 754 } 755 756 if (lexer.token() == Token.EXPLAIN) { 757 SQLStatement stmt = this.parseExplain(); 758 statementList.add(stmt); 759 return true; 760 } 761 762 763 if (lexer.identifierEquals(BINLOG)) { 764 SQLStatement stmt = parseBinlog(); 765 statementList.add(stmt); 766 return true; 767 } 768 769 if (lexer.identifierEquals(RESET)) { 770 SQLStatement stmt = parseReset(); 771 statementList.add(stmt); 772 return true; 773 } 774 775 if (lexer.token() == Token.ANALYZE) { 776 SQLStatement stmt = parseAnalyze(); 777 statementList.add(stmt); 778 return true; 779 } 780 781 if (lexer.token() == Token.OPTIMIZE) { 782 SQLStatement stmt = parseOptimize(); 783 statementList.add(stmt); 784 return true; 785 } 786 787 if (lexer.identifierEquals("HELP")) { 788 lexer.nextToken(); 789 MySqlHelpStatement stmt = new MySqlHelpStatement(); 790 stmt.setContent(this.exprParser.primary()); 791 statementList.add(stmt); 792 return true; 793 } 794 795 if (lexer.identifierEquals("FLUSH")) { 796 SQLStatement stmt = parseFlush(); 797 statementList.add(stmt); 798 return true; 799 } 800 801 if (lexer.token() == Token.DESC || lexer.identifierEquals(DESCRIBE)) { 802 SQLStatement stmt = parseDescribe(); 803 statementList.add(stmt); 804 return true; 805 } 806 807 if (lexer.token() == Token.LOCK) { 808 lexer.nextToken(); 809 string val = lexer.stringVal(); 810 bool isLockTables = equalsIgnoreCase(TABLES, val) && lexer.token() == Token.IDENTIFIER; 811 bool isLockTable = equalsIgnoreCase("TABLE",val) && lexer.token() == Token.TABLE; 812 if (isLockTables || isLockTable) { 813 lexer.nextToken(); 814 } else { 815 setErrorEndPos(lexer.pos()); 816 throw new ParserException("syntax error, expect TABLES or TABLE, actual " ~ lexer.token() ~ ", " ~ lexer.info()); 817 } 818 819 MySqlLockTableStatement stmt = new MySqlLockTableStatement(); 820 821 for(;;) { 822 MySqlLockTableStatement.Item item = new MySqlLockTableStatement.Item(); 823 824 SQLExprTableSource tableSource = null; 825 SQLName tableName = this.exprParser.name(); 826 827 828 if (lexer.token() == Token.AS) { 829 lexer.nextToken(); 830 string as = lexer.stringVal(); 831 tableSource = new SQLExprTableSource(tableName, as); 832 lexer.nextToken(); 833 } else { 834 tableSource = new SQLExprTableSource(tableName); 835 } 836 item.setTableSource(tableSource); 837 stmt.getItems().add(item); 838 839 if (lexer.token() == Token.COMMA) { 840 lexer.nextToken(); 841 continue; 842 } 843 844 if (lexer.identifierEquals(READ)) { 845 lexer.nextToken(); 846 if (lexer.identifierEquals(LOCAL)) { 847 lexer.nextToken(); 848 item.setLockType(MySqlLockTableStatement.LockType.READ_LOCAL); 849 } else { 850 item.setLockType(MySqlLockTableStatement.LockType.READ); 851 } 852 } else if (lexer.identifierEquals(WRITE)) { 853 lexer.nextToken(); 854 item.setLockType(MySqlLockTableStatement.LockType.WRITE); 855 } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { 856 lexer.nextToken(); 857 acceptIdentifier(WRITE); 858 lexer.nextToken(); 859 item.setLockType(MySqlLockTableStatement.LockType.LOW_PRIORITY_WRITE); 860 } else { 861 throw new ParserException( 862 "syntax error, expect READ or WRITE OR AS, actual " ~ lexer.token() ~ ", " ~ lexer.info()); 863 } 864 865 if (lexer.token() == Token.HINT) { 866 item.setHints(this.exprParser.parseHints()); 867 } 868 869 if (lexer.token() == Token.COMMA) { 870 lexer.nextToken(); 871 continue; 872 } 873 break; 874 } 875 876 statementList.add(stmt); 877 return true; 878 } 879 880 if (lexer.identifierEquals("UNLOCK")) { 881 lexer.nextToken(); 882 string val = lexer.stringVal(); 883 bool isUnLockTables = equalsIgnoreCase(TABLES, val) && lexer.token() == Token.IDENTIFIER; 884 bool isUnLockTable = equalsIgnoreCase("TABLE",val) && lexer.token() == Token.TABLE; 885 statementList.add(new MySqlUnlockTablesStatement()); 886 if (isUnLockTables || isUnLockTable) { 887 lexer.nextToken(); 888 } else { 889 setErrorEndPos(lexer.pos()); 890 throw new ParserException("syntax error, expect TABLES or TABLE, actual " ~ lexer.token() ~ ", " ~ lexer.info()); 891 } 892 return true; 893 } 894 895 if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { 896 statementList.add(this.parseChecksum()); 897 return true; 898 } 899 900 if (lexer.token() == Token.HINT) { 901 List!(SQLCommentHint) hints = this.exprParser.parseHints(); 902 903 bool tddlHints = false; 904 bool accept = false; 905 906 907 bool acceptHint = false; 908 switch (lexer.token()) { 909 case Token.SELECT: 910 case Token.WITH: 911 case Token.DELETE: 912 case Token.UPDATE: 913 case Token.INSERT: 914 case Token.SHOW: 915 case Token.REPLACE: 916 case Token.TRUNCATE: 917 case Token.DROP: 918 case Token.ALTER: 919 case Token.CREATE: 920 case Token.CHECK: 921 case Token.SET: 922 acceptHint = true; 923 break; 924 case Token.IDENTIFIER: 925 acceptHint = lexer.hash_lower() == FnvHash.Constants.DUMP 926 || lexer.hash_lower() == FnvHash.Constants.RENAME; 927 break; 928 default: 929 break; 930 } 931 if (hints.size() == 1 932 && statementList.size() == 0 933 && acceptHint) { 934 SQLCommentHint hint = hints.get(0); 935 string hintText = toUpper(hint.getText()); 936 if (startsWith(hintText,"+TDDL") 937 || startsWith(hintText,"+ TDDL") 938 || startsWith(hintText,"TDDL") 939 || startsWith(hintText,"!TDDL")) 940 { 941 tddlHints = true; 942 } else if(startsWith(hintText,"+")) { 943 accept = true; 944 } 945 } 946 947 if (tddlHints) { 948 SQLStatementImpl stmt = cast(SQLStatementImpl)this.parseStatement(); 949 stmt.setHeadHints(hints); 950 statementList.add(stmt); 951 return true; 952 } else if (accept) { 953 SQLStatementImpl stmt = cast(SQLStatementImpl) this.parseStatement(); 954 stmt.setHeadHints(hints); 955 statementList.add(stmt); 956 return true; 957 } 958 959 MySqlHintStatement stmt = new MySqlHintStatement(); 960 stmt.setHints(hints); 961 962 statementList.add(stmt); 963 return true; 964 } 965 966 if (lexer.token() == Token.BEGIN) { 967 statementList.add(this.parseBlock()); 968 return true; 969 } 970 971 if (lexer.token() == Token.IDENTIFIER) { 972 string label = lexer.stringVal(); 973 char ch = lexer.current(); 974 int bp = lexer.bp(); 975 lexer.nextToken(); 976 if (lexer.token() == Token.VARIANT && lexer.stringVal() == ":") { 977 lexer.nextToken(); 978 if (lexer.token() == Token.LOOP) { 979 // parse loop statement 980 statementList.add(this.parseLoop(label)); 981 } else if (lexer.token() == Token.WHILE) { 982 // parse while statement with label 983 statementList.add(this.parseWhile(label)); 984 } else if (lexer.token() == Token.BEGIN) { 985 // parse begin-end statement with label 986 SQLBlockStatement block = this.parseBlock(label); 987 statementList.add(block); 988 } else if (lexer.token() == Token.REPEAT) { 989 // parse repeat statement with label 990 statementList.add(this.parseRepeat(label)); 991 } 992 return true; 993 } else { 994 lexer.reset(bp, ch, Token.IDENTIFIER); 995 } 996 997 } 998 999 return false; 1000 } 1001 1002 public SQLStatement parseFlush() { 1003 acceptIdentifier("FLUSH"); 1004 MySqlFlushStatement stmt = new MySqlFlushStatement(); 1005 1006 if (lexer.identifierEquals("NO_WRITE_TO_BINLOG")) { 1007 lexer.nextToken(); 1008 stmt.setNoWriteToBinlog(true); 1009 } 1010 1011 if (lexer.identifierEquals("LOCAL")) { 1012 lexer.nextToken(); 1013 stmt.setLocal(true); 1014 } 1015 1016 for (;;) { 1017 if (lexer.token() == Token.BINARY || lexer.identifierEquals("BINARY")) { 1018 lexer.nextToken(); 1019 acceptIdentifier("LOGS"); 1020 stmt.setBinaryLogs(true); 1021 } else if (lexer.identifierEquals("DES_KEY_FILE")) { 1022 lexer.nextToken(); 1023 stmt.setDesKeyFile(true); 1024 } else if (lexer.identifierEquals("ENGINE")) { 1025 lexer.nextToken(); 1026 acceptIdentifier("LOGS"); 1027 stmt.setEngineLogs(true); 1028 } else if (lexer.identifierEquals("ERROR")) { 1029 lexer.nextToken(); 1030 acceptIdentifier("LOGS"); 1031 stmt.setErrorLogs(true); 1032 } else if (lexer.identifierEquals("GENERAL")) { 1033 lexer.nextToken(); 1034 acceptIdentifier("LOGS"); 1035 stmt.setGeneralLogs(true); 1036 } else if (lexer.identifierEquals("HOSTS")) { 1037 lexer.nextToken(); 1038 stmt.setHots(true); 1039 } else if (lexer.identifierEquals("LOGS")) { 1040 lexer.nextToken(); 1041 stmt.setLogs(true); 1042 } else if (lexer.identifierEquals("PRIVILEGES")) { 1043 lexer.nextToken(); 1044 stmt.setPrivileges(true); 1045 } else if (lexer.identifierEquals("OPTIMIZER_COSTS")) { 1046 lexer.nextToken(); 1047 stmt.setOptimizerCosts(true); 1048 } else if (lexer.identifierEquals("QUERY")) { 1049 lexer.nextToken(); 1050 accept(Token.CACHE); 1051 stmt.setQueryCache(true); 1052 } else if (lexer.identifierEquals("RELAY")) { 1053 lexer.nextToken(); 1054 acceptIdentifier("LOGS"); 1055 stmt.setRelayLogs(true); 1056 if (lexer.token() == Token.FOR) { 1057 lexer.nextToken(); 1058 acceptIdentifier("CHANNEL"); 1059 stmt.setRelayLogsForChannel(this.exprParser.primary()); 1060 } 1061 } else if (lexer.identifierEquals("SLOW")) { 1062 lexer.nextToken(); 1063 acceptIdentifier("LOGS"); 1064 stmt.setSlowLogs(true); 1065 } else if (lexer.identifierEquals(STATUS)) { 1066 lexer.nextToken(); 1067 stmt.setStatus(true); 1068 } else if (lexer.identifierEquals("USER_RESOURCES")) { 1069 lexer.nextToken(); 1070 stmt.setUserResources(true); 1071 } else if (lexer.token() == Token.COMMA) { 1072 lexer.nextToken(); 1073 continue; 1074 } else { 1075 break; 1076 } 1077 } 1078 1079 if (lexer.identifierEquals("TABLES")) { 1080 lexer.nextToken(); 1081 1082 stmt.setTableOption(true); 1083 1084 if (lexer.token() == Token.WITH) { 1085 lexer.nextToken(); 1086 acceptIdentifier("READ"); 1087 accept(Token.LOCK); 1088 stmt.setWithReadLock(true); 1089 } 1090 for(;;) { 1091 if (lexer.token() == Token.IDENTIFIER) { 1092 for (; ; ) { 1093 SQLName name = this.exprParser.name(); 1094 stmt.addTable(name); 1095 1096 if (lexer.token() == Token.COMMA) { 1097 lexer.nextToken(); 1098 continue; 1099 } 1100 break; 1101 } 1102 break; 1103 } 1104 break; 1105 } 1106 1107 if (stmt.getTables().size() != 0) { 1108 if (lexer.token() == Token.FOR) { 1109 lexer.nextToken(); 1110 acceptIdentifier("EXPORT"); 1111 stmt.setForExport(true); 1112 } else if (lexer.token() == Token.WITH) { 1113 lexer.nextToken(); 1114 acceptIdentifier("READ"); 1115 accept(Token.LOCK); 1116 stmt.setWithReadLock(true); 1117 } 1118 } 1119 1120 } 1121 1122 return stmt; 1123 } 1124 1125 override public SQLBlockStatement parseBlock() { 1126 SQLBlockStatement block = new SQLBlockStatement(); 1127 block.setDbType(dbType); 1128 1129 accept(Token.BEGIN); 1130 List!(SQLStatement) statementList = block.getStatementList(); 1131 this.parseStatementList(statementList, -1, block); 1132 1133 if (lexer.token() != Token.END 1134 && statementList.size() > 0 1135 && (cast(SQLCommitStatement)statementList.get(statementList.size() - 1) !is null 1136 || cast(SQLRollbackStatement)statementList.get(statementList.size() - 1) !is null)) { 1137 block.setEndOfCommit(true); 1138 return block; 1139 } 1140 accept(Token.END); 1141 1142 return block; 1143 } 1144 1145 override public MySqlExplainStatement parseDescribe() { 1146 // see https://dev.mysql.com/doc/refman/5.7/en/explain.html 1147 MySqlExplainStatement describe = new MySqlExplainStatement(); 1148 1149 // {DESCRIBE | DESC} 1150 if (lexer.token() == Token.DESC || lexer.identifierEquals(DESCRIBE)) { 1151 lexer.nextToken(); 1152 describe.setDescribe(true); 1153 } else { 1154 throw new ParserException("expect one of {DESCRIBE | DESC} , actual " ~ lexer.token() ~ ", " ~ lexer.info()); 1155 } 1156 1157 return parseExplain(describe); 1158 } 1159 1160 override public MySqlExplainStatement parseExplain() { 1161 // see https://dev.mysql.com/doc/refman/5.7/en/explain.html 1162 MySqlExplainStatement explain = new MySqlExplainStatement(); 1163 1164 // {EXPLAIN} 1165 if (lexer.token() == Token.EXPLAIN) { 1166 lexer.nextToken(); 1167 } else { 1168 throw new ParserException("expect EXPLAIN , actual " ~ lexer.token() ~ ", " ~ lexer.info()); 1169 } 1170 1171 return parseExplain(explain); 1172 } 1173 1174 1175 private MySqlExplainStatement parseExplain(MySqlExplainStatement explain) { 1176 1177 if (lexer.token() == Token.HINT) { 1178 List!(SQLCommentHint) hints = this.exprParser.parseHints(); 1179 explain.setHints(hints); 1180 } 1181 // see https://dev.mysql.com/doc/refman/5.7/en/explain.html 1182 1183 bool table = false; 1184 if (lexer.token() == Token.IDENTIFIER) { 1185 string stringVal = lexer.stringVal(); 1186 1187 if (equalsIgnoreCase(stringVal, EXTENDED) 1188 || equalsIgnoreCase(stringVal, PARTITIONS)) { 1189 explain.setType(stringVal); 1190 lexer.nextToken(); 1191 } else if (equalsIgnoreCase(stringVal, FORMAT)) { 1192 explain.setType(stringVal); 1193 lexer.nextToken(); 1194 accept(Token.EQ); 1195 1196 string format = lexer.stringVal(); 1197 explain.setFormat(format); 1198 accept(Token.IDENTIFIER); 1199 } else { 1200 explain.setTableName(exprParser.name()); 1201 if (lexer.token() == Token.IDENTIFIER) { 1202 explain.setColumnName(exprParser.name()); 1203 } else if (lexer.token() == Token.LITERAL_CHARS) { 1204 explain.setWild(exprParser.expr()); 1205 } 1206 table = true; 1207 } 1208 } 1209 1210 if (lexer.token() == Token.FOR) { 1211 lexer.nextToken(); 1212 acceptIdentifier(CONNECTION); 1213 explain.setConnectionId(exprParser.expr()); 1214 } else if (!table) { 1215 explain.setStatement(this.parseStatement()); 1216 } 1217 1218 return explain; 1219 } 1220 1221 override public SQLStatement parseShow() { 1222 accept(Token.SHOW); 1223 1224 if (lexer.token() == Token.COMMENT) { 1225 lexer.nextToken(); 1226 } 1227 1228 bool full = false; 1229 if (lexer.token() == Token.FULL) { 1230 lexer.nextToken(); 1231 full = true; 1232 } 1233 1234 if (lexer.identifierEquals("PROCESSLIST")) { 1235 lexer.nextToken(); 1236 MySqlShowProcessListStatement stmt = new MySqlShowProcessListStatement(); 1237 stmt.setFull(full); 1238 return stmt; 1239 } 1240 1241 if (lexer.identifierEquals("COLUMNS") || lexer.identifierEquals("FIELDS")) { 1242 lexer.nextToken(); 1243 1244 MySqlShowColumnsStatement stmt = parseShowColumns(); 1245 stmt.setFull(full); 1246 1247 return stmt; 1248 } 1249 1250 if (lexer.identifierEquals("COLUMNS")) { 1251 lexer.nextToken(); 1252 1253 MySqlShowColumnsStatement stmt = parseShowColumns(); 1254 1255 return stmt; 1256 } 1257 1258 if (lexer.identifierEquals(TABLES)) { 1259 lexer.nextToken(); 1260 1261 SQLShowTablesStatement stmt = parseShowTabless(); 1262 stmt.setFull(full); 1263 1264 return stmt; 1265 } 1266 1267 if (lexer.identifierEquals("DATABASES")) { 1268 lexer.nextToken(); 1269 1270 MySqlShowDatabasesStatement stmt = parseShowDatabases(); 1271 1272 return stmt; 1273 } 1274 1275 if (lexer.identifierEquals("WARNINGS")) { 1276 lexer.nextToken(); 1277 1278 MySqlShowWarningsStatement stmt = parseShowWarnings(); 1279 1280 return stmt; 1281 } 1282 1283 if (lexer.identifierEquals("COUNT")) { 1284 lexer.nextToken(); 1285 accept(Token.LPAREN); 1286 accept(Token.STAR); 1287 accept(Token.RPAREN); 1288 1289 if (lexer.identifierEquals(FnvHash.Constants.ERRORS)) { 1290 lexer.nextToken(); 1291 1292 MySqlShowErrorsStatement stmt = new MySqlShowErrorsStatement(); 1293 stmt.setCount(true); 1294 1295 return stmt; 1296 } else { 1297 acceptIdentifier("WARNINGS"); 1298 1299 MySqlShowWarningsStatement stmt = new MySqlShowWarningsStatement(); 1300 stmt.setCount(true); 1301 1302 return stmt; 1303 } 1304 } 1305 1306 if (lexer.identifierEquals(FnvHash.Constants.ERRORS)) { 1307 lexer.nextToken(); 1308 1309 MySqlShowErrorsStatement stmt = new MySqlShowErrorsStatement(); 1310 stmt.setLimit(this.exprParser.parseLimit()); 1311 1312 return stmt; 1313 } 1314 1315 if (lexer.identifierEquals(STATUS)) { 1316 lexer.nextToken(); 1317 1318 MySqlShowStatusStatement stmt = parseShowStatus(); 1319 1320 return stmt; 1321 } 1322 1323 if (lexer.identifierEquals(VARIABLES)) { 1324 lexer.nextToken(); 1325 1326 MySqlShowVariantsStatement stmt = parseShowVariants(); 1327 1328 return stmt; 1329 } 1330 1331 if (lexer.identifierEquals(GLOBAL)) { 1332 lexer.nextToken(); 1333 1334 if (lexer.identifierEquals(STATUS)) { 1335 lexer.nextToken(); 1336 MySqlShowStatusStatement stmt = parseShowStatus(); 1337 stmt.setGlobal(true); 1338 return stmt; 1339 } 1340 1341 if (lexer.identifierEquals(VARIABLES)) { 1342 lexer.nextToken(); 1343 MySqlShowVariantsStatement stmt = parseShowVariants(); 1344 stmt.setGlobal(true); 1345 return stmt; 1346 } 1347 } 1348 1349 if (lexer.identifierEquals(SESSION)) { 1350 lexer.nextToken(); 1351 1352 if (lexer.identifierEquals(STATUS)) { 1353 lexer.nextToken(); 1354 MySqlShowStatusStatement stmt = parseShowStatus(); 1355 stmt.setSession(true); 1356 return stmt; 1357 } 1358 1359 if (lexer.identifierEquals(VARIABLES)) { 1360 lexer.nextToken(); 1361 MySqlShowVariantsStatement stmt = parseShowVariants(); 1362 stmt.setSession(true); 1363 return stmt; 1364 } 1365 } 1366 1367 if (lexer.identifierEquals("COBAR_STATUS")) { 1368 lexer.nextToken(); 1369 return new CobarShowStatus(); 1370 } 1371 1372 if (lexer.identifierEquals("AUTHORS")) { 1373 lexer.nextToken(); 1374 return new MySqlShowAuthorsStatement(); 1375 } 1376 1377 if (lexer.token() == Token.BINARY) { 1378 lexer.nextToken(); 1379 acceptIdentifier("LOGS"); 1380 return new MySqlShowBinaryLogsStatement(); 1381 } 1382 1383 if (lexer.identifierEquals("MASTER")) { 1384 lexer.nextToken(); 1385 if (lexer.identifierEquals("LOGS")) { 1386 lexer.nextToken(); 1387 return new MySqlShowMasterLogsStatement(); 1388 } 1389 acceptIdentifier(STATUS); 1390 return new MySqlShowMasterStatusStatement(); 1391 } 1392 1393 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 1394 lexer.nextToken(); 1395 accept(Token.SET); 1396 MySqlShowCharacterSetStatement stmt = new MySqlShowCharacterSetStatement(); 1397 1398 if (lexer.token() == Token.LIKE) { 1399 lexer.nextToken(); 1400 stmt.setPattern(this.exprParser.expr()); 1401 } 1402 1403 if (lexer.token() == Token.WHERE) { 1404 lexer.nextToken(); 1405 stmt.setWhere(this.exprParser.expr()); 1406 } 1407 1408 return stmt; 1409 } 1410 1411 if (lexer.identifierEquals("COLLATION")) { 1412 lexer.nextToken(); 1413 MySqlShowCollationStatement stmt = new MySqlShowCollationStatement(); 1414 1415 if (lexer.token() == Token.LIKE) { 1416 lexer.nextToken(); 1417 stmt.setPattern(this.exprParser.expr()); 1418 } 1419 1420 if (lexer.token() == Token.WHERE) { 1421 lexer.nextToken(); 1422 stmt.setWhere(this.exprParser.expr()); 1423 } 1424 1425 return stmt; 1426 } 1427 1428 if (lexer.identifierEquals(BINLOG)) { 1429 lexer.nextToken(); 1430 acceptIdentifier(EVENTS); 1431 MySqlShowBinLogEventsStatement stmt = new MySqlShowBinLogEventsStatement(); 1432 1433 if (lexer.token() == Token.IN) { 1434 lexer.nextToken(); 1435 stmt.setIn(this.exprParser.expr()); 1436 } 1437 1438 if (lexer.token() == Token.FROM) { 1439 lexer.nextToken(); 1440 stmt.setFrom(this.exprParser.expr()); 1441 } 1442 1443 stmt.setLimit(this.exprParser.parseLimit()); 1444 1445 return stmt; 1446 } 1447 1448 if (lexer.identifierEquals("CONTRIBUTORS")) { 1449 lexer.nextToken(); 1450 return new MySqlShowContributorsStatement(); 1451 } 1452 1453 if (lexer.token() == Token.CREATE) { 1454 lexer.nextToken(); 1455 1456 if (lexer.token() == Token.DATABASE) { 1457 lexer.nextToken(); 1458 1459 MySqlShowCreateDatabaseStatement stmt = new MySqlShowCreateDatabaseStatement(); 1460 stmt.setDatabase(this.exprParser.name()); 1461 return stmt; 1462 } 1463 1464 if (lexer.identifierEquals("EVENT")) { 1465 lexer.nextToken(); 1466 1467 MySqlShowCreateEventStatement stmt = new MySqlShowCreateEventStatement(); 1468 stmt.setEventName(this.exprParser.name()); 1469 return stmt; 1470 } 1471 1472 if (lexer.token() == Token.FUNCTION) { 1473 lexer.nextToken(); 1474 1475 MySqlShowCreateFunctionStatement stmt = new MySqlShowCreateFunctionStatement(); 1476 stmt.setName(this.exprParser.name()); 1477 return stmt; 1478 } 1479 1480 if (lexer.token() == Token.PROCEDURE) { 1481 lexer.nextToken(); 1482 1483 MySqlShowCreateProcedureStatement stmt = new MySqlShowCreateProcedureStatement(); 1484 stmt.setName(this.exprParser.name()); 1485 return stmt; 1486 } 1487 1488 if (lexer.token() == Token.TABLE) { 1489 lexer.nextToken(); 1490 1491 MySqlShowCreateTableStatement stmt = new MySqlShowCreateTableStatement(); 1492 stmt.setName(this.exprParser.name()); 1493 return stmt; 1494 } 1495 1496 if (lexer.token() == Token.VIEW) { 1497 lexer.nextToken(); 1498 1499 MySqlShowCreateViewStatement stmt = new MySqlShowCreateViewStatement(); 1500 stmt.setName(this.exprParser.name()); 1501 return stmt; 1502 } 1503 1504 if (lexer.token() == Token.TRIGGER) { 1505 lexer.nextToken(); 1506 1507 MySqlShowCreateTriggerStatement stmt = new MySqlShowCreateTriggerStatement(); 1508 stmt.setName(this.exprParser.name()); 1509 return stmt; 1510 } 1511 1512 throw new ParserException("TODO " ~ lexer.info()); 1513 } 1514 1515 if (lexer.identifierEquals(ENGINE)) { 1516 lexer.nextToken(); 1517 MySqlShowEngineStatement stmt = new MySqlShowEngineStatement(); 1518 stmt.setName(this.exprParser.name()); 1519 stmt.setOption(MySqlShowEngineStatement.Option(toUpper(lexer.stringVal()))); 1520 lexer.nextToken(); 1521 return stmt; 1522 } 1523 1524 if (lexer.identifierEquals("STORAGE")) { 1525 lexer.nextToken(); 1526 acceptIdentifier(ENGINES); 1527 MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement(); 1528 stmt.setStorage(true); 1529 return stmt; 1530 } 1531 1532 if (lexer.identifierEquals(ENGINES)) { 1533 lexer.nextToken(); 1534 MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement(); 1535 return stmt; 1536 } 1537 1538 if (lexer.identifierEquals(EVENTS)) { 1539 lexer.nextToken(); 1540 MySqlShowEventsStatement stmt = new MySqlShowEventsStatement(); 1541 1542 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1543 lexer.nextToken(); 1544 stmt.setSchema(this.exprParser.name()); 1545 } 1546 1547 if (lexer.token() == Token.LIKE) { 1548 lexer.nextToken(); 1549 stmt.setLike(this.exprParser.expr()); 1550 } 1551 1552 if (lexer.token() == Token.WHERE) { 1553 lexer.nextToken(); 1554 stmt.setWhere(this.exprParser.expr()); 1555 } 1556 return stmt; 1557 } 1558 1559 if (lexer.token() == Token.FUNCTION) { 1560 lexer.nextToken(); 1561 1562 if (lexer.identifierEquals("CODE")) { 1563 lexer.nextToken(); 1564 MySqlShowFunctionCodeStatement stmt = new MySqlShowFunctionCodeStatement(); 1565 stmt.setName(this.exprParser.name()); 1566 return stmt; 1567 } 1568 1569 acceptIdentifier(STATUS); 1570 MySqlShowFunctionStatusStatement stmt = new MySqlShowFunctionStatusStatement(); 1571 1572 if (lexer.token() == Token.LIKE) { 1573 lexer.nextToken(); 1574 stmt.setLike(this.exprParser.expr()); 1575 } 1576 1577 if (lexer.token() == Token.WHERE) { 1578 lexer.nextToken(); 1579 stmt.setWhere(this.exprParser.expr()); 1580 } 1581 return stmt; 1582 } 1583 1584 // MySqlShowFunctionStatusStatement 1585 1586 if (lexer.identifierEquals(ENGINE)) { 1587 lexer.nextToken(); 1588 MySqlShowEngineStatement stmt = new MySqlShowEngineStatement(); 1589 stmt.setName(this.exprParser.name()); 1590 stmt.setOption(MySqlShowEngineStatement.Option(toUpper(lexer.stringVal()))); 1591 lexer.nextToken(); 1592 return stmt; 1593 } 1594 1595 if (lexer.identifierEquals("STORAGE")) { 1596 lexer.nextToken(); 1597 accept(Token.EQ); 1598 accept(Token.DEFAULT); 1599 MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement(); 1600 stmt.setStorage(true); 1601 return stmt; 1602 } 1603 1604 if (lexer.identifierEquals(ENGINES)) { 1605 lexer.nextToken(); 1606 MySqlShowEnginesStatement stmt = new MySqlShowEnginesStatement(); 1607 return stmt; 1608 } 1609 1610 if (lexer.identifierEquals("GRANTS")) { 1611 lexer.nextToken(); 1612 MySqlShowGrantsStatement stmt = new MySqlShowGrantsStatement(); 1613 1614 if (lexer.token() == Token.FOR) { 1615 lexer.nextToken(); 1616 stmt.setUser(this.exprParser.expr()); 1617 } 1618 1619 return stmt; 1620 } 1621 1622 if (lexer.token() == Token.INDEX || lexer.identifierEquals("INDEXES")) { 1623 lexer.nextToken(); 1624 MySqlShowIndexesStatement stmt = new MySqlShowIndexesStatement(); 1625 1626 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1627 lexer.nextToken(); 1628 SQLName table = exprParser.name(); 1629 stmt.setTable(table); 1630 1631 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1632 lexer.nextToken(); 1633 SQLName database = exprParser.name(); 1634 stmt.setDatabase(database); 1635 } 1636 } 1637 1638 if (lexer.token() == Token.HINT) { 1639 stmt.setHints(this.exprParser.parseHints()); 1640 } 1641 1642 return stmt; 1643 } 1644 1645 if (lexer.identifierEquals("KEYS")) { 1646 lexer.nextToken(); 1647 MySqlShowKeysStatement stmt = new MySqlShowKeysStatement(); 1648 1649 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1650 lexer.nextToken(); 1651 SQLName table = exprParser.name(); 1652 stmt.setTable(table); 1653 1654 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1655 lexer.nextToken(); 1656 SQLName database = exprParser.name(); 1657 stmt.setDatabase(database); 1658 } 1659 } 1660 1661 return stmt; 1662 } 1663 1664 if (lexer.token() == Token.OPEN || lexer.identifierEquals("OPEN")) { 1665 lexer.nextToken(); 1666 acceptIdentifier(TABLES); 1667 MySqlShowOpenTablesStatement stmt = new MySqlShowOpenTablesStatement(); 1668 1669 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1670 lexer.nextToken(); 1671 stmt.setDatabase(this.exprParser.name()); 1672 } 1673 1674 if (lexer.token() == Token.LIKE) { 1675 lexer.nextToken(); 1676 stmt.setLike(this.exprParser.expr()); 1677 } 1678 1679 if (lexer.token() == Token.WHERE) { 1680 lexer.nextToken(); 1681 stmt.setWhere(this.exprParser.expr()); 1682 } 1683 return stmt; 1684 } 1685 1686 if (lexer.identifierEquals("PLUGINS")) { 1687 lexer.nextToken(); 1688 MySqlShowPluginsStatement stmt = new MySqlShowPluginsStatement(); 1689 return stmt; 1690 } 1691 1692 if (lexer.identifierEquals("PRIVILEGES")) { 1693 lexer.nextToken(); 1694 MySqlShowPrivilegesStatement stmt = new MySqlShowPrivilegesStatement(); 1695 return stmt; 1696 } 1697 1698 if (lexer.token() == Token.PROCEDURE) { 1699 lexer.nextToken(); 1700 1701 if (lexer.identifierEquals("CODE")) { 1702 lexer.nextToken(); 1703 MySqlShowProcedureCodeStatement stmt = new MySqlShowProcedureCodeStatement(); 1704 stmt.setName(this.exprParser.name()); 1705 return stmt; 1706 } 1707 1708 acceptIdentifier(STATUS); 1709 MySqlShowProcedureStatusStatement stmt = new MySqlShowProcedureStatusStatement(); 1710 1711 if (lexer.token() == Token.LIKE) { 1712 lexer.nextToken(); 1713 stmt.setLike(this.exprParser.expr()); 1714 } 1715 1716 if (lexer.token() == Token.WHERE) { 1717 lexer.nextToken(); 1718 stmt.setWhere(this.exprParser.expr()); 1719 } 1720 return stmt; 1721 } 1722 1723 if (lexer.identifierEquals("PROCESSLIST")) { 1724 lexer.nextToken(); 1725 MySqlShowProcessListStatement stmt = new MySqlShowProcessListStatement(); 1726 return stmt; 1727 } 1728 1729 if (lexer.identifierEquals("PROFILES")) { 1730 lexer.nextToken(); 1731 MySqlShowProfilesStatement stmt = new MySqlShowProfilesStatement(); 1732 return stmt; 1733 } 1734 1735 if (lexer.identifierEquals("PROFILE")) { 1736 lexer.nextToken(); 1737 MySqlShowProfileStatement stmt = new MySqlShowProfileStatement(); 1738 1739 for (; ; ) { 1740 if (lexer.token() == Token.ALL) { 1741 stmt.getTypes().add(MySqlShowProfileStatement.Type.ALL); 1742 lexer.nextToken(); 1743 } else if (lexer.identifierEquals("BLOCK")) { 1744 lexer.nextToken(); 1745 acceptIdentifier("IO"); 1746 stmt.getTypes().add(MySqlShowProfileStatement.Type.BLOCK_IO); 1747 } else if (lexer.identifierEquals("CONTEXT")) { 1748 lexer.nextToken(); 1749 acceptIdentifier("SWITCHES"); 1750 stmt.getTypes().add(MySqlShowProfileStatement.Type.CONTEXT_SWITCHES); 1751 } else if (lexer.identifierEquals("CPU")) { 1752 lexer.nextToken(); 1753 stmt.getTypes().add(MySqlShowProfileStatement.Type.CPU); 1754 } else if (lexer.identifierEquals("IPC")) { 1755 lexer.nextToken(); 1756 stmt.getTypes().add(MySqlShowProfileStatement.Type.IPC); 1757 } else if (lexer.identifierEquals("MEMORY")) { 1758 lexer.nextToken(); 1759 stmt.getTypes().add(MySqlShowProfileStatement.Type.MEMORY); 1760 } else if (lexer.identifierEquals("PAGE")) { 1761 lexer.nextToken(); 1762 acceptIdentifier("FAULTS"); 1763 stmt.getTypes().add(MySqlShowProfileStatement.Type.PAGE_FAULTS); 1764 } else if (lexer.identifierEquals("SOURCE")) { 1765 lexer.nextToken(); 1766 stmt.getTypes().add(MySqlShowProfileStatement.Type.SOURCE); 1767 } else if (lexer.identifierEquals("SWAPS")) { 1768 lexer.nextToken(); 1769 stmt.getTypes().add(MySqlShowProfileStatement.Type.SWAPS); 1770 } else { 1771 break; 1772 } 1773 1774 if (lexer.token() == Token.COMMA) { 1775 lexer.nextToken(); 1776 continue; 1777 } 1778 break; 1779 } 1780 1781 if (lexer.token() == Token.FOR) { 1782 lexer.nextToken(); 1783 acceptIdentifier("QUERY"); 1784 stmt.setForQuery(this.exprParser.primary()); 1785 } 1786 1787 stmt.setLimit(this.exprParser.parseLimit()); 1788 1789 return stmt; 1790 } 1791 1792 if (lexer.identifierEquals("RELAYLOG")) { 1793 lexer.nextToken(); 1794 acceptIdentifier(EVENTS); 1795 MySqlShowRelayLogEventsStatement stmt = new MySqlShowRelayLogEventsStatement(); 1796 1797 if (lexer.token() == Token.IN) { 1798 lexer.nextToken(); 1799 stmt.setLogName(this.exprParser.primary()); 1800 } 1801 1802 if (lexer.token() == Token.FROM) { 1803 lexer.nextToken(); 1804 stmt.setFrom(this.exprParser.primary()); 1805 } 1806 1807 stmt.setLimit(this.exprParser.parseLimit()); 1808 1809 return stmt; 1810 } 1811 1812 if (lexer.identifierEquals("RELAYLOG")) { 1813 lexer.nextToken(); 1814 acceptIdentifier(EVENTS); 1815 MySqlShowRelayLogEventsStatement stmt = new MySqlShowRelayLogEventsStatement(); 1816 1817 if (lexer.token() == Token.IN) { 1818 lexer.nextToken(); 1819 stmt.setLogName(this.exprParser.primary()); 1820 } 1821 1822 if (lexer.token() == Token.FROM) { 1823 lexer.nextToken(); 1824 stmt.setFrom(this.exprParser.primary()); 1825 } 1826 1827 stmt.setLimit(this.exprParser.parseLimit()); 1828 1829 return stmt; 1830 } 1831 1832 if (lexer.identifierEquals("SLAVE")) { 1833 lexer.nextToken(); 1834 if (lexer.identifierEquals(STATUS)) { 1835 lexer.nextToken(); 1836 return new MySqlShowSlaveStatusStatement(); 1837 } else { 1838 acceptIdentifier("HOSTS"); 1839 MySqlShowSlaveHostsStatement stmt = new MySqlShowSlaveHostsStatement(); 1840 return stmt; 1841 } 1842 } 1843 1844 if (lexer.token() == Token.TABLE) { 1845 lexer.nextToken(); 1846 acceptIdentifier(STATUS); 1847 MySqlShowTableStatusStatement stmt = new MySqlShowTableStatusStatement(); 1848 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1849 lexer.nextToken(); 1850 stmt.setDatabase(this.exprParser.name()); 1851 } 1852 1853 if (lexer.token() == Token.LIKE) { 1854 lexer.nextToken(); 1855 stmt.setLike(this.exprParser.expr()); 1856 } 1857 1858 if (lexer.token() == Token.WHERE) { 1859 lexer.nextToken(); 1860 stmt.setWhere(this.exprParser.expr()); 1861 } 1862 1863 return stmt; 1864 } 1865 1866 if (lexer.token() == Token.DATABASE) { 1867 lexer.nextToken(); 1868 accept(Token.PARTITION); 1869 acceptIdentifier("STATUS"); 1870 accept(Token.FOR); 1871 MySqlShowDatabasePartitionStatusStatement stmt = new MySqlShowDatabasePartitionStatusStatement(); 1872 stmt.setDatabase(this.exprParser.name()); 1873 return stmt; 1874 } 1875 1876 if (lexer.identifierEquals("TRIGGERS")) { 1877 lexer.nextToken(); 1878 MySqlShowTriggersStatement stmt = new MySqlShowTriggersStatement(); 1879 1880 if (lexer.token() == Token.FROM) { 1881 lexer.nextToken(); 1882 SQLName database = exprParser.name(); 1883 stmt.setDatabase(database); 1884 } 1885 1886 if (lexer.token() == Token.LIKE) { 1887 lexer.nextToken(); 1888 SQLExpr like = exprParser.expr(); 1889 stmt.setLike(like); 1890 } 1891 1892 if (lexer.token() == Token.WHERE) { 1893 lexer.nextToken(); 1894 SQLExpr where = exprParser.expr(); 1895 stmt.setWhere(where); 1896 } 1897 1898 return stmt; 1899 } 1900 1901 // MySqlShowSlaveHostsStatement 1902 throw new ParserException("TODO " ~ lexer.info()); 1903 } 1904 1905 private MySqlShowStatusStatement parseShowStatus() { 1906 MySqlShowStatusStatement stmt = new MySqlShowStatusStatement(); 1907 1908 if (lexer.token() == Token.LIKE) { 1909 lexer.nextToken(); 1910 SQLExpr like = exprParser.expr(); 1911 stmt.setLike(like); 1912 } 1913 1914 if (lexer.token() == Token.WHERE) { 1915 lexer.nextToken(); 1916 SQLExpr where = exprParser.expr(); 1917 stmt.setWhere(where); 1918 } 1919 1920 return stmt; 1921 } 1922 1923 private MySqlShowVariantsStatement parseShowVariants() { 1924 MySqlShowVariantsStatement stmt = new MySqlShowVariantsStatement(); 1925 1926 if (lexer.token() == Token.LIKE) { 1927 lexer.nextToken(); 1928 SQLExpr like = exprParser.expr(); 1929 stmt.setLike(like); 1930 } 1931 1932 if (lexer.token() == Token.WHERE) { 1933 lexer.nextToken(); 1934 SQLExpr where = exprParser.expr(); 1935 stmt.setWhere(where); 1936 } 1937 1938 return stmt; 1939 } 1940 1941 private MySqlShowWarningsStatement parseShowWarnings() { 1942 MySqlShowWarningsStatement stmt = new MySqlShowWarningsStatement(); 1943 1944 stmt.setLimit(this.exprParser.parseLimit()); 1945 1946 return stmt; 1947 } 1948 1949 private MySqlShowDatabasesStatement parseShowDatabases() { 1950 MySqlShowDatabasesStatement stmt = new MySqlShowDatabasesStatement(); 1951 1952 if (lexer.token() == Token.LIKE) { 1953 lexer.nextToken(); 1954 SQLExpr like = exprParser.expr(); 1955 stmt.setLike(like); 1956 } 1957 1958 if (lexer.token() == Token.WHERE) { 1959 lexer.nextToken(); 1960 SQLExpr where = exprParser.expr(); 1961 stmt.setWhere(where); 1962 } 1963 1964 return stmt; 1965 } 1966 1967 private SQLShowTablesStatement parseShowTabless() { 1968 SQLShowTablesStatement stmt = new SQLShowTablesStatement(); 1969 1970 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 1971 lexer.nextToken(); 1972 SQLName database = exprParser.name(); 1973 if (lexer.token() == Token.SUB && cast(SQLIdentifierExpr)(database) !is null) { 1974 lexer.mark(); 1975 lexer.nextToken(); 1976 string strVal = lexer.stringVal(); 1977 lexer.nextToken(); 1978 if (cast(SQLIdentifierExpr)(database) !is null) { 1979 SQLIdentifierExpr ident = cast(SQLIdentifierExpr) database; 1980 database = new SQLIdentifierExpr(ident.getName() ~ "-" ~ strVal); 1981 } 1982 } 1983 stmt.setDatabase(database); 1984 } 1985 1986 if (lexer.token() == Token.LIKE) { 1987 lexer.nextToken(); 1988 SQLExpr like = exprParser.expr(); 1989 stmt.setLike(like); 1990 } 1991 1992 if (lexer.token() == Token.WHERE) { 1993 lexer.nextToken(); 1994 SQLExpr where = exprParser.expr(); 1995 stmt.setWhere(where); 1996 } 1997 1998 return stmt; 1999 } 2000 2001 private MySqlShowColumnsStatement parseShowColumns() { 2002 MySqlShowColumnsStatement stmt = new MySqlShowColumnsStatement(); 2003 2004 if (lexer.token() == Token.FROM) { 2005 lexer.nextToken(); 2006 SQLName table = exprParser.name(); 2007 stmt.setTable(table); 2008 2009 if (lexer.token() == Token.FROM || lexer.token() == Token.IN) { 2010 lexer.nextToken(); 2011 SQLName database = exprParser.name(); 2012 stmt.setDatabase(database); 2013 } 2014 } 2015 2016 if (lexer.token() == Token.LIKE) { 2017 lexer.nextToken(); 2018 SQLExpr like = exprParser.expr(); 2019 stmt.setLike(like); 2020 } 2021 2022 if (lexer.token() == Token.WHERE) { 2023 lexer.nextToken(); 2024 SQLExpr where = exprParser.expr(); 2025 stmt.setWhere(where); 2026 } 2027 2028 return stmt; 2029 } 2030 2031 public SQLStartTransactionStatement parseStart() { 2032 acceptIdentifier("START"); 2033 acceptIdentifier("TRANSACTION"); 2034 2035 SQLStartTransactionStatement stmt = new SQLStartTransactionStatement(); 2036 stmt.setDbType(dbType); 2037 2038 if (lexer.token() == Token.WITH) { 2039 lexer.nextToken(); 2040 acceptIdentifier("CONSISTENT"); 2041 acceptIdentifier("SNAPSHOT"); 2042 stmt.setConsistentSnapshot(true); 2043 } 2044 2045 if (lexer.token() == Token.BEGIN) { 2046 lexer.nextToken(); 2047 stmt.setBegin(true); 2048 if (lexer.identifierEquals("WORK")) { 2049 lexer.nextToken(); 2050 stmt.setWork(true); 2051 } 2052 } 2053 2054 if (lexer.token() == Token.HINT) { 2055 stmt.setHints(this.exprParser.parseHints()); 2056 } 2057 2058 return stmt; 2059 } 2060 2061 override 2062 public SQLRollbackStatement parseRollback() { 2063 acceptIdentifier("ROLLBACK"); 2064 2065 SQLRollbackStatement stmt = new SQLRollbackStatement(); 2066 2067 if (lexer.identifierEquals("WORK")) { 2068 lexer.nextToken(); 2069 } 2070 2071 if (lexer.token() == Token.AND) { 2072 lexer.nextToken(); 2073 if (lexer.token() == Token.NOT) { 2074 lexer.nextToken(); 2075 acceptIdentifier(CHAIN); 2076 stmt.setChain(Boolean.FALSE); 2077 } else { 2078 acceptIdentifier(CHAIN); 2079 stmt.setChain(Boolean.TRUE); 2080 } 2081 } 2082 2083 if (lexer.token() == Token.TO) { 2084 lexer.nextToken(); 2085 2086 if (lexer.identifierEquals("SAVEPOINT")) { 2087 lexer.nextToken(); 2088 } 2089 2090 stmt.setTo(this.exprParser.name()); 2091 } 2092 2093 return stmt; 2094 } 2095 2096 override public SQLStatement parseCommit() { 2097 acceptIdentifier("COMMIT"); 2098 2099 SQLCommitStatement stmt = new SQLCommitStatement(); 2100 2101 if (lexer.identifierEquals("WORK")) { 2102 lexer.nextToken(); 2103 stmt.setWork(true); 2104 } 2105 2106 if (lexer.token() == Token.AND) { 2107 lexer.nextToken(); 2108 if (lexer.token() == Token.NOT) { 2109 lexer.nextToken(); 2110 acceptIdentifier(CHAIN); 2111 stmt.setChain(Boolean.FALSE); 2112 } else { 2113 acceptIdentifier(CHAIN); 2114 stmt.setChain(Boolean.TRUE); 2115 } 2116 } 2117 2118 return stmt; 2119 } 2120 2121 public SQLReplaceStatement parseReplace() { 2122 SQLReplaceStatement stmt = new SQLReplaceStatement(); 2123 2124 accept(Token.REPLACE); 2125 2126 if (lexer.token() == Token.COMMENT) { 2127 lexer.nextToken(); 2128 } 2129 2130 if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { 2131 stmt.setLowPriority(true); 2132 lexer.nextToken(); 2133 } 2134 2135 if (lexer.identifierEquals(FnvHash.Constants.DELAYED)) { 2136 stmt.setDelayed(true); 2137 lexer.nextToken(); 2138 } 2139 2140 if (lexer.token() == Token.INTO) { 2141 lexer.nextToken(); 2142 } 2143 2144 SQLName tableName = exprParser.name(); 2145 stmt.setTableName(tableName); 2146 2147 if (lexer.token() == Token.LPAREN) { 2148 lexer.nextToken(); 2149 if (lexer.token() == Token.SELECT) { 2150 SQLQueryExpr queryExpr = cast(SQLQueryExpr) this.exprParser.expr(); 2151 stmt.setQuery(queryExpr); 2152 } else { 2153 this.exprParser.exprList(stmt.getColumns(), stmt); 2154 } 2155 accept(Token.RPAREN); 2156 } 2157 2158 if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) { 2159 lexer.nextToken(); 2160 2161 parseValueClause(stmt.getValuesList(), 0, stmt); 2162 } else if (lexer.token() == Token.SELECT) { 2163 SQLQueryExpr queryExpr = cast(SQLQueryExpr) this.exprParser.expr(); 2164 stmt.setQuery(queryExpr); 2165 } else if (lexer.token() == Token.SET) { 2166 lexer.nextToken(); 2167 2168 ValuesClause values = new ValuesClause(); 2169 values.setParent(stmt); 2170 stmt.getValuesList().add(values); 2171 for (; ; ) { 2172 stmt.addColumn(this.exprParser.name()); 2173 if (lexer.token() == Token.COLONEQ) { 2174 lexer.nextToken(); 2175 } else { 2176 accept(Token.EQ); 2177 } 2178 values.addValue(this.exprParser.expr()); 2179 2180 if (lexer.token() == (Token.COMMA)) { 2181 lexer.nextToken(); 2182 continue; 2183 } 2184 2185 break; 2186 } 2187 } else if (lexer.token() == Token.LPAREN) { 2188 SQLSelect select = this.createSQLSelectParser().select(); 2189 SQLQueryExpr queryExpr = new SQLQueryExpr(select); 2190 stmt.setQuery(queryExpr); 2191 } 2192 2193 return stmt; 2194 } 2195 2196 protected SQLStatement parseLoad() { 2197 acceptIdentifier("LOAD"); 2198 2199 if (lexer.identifierEquals("DATA")) { 2200 SQLStatement stmt = parseLoadDataInFile(); 2201 return stmt; 2202 } 2203 2204 if (lexer.identifierEquals("XML")) { 2205 SQLStatement stmt = parseLoadXml(); 2206 return stmt; 2207 } 2208 2209 throw new ParserException("TODO. " ~ lexer.info()); 2210 } 2211 2212 protected MySqlLoadXmlStatement parseLoadXml() { 2213 acceptIdentifier("XML"); 2214 2215 MySqlLoadXmlStatement stmt = new MySqlLoadXmlStatement(); 2216 2217 if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { 2218 stmt.setLowPriority(true); 2219 lexer.nextToken(); 2220 } 2221 2222 if (lexer.identifierEquals("CONCURRENT")) { 2223 stmt.setConcurrent(true); 2224 lexer.nextToken(); 2225 } 2226 2227 if (lexer.identifierEquals(LOCAL)) { 2228 stmt.setLocal(true); 2229 lexer.nextToken(); 2230 } 2231 2232 acceptIdentifier("INFILE"); 2233 2234 SQLLiteralExpr fileName = cast(SQLLiteralExpr) exprParser.expr(); 2235 stmt.setFileName(fileName); 2236 2237 if (lexer.token() == Token.REPLACE) { 2238 stmt.setReplicate(true); 2239 lexer.nextToken(); 2240 } 2241 2242 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 2243 stmt.setIgnore(true); 2244 lexer.nextToken(); 2245 } 2246 2247 accept(Token.INTO); 2248 accept(Token.TABLE); 2249 2250 SQLName tableName = exprParser.name(); 2251 stmt.setTableName(tableName); 2252 2253 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 2254 lexer.nextToken(); 2255 accept(Token.SET); 2256 2257 if (lexer.token() != Token.LITERAL_CHARS) { 2258 throw new ParserException("syntax error, illegal charset. " ~ lexer.info()); 2259 } 2260 2261 string charset = lexer.stringVal(); 2262 lexer.nextToken(); 2263 stmt.setCharset(charset); 2264 } 2265 2266 if (lexer.identifierEquals("ROWS")) { 2267 lexer.nextToken(); 2268 accept(Token.IDENTIFIED); 2269 accept(Token.BY); 2270 SQLExpr rowsIdentifiedBy = exprParser.expr(); 2271 stmt.setRowsIdentifiedBy(rowsIdentifiedBy); 2272 } 2273 2274 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 2275 throw new ParserException("TODO. " ~ lexer.info()); 2276 } 2277 2278 if (lexer.token() == Token.SET) { 2279 throw new ParserException("TODO. " ~ lexer.info()); 2280 } 2281 2282 return stmt; 2283 } 2284 2285 protected MySqlLoadDataInFileStatement parseLoadDataInFile() { 2286 2287 acceptIdentifier("DATA"); 2288 2289 MySqlLoadDataInFileStatement stmt = new MySqlLoadDataInFileStatement(); 2290 2291 if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { 2292 stmt.setLowPriority(true); 2293 lexer.nextToken(); 2294 } 2295 2296 if (lexer.identifierEquals("CONCURRENT")) { 2297 stmt.setConcurrent(true); 2298 lexer.nextToken(); 2299 } 2300 2301 if (lexer.identifierEquals(LOCAL)) { 2302 stmt.setLocal(true); 2303 lexer.nextToken(); 2304 } 2305 2306 acceptIdentifier("INFILE"); 2307 2308 SQLLiteralExpr fileName = cast(SQLLiteralExpr) exprParser.expr(); 2309 stmt.setFileName(fileName); 2310 2311 if (lexer.token() == Token.REPLACE) { 2312 stmt.setReplicate(true); 2313 lexer.nextToken(); 2314 } 2315 2316 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 2317 stmt.setIgnore(true); 2318 lexer.nextToken(); 2319 } 2320 2321 accept(Token.INTO); 2322 accept(Token.TABLE); 2323 2324 SQLName tableName = exprParser.name(); 2325 stmt.setTableName(tableName); 2326 2327 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 2328 lexer.nextToken(); 2329 accept(Token.SET); 2330 2331 if (lexer.token() != Token.LITERAL_CHARS) { 2332 throw new ParserException("syntax error, illegal charset. " ~ lexer.info()); 2333 } 2334 2335 string charset = lexer.stringVal(); 2336 lexer.nextToken(); 2337 stmt.setCharset(charset); 2338 } 2339 2340 if (lexer.identifierEquals("FIELDS") || lexer.identifierEquals("COLUMNS")) { 2341 lexer.nextToken(); 2342 if (lexer.identifierEquals("TERMINATED")) { 2343 lexer.nextToken(); 2344 accept(Token.BY); 2345 stmt.setColumnsTerminatedBy(new SQLCharExpr(lexer.stringVal())); 2346 lexer.nextToken(); 2347 } 2348 2349 if (lexer.identifierEquals("OPTIONALLY")) { 2350 stmt.setColumnsEnclosedOptionally(true); 2351 lexer.nextToken(); 2352 } 2353 2354 if (lexer.identifierEquals("ENCLOSED")) { 2355 lexer.nextToken(); 2356 accept(Token.BY); 2357 stmt.setColumnsEnclosedBy(new SQLCharExpr(lexer.stringVal())); 2358 lexer.nextToken(); 2359 } 2360 2361 if (lexer.identifierEquals("ESCAPED")) { 2362 lexer.nextToken(); 2363 accept(Token.BY); 2364 stmt.setColumnsEscaped(new SQLCharExpr(lexer.stringVal())); 2365 lexer.nextToken(); 2366 } 2367 } 2368 2369 if (lexer.identifierEquals("LINES")) { 2370 lexer.nextToken(); 2371 if (lexer.identifierEquals("STARTING")) { 2372 lexer.nextToken(); 2373 accept(Token.BY); 2374 stmt.setLinesStartingBy(new SQLCharExpr(lexer.stringVal())); 2375 lexer.nextToken(); 2376 } 2377 2378 if (lexer.identifierEquals("TERMINATED")) { 2379 lexer.nextToken(); 2380 accept(Token.BY); 2381 stmt.setLinesTerminatedBy(new SQLCharExpr(lexer.stringVal())); 2382 lexer.nextToken(); 2383 } 2384 } 2385 2386 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 2387 lexer.nextToken(); 2388 stmt.setIgnoreLinesNumber(this.exprParser.expr()); 2389 acceptIdentifier("LINES"); 2390 } 2391 2392 if (lexer.token() == Token.LPAREN) { 2393 lexer.nextToken(); 2394 this.exprParser.exprList(stmt.getColumns(), stmt); 2395 accept(Token.RPAREN); 2396 } 2397 2398 if (lexer.token() == Token.SET) { 2399 lexer.nextToken(); 2400 this.exprParser.exprList(stmt.getSetList(), stmt); 2401 } 2402 2403 return stmt; 2404 2405 } 2406 2407 public MySqlPrepareStatement parsePrepare() { 2408 acceptIdentifier("PREPARE"); 2409 2410 SQLName name = exprParser.name(); 2411 accept(Token.FROM); 2412 SQLExpr from = exprParser.expr(); 2413 2414 return new MySqlPrepareStatement(name, from); 2415 } 2416 2417 public MySqlExecuteStatement parseExecute() { 2418 acceptIdentifier("EXECUTE"); 2419 2420 MySqlExecuteStatement stmt = new MySqlExecuteStatement(); 2421 2422 SQLName statementName = exprParser.name(); 2423 stmt.setStatementName(statementName); 2424 2425 if (lexer.identifierEquals("USING")) { 2426 lexer.nextToken(); 2427 exprParser.exprList(stmt.getParameters(), stmt); 2428 } else if (lexer.token() == Token.IDENTIFIER) { 2429 exprParser.exprList(stmt.getParameters(), stmt); 2430 } 2431 2432 return stmt; 2433 } 2434 2435 public MysqlDeallocatePrepareStatement parseDeallocatePrepare() { 2436 acceptIdentifier("DEALLOCATE"); 2437 acceptIdentifier("PREPARE"); 2438 2439 MysqlDeallocatePrepareStatement stmt = new MysqlDeallocatePrepareStatement(); 2440 SQLName statementName = exprParser.name(); 2441 stmt.setStatementName(statementName); 2442 2443 return stmt; 2444 } 2445 2446 override public SQLInsertStatement parseInsert() { 2447 MySqlInsertStatement stmt = new MySqlInsertStatement(); 2448 2449 SQLName tableName = null; 2450 if (lexer.token() == Token.INSERT) { 2451 lexer.nextToken(); 2452 2453 for (; ; ) { 2454 if (lexer.token() == Token.IDENTIFIER) { 2455 long hash = lexer.hash_lower(); 2456 2457 if (hash == FnvHash.Constants.LOW_PRIORITY) { 2458 stmt.setLowPriority(true); 2459 lexer.nextToken(); 2460 continue; 2461 } 2462 2463 if (hash == FnvHash.Constants.DELAYED) { 2464 stmt.setDelayed(true); 2465 lexer.nextToken(); 2466 continue; 2467 } 2468 2469 if (hash == FnvHash.Constants.HIGH_PRIORITY) { 2470 stmt.setHighPriority(true); 2471 lexer.nextToken(); 2472 continue; 2473 } 2474 2475 if (hash == FnvHash.Constants.IGNORE) { 2476 stmt.setIgnore(true); 2477 lexer.nextToken(); 2478 continue; 2479 } 2480 2481 if (hash == FnvHash.Constants.ROLLBACK_ON_FAIL) { 2482 stmt.setRollbackOnFail(true); 2483 lexer.nextToken(); 2484 continue; 2485 } 2486 } 2487 2488 2489 break; 2490 } 2491 2492 if (lexer.token() == Token.INTO) { 2493 lexer.nextToken(); 2494 } 2495 2496 if (lexer.token() == Token.LINE_COMMENT) { 2497 lexer.nextToken(); 2498 } 2499 2500 tableName = this.exprParser.name(); 2501 stmt.setTableName(tableName); 2502 2503 if (lexer.token() == Token.HINT) { 2504 string comment = "/*" ~ lexer.stringVal() ~ "*/"; 2505 lexer.nextToken(); 2506 stmt.getTableSource().addAfterComment(comment); 2507 } 2508 2509 if (lexer.token() == Token.IDENTIFIER 2510 && !lexer.identifierEquals(FnvHash.Constants.VALUE)) { 2511 stmt.setAlias(lexer.stringVal()); 2512 lexer.nextToken(); 2513 } 2514 2515 } 2516 2517 int columnSize = 0; 2518 if (lexer.token() == Token.LPAREN) { 2519 bool useInsertColumnsCache = lexer.isEnabled(SQLParserFeature.UseInsertColumnsCache); 2520 InsertColumnsCache insertColumnsCache = null; 2521 2522 InsertColumnsCache.Entry cachedColumns = null; 2523 if (useInsertColumnsCache) { 2524 insertColumnsCache = this.insertColumnsCache; 2525 if (insertColumnsCache is null) { 2526 insertColumnsCache = InsertColumnsCache.global; 2527 } 2528 2529 if (tableName !is null) { 2530 cachedColumns = insertColumnsCache.get(tableName.hashCode64()); 2531 } 2532 } 2533 2534 int pos = lexer.pos(); 2535 if (cachedColumns !is null 2536 && lexer.text.startsWith(cachedColumns.columnsString, pos)) { 2537 if (!lexer.isEnabled(SQLParserFeature.OptimizedForParameterized)) { 2538 List!(SQLExpr) columns = stmt.getColumns(); 2539 List!(SQLExpr) cachedColumns2 = cachedColumns.columns; 2540 for (int i = 0, size = cachedColumns2.size(); i < size; i++) { 2541 columns.add(cachedColumns2.get(i).clone()); 2542 } 2543 } 2544 stmt.setColumnsString(cachedColumns.columnsFormattedString, cachedColumns.columnsFormattedStringHash); 2545 int p2 = pos + cast(int)(cachedColumns.columnsString.length); 2546 lexer.reset(p2); 2547 lexer.nextToken(); 2548 } else { 2549 lexer.nextToken(); 2550 if (lexer.token() == Token.SELECT) { 2551 SQLSelect select = this.exprParser.createSelectParser().select(); 2552 select.setParent(stmt); 2553 stmt.setQuery(select); 2554 } else { 2555 List!(SQLExpr) columns = stmt.getColumns(); 2556 2557 if (lexer.token() != Token.RPAREN) { 2558 for (; ; ) { 2559 string identName; 2560 long hash; 2561 2562 Token token = lexer.token(); 2563 if (token == Token.IDENTIFIER) { 2564 identName = lexer.stringVal(); 2565 hash = lexer.hash_lower(); 2566 } else if (token == Token.LITERAL_CHARS) { 2567 identName = '\'' ~ lexer.stringVal() ~ '\''; 2568 hash = 0; 2569 } else { 2570 identName = lexer.stringVal(); 2571 hash = 0; 2572 } 2573 lexer.nextTokenComma(); 2574 SQLExpr expr = new SQLIdentifierExpr(identName, hash); 2575 while (lexer.token() == Token.DOT) { 2576 lexer.nextToken(); 2577 string propertyName = lexer.stringVal(); 2578 lexer.nextToken(); 2579 expr = new SQLPropertyExpr(expr, propertyName); 2580 } 2581 2582 expr.setParent(stmt); 2583 columns.add(expr); 2584 columnSize++; 2585 2586 if (lexer.token() == Token.COMMA) { 2587 lexer.nextTokenIdent(); 2588 continue; 2589 } 2590 2591 break; 2592 } 2593 columnSize = stmt.getColumns().size(); 2594 2595 if (insertColumnsCache !is null && tableName !is null) { 2596 string columnsString = lexer.subString(pos, lexer.pos() - pos); 2597 2598 List!(SQLExpr) clonedColumns = new ArrayList!(SQLExpr)(columnSize); 2599 for (int i = 0; i < columns.size(); i++) { 2600 clonedColumns.add(columns.get(i).clone()); 2601 } 2602 2603 StringBuilder buf = new StringBuilder(); 2604 SQLASTOutputVisitor outputVisitor = SQLUtils.createOutputVisitor(buf, dbType); 2605 outputVisitor.printInsertColumns(columns); 2606 2607 string formattedColumnsString = buf.toString(); 2608 long columnsFormattedStringHash = FnvHash.fnv1a_64_lower(formattedColumnsString); 2609 2610 insertColumnsCache.put(tableName.hashCode64(), columnsString, formattedColumnsString, clonedColumns); 2611 stmt.setColumnsString(formattedColumnsString, columnsFormattedStringHash); 2612 } 2613 } 2614 } 2615 accept(Token.RPAREN); 2616 } 2617 } 2618 2619 if (lexer.token() == Token.LINE_COMMENT) { 2620 lexer.nextToken(); 2621 } 2622 2623 if (lexer.token() == Token.VALUES || lexer.identifierEquals(FnvHash.Constants.VALUE)) { 2624 lexer.nextTokenLParen(); 2625 parseValueClause(stmt.getValuesList(), columnSize, stmt); 2626 } else if (lexer.token() == Token.SET) { 2627 lexer.nextToken(); 2628 2629 ValuesClause values = new ValuesClause(); 2630 stmt.addValueCause(values); 2631 2632 for (; ; ) { 2633 SQLName name = this.exprParser.name(); 2634 stmt.addColumn(name); 2635 if (lexer.token() == Token.EQ) { 2636 lexer.nextToken(); 2637 } else { 2638 accept(Token.COLONEQ); 2639 } 2640 values.addValue(this.exprParser.expr()); 2641 2642 if (lexer.token() == Token.COMMA) { 2643 lexer.nextToken(); 2644 continue; 2645 } 2646 2647 break; 2648 } 2649 2650 } else if (lexer.token() == (Token.SELECT)) { 2651 SQLSelect select = this.exprParser.createSelectParser().select(); 2652 select.setParent(stmt); 2653 stmt.setQuery(select); 2654 } else if (lexer.token() == (Token.LPAREN)) { 2655 lexer.nextToken(); 2656 SQLSelect select = this.exprParser.createSelectParser().select(); 2657 select.setParent(stmt); 2658 stmt.setQuery(select); 2659 accept(Token.RPAREN); 2660 } 2661 2662 if (lexer.token() == Token.ON) { 2663 lexer.nextToken(); 2664 acceptIdentifier("DUPLICATE"); 2665 accept(Token.KEY); 2666 accept(Token.UPDATE); 2667 2668 List!(SQLExpr) duplicateKeyUpdate = stmt.getDuplicateKeyUpdate(); 2669 for (;;) { 2670 SQLName name = this.exprParser.name(); 2671 accept(Token.EQ); 2672 SQLExpr value; 2673 try { 2674 value = this.exprParser.expr(); 2675 } catch (EOFParserException e) { 2676 throw new ParserException("EOF, " ~ name.stringof ~ "=", e); 2677 } 2678 2679 SQLBinaryOpExpr assignment = new SQLBinaryOpExpr(name, SQLBinaryOperator.Equality, value); 2680 assignment.setParent(stmt); 2681 duplicateKeyUpdate.add(assignment); 2682 2683 if (lexer.token() == Token.COMMA) { 2684 lexer.nextTokenIdent(); 2685 continue; 2686 } 2687 break; 2688 } 2689 } 2690 2691 return stmt; 2692 } 2693 2694 override public MySqlSelectParser createSQLSelectParser() { 2695 return new MySqlSelectParser(this.exprParser, selectListCache); 2696 } 2697 2698 override public SQLStatement parseSet() { 2699 accept(Token.SET); 2700 2701 if (lexer.identifierEquals(FnvHash.Constants.PASSWORD)) { 2702 lexer.nextToken(); 2703 SQLSetStatement stmt = new SQLSetStatement(); 2704 stmt.setDbType(dbType); 2705 stmt.setOption(SQLSetStatement.Option.PASSWORD); 2706 2707 SQLExpr user = null; 2708 if (lexer.token() == Token.FOR) { 2709 lexer.nextToken(); 2710 user = this.exprParser.name(); 2711 } 2712 2713 accept(Token.EQ); 2714 2715 SQLExpr password = this.exprParser.expr(); 2716 2717 stmt.set(user, password); 2718 2719 return stmt; 2720 } 2721 2722 Boolean global = null; 2723 Boolean session = null; 2724 if (lexer.identifierEquals(GLOBAL)) { 2725 global = Boolean.TRUE; 2726 lexer.nextToken(); 2727 } else if (lexer.identifierEquals(SESSION)) { 2728 global = Boolean.FALSE; 2729 session = Boolean.TRUE; 2730 lexer.nextToken(); 2731 } 2732 2733 if (lexer.identifierEquals("TRANSACTION")) { 2734 MySqlSetTransactionStatement stmt = new MySqlSetTransactionStatement(); 2735 stmt.setGlobal(global); 2736 stmt.setSession(session); 2737 2738 lexer.nextToken(); 2739 if (lexer.identifierEquals("ISOLATION")) { 2740 lexer.nextToken(); 2741 acceptIdentifier("LEVEL"); 2742 2743 if (lexer.identifierEquals(READ)) { 2744 lexer.nextToken(); 2745 2746 if (lexer.identifierEquals("UNCOMMITTED")) { 2747 stmt.setIsolationLevel("READ UNCOMMITTED"); 2748 lexer.nextToken(); 2749 } else if (lexer.identifierEquals(WRITE)) { 2750 stmt.setIsolationLevel("READ WRITE"); 2751 lexer.nextToken(); 2752 } else if (lexer.identifierEquals("ONLY")) { 2753 stmt.setIsolationLevel("READ ONLY"); 2754 lexer.nextToken(); 2755 } else if (lexer.identifierEquals("COMMITTED")) { 2756 stmt.setIsolationLevel("READ COMMITTED"); 2757 lexer.nextToken(); 2758 } else { 2759 throw new ParserException("UNKOWN TRANSACTION LEVEL : " ~ lexer.stringVal() ~ ", " ~ lexer.info()); 2760 } 2761 } else if (lexer.identifierEquals("SERIALIZABLE")) { 2762 stmt.setIsolationLevel("SERIALIZABLE"); 2763 lexer.nextToken(); 2764 } else if (lexer.identifierEquals("REPEATABLE")) { 2765 lexer.nextToken(); 2766 if (lexer.identifierEquals(READ)) { 2767 stmt.setIsolationLevel("REPEATABLE READ"); 2768 lexer.nextToken(); 2769 } else { 2770 throw new ParserException("UNKOWN TRANSACTION LEVEL : " ~ lexer.stringVal() ~ ", " ~ lexer.info()); 2771 } 2772 } else { 2773 throw new ParserException("UNKOWN TRANSACTION LEVEL : " ~ lexer.stringVal() ~ ", " ~ lexer.info()); 2774 } 2775 } else if (lexer.identifierEquals(READ)) { 2776 lexer.nextToken(); 2777 if (lexer.identifierEquals("ONLY")) { 2778 stmt.setAccessModel("ONLY"); 2779 lexer.nextToken(); 2780 } else if (lexer.identifierEquals("WRITE")) { 2781 stmt.setAccessModel("WRITE"); 2782 lexer.nextToken(); 2783 } else { 2784 throw new ParserException("UNKOWN ACCESS MODEL : " ~ lexer.stringVal() ~ ", " ~ lexer.info()); 2785 } 2786 } 2787 2788 return stmt; 2789 // } else if (lexer.identifierEquals("NAMES")) { 2790 // lexer.nextToken(); 2791 // 2792 // MySqlSetNamesStatement stmt = new MySqlSetNamesStatement(); 2793 // if (lexer.token() == Token.DEFAULT) { 2794 // lexer.nextToken(); 2795 // stmt.setDefault(true); 2796 // } else { 2797 // string charSet = lexer.stringVal(); 2798 // stmt.setCharSet(charSet); 2799 // lexer.nextToken(); 2800 // if (lexer.identifierEquals(COLLATE2)) { 2801 // lexer.nextToken(); 2802 // 2803 // string collate = lexer.stringVal(); 2804 // stmt.setCollate(collate); 2805 // lexer.nextToken(); 2806 // } 2807 // } 2808 // return stmt; 2809 // } else if (lexer.identifierEquals(CHARACTER)) { 2810 // lexer.nextToken(); 2811 // 2812 // accept(Token.SET); 2813 // 2814 // MySqlSetCharSetStatement stmt = new MySqlSetCharSetStatement(); 2815 // if (lexer.token() == Token.DEFAULT) { 2816 // lexer.nextToken(); 2817 // stmt.setDefault(true); 2818 // } else { 2819 // string charSet = lexer.stringVal(); 2820 // stmt.setCharSet(charSet); 2821 // lexer.nextToken(); 2822 // if (lexer.identifierEquals(COLLATE2)) { 2823 // lexer.nextToken(); 2824 // 2825 // string collate = lexer.stringVal(); 2826 // stmt.setCollate(collate); 2827 // lexer.nextToken(); 2828 // } 2829 // } 2830 // return stmt; 2831 } else { 2832 SQLSetStatement stmt = new SQLSetStatement(getDbType()); 2833 2834 parseAssignItems(stmt.getItems(), stmt); 2835 2836 if (global !is null && global) { 2837 SQLVariantRefExpr varRef = cast(SQLVariantRefExpr) stmt.getItems().get(0).getTarget(); 2838 varRef.setGlobal(true); 2839 } 2840 2841 if(session !is null && session){ 2842 SQLVariantRefExpr varRef = cast(SQLVariantRefExpr) stmt.getItems().get(0).getTarget(); 2843 varRef.setSession(true); 2844 } 2845 2846 if (lexer.token() == Token.HINT) { 2847 stmt.setHints(this.exprParser.parseHints()); 2848 } 2849 2850 return stmt; 2851 } 2852 } 2853 2854 override public SQLStatement parseAlter() { 2855 accept(Token.ALTER); 2856 2857 if (lexer.token() == Token.USER) { 2858 return parseAlterUser(); 2859 } 2860 2861 bool ignore = false; 2862 2863 if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { 2864 ignore = true; 2865 lexer.nextToken(); 2866 } 2867 2868 if (lexer.token() == Token.TABLE) { 2869 return parseAlterTable(ignore); 2870 } 2871 2872 if (lexer.token() == Token.DATABASE 2873 || lexer.token() == Token.SCHEMA) { 2874 return parseAlterDatabase(); 2875 } 2876 2877 if (lexer.identifierEquals(FnvHash.Constants.EVENT)) { 2878 return parseAlterEvent(); 2879 } 2880 2881 if (lexer.token() == Token.FUNCTION) { 2882 return parseAlterFunction(); 2883 } 2884 2885 if (lexer.token() == Token.PROCEDURE) { 2886 return parseAlterProcedure(); 2887 } 2888 2889 if (lexer.token() == Token.TABLESPACE) { 2890 return parseAlterTableSpace(); 2891 } 2892 2893 if (lexer.token() == Token.VIEW) { 2894 return parseAlterView(); 2895 } 2896 2897 if (lexer.identifierEquals(FnvHash.Constants.LOGFILE)) { 2898 return parseAlterLogFileGroup(); 2899 } 2900 2901 if (lexer.identifierEquals(FnvHash.Constants.SERVER)) { 2902 return parseAlterServer(); 2903 } 2904 2905 if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) { 2906 return parseAlterView(); 2907 } 2908 2909 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 2910 Lexer.SavePoint savePoint = lexer.mark(); 2911 lexer.nextToken(); 2912 accept(Token.EQ); 2913 this.getExprParser().userName(); 2914 if (lexer.identifierEquals(FnvHash.Constants.EVENT)) { 2915 lexer.reset(savePoint); 2916 return parseAlterEvent(); 2917 } else { 2918 lexer.reset(savePoint); 2919 return parseAlterView(); 2920 } 2921 } 2922 2923 throw new ParserException("TODO " ~ lexer.info()); 2924 } 2925 2926 protected SQLStatement parseAlterView() { 2927 if (lexer.token() == Token.ALTER) { 2928 lexer.nextToken(); 2929 } 2930 2931 SQLAlterViewStatement createView = new SQLAlterViewStatement(getDbType()); 2932 2933 if (lexer.identifierEquals("ALGORITHM")) { 2934 lexer.nextToken(); 2935 accept(Token.EQ); 2936 string algorithm = lexer.stringVal(); 2937 createView.setAlgorithm(algorithm); 2938 lexer.nextToken(); 2939 } 2940 2941 if (lexer.identifierEquals("DEFINER")) { 2942 lexer.nextToken(); 2943 accept(Token.EQ); 2944 SQLName definer = cast(SQLName) this.exprParser.expr(); 2945 createView.setDefiner(definer); 2946 } 2947 2948 if (lexer.identifierEquals("SQL")) { 2949 lexer.nextToken(); 2950 acceptIdentifier("SECURITY"); 2951 string sqlSecurity = lexer.stringVal(); 2952 createView.setSqlSecurity(sqlSecurity); 2953 lexer.nextToken(); 2954 } 2955 2956 if (lexer.identifierEquals("FORCE")) { 2957 lexer.nextToken(); 2958 createView.setForce(true); 2959 } 2960 2961 this.accept(Token.VIEW); 2962 2963 if (lexer.token() == Token.IF || lexer.identifierEquals("IF")) { 2964 lexer.nextToken(); 2965 accept(Token.NOT); 2966 accept(Token.EXISTS); 2967 createView.setIfNotExists(true); 2968 } 2969 2970 createView.setName(exprParser.name()); 2971 2972 if (lexer.token() == Token.LPAREN) { 2973 lexer.nextToken(); 2974 2975 for (;;) { 2976 2977 if (lexer.token() == Token.CONSTRAINT) { 2978 SQLTableConstraint constraint = cast(SQLTableConstraint) this.exprParser.parseConstaint(); 2979 createView.addColumn(constraint); 2980 } else { 2981 SQLColumnDefinition column = new SQLColumnDefinition(); 2982 column.setDbType(dbType); 2983 SQLName expr = this.exprParser.name(); 2984 column.setName(expr); 2985 2986 this.exprParser.parseColumnRest(column); 2987 2988 if (lexer.token() == Token.COMMENT) { 2989 lexer.nextToken(); 2990 2991 SQLExpr comment; 2992 if (lexer.token() == Token.LITERAL_ALIAS) { 2993 string alias_p = lexer.stringVal(); 2994 if (alias_p.length > 2 && charAt(alias_p, 0) == '"' && charAt(alias_p, alias_p.length - 1) == '"') { 2995 alias_p = alias_p.substring(1, cast(int)(alias_p.length - 1)); 2996 } 2997 comment = new SQLCharExpr(alias_p); 2998 lexer.nextToken(); 2999 } else { 3000 comment = this.exprParser.primary(); 3001 } 3002 column.setComment(comment); 3003 } 3004 3005 column.setParent(createView); 3006 createView.addColumn(column); 3007 } 3008 3009 if (lexer.token() == Token.COMMA) { 3010 lexer.nextToken(); 3011 } else { 3012 break; 3013 } 3014 } 3015 3016 accept(Token.RPAREN); 3017 } 3018 3019 if (lexer.token() == Token.COMMENT) { 3020 lexer.nextToken(); 3021 SQLCharExpr comment = cast(SQLCharExpr) exprParser.primary(); 3022 createView.setComment(comment); 3023 } 3024 3025 this.accept(Token.AS); 3026 3027 SQLSelectParser selectParser = this.createSQLSelectParser(); 3028 createView.setSubQuery(selectParser.select()); 3029 3030 if (lexer.token() == Token.WITH) { 3031 lexer.nextToken(); 3032 3033 if (lexer.identifierEquals("CASCADED")) { 3034 createView.setWithCascaded(true); 3035 lexer.nextToken(); 3036 } else if (lexer.identifierEquals("LOCAL")){ 3037 createView.setWithLocal(true); 3038 lexer.nextToken(); 3039 } else if (lexer.identifierEquals("READ")) { 3040 lexer.nextToken(); 3041 accept(Token.ONLY); 3042 createView.setWithReadOnly(true); 3043 } 3044 3045 if (lexer.token() == Token.CHECK) { 3046 lexer.nextToken(); 3047 acceptIdentifier("OPTION"); 3048 createView.setWithCheckOption(true); 3049 } 3050 } 3051 3052 return createView; 3053 } 3054 3055 protected SQLStatement parseAlterTableSpace() { 3056 if (lexer.token() == Token.ALTER) { 3057 lexer.nextToken(); 3058 } 3059 3060 accept(Token.TABLESPACE); 3061 3062 SQLName name = this.exprParser.name(); 3063 3064 MySqlAlterTablespaceStatement stmt = new MySqlAlterTablespaceStatement(); 3065 stmt.setName(name); 3066 3067 if (lexer.identifierEquals(FnvHash.Constants.ADD)) { 3068 lexer.nextToken(); 3069 acceptIdentifier("DATAFILE"); 3070 SQLExpr file = this.exprParser.primary(); 3071 stmt.setAddDataFile(file); 3072 } else if (lexer.token() == Token.DROP) { 3073 lexer.nextToken(); 3074 acceptIdentifier("DATAFILE"); 3075 SQLExpr file = this.exprParser.primary(); 3076 stmt.setDropDataFile(file); 3077 } 3078 3079 if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) { 3080 lexer.nextToken(); 3081 if (lexer.token() == Token.EQ) { 3082 lexer.nextToken(); 3083 } 3084 SQLExpr initialSize = this.exprParser.expr(); 3085 stmt.setInitialSize(initialSize); 3086 } 3087 3088 if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { 3089 lexer.nextToken(); 3090 stmt.setWait(true); 3091 } 3092 3093 if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) { 3094 lexer.nextToken(); 3095 if (lexer.token() == Token.EQ) { 3096 lexer.nextToken(); 3097 } 3098 SQLExpr engine = this.exprParser.expr(); 3099 stmt.setEngine(engine); 3100 } 3101 3102 return stmt; 3103 } 3104 3105 protected SQLStatement parseAlterServer() { 3106 if (lexer.token() == Token.ALTER) { 3107 lexer.nextToken(); 3108 } 3109 acceptIdentifier("SERVER"); 3110 3111 SQLName name = this.exprParser.name(); 3112 3113 MySqlAlterServerStatement stmt = new MySqlAlterServerStatement(); 3114 stmt.setName(name); 3115 3116 acceptIdentifier("OPTIONS"); 3117 accept(Token.LPAREN); 3118 if (lexer.token() == Token.USER) { 3119 lexer.nextToken(); 3120 SQLExpr user = this.exprParser.name(); 3121 stmt.setUser(user); 3122 } 3123 accept(Token.RPAREN); 3124 3125 return stmt; 3126 } 3127 3128 protected SQLStatement parseCreateLogFileGroup() { 3129 if (lexer.token() == Token.ALTER) { 3130 lexer.nextToken(); 3131 } 3132 acceptIdentifier("LOGFILE"); 3133 accept(Token.GROUP); 3134 3135 SQLName name = this.exprParser.name(); 3136 3137 MySqlCreateAddLogFileGroupStatement stmt = new MySqlCreateAddLogFileGroupStatement(); 3138 stmt.setName(name); 3139 3140 acceptIdentifier("ADD"); 3141 acceptIdentifier("UNDOFILE"); 3142 3143 SQLExpr fileName = this.exprParser.primary(); 3144 stmt.setAddUndoFile(fileName); 3145 3146 if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) { 3147 lexer.nextToken(); 3148 if (lexer.token() == Token.EQ) { 3149 lexer.nextToken(); 3150 } 3151 SQLExpr initialSize = this.exprParser.expr(); 3152 stmt.setInitialSize(initialSize); 3153 } 3154 3155 if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { 3156 lexer.nextToken(); 3157 stmt.setWait(true); 3158 } 3159 3160 if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) { 3161 lexer.nextToken(); 3162 if (lexer.token() == Token.EQ) { 3163 lexer.nextToken(); 3164 } 3165 SQLExpr engine = this.exprParser.expr(); 3166 stmt.setEngine(engine); 3167 } 3168 3169 return stmt; 3170 } 3171 3172 protected SQLStatement parseAlterLogFileGroup() { 3173 if (lexer.token() == Token.ALTER) { 3174 lexer.nextToken(); 3175 } 3176 acceptIdentifier("LOGFILE"); 3177 accept(Token.GROUP); 3178 3179 SQLName name = this.exprParser.name(); 3180 3181 MySqlAlterLogFileGroupStatement stmt = new MySqlAlterLogFileGroupStatement(); 3182 stmt.setName(name); 3183 3184 acceptIdentifier("ADD"); 3185 acceptIdentifier("UNDOFILE"); 3186 3187 SQLExpr fileName = this.exprParser.primary(); 3188 stmt.setAddUndoFile(fileName); 3189 3190 if (lexer.identifierEquals(FnvHash.Constants.INITIAL_SIZE)) { 3191 lexer.nextToken(); 3192 if (lexer.token() == Token.EQ) { 3193 lexer.nextToken(); 3194 } 3195 SQLExpr initialSize = this.exprParser.expr(); 3196 stmt.setInitialSize(initialSize); 3197 } 3198 3199 if (lexer.identifierEquals(FnvHash.Constants.WAIT)) { 3200 lexer.nextToken(); 3201 stmt.setWait(true); 3202 } 3203 3204 if (lexer.identifierEquals(FnvHash.Constants.ENGINE)) { 3205 lexer.nextToken(); 3206 if (lexer.token() == Token.EQ) { 3207 lexer.nextToken(); 3208 } 3209 SQLExpr engine = this.exprParser.expr(); 3210 stmt.setEngine(engine); 3211 } 3212 3213 return stmt; 3214 } 3215 3216 protected SQLStatement parseAlterProcedure() { 3217 if (lexer.token() == Token.ALTER) { 3218 lexer.nextToken(); 3219 } 3220 accept(Token.PROCEDURE); 3221 3222 SQLAlterProcedureStatement stmt = new SQLAlterProcedureStatement(); 3223 stmt.setDbType(dbType); 3224 3225 SQLName name = this.exprParser.name(); 3226 stmt.setName(name); 3227 3228 // for mysql 3229 for (;;) { 3230 if (lexer.token() == Token.COMMENT) { 3231 lexer.nextToken(); 3232 SQLExpr comment = this.exprParser.primary(); 3233 stmt.setComment(comment); 3234 } else if (lexer.identifierEquals(FnvHash.Constants.LANGUAGE)) { 3235 lexer.nextToken(); 3236 acceptIdentifier("SQL"); 3237 stmt.setLanguageSql(true); 3238 } else if (lexer.identifierEquals(FnvHash.Constants.SQL)) { 3239 lexer.nextToken(); 3240 acceptIdentifier("SECURITY"); 3241 3242 SQLExpr sqlSecurity = this.exprParser.name(); 3243 stmt.setSqlSecurity(sqlSecurity); 3244 } else if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) { 3245 lexer.nextToken(); 3246 acceptIdentifier("SQL"); 3247 stmt.setContainsSql(true); 3248 } else { 3249 break; 3250 } 3251 } 3252 3253 return stmt; 3254 } 3255 3256 override protected SQLStatement parseAlterFunction() { 3257 if (lexer.token() == Token.ALTER) { 3258 lexer.nextToken(); 3259 } 3260 accept(Token.FUNCTION); 3261 3262 SQLAlterFunctionStatement stmt = new SQLAlterFunctionStatement(); 3263 stmt.setDbType(dbType); 3264 3265 SQLName name = this.exprParser.name(); 3266 stmt.setName(name); 3267 3268 // for mysql 3269 for (;;) { 3270 if (lexer.token() == Token.COMMENT) { 3271 lexer.nextToken(); 3272 SQLExpr comment = this.exprParser.primary(); 3273 stmt.setComment(comment); 3274 } else if (lexer.identifierEquals(FnvHash.Constants.LANGUAGE)) { 3275 lexer.nextToken(); 3276 acceptIdentifier("SQL"); 3277 stmt.setLanguageSql(true); 3278 } else if (lexer.identifierEquals(FnvHash.Constants.SQL)) { 3279 lexer.nextToken(); 3280 acceptIdentifier("SECURITY"); 3281 3282 SQLExpr sqlSecurity = this.exprParser.name(); 3283 stmt.setSqlSecurity(sqlSecurity); 3284 } else if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) { 3285 lexer.nextToken(); 3286 acceptIdentifier("SQL"); 3287 stmt.setContainsSql(true); 3288 } else { 3289 break; 3290 } 3291 } 3292 3293 return stmt; 3294 } 3295 3296 protected SQLStatement parseCreateEvent() { 3297 if (lexer.token() == Token.CREATE) { 3298 lexer.nextToken(); 3299 } 3300 3301 MySqlCreateEventStatement stmt = new MySqlCreateEventStatement(); 3302 3303 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 3304 lexer.nextToken(); 3305 accept(Token.EQ); 3306 SQLName definer = this.getExprParser().userName(); 3307 stmt.setDefiner(definer); 3308 3309 if (lexer.token() == Token.LPAREN) { 3310 lexer.nextToken(); 3311 accept(Token.RPAREN); 3312 } 3313 } 3314 3315 acceptIdentifier("EVENT"); 3316 3317 if (lexer.token() == Token.IF) { 3318 lexer.nextToken(); 3319 accept(Token.NOT); 3320 accept(Token.EXISTS); 3321 stmt.setIfNotExists(true); 3322 } 3323 3324 SQLName eventName = this.exprParser.name(); 3325 stmt.setName(eventName); 3326 3327 while (lexer.token() == Token.ON) { 3328 lexer.nextToken(); 3329 if (lexer.identifierEquals(FnvHash.Constants.SCHEDULE)) { 3330 lexer.nextToken(); 3331 MySqlEventSchedule schedule = parseSchedule(); 3332 stmt.setSchedule(schedule); 3333 } else if (lexer.identifierEquals(FnvHash.Constants.COMPLETION)) { 3334 lexer.nextToken(); 3335 3336 bool value; 3337 if (lexer.token() == Token.NOT) { 3338 lexer.nextToken(); 3339 value = false; 3340 } else { 3341 value = true; 3342 } 3343 acceptIdentifier("PRESERVE"); 3344 stmt.setOnCompletionPreserve(value); 3345 } else { 3346 throw new ParserException("TODO " ~ lexer.info()); 3347 } 3348 } 3349 3350 if (lexer.identifierEquals(FnvHash.Constants.RENAME)) { 3351 lexer.nextToken(); 3352 accept(Token.TO); 3353 SQLName renameTo = this.exprParser.name(); 3354 stmt.setRenameTo(renameTo); 3355 } 3356 3357 if (lexer.token() == Token.ENABLE) { 3358 stmt.setEnable(new Boolean(true)); 3359 lexer.nextToken(); 3360 } else if (lexer.token() == Token.DISABLE) { 3361 lexer.nextToken(); 3362 stmt.setEnable(new Boolean(false)); 3363 3364 if (lexer.token() == Token.ON) { 3365 lexer.nextToken(); 3366 acceptIdentifier("SLAVE"); 3367 stmt.setDisableOnSlave(true); 3368 } 3369 } 3370 3371 if (lexer.token() == Token.COMMENT) { 3372 lexer.nextToken(); 3373 SQLExpr comment = this.exprParser.primary(); 3374 stmt.setComment(comment); 3375 } 3376 3377 if (lexer.token() == Token.DO) { 3378 lexer.nextToken(); 3379 SQLStatement eventBody = this.parseStatement(); 3380 stmt.setEventBody(eventBody); 3381 } else if (lexer.token() == Token.IDENTIFIER) { 3382 SQLExpr expr = this.exprParser.expr(); 3383 SQLExprStatement eventBody = new SQLExprStatement(expr); 3384 eventBody.setDbType(dbType); 3385 stmt.setEventBody(eventBody); 3386 } 3387 3388 return stmt; 3389 } 3390 3391 protected SQLStatement parseAlterEvent() { 3392 if (lexer.token() == Token.ALTER) { 3393 lexer.nextToken(); 3394 } 3395 3396 MySqlAlterEventStatement stmt = new MySqlAlterEventStatement(); 3397 3398 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 3399 lexer.nextToken(); 3400 accept(Token.EQ); 3401 SQLName definer = this.getExprParser().userName(); 3402 stmt.setDefiner(definer); 3403 } 3404 3405 acceptIdentifier("EVENT"); 3406 3407 SQLName eventName = this.exprParser.name(); 3408 stmt.setName(eventName); 3409 3410 while (lexer.token() == Token.ON) { 3411 lexer.nextToken(); 3412 if (lexer.identifierEquals(FnvHash.Constants.SCHEDULE)) { 3413 lexer.nextToken(); 3414 MySqlEventSchedule schedule = parseSchedule(); 3415 stmt.setSchedule(schedule); 3416 } else if (lexer.identifierEquals(FnvHash.Constants.COMPLETION)) { 3417 lexer.nextToken(); 3418 3419 bool value; 3420 if (lexer.token() == Token.NOT) { 3421 lexer.nextToken(); 3422 value = false; 3423 } else { 3424 value = true; 3425 } 3426 acceptIdentifier("PRESERVE"); 3427 stmt.setOnCompletionPreserve(value); 3428 } else { 3429 throw new ParserException("TODO " ~ lexer.info()); 3430 } 3431 } 3432 3433 if (lexer.identifierEquals(FnvHash.Constants.RENAME)) { 3434 lexer.nextToken(); 3435 accept(Token.TO); 3436 SQLName renameTo = this.exprParser.name(); 3437 stmt.setRenameTo(renameTo); 3438 } 3439 3440 if (lexer.token() == Token.ENABLE) { 3441 stmt.setEnable(new Boolean(true)); 3442 lexer.nextToken(); 3443 } else if (lexer.token() == Token.DISABLE) { 3444 lexer.nextToken(); 3445 stmt.setEnable(new Boolean(false)); 3446 3447 if (lexer.token() == Token.ON) { 3448 lexer.nextToken(); 3449 acceptIdentifier("SLAVE"); 3450 stmt.setDisableOnSlave(true); 3451 } 3452 } 3453 3454 if (lexer.token() == Token.COMMENT) { 3455 lexer.nextToken(); 3456 SQLExpr comment = this.exprParser.primary(); 3457 stmt.setComment(comment); 3458 } 3459 3460 if (lexer.token() == Token.DO) { 3461 lexer.nextToken(); 3462 SQLStatement eventBody = this.parseStatement(); 3463 stmt.setEventBody(eventBody); 3464 } else if (lexer.token() == Token.IDENTIFIER) { 3465 SQLExpr expr = this.exprParser.expr(); 3466 SQLExprStatement eventBody = new SQLExprStatement(expr); 3467 eventBody.setDbType(dbType); 3468 stmt.setEventBody(eventBody); 3469 } 3470 3471 return stmt; 3472 } 3473 3474 private MySqlEventSchedule parseSchedule() { 3475 MySqlEventSchedule schedule = new MySqlEventSchedule(); 3476 3477 if (lexer.identifierEquals(FnvHash.Constants.AT)) { 3478 lexer.nextToken(); 3479 schedule.setAt(this.exprParser.expr()); 3480 } else if (lexer.identifierEquals(FnvHash.Constants.EVERY)) { 3481 lexer.nextToken(); 3482 SQLExpr value = this.exprParser.expr(); 3483 string unit = lexer.stringVal(); 3484 lexer.nextToken(); 3485 3486 SQLIntervalExpr intervalExpr = new SQLIntervalExpr(); 3487 intervalExpr.setValue(value); 3488 intervalExpr.setUnit(SQLIntervalUnit(toUpper(unit))); 3489 3490 schedule.setEvery(intervalExpr); 3491 } 3492 3493 if (lexer.identifierEquals(FnvHash.Constants.STARTS)) { 3494 lexer.nextToken(); 3495 schedule.setStarts(this.exprParser.expr()); 3496 3497 if (lexer.identifierEquals(FnvHash.Constants.ENDS)) { 3498 lexer.nextToken(); 3499 schedule.setEnds(this.exprParser.expr()); 3500 } 3501 } else if (lexer.identifierEquals(FnvHash.Constants.ENDS)) { 3502 lexer.nextToken(); 3503 schedule.setEnds(this.exprParser.expr()); 3504 } 3505 3506 return schedule; 3507 } 3508 3509 protected SQLStatement parseAlterTable(bool ignore) { 3510 lexer.nextToken(); 3511 3512 SQLAlterTableStatement stmt = new SQLAlterTableStatement(getDbType()); 3513 stmt.setIgnore(ignore); 3514 stmt.setName(this.exprParser.name()); 3515 3516 for (; ; ) { 3517 if (lexer.token() == Token.DROP) { 3518 parseAlterDrop(stmt); 3519 } else if (lexer.token() == Token.TRUNCATE) { 3520 lexer.nextToken(); 3521 accept(Token.PARTITION); 3522 3523 SQLAlterTableTruncatePartition item = new SQLAlterTableTruncatePartition(); 3524 if (lexer.token() == Token.ALL) { 3525 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3526 lexer.nextToken(); 3527 } else { 3528 this.exprParser.names(item.getPartitions(), item); 3529 } 3530 stmt.addItem(item); 3531 } else if (lexer.identifierEquals("ADD")) { 3532 lexer.nextToken(); 3533 3534 if (lexer.token() == Token.COLUMN) { 3535 lexer.nextToken(); 3536 parseAlterTableAddColumn(stmt); 3537 } else if (lexer.token() == Token.INDEX 3538 || lexer.token() == Token.FULLTEXT 3539 || lexer.identifierEquals(FnvHash.Constants.SPATIAL)) { 3540 SQLAlterTableAddIndex item = parseAlterTableAddIndex(); 3541 item.setParent(stmt); 3542 stmt.addItem(item); 3543 } else if (lexer.token() == Token.UNIQUE) { 3544 SQLAlterTableAddIndex item = parseAlterTableAddIndex(); 3545 item.setParent(stmt); 3546 stmt.addItem(item); 3547 } else if (lexer.token() == Token.PRIMARY) { 3548 SQLPrimaryKey primaryKey = this.exprParser.parsePrimaryKey(); 3549 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey); 3550 stmt.addItem(item); 3551 } else if (lexer.token() == Token.KEY) { 3552 // throw new ParserException("TODO " ~ lexer.token() + 3553 // " " ~ lexer.stringVal()); 3554 SQLAlterTableAddIndex item = parseAlterTableAddIndex(); 3555 item.setParent(stmt); 3556 stmt.addItem(item); 3557 } else if (lexer.token() == Token.FOREIGN) { 3558 MysqlForeignKey fk = this.getExprParser().parseForeignKey(); 3559 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk); 3560 3561 stmt.addItem(item); 3562 } else if (lexer.token() == Token.CONSTRAINT) { 3563 lexer.nextToken(); 3564 3565 if (lexer.token() == Token.PRIMARY) { 3566 SQLPrimaryKey primaryKey = (cast(MySqlExprParser) this.exprParser).parsePrimaryKey(); 3567 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey); 3568 item.setParent(stmt); 3569 3570 stmt.addItem(item); 3571 } else if (lexer.token() == Token.FOREIGN) { 3572 MysqlForeignKey fk = this.getExprParser().parseForeignKey(); 3573 fk.setHasConstraint(true); 3574 3575 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk); 3576 3577 stmt.addItem(item); 3578 } else if (lexer.token() == Token.UNIQUE) { 3579 3580 SQLUnique unique = this.exprParser.parseUnique(); 3581 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique); 3582 stmt.addItem(item); 3583 } else { 3584 SQLName constraintName = this.exprParser.name(); 3585 3586 if (lexer.token() == Token.PRIMARY) { 3587 SQLPrimaryKey primaryKey = (cast(MySqlExprParser) this.exprParser).parsePrimaryKey(); 3588 3589 primaryKey.setName(constraintName); 3590 3591 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(primaryKey); 3592 item.setParent(stmt); 3593 3594 stmt.addItem(item); 3595 } else if (lexer.token() == Token.FOREIGN) { 3596 MysqlForeignKey fk = this.getExprParser().parseForeignKey(); 3597 fk.setName(constraintName); 3598 fk.setHasConstraint(true); 3599 3600 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(fk); 3601 3602 stmt.addItem(item); 3603 } else if (lexer.token() == Token.UNIQUE) { 3604 SQLUnique unique = this.exprParser.parseUnique(); 3605 SQLAlterTableAddConstraint item = new SQLAlterTableAddConstraint(unique); 3606 stmt.addItem(item); 3607 } else { 3608 throw new ParserException("TODO " ~ lexer.info()); 3609 } 3610 } 3611 } else if (lexer.token() == Token.PARTITION) { 3612 lexer.nextToken(); 3613 3614 SQLAlterTableAddPartition item = new SQLAlterTableAddPartition(); 3615 3616 if (lexer.identifierEquals("PARTITIONS")) { 3617 lexer.nextToken(); 3618 item.setPartitionCount(this.exprParser.integerExpr()); 3619 } 3620 3621 if (lexer.token() == Token.LPAREN) { 3622 lexer.nextToken(); 3623 SQLPartition partition = this.getExprParser().parsePartition(); 3624 accept(Token.RPAREN); 3625 item.addPartition(partition); 3626 } 3627 3628 stmt.addItem(item); 3629 } else { 3630 parseAlterTableAddColumn(stmt); 3631 } 3632 } else if (lexer.token() == Token.ALTER) { 3633 lexer.nextToken(); 3634 if (lexer.token() == Token.COLUMN) { 3635 lexer.nextToken(); 3636 } 3637 3638 MySqlAlterTableAlterColumn alterColumn = new MySqlAlterTableAlterColumn(); 3639 alterColumn.setColumn(this.exprParser.name()); 3640 3641 if (lexer.token() == Token.SET) { 3642 lexer.nextToken(); 3643 accept(Token.DEFAULT); 3644 3645 alterColumn.setDefaultExpr(this.exprParser.expr()); 3646 } else { 3647 accept(Token.DROP); 3648 accept(Token.DEFAULT); 3649 alterColumn.setDropDefault(true); 3650 } 3651 3652 stmt.addItem(alterColumn); 3653 } else if (lexer.identifierEquals("CHANGE")) { 3654 lexer.nextToken(); 3655 if (lexer.token() == Token.COLUMN) { 3656 lexer.nextToken(); 3657 } 3658 MySqlAlterTableChangeColumn item = new MySqlAlterTableChangeColumn(); 3659 item.setColumnName(this.exprParser.name()); 3660 item.setNewColumnDefinition(this.exprParser.parseColumn()); 3661 if (lexer.identifierEquals("AFTER")) { 3662 lexer.nextToken(); 3663 item.setAfterColumn(this.exprParser.name()); 3664 } else if (lexer.identifierEquals("FIRST")) { 3665 lexer.nextToken(); 3666 if (lexer.token() == Token.IDENTIFIER) { 3667 item.setFirstColumn(this.exprParser.name()); 3668 } else { 3669 item.setFirst(true); 3670 } 3671 } 3672 stmt.addItem(item); 3673 } else if (lexer.identifierEquals("MODIFY")) { 3674 lexer.nextToken(); 3675 3676 if (lexer.token() == Token.COLUMN) { 3677 lexer.nextToken(); 3678 } 3679 3680 bool paren = false; 3681 if (lexer.token() == Token.LPAREN) { 3682 paren = true; 3683 lexer.nextToken(); 3684 } 3685 3686 for (; ; ) { 3687 MySqlAlterTableModifyColumn item = new MySqlAlterTableModifyColumn(); 3688 item.setNewColumnDefinition(this.exprParser.parseColumn()); 3689 if (lexer.identifierEquals("AFTER")) { 3690 lexer.nextToken(); 3691 item.setAfterColumn(this.exprParser.name()); 3692 } else if (lexer.identifierEquals("FIRST")) { 3693 lexer.nextToken(); 3694 if (lexer.token() == Token.IDENTIFIER) { 3695 item.setFirstColumn(this.exprParser.name()); 3696 } else { 3697 item.setFirst(true); 3698 } 3699 } 3700 stmt.addItem(item); 3701 3702 if (paren && lexer.token() == Token.COMMA) { 3703 lexer.nextToken(); 3704 continue; 3705 } 3706 break; 3707 } 3708 3709 if (paren) { 3710 accept(Token.RPAREN); 3711 } 3712 } else if (lexer.token() == Token.DISABLE) { 3713 lexer.nextToken(); 3714 3715 if (lexer.token() == Token.CONSTRAINT) { 3716 lexer.nextToken(); 3717 SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint(); 3718 item.setConstraintName(this.exprParser.name()); 3719 stmt.addItem(item); 3720 } else { 3721 acceptIdentifier("KEYS"); 3722 SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys(); 3723 stmt.addItem(item); 3724 } 3725 } else if (lexer.token() == Token.ENABLE) { 3726 lexer.nextToken(); 3727 if (lexer.token() == Token.CONSTRAINT) { 3728 lexer.nextToken(); 3729 SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint(); 3730 item.setConstraintName(this.exprParser.name()); 3731 stmt.addItem(item); 3732 } else { 3733 acceptIdentifier("KEYS"); 3734 SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys(); 3735 stmt.addItem(item); 3736 } 3737 } else if (lexer.identifierEquals("RENAME")) { 3738 lexer.nextToken(); 3739 3740 if (lexer.token() == Token.INDEX) { 3741 lexer.nextToken(); 3742 SQLName name = this.exprParser.name(); 3743 accept(Token.TO); 3744 SQLName to = this.exprParser.name(); 3745 SQLAlterTableRenameIndex item = new SQLAlterTableRenameIndex(name, to); 3746 stmt.addItem(item); 3747 continue; 3748 } 3749 3750 if (lexer.token() == Token.TO || lexer.token() == Token.AS) { 3751 lexer.nextToken(); 3752 } 3753 3754 if (stmt.getItems().size() > 0) { 3755 SQLAlterTableRename item = new SQLAlterTableRename(); 3756 SQLName to = this.exprParser.name(); 3757 item.setTo(to); 3758 stmt.addItem(item); 3759 } else { 3760 MySqlRenameTableStatement renameStmt = new MySqlRenameTableStatement(); 3761 MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item(); 3762 item.setName(cast(SQLName) stmt.getTableSource().getExpr()); 3763 item.setTo(this.exprParser.name()); 3764 // SQLAlterTableRename 3765 renameStmt.addItem(item); 3766 3767 return renameStmt; 3768 } 3769 } else if (lexer.token() == Token.ORDER) { 3770 throw new ParserException("TODO " ~ lexer.info()); 3771 } else if (lexer.identifierEquals("CONVERT")) { 3772 lexer.nextToken(); 3773 accept(Token.TO); 3774 acceptIdentifier("CHARACTER"); 3775 accept(Token.SET); 3776 3777 SQLAlterTableConvertCharSet item = new SQLAlterTableConvertCharSet(); 3778 SQLExpr charset = this.exprParser.primary(); 3779 item.setCharset(charset); 3780 3781 if (lexer.identifierEquals("COLLATE")) { 3782 lexer.nextToken(); 3783 SQLExpr collate = this.exprParser.primary(); 3784 item.setCollate(collate); 3785 } 3786 3787 stmt.addItem(item); 3788 } else if (lexer.token() == Token.DEFAULT) { 3789 lexer.nextToken(); 3790 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 3791 SQLAlterCharacter item = alterTableCharacter(); 3792 stmt.addItem(item); 3793 } else { 3794 throw new ParserException("TODO " ~ lexer.info()); 3795 } 3796 } else if (lexer.identifierEquals("DISCARD")) { 3797 lexer.nextToken(); 3798 3799 if (lexer.token() == Token.PARTITION) { 3800 lexer.nextToken(); 3801 SQLAlterTableDiscardPartition item = new SQLAlterTableDiscardPartition(); 3802 3803 if (lexer.token() == Token.ALL) { 3804 lexer.nextToken(); 3805 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3806 } else { 3807 this.exprParser.names(item.getPartitions(), item); 3808 } 3809 3810 if (lexer.token() == Token.TABLESPACE) { 3811 lexer.nextToken(); 3812 item.setTablespace(true); 3813 } 3814 3815 stmt.addItem(item); 3816 } else { 3817 accept(Token.TABLESPACE); 3818 MySqlAlterTableDiscardTablespace item = new MySqlAlterTableDiscardTablespace(); 3819 stmt.addItem(item); 3820 } 3821 } else if (lexer.token() == Token.CHECK) { 3822 lexer.nextToken(); 3823 accept(Token.PARTITION); 3824 3825 SQLAlterTableCheckPartition item = new SQLAlterTableCheckPartition(); 3826 3827 if (lexer.token() == Token.ALL) { 3828 lexer.nextToken(); 3829 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3830 } else { 3831 this.exprParser.names(item.getPartitions(), item); 3832 } 3833 3834 stmt.addItem(item); 3835 3836 } else if (lexer.identifierEquals("IMPORT")) { 3837 lexer.nextToken(); 3838 3839 if (lexer.token() == Token.PARTITION) { 3840 lexer.nextToken(); 3841 SQLAlterTableImportPartition item = new SQLAlterTableImportPartition(); 3842 3843 if (lexer.token() == Token.ALL) { 3844 lexer.nextToken(); 3845 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3846 } else { 3847 this.exprParser.names(item.getPartitions(), item); 3848 } 3849 3850 stmt.addItem(item); 3851 } else { 3852 accept(Token.TABLESPACE); 3853 MySqlAlterTableImportTablespace item = new MySqlAlterTableImportTablespace(); 3854 stmt.addItem(item); 3855 } 3856 } else if (lexer.token() == Token.ANALYZE) { 3857 lexer.nextToken(); 3858 accept(Token.PARTITION); 3859 3860 SQLAlterTableAnalyzePartition item = new SQLAlterTableAnalyzePartition(); 3861 3862 if (lexer.token() == Token.ALL) { 3863 lexer.nextToken(); 3864 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3865 } else { 3866 this.exprParser.names(item.getPartitions(), item); 3867 } 3868 stmt.addItem(item); 3869 } else if (lexer.identifierEquals("FORCE")) { 3870 throw new ParserException("TODO " ~ lexer.info()); 3871 } else if (lexer.identifierEquals("COALESCE")) { 3872 lexer.nextToken(); 3873 accept(Token.PARTITION); 3874 3875 SQLAlterTableCoalescePartition item = new SQLAlterTableCoalescePartition(); 3876 SQLIntegerExpr countExpr = this.exprParser.integerExpr(); 3877 item.setCount(countExpr); 3878 stmt.addItem(item); 3879 } else if (lexer.identifierEquals("REORGANIZE")) { 3880 lexer.nextToken(); 3881 accept(Token.PARTITION); 3882 3883 SQLAlterTableReOrganizePartition item = new SQLAlterTableReOrganizePartition(); 3884 3885 this.exprParser.names(item.getNames(), item); 3886 3887 accept(Token.INTO); 3888 accept(Token.LPAREN); 3889 for (; ; ) { 3890 SQLPartition partition = this.getExprParser().parsePartition(); 3891 3892 item.addPartition(partition); 3893 3894 if (lexer.token() == Token.COMMA) { 3895 lexer.nextToken(); 3896 continue; 3897 } else { 3898 break; 3899 } 3900 } 3901 accept(Token.RPAREN); 3902 stmt.addItem(item); 3903 } else if (lexer.identifierEquals("EXCHANGE")) { 3904 lexer.nextToken(); 3905 accept(Token.PARTITION); 3906 3907 SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition(); 3908 3909 SQLName partition = this.exprParser.name(); 3910 item.setPartition(partition); 3911 3912 accept(Token.WITH); 3913 accept(Token.TABLE); 3914 SQLName table = this.exprParser.name(); 3915 item.setTable(table); 3916 3917 if (lexer.token() == Token.WITH) { 3918 lexer.nextToken(); 3919 acceptIdentifier("VALIDATION"); 3920 item.setValidation(true); 3921 } else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) { 3922 lexer.nextToken(); 3923 acceptIdentifier("VALIDATION"); 3924 item.setValidation(false); 3925 } 3926 3927 3928 stmt.addItem(item); 3929 } else if (lexer.token() == Token.OPTIMIZE) { 3930 lexer.nextToken(); 3931 3932 accept(Token.PARTITION); 3933 3934 SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition(); 3935 3936 if (lexer.token() == Token.ALL) { 3937 lexer.nextToken(); 3938 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3939 } else { 3940 this.exprParser.names(item.getPartitions(), item); 3941 } 3942 3943 stmt.addItem(item); 3944 } else if (lexer.identifierEquals("REBUILD")) { 3945 lexer.nextToken(); 3946 3947 accept(Token.PARTITION); 3948 3949 SQLAlterTableRebuildPartition item = new SQLAlterTableRebuildPartition(); 3950 3951 if (lexer.token() == Token.ALL) { 3952 lexer.nextToken(); 3953 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3954 } else { 3955 this.exprParser.names(item.getPartitions(), item); 3956 } 3957 3958 stmt.addItem(item); 3959 } else if (lexer.identifierEquals("REPAIR")) { 3960 lexer.nextToken(); 3961 3962 accept(Token.PARTITION); 3963 3964 SQLAlterTableRepairPartition item = new SQLAlterTableRepairPartition(); 3965 3966 if (lexer.token() == Token.ALL) { 3967 lexer.nextToken(); 3968 item.getPartitions().add(new SQLIdentifierExpr("ALL")); 3969 } else { 3970 this.exprParser.names(item.getPartitions(), item); 3971 } 3972 3973 stmt.addItem(item); 3974 } else if (lexer.identifierEquals("REMOVE")) { 3975 lexer.nextToken(); 3976 acceptIdentifier("PARTITIONING"); 3977 stmt.setRemovePatiting(true); 3978 } else if (lexer.identifierEquals("UPGRADE")) { 3979 lexer.nextToken(); 3980 acceptIdentifier("PARTITIONING"); 3981 stmt.setUpgradePatiting(true); 3982 } else if (lexer.identifierEquals("ALGORITHM")) { 3983 lexer.nextToken(); 3984 accept(Token.EQ); 3985 stmt.addItem(new MySqlAlterTableOption("ALGORITHM", lexer.stringVal())); 3986 lexer.nextToken(); 3987 } else if (lexer.identifierEquals(ENGINE)) { 3988 lexer.nextToken(); 3989 accept(Token.EQ); 3990 stmt.addItem(new MySqlAlterTableOption(ENGINE, lexer.stringVal())); 3991 lexer.nextToken(); 3992 } else if (lexer.identifierEquals(AUTO_INCREMENT)) { 3993 lexer.nextToken(); 3994 accept(Token.EQ); 3995 stmt.addItem(new MySqlAlterTableOption(AUTO_INCREMENT, new SQLIntegerExpr(lexer.integerValue()))); 3996 lexer.nextToken(); 3997 } else if (lexer.identifierEquals(COLLATE2)) { 3998 lexer.nextToken(); 3999 accept(Token.EQ); 4000 stmt.addItem(new MySqlAlterTableOption(COLLATE2, lexer.stringVal())); 4001 lexer.nextToken(); 4002 } else if (lexer.identifierEquals("PACK_KEYS")) { 4003 lexer.nextToken(); 4004 accept(Token.EQ); 4005 if (lexer.identifierEquals("PACK")) { 4006 lexer.nextToken(); 4007 accept(Token.ALL); 4008 stmt.addItem(new MySqlAlterTableOption("PACK_KEYS", "PACK ALL")); 4009 } else { 4010 stmt.addItem(new MySqlAlterTableOption("PACK_KEYS", lexer.stringVal())); 4011 lexer.nextToken(); 4012 } 4013 } else if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 4014 SQLAlterCharacter item = alterTableCharacter(); 4015 stmt.addItem(item); 4016 } else if (lexer.token() == Token.COMMENT) { 4017 lexer.nextToken(); 4018 if (lexer.token() == Token.EQ) { 4019 accept(Token.EQ); 4020 } 4021 stmt.addItem(new MySqlAlterTableOption("COMMENT", '\'' ~ lexer.stringVal() ~ '\'')); 4022 lexer.nextToken(); 4023 } else if (lexer.token() == Token.UNION) { 4024 lexer.nextToken(); 4025 if (lexer.token() == Token.EQ) { 4026 lexer.nextToken(); 4027 } 4028 4029 accept(Token.LPAREN); 4030 SQLTableSource tableSrc = this.createSQLSelectParser().parseTableSource(); 4031 stmt.getTableOptions().put("UNION", tableSrc); 4032 accept(Token.RPAREN); 4033 } else if (lexer.identifierEquals("ROW_FORMAT")) { 4034 lexer.nextToken(); 4035 if (lexer.token() == Token.EQ) { 4036 lexer.nextToken(); 4037 } 4038 4039 if (lexer.token() == Token.DEFAULT || lexer.token() == Token.IDENTIFIER) { 4040 SQLIdentifierExpr rowFormat = new SQLIdentifierExpr(lexer.stringVal()); 4041 lexer.nextToken(); 4042 stmt.getTableOptions().put("ROW_FORMAT", rowFormat); 4043 } else { 4044 throw new ParserException("illegal syntax. " ~ lexer.info()); 4045 } 4046 4047 } else { 4048 break; 4049 } 4050 4051 if (lexer.token() == Token.COMMA) { 4052 lexer.nextToken(); 4053 continue; 4054 } else { 4055 break; 4056 } 4057 } 4058 4059 return stmt; 4060 } 4061 4062 private SQLAlterCharacter alterTableCharacter() { 4063 lexer.nextToken(); 4064 accept(Token.SET); 4065 accept(Token.EQ); 4066 SQLAlterCharacter item = new SQLAlterCharacter(); 4067 item.setCharacterSet(this.exprParser.primary()); 4068 if (lexer.token() == Token.COMMA) { 4069 lexer.nextToken(); 4070 acceptIdentifier(COLLATE2); 4071 accept(Token.EQ); 4072 item.setCollate(this.exprParser.primary()); 4073 } 4074 return item; 4075 } 4076 4077 protected void parseAlterTableAddColumn(SQLAlterTableStatement stmt) { 4078 bool parenFlag = false; 4079 if (lexer.token() == Token.LPAREN) { 4080 lexer.nextToken(); 4081 parenFlag = true; 4082 } 4083 4084 SQLAlterTableAddColumn item = new SQLAlterTableAddColumn(); 4085 for (; ; ) { 4086 4087 SQLColumnDefinition columnDef = this.exprParser.parseColumn(); 4088 item.addColumn(columnDef); 4089 if (lexer.identifierEquals("AFTER")) { 4090 lexer.nextToken(); 4091 item.setAfterColumn(this.exprParser.name()); 4092 } else if (lexer.identifierEquals("FIRST")) { 4093 lexer.nextToken(); 4094 if (lexer.token() == Token.IDENTIFIER) { 4095 item.setFirstColumn(this.exprParser.name()); 4096 } else { 4097 item.setFirst(true); 4098 } 4099 } 4100 4101 if (parenFlag && lexer.token() == Token.COMMA) { 4102 lexer.nextToken(); 4103 continue; 4104 } 4105 4106 break; 4107 } 4108 4109 stmt.addItem(item); 4110 4111 if (parenFlag) { 4112 accept(Token.RPAREN); 4113 } 4114 } 4115 4116 override public void parseAlterDrop(SQLAlterTableStatement stmt) { 4117 lexer.nextToken(); 4118 if (lexer.token() == Token.INDEX) { 4119 lexer.nextToken(); 4120 SQLName indexName = this.exprParser.name(); 4121 SQLAlterTableDropIndex item = new SQLAlterTableDropIndex(); 4122 item.setIndexName(indexName); 4123 stmt.addItem(item); 4124 } else if (lexer.token() == Token.FOREIGN) { 4125 lexer.nextToken(); 4126 accept(Token.KEY); 4127 SQLName indexName = this.exprParser.name(); 4128 SQLAlterTableDropForeignKey item = new SQLAlterTableDropForeignKey(); 4129 item.setIndexName(indexName); 4130 stmt.addItem(item); 4131 } else if (lexer.token() == Token.KEY) { 4132 lexer.nextToken(); 4133 SQLName keyName = this.exprParser.name(); 4134 SQLAlterTableDropKey item = new SQLAlterTableDropKey(); 4135 item.setKeyName(keyName); 4136 stmt.addItem(item); 4137 } else if (lexer.token() == Token.PRIMARY) { 4138 lexer.nextToken(); 4139 accept(Token.KEY); 4140 SQLAlterTableDropPrimaryKey item = new SQLAlterTableDropPrimaryKey(); 4141 stmt.addItem(item); 4142 } else if (lexer.token() == Token.CONSTRAINT) { 4143 lexer.nextToken(); 4144 SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint(); 4145 item.setConstraintName(this.exprParser.name()); 4146 stmt.addItem(item); 4147 } else if (lexer.token() == Token.COLUMN) { 4148 lexer.nextToken(); 4149 SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); 4150 4151 SQLName name = exprParser.name(); 4152 name.setParent(item); 4153 item.addColumn(name); 4154 4155 while (lexer.token() == Token.COMMA) { 4156 char markChar = lexer.current(); 4157 int markBp = lexer.bp(); 4158 4159 lexer.nextToken(); 4160 if (lexer.identifierEquals("CHANGE")) { 4161 lexer.reset(markBp, markChar, Token.COMMA); 4162 break; 4163 } 4164 4165 if (lexer.token() == Token.IDENTIFIER) { 4166 if ("ADD".equalsIgnoreCase(lexer.stringVal())) { 4167 lexer.reset(markBp, markChar, Token.COMMA); 4168 break; 4169 } 4170 name = exprParser.name(); 4171 name.setParent(item); 4172 } else { 4173 lexer.reset(markBp, markChar, Token.COMMA); 4174 break; 4175 } 4176 } 4177 4178 stmt.addItem(item); 4179 } else if (lexer.token() == Token.PARTITION) { 4180 SQLAlterTableDropPartition dropPartition = parseAlterTableDropPartition(false); 4181 stmt.addItem(dropPartition); 4182 } else if (lexer.token() == Token.IDENTIFIER) { 4183 SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); 4184 4185 SQLName name = this.exprParser.name(); 4186 item.addColumn(name); 4187 stmt.addItem(item); 4188 4189 if (lexer.token() == Token.COMMA) { 4190 lexer.nextToken(); 4191 } 4192 4193 if (lexer.token() == Token.DROP) { 4194 parseAlterDrop(stmt); 4195 } 4196 } else { 4197 super.parseAlterDrop(stmt); 4198 } 4199 } 4200 4201 override public SQLStatement parseRename() { 4202 MySqlRenameTableStatement stmt = new MySqlRenameTableStatement(); 4203 4204 acceptIdentifier("RENAME"); 4205 4206 accept(Token.TABLE); 4207 4208 for (; ; ) { 4209 MySqlRenameTableStatement.Item item = new MySqlRenameTableStatement.Item(); 4210 item.setName(this.exprParser.name()); 4211 accept(Token.TO); 4212 item.setTo(this.exprParser.name()); 4213 4214 stmt.addItem(item); 4215 4216 if (lexer.token() == Token.COMMA) { 4217 lexer.nextToken(); 4218 continue; 4219 } 4220 4221 break; 4222 } 4223 4224 return stmt; 4225 } 4226 4227 override public SQLStatement parseCreateDatabase() { 4228 if (lexer.token() == Token.CREATE) { 4229 lexer.nextToken(); 4230 } 4231 4232 if (lexer.token() == Token.SCHEMA) { 4233 lexer.nextToken(); 4234 } else { 4235 accept(Token.DATABASE); 4236 } 4237 4238 SQLCreateDatabaseStatement stmt = new SQLCreateDatabaseStatement(DBType.MYSQL.name); 4239 4240 if (lexer.token() == Token.IF) { 4241 lexer.nextToken(); 4242 accept(Token.NOT); 4243 accept(Token.EXISTS); 4244 stmt.setIfNotExists(true); 4245 } 4246 4247 stmt.setName(this.exprParser.name()); 4248 4249 if (lexer.token() == Token.DEFAULT) { 4250 lexer.nextToken(); 4251 } 4252 4253 if (lexer.token() == Token.HINT) { 4254 stmt.setHints(this.exprParser.parseHints()); 4255 } 4256 4257 if (lexer.token() == Token.DEFAULT) { 4258 lexer.nextToken(); 4259 } 4260 4261 for (;;) { 4262 if (lexer.identifierEquals("CHARACTER")) { 4263 lexer.nextToken(); 4264 accept(Token.SET); 4265 if (lexer.token() == Token.EQ) { 4266 lexer.nextToken(); 4267 } 4268 string charset = lexer.stringVal(); 4269 accept(Token.IDENTIFIER); 4270 stmt.setCharacterSet(charset); 4271 } else if (lexer.identifierEquals("CHARSET")) { 4272 lexer.nextToken(); 4273 if (lexer.token() == Token.EQ) { 4274 lexer.nextToken(); 4275 } 4276 string charset = lexer.stringVal(); 4277 accept(Token.IDENTIFIER); 4278 stmt.setCharacterSet(charset); 4279 } else if (lexer.token() == Token.DEFAULT) { 4280 lexer.nextToken(); 4281 } else if (lexer.identifierEquals("COLLATE")) { 4282 lexer.nextToken(); 4283 if (lexer.token() == Token.EQ) { 4284 lexer.nextToken(); 4285 } 4286 string collate = lexer.stringVal(); 4287 accept(Token.IDENTIFIER); 4288 stmt.setCollate(collate); 4289 } else { 4290 break; 4291 } 4292 4293 4294 4295 4296 } 4297 4298 return stmt; 4299 } 4300 4301 override protected void parseUpdateSet(SQLUpdateStatement update) { 4302 accept(Token.SET); 4303 4304 for (; ; ) { 4305 SQLUpdateSetItem item = this.exprParser.parseUpdateSetItem(); 4306 update.addItem(item); 4307 4308 if (lexer.token() != Token.COMMA) { 4309 break; 4310 } 4311 4312 lexer.nextToken(); 4313 } 4314 } 4315 4316 public SQLStatement parseAlterDatabase() { 4317 if (lexer.token() == Token.SCHEMA) { 4318 lexer.nextToken(); 4319 } else { 4320 accept(Token.DATABASE); 4321 } 4322 4323 SQLAlterDatabaseStatement stmt = new SQLAlterDatabaseStatement(dbType); 4324 4325 SQLName name = this.exprParser.name(); 4326 stmt.setName(name); 4327 4328 if (lexer.identifierEquals("UPGRADE")) { 4329 lexer.nextToken(); 4330 acceptIdentifier("DATA"); 4331 acceptIdentifier("DIRECTORY"); 4332 acceptIdentifier("NAME"); 4333 stmt.setUpgradeDataDirectoryName(true); 4334 } 4335 4336 if (lexer.token() == Token.DEFAULT) { 4337 lexer.nextToken(); 4338 if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 4339 SQLAlterCharacter item = alterTableCharacter(); 4340 stmt.setCharacter(item); 4341 } else { 4342 throw new ParserException("TODO " ~ lexer.info()); 4343 } 4344 } else if (lexer.identifierEquals(FnvHash.Constants.CHARACTER)) { 4345 SQLAlterCharacter item = alterTableCharacter(); 4346 stmt.setCharacter(item); 4347 } 4348 4349 return stmt; 4350 } 4351 4352 public MySqlAlterUserStatement parseAlterUser() { 4353 accept(Token.USER); 4354 4355 MySqlAlterUserStatement stmt = new MySqlAlterUserStatement(); 4356 for (; ; ) { 4357 SQLExpr user = this.exprParser.expr(); 4358 acceptIdentifier("PASSWORD"); 4359 acceptIdentifier("EXPIRE"); 4360 stmt.addUser(user); 4361 4362 if (lexer.token() == Token.COMMA) { 4363 lexer.nextToken(); 4364 continue; 4365 } 4366 4367 break; 4368 } 4369 return stmt; 4370 } 4371 4372 override public MySqlExprParser getExprParser() { 4373 return cast(MySqlExprParser) exprParser; 4374 } 4375 4376 4377 override public SQLCreateFunctionStatement parseCreateFunction() { 4378 SQLCreateFunctionStatement stmt = new SQLCreateFunctionStatement(); 4379 stmt.setDbType(dbType); 4380 4381 if (lexer.token() == Token.CREATE) { 4382 lexer.nextToken(); 4383 4384 if (lexer.token() == Token.OR) { 4385 lexer.nextToken(); 4386 accept(Token.REPLACE); 4387 stmt.setOrReplace(true); 4388 } 4389 } 4390 4391 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 4392 lexer.nextToken(); 4393 accept(Token.EQ); 4394 SQLName definer = this.getExprParser().userName(); 4395 stmt.setDefiner(definer); 4396 } 4397 4398 accept(Token.FUNCTION); 4399 4400 stmt.setName(this.exprParser.name()); 4401 4402 if (lexer.token() == Token.LPAREN) {// match "(" 4403 lexer.nextToken(); 4404 parserParameters(stmt.getParameters(), stmt); 4405 accept(Token.RPAREN);// match ")" 4406 } 4407 4408 acceptIdentifier("RETURNS"); 4409 SQLDataType dataType = this.exprParser.parseDataType(); 4410 stmt.setReturnDataType(dataType); 4411 4412 for (;;) { 4413 if (lexer.identifierEquals("DETERMINISTIC")) { 4414 lexer.nextToken(); 4415 stmt.setDeterministic(true); 4416 continue; 4417 } 4418 4419 break; 4420 } 4421 4422 SQLStatement block; 4423 if (lexer.token() == Token.BEGIN) { 4424 block = this.parseBlock(); 4425 } else { 4426 block = this.parseStatement(); 4427 } 4428 4429 stmt.setBlock(block); 4430 4431 return stmt; 4432 } 4433 /** 4434 * parse create procedure statement 4435 */ 4436 override public SQLCreateProcedureStatement parseCreateProcedure() { 4437 /** 4438 * CREATE OR REPALCE PROCEDURE SP_NAME(parameter_list) BEGIN block_statement END 4439 */ 4440 SQLCreateProcedureStatement stmt = new SQLCreateProcedureStatement(); 4441 stmt.setDbType(dbType); 4442 4443 if (lexer.token() == Token.CREATE) { 4444 lexer.nextToken(); 4445 4446 if (lexer.token() == Token.OR) { 4447 lexer.nextToken(); 4448 accept(Token.REPLACE); 4449 stmt.setOrReplace(true); 4450 } 4451 } 4452 4453 if (lexer.identifierEquals(FnvHash.Constants.DEFINER)) { 4454 lexer.nextToken(); 4455 accept(Token.EQ); 4456 SQLName definer = this.getExprParser().userName(); 4457 stmt.setDefiner(definer); 4458 } 4459 4460 accept(Token.PROCEDURE); 4461 4462 stmt.setName(this.exprParser.name()); 4463 4464 if (lexer.token() == Token.LPAREN) {// match "(" 4465 lexer.nextToken(); 4466 parserParameters(stmt.getParameters(), stmt); 4467 accept(Token.RPAREN);// match ")" 4468 } 4469 4470 for (;;) { 4471 if (lexer.identifierEquals(FnvHash.Constants.DETERMINISTIC)) { 4472 lexer.nextToken(); 4473 stmt.setDeterministic(true); 4474 continue; 4475 } 4476 if (lexer.identifierEquals(FnvHash.Constants.CONTAINS) || lexer.token() == Token.CONTAINS) { 4477 lexer.nextToken(); 4478 acceptIdentifier("SQL"); 4479 stmt.setContainsSql(true); 4480 continue; 4481 } 4482 4483 if (lexer.identifierEquals(FnvHash.Constants.SQL)) { 4484 lexer.nextToken(); 4485 acceptIdentifier("SECURITY"); 4486 SQLName authid = this.exprParser.name(); 4487 stmt.setAuthid(authid); 4488 } 4489 4490 break; 4491 } 4492 4493 SQLStatement block; 4494 if (lexer.token() == Token.BEGIN) { 4495 block = this.parseBlock(); 4496 } else { 4497 block = this.parseStatement(); 4498 } 4499 4500 stmt.setBlock(block); 4501 4502 return stmt; 4503 } 4504 4505 /** 4506 * parse create procedure parameters 4507 * 4508 * @param parameters 4509 */ 4510 private void parserParameters(List!(SQLParameter) parameters, SQLObject parent) { 4511 if (lexer.token() == Token.RPAREN) { 4512 return; 4513 } 4514 4515 for (; ; ) { 4516 SQLParameter parameter = new SQLParameter(); 4517 4518 if (lexer.token() == Token.CURSOR) { 4519 lexer.nextToken(); 4520 4521 parameter.setName(this.exprParser.name()); 4522 4523 accept(Token.IS); 4524 SQLSelect select = this.createSQLSelectParser().select(); 4525 4526 SQLDataTypeImpl dataType = new SQLDataTypeImpl(); 4527 dataType.setName("CURSOR"); 4528 parameter.setDataType(dataType); 4529 4530 parameter.setDefaultValue(new SQLQueryExpr(select)); 4531 4532 } else if (lexer.token() == Token.IN || lexer.token() == Token.OUT || lexer.token() == Token.INOUT) { 4533 4534 if (lexer.token() == Token.IN) { 4535 parameter.setParamType(SQLParameter.ParameterType.IN); 4536 } else if (lexer.token() == Token.OUT) { 4537 parameter.setParamType(SQLParameter.ParameterType.OUT); 4538 } else if (lexer.token() == Token.INOUT) { 4539 parameter.setParamType(SQLParameter.ParameterType.INOUT); 4540 } 4541 lexer.nextToken(); 4542 4543 parameter.setName(this.exprParser.name()); 4544 4545 parameter.setDataType(this.exprParser.parseDataType()); 4546 } else { 4547 parameter.setParamType(SQLParameter.ParameterType.DEFAULT);// default parameter type is in 4548 parameter.setName(this.exprParser.name()); 4549 parameter.setDataType(this.exprParser.parseDataType()); 4550 4551 if (lexer.token() == Token.COLONEQ) { 4552 lexer.nextToken(); 4553 parameter.setDefaultValue(this.exprParser.expr()); 4554 } 4555 } 4556 4557 parameters.add(parameter); 4558 if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) { 4559 lexer.nextToken(); 4560 } 4561 4562 if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) { 4563 continue; 4564 } 4565 4566 break; 4567 } 4568 } 4569 4570 /** 4571 * parse procedure statement block 4572 * 4573 * @param statementList 4574 */ 4575 private void parseProcedureStatementList(List!(SQLStatement) statementList) { 4576 parseProcedureStatementList(statementList, -1); 4577 } 4578 4579 /** 4580 * parse procedure statement block 4581 */ 4582 private void parseProcedureStatementList(List!(SQLStatement) statementList, int max) { 4583 4584 for (; ; ) { 4585 if (max != -1) { 4586 if (statementList.size() >= max) { 4587 return; 4588 } 4589 } 4590 4591 if (lexer.token() == Token.EOF) { 4592 return; 4593 } 4594 if (lexer.token() == Token.END) { 4595 return; 4596 } 4597 if (lexer.token() == Token.ELSE) { 4598 return; 4599 } 4600 if (lexer.token() == (Token.SEMI)) { 4601 lexer.nextToken(); 4602 continue; 4603 } 4604 if (lexer.token() == Token.WHEN) { 4605 return; 4606 } 4607 if (lexer.token() == Token.UNTIL) { 4608 return; 4609 } 4610 // select into 4611 if (lexer.token() == (Token.SELECT)) { 4612 statementList.add(this.parseSelectInto()); 4613 continue; 4614 } 4615 4616 // update 4617 if (lexer.token() == (Token.UPDATE)) { 4618 statementList.add(parseUpdateStatement()); 4619 continue; 4620 } 4621 4622 // create 4623 if (lexer.token() == (Token.CREATE)) { 4624 statementList.add(parseCreate()); 4625 continue; 4626 } 4627 4628 // insert 4629 if (lexer.token() == Token.INSERT) { 4630 SQLStatement stmt = parseInsert(); 4631 statementList.add(stmt); 4632 continue; 4633 } 4634 4635 // delete 4636 if (lexer.token() == (Token.DELETE)) { 4637 statementList.add(parseDeleteStatement()); 4638 continue; 4639 } 4640 4641 // call 4642 if (lexer.token() == Token.LBRACE || lexer.identifierEquals("CALL")) { 4643 statementList.add(this.parseCall()); 4644 continue; 4645 } 4646 4647 // begin 4648 if (lexer.token() == Token.BEGIN) { 4649 statementList.add(this.parseBlock()); 4650 continue; 4651 } 4652 4653 if (lexer.token() == Token.VARIANT) { 4654 SQLExpr variant = this.exprParser.primary(); 4655 if (cast(SQLBinaryOpExpr)(variant) !is null) { 4656 SQLBinaryOpExpr binaryOpExpr = cast(SQLBinaryOpExpr) variant; 4657 if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) { 4658 SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight(), 4659 getDbType()); 4660 statementList.add(stmt); 4661 continue; 4662 } 4663 } 4664 accept(Token.COLONEQ); 4665 SQLExpr value = this.exprParser.expr(); 4666 4667 SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType()); 4668 statementList.add(stmt); 4669 continue; 4670 } 4671 4672 // select 4673 if (lexer.token() == Token.LPAREN) { 4674 char ch = lexer.current(); 4675 int bp = lexer.bp(); 4676 lexer.nextToken(); 4677 4678 if (lexer.token() == Token.SELECT) { 4679 lexer.reset(bp, ch, Token.LPAREN); 4680 statementList.add(this.parseSelect()); 4681 continue; 4682 } else { 4683 throw new ParserException("TODO. " ~ lexer.info()); 4684 } 4685 } 4686 // assign statement 4687 if (lexer.token() == Token.SET) { 4688 statementList.add(this.parseAssign()); 4689 continue; 4690 } 4691 4692 // while statement 4693 if (lexer.token() == Token.WHILE) { 4694 SQLStatement stmt = this.parseWhile(); 4695 statementList.add(stmt); 4696 continue; 4697 } 4698 4699 // loop statement 4700 if (lexer.token() == Token.LOOP) { 4701 statementList.add(this.parseLoop()); 4702 continue; 4703 } 4704 4705 // if statement 4706 if (lexer.token() == Token.IF) { 4707 statementList.add(this.parseIf()); 4708 continue; 4709 } 4710 4711 // case statement 4712 if (lexer.token() == Token.CASE) { 4713 statementList.add(this.parseCase()); 4714 continue; 4715 } 4716 4717 // declare statement 4718 if (lexer.token() == Token.DECLARE) { 4719 SQLStatement stmt = this.parseDeclare(); 4720 statementList.add(stmt); 4721 continue; 4722 } 4723 4724 // leave statement 4725 if (lexer.token() == Token.LEAVE) { 4726 statementList.add(this.parseLeave()); 4727 continue; 4728 } 4729 4730 // iterate statement 4731 if (lexer.token() == Token.ITERATE) { 4732 statementList.add(this.parseIterate()); 4733 continue; 4734 } 4735 4736 // repeat statement 4737 if (lexer.token() == Token.REPEAT) { 4738 statementList.add(this.parseRepeat()); 4739 continue; 4740 } 4741 4742 // open cursor 4743 if (lexer.token() == Token.OPEN) { 4744 statementList.add(this.parseOpen()); 4745 continue; 4746 } 4747 4748 // close cursor 4749 if (lexer.token() == Token.CLOSE) { 4750 statementList.add(this.parseClose()); 4751 continue; 4752 } 4753 4754 // fetch cursor into 4755 if (lexer.token() == Token.FETCH) { 4756 statementList.add(this.parseFetch()); 4757 continue; 4758 } 4759 4760 if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { 4761 statementList.add(this.parseChecksum()); 4762 continue; 4763 } 4764 4765 if (lexer.token() == Token.IDENTIFIER) { 4766 string label = lexer.stringVal(); 4767 char ch = lexer.current(); 4768 int bp = lexer.bp(); 4769 lexer.nextToken(); 4770 if (lexer.token() == Token.VARIANT && lexer.stringVal() == ":") { 4771 lexer.nextToken(); 4772 if (lexer.token() == Token.LOOP) { 4773 // parse loop statement 4774 statementList.add(this.parseLoop(label)); 4775 } else if (lexer.token() == Token.WHILE) { 4776 // parse while statement with label 4777 statementList.add(this.parseWhile(label)); 4778 } else if (lexer.token() == Token.BEGIN) { 4779 // parse begin-end statement with label 4780 statementList.add(this.parseBlock(label)); 4781 } else if (lexer.token() == Token.REPEAT) { 4782 // parse repeat statement with label 4783 statementList.add(this.parseRepeat(label)); 4784 } 4785 continue; 4786 } else { 4787 lexer.reset(bp, ch, Token.IDENTIFIER); 4788 } 4789 4790 } 4791 throw new ParserException("TODO, " ~ lexer.info()); 4792 } 4793 4794 } 4795 4796 4797 public MySqlChecksumTableStatement parseChecksum() { 4798 MySqlChecksumTableStatement stmt = new MySqlChecksumTableStatement(); 4799 if (lexer.identifierEquals(FnvHash.Constants.CHECKSUM)) { 4800 lexer.nextToken(); 4801 } else { 4802 throw new ParserException("TODO " ~ lexer.info()); 4803 } 4804 4805 for (;;) { 4806 SQLExprTableSource table = cast(SQLExprTableSource) this.createSQLSelectParser().parseTableSource(); 4807 stmt.addTable(table); 4808 4809 if (lexer.token() == Token.COMMA) { 4810 lexer.nextToken(); 4811 continue; 4812 } 4813 4814 break; 4815 } 4816 4817 return stmt; 4818 } 4819 4820 /** 4821 * parse if statement 4822 * 4823 * @return MySqlIfStatement 4824 */ 4825 override public SQLIfStatement parseIf() { 4826 accept(Token.IF); 4827 4828 SQLIfStatement stmt = new SQLIfStatement(); 4829 4830 stmt.setCondition(this.exprParser.expr()); 4831 4832 accept(Token.THEN); 4833 4834 this.parseStatementList(stmt.getStatements(), -1, stmt); 4835 4836 while (lexer.token() == Token.ELSE) { 4837 lexer.nextToken(); 4838 4839 if (lexer.token() == Token.IF) { 4840 lexer.nextToken(); 4841 4842 SQLIfStatement.ElseIf elseIf = new SQLIfStatement.ElseIf(); 4843 4844 elseIf.setCondition(this.exprParser.expr()); 4845 elseIf.setParent(stmt); 4846 4847 accept(Token.THEN); 4848 this.parseStatementList(elseIf.getStatements(), -1, elseIf); 4849 4850 4851 stmt.getElseIfList().add(elseIf); 4852 } else { 4853 SQLIfStatement.Else elseItem = new SQLIfStatement.Else(); 4854 this.parseStatementList(elseItem.getStatements(), -1, elseItem); 4855 stmt.setElseItem(elseItem); 4856 break; 4857 } 4858 } 4859 4860 accept(Token.END); 4861 accept(Token.IF); 4862 accept(Token.SEMI); 4863 stmt.setAfterSemi(true); 4864 4865 return stmt; 4866 } 4867 4868 /** 4869 * parse while statement 4870 * 4871 * @return MySqlWhileStatement 4872 */ 4873 override public SQLWhileStatement parseWhile() { 4874 accept(Token.WHILE); 4875 SQLWhileStatement stmt = new SQLWhileStatement(); 4876 4877 stmt.setCondition(this.exprParser.expr()); 4878 4879 accept(Token.DO); 4880 4881 this.parseStatementList(stmt.getStatements(), -1, stmt); 4882 4883 accept(Token.END); 4884 4885 accept(Token.WHILE); 4886 4887 accept(Token.SEMI); 4888 4889 return stmt; 4890 4891 } 4892 4893 /** 4894 * parse while statement with label 4895 * 4896 * @return MySqlWhileStatement 4897 */ 4898 public SQLWhileStatement parseWhile(string label) { 4899 accept(Token.WHILE); 4900 4901 SQLWhileStatement stmt = new SQLWhileStatement(); 4902 4903 stmt.setLabelName(label); 4904 4905 stmt.setCondition(this.exprParser.expr()); 4906 4907 accept(Token.DO); 4908 4909 this.parseStatementList(stmt.getStatements(), -1, stmt); 4910 4911 accept(Token.END); 4912 4913 accept(Token.WHILE); 4914 4915 acceptIdentifier(label); 4916 4917 accept(Token.SEMI); 4918 4919 return stmt; 4920 4921 } 4922 4923 /** 4924 * parse case statement 4925 * 4926 * @return MySqlCaseStatement 4927 */ 4928 override public MySqlCaseStatement parseCase() { 4929 MySqlCaseStatement stmt = new MySqlCaseStatement(); 4930 accept(Token.CASE); 4931 4932 if (lexer.token() == Token.WHEN)// grammar 1 4933 { 4934 while (lexer.token() == Token.WHEN) { 4935 4936 MySqlCaseStatement.MySqlWhenStatement when = new MySqlCaseStatement.MySqlWhenStatement(); 4937 // when expr 4938 when.setCondition(exprParser.expr()); 4939 4940 accept(Token.THEN); 4941 4942 // when block 4943 this.parseStatementList(when.getStatements(), -1, when); 4944 4945 stmt.addWhenStatement(when); 4946 } 4947 if (lexer.token() == Token.ELSE) { 4948 // parse else block 4949 SQLIfStatement.Else elseStmt = new SQLIfStatement.Else(); 4950 this.parseStatementList(elseStmt.getStatements(), -1, elseStmt); 4951 stmt.setElseItem(elseStmt); 4952 } 4953 } else// grammar 2 4954 { 4955 // case expr 4956 stmt.setCondition(exprParser.expr()); 4957 4958 while (lexer.token() == Token.WHEN) { 4959 accept(Token.WHEN); 4960 MySqlCaseStatement.MySqlWhenStatement when = new MySqlCaseStatement.MySqlWhenStatement(); 4961 // when expr 4962 when.setCondition(exprParser.expr()); 4963 4964 accept(Token.THEN); 4965 4966 // when block 4967 this.parseStatementList(when.getStatements(), -1, when); 4968 4969 stmt.addWhenStatement(when); 4970 } 4971 if (lexer.token() == Token.ELSE) { 4972 accept(Token.ELSE); 4973 // else block 4974 SQLIfStatement.Else elseStmt = new SQLIfStatement.Else(); 4975 this.parseStatementList(elseStmt.getStatements(), -1, elseStmt); 4976 stmt.setElseItem(elseStmt); 4977 } 4978 } 4979 accept(Token.END); 4980 accept(Token.CASE); 4981 accept(Token.SEMI); 4982 return stmt; 4983 4984 } 4985 4986 /** 4987 * parse declare statement 4988 */ 4989 override public SQLStatement parseDeclare() { 4990 char markChar = lexer.current(); 4991 int markBp = lexer.bp(); 4992 4993 lexer.nextToken(); 4994 4995 if (lexer.token() == Token.CONTINUE) { 4996 lexer.reset(markBp, markChar, Token.DECLARE); 4997 return this.parseDeclareHandler(); 4998 } 4999 5000 lexer.nextToken(); 5001 if (lexer.token() == Token.CURSOR) { 5002 lexer.reset(markBp, markChar, Token.DECLARE); 5003 return this.parseCursorDeclare(); 5004 } else if (lexer.identifierEquals("HANDLER")) { 5005 //DECLARE异常处理程序 [add by zhujun 2016-04-16] 5006 lexer.reset(markBp, markChar, Token.DECLARE); 5007 return this.parseDeclareHandler(); 5008 } else if (lexer.token() == Token.CONDITION) { 5009 //DECLARE异常 [add by zhujun 2016-04-17] 5010 lexer.reset(markBp, markChar, Token.DECLARE); 5011 return this.parseDeclareCondition(); 5012 } else { 5013 lexer.reset(markBp, markChar, Token.DECLARE); 5014 } 5015 5016 MySqlDeclareStatement stmt = new MySqlDeclareStatement(); 5017 accept(Token.DECLARE); 5018 // lexer.nextToken(); 5019 for (; ; ) { 5020 SQLDeclareItem item = new SQLDeclareItem(); 5021 item.setName(exprParser.name()); 5022 5023 stmt.addVar(item); 5024 if (lexer.token() == Token.COMMA) { 5025 lexer.nextToken(); 5026 stmt.setAfterSemi(true); 5027 continue; 5028 } else if (lexer.token() != Token.EOF) { 5029 // var type 5030 item.setDataType(exprParser.parseDataType()); 5031 5032 if (lexer.token() == Token.DEFAULT) { 5033 lexer.nextToken(); 5034 SQLExpr defaultValue = this.exprParser.primary(); 5035 item.setValue(defaultValue); 5036 } 5037 5038 break; 5039 } else { 5040 throw new ParserException("TODO. " ~ lexer.info()); 5041 } 5042 } 5043 return stmt; 5044 } 5045 5046 /** 5047 * parse assign statement 5048 */ 5049 public SQLSetStatement parseAssign() { 5050 accept(Token.SET); 5051 SQLSetStatement stmt = new SQLSetStatement(getDbType()); 5052 parseAssignItems(stmt.getItems(), stmt); 5053 return stmt; 5054 } 5055 5056 /** 5057 * parse select into 5058 */ 5059 public MySqlSelectIntoStatement parseSelectInto() { 5060 MySqlSelectIntoParser parse = new MySqlSelectIntoParser(this.exprParser); 5061 return parse.parseSelectInto(); 5062 } 5063 5064 /** 5065 * parse loop statement 5066 */ 5067 public SQLLoopStatement parseLoop() { 5068 SQLLoopStatement loopStmt = new SQLLoopStatement(); 5069 accept(Token.LOOP); 5070 this.parseStatementList(loopStmt.getStatements(), -1, loopStmt); 5071 accept(Token.END); 5072 accept(Token.LOOP); 5073 accept(Token.SEMI); 5074 loopStmt.setAfterSemi(true); 5075 return loopStmt; 5076 } 5077 5078 /** 5079 * parse loop statement with label 5080 */ 5081 public SQLLoopStatement parseLoop(string label) { 5082 SQLLoopStatement loopStmt = new SQLLoopStatement(); 5083 loopStmt.setLabelName(label); 5084 accept(Token.LOOP); 5085 this.parseStatementList(loopStmt.getStatements(), -1, loopStmt); 5086 accept(Token.END); 5087 accept(Token.LOOP); 5088 if (lexer.token() != Token.SEMI) { 5089 acceptIdentifier(label); 5090 } 5091 accept(Token.SEMI); 5092 loopStmt.setAfterSemi(true); 5093 return loopStmt; 5094 } 5095 5096 /** 5097 * parse loop statement with label 5098 */ 5099 public SQLBlockStatement parseBlock(string label) { 5100 SQLBlockStatement block = new SQLBlockStatement(); 5101 block.setLabelName(label); 5102 accept(Token.BEGIN); 5103 this.parseStatementList(block.getStatementList(), -1, block); 5104 accept(Token.END); 5105 acceptIdentifier(label); 5106 return block; 5107 } 5108 5109 /** 5110 * parse leave statement 5111 */ 5112 override public MySqlLeaveStatement parseLeave() { 5113 accept(Token.LEAVE); 5114 MySqlLeaveStatement leaveStmt = new MySqlLeaveStatement(); 5115 leaveStmt.setLabelName(exprParser.name().getSimpleName()); 5116 accept(Token.SEMI); 5117 return leaveStmt; 5118 } 5119 5120 /** 5121 * parse iterate statement 5122 */ 5123 public MySqlIterateStatement parseIterate() { 5124 accept(Token.ITERATE); 5125 MySqlIterateStatement iterateStmt = new MySqlIterateStatement(); 5126 iterateStmt.setLabelName(exprParser.name().getSimpleName()); 5127 accept(Token.SEMI); 5128 return iterateStmt; 5129 } 5130 5131 /** 5132 * parse repeat statement 5133 * 5134 * @return 5135 */ 5136 override public MySqlRepeatStatement parseRepeat() { 5137 MySqlRepeatStatement stmt = new MySqlRepeatStatement(); 5138 accept(Token.REPEAT); 5139 parseStatementList(stmt.getStatements(), -1, stmt); 5140 accept(Token.UNTIL); 5141 stmt.setCondition(exprParser.expr()); 5142 accept(Token.END); 5143 accept(Token.REPEAT); 5144 accept(Token.SEMI); 5145 stmt.setAfterSemi(true); 5146 return stmt; 5147 } 5148 5149 /** 5150 * parse repeat statement with label 5151 * 5152 * @param label 5153 * @return 5154 */ 5155 public MySqlRepeatStatement parseRepeat(string label) { 5156 MySqlRepeatStatement repeatStmt = new MySqlRepeatStatement(); 5157 repeatStmt.setLabelName(label); 5158 accept(Token.REPEAT); 5159 this.parseStatementList(repeatStmt.getStatements(), -1, repeatStmt); 5160 accept(Token.UNTIL); 5161 repeatStmt.setCondition(exprParser.expr()); 5162 accept(Token.END); 5163 accept(Token.REPEAT); 5164 acceptIdentifier(label); 5165 accept(Token.SEMI); 5166 return repeatStmt; 5167 } 5168 5169 /** 5170 * parse cursor declare statement 5171 * 5172 * @return 5173 */ 5174 public MySqlCursorDeclareStatement parseCursorDeclare() { 5175 MySqlCursorDeclareStatement stmt = new MySqlCursorDeclareStatement(); 5176 accept(Token.DECLARE); 5177 5178 stmt.setCursorName(exprParser.name()); 5179 5180 accept(Token.CURSOR); 5181 5182 accept(Token.FOR); 5183 5184 //SQLSelectStatement selelctStmt = cast(SQLSelectStatement) parseSelect(); 5185 SQLSelect select = this.createSQLSelectParser().select(); 5186 stmt.setSelect(select); 5187 5188 accept(Token.SEMI); 5189 5190 return stmt; 5191 } 5192 5193 /** 5194 * zhujun [455910092@qq.com] 5195 * parse spstatement 5196 * 5197 * @return 5198 */ 5199 public SQLStatement parseSpStatement() { 5200 5201 // update 5202 if (lexer.token() == (Token.UPDATE)) { 5203 return parseUpdateStatement(); 5204 } 5205 5206 // create 5207 if (lexer.token() == (Token.CREATE)) { 5208 return parseCreate(); 5209 } 5210 5211 // insert 5212 if (lexer.token() == Token.INSERT) { 5213 return parseInsert(); 5214 } 5215 5216 // delete 5217 if (lexer.token() == (Token.DELETE)) { 5218 return parseDeleteStatement(); 5219 } 5220 5221 // begin 5222 if (lexer.token() == Token.BEGIN) { 5223 return this.parseBlock(); 5224 } 5225 5226 // select 5227 if (lexer.token() == Token.LPAREN) { 5228 char ch = lexer.current(); 5229 int bp = lexer.bp(); 5230 lexer.nextToken(); 5231 5232 if (lexer.token() == Token.SELECT) { 5233 lexer.reset(bp, ch, Token.LPAREN); 5234 return this.parseSelect(); 5235 } else { 5236 throw new ParserException("TODO. " ~ lexer.info()); 5237 } 5238 } 5239 // assign statement 5240 if (lexer.token() == Token.SET) { 5241 return parseAssign(); 5242 } 5243 5244 throw new ParserException("error sp_statement. " ~ lexer.info()); 5245 } 5246 5247 /** 5248 * 定义异常处理程序 5249 * 5250 * @return 5251 */ 5252 public MySqlDeclareHandlerStatement parseDeclareHandler() { 5253 //DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement 5254 //handler_type 取值为 CONTINUE | EXIT | UNDO 5255 //condition_value 取值为 SQLWARNING | NOT FOUND | SQLEXCEPTION | SQLSTATE value(异常码 e.g 1062) 5256 5257 MySqlDeclareHandlerStatement stmt = new MySqlDeclareHandlerStatement(); 5258 accept(Token.DECLARE); 5259 //string handlerType = exprParser.name().getSimpleName(); 5260 if (lexer.token() == Token.CONTINUE) { 5261 stmt.setHandleType(MySqlHandlerType.CONTINUE); 5262 } else if (lexer.token() == Token.EXIT) { 5263 stmt.setHandleType(MySqlHandlerType.CONTINUE); 5264 } else if (lexer.token() == Token.UNDO) { 5265 stmt.setHandleType(MySqlHandlerType.CONTINUE); 5266 } else { 5267 throw new ParserException("unkown handle type. " ~ lexer.info()); 5268 } 5269 lexer.nextToken(); 5270 5271 acceptIdentifier("HANDLER"); 5272 5273 accept(Token.FOR); 5274 5275 for (; ; ) { 5276 string tokenName = lexer.stringVal(); 5277 ConditionValue condition = new ConditionValue(); 5278 5279 if (equalsIgnoreCase(tokenName, "NOT")) {//for 'NOT FOUND' 5280 lexer.nextToken(); 5281 acceptIdentifier("FOUND"); 5282 condition.setType(ConditionValue.ConditionType.SYSTEM); 5283 condition.setValue("NOT FOUND"); 5284 5285 } else if (equalsIgnoreCase(tokenName, "SQLSTATE")) { //for SQLSTATE (SQLSTATE '10001') 5286 condition.setType(ConditionValue.ConditionType.SQLSTATE); 5287 lexer.nextToken(); 5288 //condition.setValue(lexer.stringVal()); 5289 //lexer.nextToken(); 5290 condition.setValue((cast(Object)(exprParser.name())).toString()); 5291 } else if (lexer.identifierEquals("SQLEXCEPTION")) { //for SQLEXCEPTION 5292 condition.setType(ConditionValue.ConditionType.SYSTEM); 5293 condition.setValue(lexer.stringVal()); 5294 lexer.nextToken(); 5295 } else if (lexer.identifierEquals("SQLWARNING")) { //for SQLWARNING 5296 condition.setType(ConditionValue.ConditionType.SYSTEM); 5297 condition.setValue(lexer.stringVal()); 5298 lexer.nextToken(); 5299 } else { //for condition_name or mysql_error_code 5300 if (lexer.token() == Token.LITERAL_INT) { 5301 condition.setType(ConditionValue.ConditionType.MYSQL_ERROR_CODE); 5302 condition.setValue((cast(Object)(lexer.integerValue())).toString()); 5303 } else { 5304 condition.setType(ConditionValue.ConditionType.SELF); 5305 condition.setValue(tokenName); 5306 } 5307 lexer.nextToken(); 5308 } 5309 stmt.getConditionValues().add(condition); 5310 if (lexer.token() == Token.COMMA) { 5311 accept(Token.COMMA); 5312 continue; 5313 } else if (lexer.token() != Token.EOF) { 5314 break; 5315 } else { 5316 throw new ParserException("declare handle not eof"); 5317 } 5318 } 5319 5320 stmt.setSpStatement(parseSpStatement()); 5321 5322 if (!(cast(SQLBlockStatement)(stmt.getSpStatement()) !is null )) { 5323 accept(Token.SEMI); 5324 } 5325 5326 5327 return stmt; 5328 } 5329 5330 /** 5331 * zhujun [455910092@qq.com] 5332 * 2016-04-17 5333 * 定义条件 5334 * 5335 * @return 5336 */ 5337 public MySqlDeclareConditionStatement parseDeclareCondition() { 5338 /* 5339 DECLARE condition_name CONDITION FOR condition_value 5340 5341 condition_value: 5342 SQLSTATE [VALUE] sqlstate_value 5343 | mysql_error_code 5344 */ 5345 MySqlDeclareConditionStatement stmt = new MySqlDeclareConditionStatement(); 5346 accept(Token.DECLARE); 5347 5348 stmt.setConditionName((cast(Object)(exprParser.name())).toString()); 5349 5350 accept(Token.CONDITION); 5351 5352 accept(Token.FOR); 5353 5354 string tokenName = lexer.stringVal(); 5355 ConditionValue condition = new ConditionValue(); 5356 if (equalsIgnoreCase(tokenName, "SQLSTATE")) { //for SQLSTATE (SQLSTATE '10001') 5357 condition.setType(ConditionValue.ConditionType.SQLSTATE); 5358 lexer.nextToken(); 5359 condition.setValue((cast(Object)exprParser.name()).toString()); 5360 } else if (lexer.token() == Token.LITERAL_INT) { 5361 condition.setType(ConditionValue.ConditionType.MYSQL_ERROR_CODE); 5362 condition.setValue(lexer.integerValue().toString()); 5363 lexer.nextToken(); 5364 } else { 5365 throw new ParserException("declare condition grammer error. " ~ lexer.info()); 5366 } 5367 5368 stmt.setConditionValue(condition); 5369 5370 accept(Token.SEMI); 5371 5372 return stmt; 5373 } 5374 }