1 5 package org.h2.command; 6 7 import java.math.BigDecimal ; 8 import java.math.BigInteger ; 9 import java.sql.SQLException ; 10 import java.text.Collator ; 11 12 import org.h2.command.ddl.AlterIndexRename; 13 import org.h2.command.ddl.AlterSequence; 14 import org.h2.command.ddl.AlterTableAddConstraint; 15 import org.h2.command.ddl.AlterTableAlterColumn; 16 import org.h2.command.ddl.AlterTableDropConstraint; 17 import org.h2.command.ddl.AlterTableRename; 18 import org.h2.command.ddl.AlterTableRenameColumn; 19 import org.h2.command.ddl.AlterUser; 20 import org.h2.command.ddl.AlterView; 21 import org.h2.command.ddl.Analyze; 22 import org.h2.command.ddl.CreateConstant; 23 import org.h2.command.ddl.CreateFunctionAlias; 24 import org.h2.command.ddl.CreateIndex; 25 import org.h2.command.ddl.CreateLinkedTable; 26 import org.h2.command.ddl.CreateRole; 27 import org.h2.command.ddl.CreateSchema; 28 import org.h2.command.ddl.CreateSequence; 29 import org.h2.command.ddl.CreateTable; 30 import org.h2.command.ddl.CreateTrigger; 31 import org.h2.command.ddl.CreateUser; 32 import org.h2.command.ddl.CreateUserDataType; 33 import org.h2.command.ddl.CreateView; 34 import org.h2.command.ddl.DropConstant; 35 import org.h2.command.ddl.DropDatabase; 36 import org.h2.command.ddl.DropFunctionAlias; 37 import org.h2.command.ddl.DropIndex; 38 import org.h2.command.ddl.DropRole; 39 import org.h2.command.ddl.DropSchema; 40 import org.h2.command.ddl.DropSequence; 41 import org.h2.command.ddl.DropTable; 42 import org.h2.command.ddl.DropTrigger; 43 import org.h2.command.ddl.DropUser; 44 import org.h2.command.ddl.DropUserDataType; 45 import org.h2.command.ddl.DropView; 46 import org.h2.command.ddl.GrantRevoke; 47 import org.h2.command.ddl.SetComment; 48 import org.h2.command.ddl.TruncateTable; 49 import org.h2.command.dml.Call; 50 import org.h2.command.dml.Delete; 51 import org.h2.command.dml.ExplainPlan; 52 import org.h2.command.dml.Insert; 53 import org.h2.command.dml.Merge; 54 import org.h2.command.dml.NoOperation; 55 import org.h2.command.dml.Query; 56 import org.h2.command.dml.RunScript; 57 import org.h2.command.dml.Script; 58 import org.h2.command.dml.Select; 59 import org.h2.command.dml.SelectOrderBy; 60 import org.h2.command.dml.SelectUnion; 61 import org.h2.command.dml.Set; 62 import org.h2.command.dml.SetTypes; 63 import org.h2.command.dml.TransactionCommand; 64 import org.h2.command.dml.Update; 65 import org.h2.constraint.ConstraintReferential; 66 import org.h2.engine.Constants; 67 import org.h2.engine.Database; 68 import org.h2.engine.DbObject; 69 import org.h2.engine.FunctionAlias; 70 import org.h2.engine.Mode; 71 import org.h2.engine.Right; 72 import org.h2.engine.Session; 73 import org.h2.engine.Setting; 74 import org.h2.engine.User; 75 import org.h2.engine.UserDataType; 76 import org.h2.expression.Aggregate; 77 import org.h2.expression.Alias; 78 import org.h2.expression.CompareLike; 79 import org.h2.expression.Comparison; 80 import org.h2.expression.ConditionAndOr; 81 import org.h2.expression.ConditionExists; 82 import org.h2.expression.ConditionIn; 83 import org.h2.expression.ConditionInSelect; 84 import org.h2.expression.ConditionNot; 85 import org.h2.expression.Expression; 86 import org.h2.expression.ExpressionColumn; 87 import org.h2.expression.ExpressionList; 88 import org.h2.expression.Function; 89 import org.h2.expression.FunctionCall; 90 import org.h2.expression.JavaFunction; 91 import org.h2.expression.Operation; 92 import org.h2.expression.Parameter; 93 import org.h2.expression.Rownum; 94 import org.h2.expression.SequenceValue; 95 import org.h2.expression.Subquery; 96 import org.h2.expression.ValueExpression; 97 import org.h2.expression.Wildcard; 98 import org.h2.index.Index; 99 import org.h2.message.Message; 100 import org.h2.schema.Schema; 101 import org.h2.schema.Sequence; 102 import org.h2.schema.TriggerObject; 103 import org.h2.table.Column; 104 import org.h2.table.FunctionTable; 105 import org.h2.table.RangeTable; 106 import org.h2.table.Table; 107 import org.h2.table.TableFilter; 108 import org.h2.table.TableView; 109 import org.h2.util.ByteUtils; 110 import org.h2.util.ObjectArray; 111 import org.h2.util.StringCache; 112 import org.h2.util.StringUtils; 113 import org.h2.value.CompareMode; 114 import org.h2.value.DataType; 115 import org.h2.value.Value; 116 import org.h2.value.ValueBoolean; 117 import org.h2.value.ValueBytes; 118 import org.h2.value.ValueDate; 119 import org.h2.value.ValueDecimal; 120 import org.h2.value.ValueInt; 121 import org.h2.value.ValueLong; 122 import org.h2.value.ValueString; 123 import org.h2.value.ValueTime; 124 import org.h2.value.ValueTimestamp; 125 126 public class Parser { 127 128 private static final int CHAR_END = -1, CHAR_VALUE = 2, CHAR_QUOTED = 3; 130 private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5, CHAR_SPECIAL_2 = 6; 131 private static final int CHAR_STRING = 7, CHAR_DECIMAL = 8; 132 133 private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, END = 4, VALUE = 5; 135 private static final int EQUAL = 6, BIGGER_EQUAL = 7, BIGGER = 8; 136 private static final int SMALLER = 9, SMALLER_EQUAL = 10, NOT_EQUAL = 11; 137 private static final int MINUS = 17, PLUS = 18; 138 private static final int STRINGCONCAT = 22; 139 private static final int OPEN = 31, CLOSE = 32, NULL = 34, TRUE = 40, FALSE = 41; 140 141 private static final int CURRENT_TIMESTAMP = 42, CURRENT_DATE = 43, CURRENT_TIME = 44, ROWNUM = 45; 142 143 private int[] characterTypes; 144 private int currentTokenType; 145 private String currentToken; 146 private boolean currentTokenQuoted; 147 private Value currentValue; 148 private String sqlCommand, originalSQL; 149 private char[] sqlCommandChars; 150 private int lastParseIndex; 151 private int parseIndex; 152 private Prepared currentPrepared; 153 private Select currentSelect; 154 private Session session; 155 private Database database; 156 private ObjectArray parameters; 157 private String schemaName; 158 private ObjectArray expected; 159 private boolean rightsChecked; 160 private boolean recompileAlways; 161 private ObjectArray indexedParameterList; 162 163 public Parser(Session session) { 164 this.session = session; 165 database = session.getDatabase(); 166 } 167 168 public Prepared prepare(String sql) throws SQLException { 169 try { 170 Prepared p = parse(sql); 171 p.prepare(); 172 return p; 173 } catch(Exception e) { 174 throw Message.convert(e); 175 } 176 } 177 178 public Prepared parseOnly(String sql) throws SQLException { 179 try { 180 Prepared p = parse(sql); 181 return p; 182 } catch(Exception e) { 183 throw Message.convert(e); 184 } 185 } 186 187 public Command prepareCommand(String sql) throws SQLException { 188 try { 189 Prepared p = parse(sql); 190 p.prepare(); 191 Command c = new CommandContainer(this, p); 192 p.setCommand(c); 193 if (isToken(";")) { 194 String remaining = originalSQL.substring(parseIndex); 195 if(remaining.trim().length()!=0) { 196 CommandList list = new CommandList(this, c, remaining); 197 c = list; 203 } 204 } else if (currentTokenType != END) { 205 throw getSyntaxError(); 207 } 208 return c; 209 } catch(Exception e) { 210 throw Message.addSQL(Message.convert(e), this.originalSQL); 211 } 212 } 213 214 private Prepared parse(String sql) throws SQLException { 215 Prepared p; 216 try { 217 p = parse(sql, false); 219 } catch(SQLException e) { 220 if(e.getErrorCode() == Message.SYNTAX_ERROR_1) { 221 p = parse(sql, true); 223 } else { 224 throw Message.addSQL(e, sql); 225 } 226 } 227 p.setPrepareAlways(recompileAlways); 228 p.setParameterList(parameters); 229 return p; 230 } 231 232 private Prepared parse(String sql, boolean withExpectedList) throws SQLException { 233 initialize(sql); 234 if(withExpectedList) { 235 expected = new ObjectArray(); 236 } else { 237 expected = null; 238 } 239 parameters = new ObjectArray(); 240 int start = lastParseIndex; 241 currentSelect = null; 242 currentPrepared = null; 243 Prepared c = null; 244 recompileAlways = false; 245 indexedParameterList = null; 246 read(); 247 String token = currentToken; 248 if(token.length()==0) { 249 c = new NoOperation(session); 250 } else { 251 char first = token.charAt(0); 252 switch (first) { 253 case '(': 254 c = parseSelect(); 255 break; 256 case 'A': 257 if(readIf("ALTER")) { 258 c = parseAlter(); 259 } else if(readIf("ANALYZE")) { 260 c = parseAnalyse(); 261 } 262 break; 263 case 'C': 264 if (readIf("COMMIT")) { 265 c = parseCommit(); 266 } else if (readIf("CREATE")) { 267 c = parseCreate(); 268 } else if (readIf("CALL")) { 269 c = parserCall(); 270 } else if (readIf("CHECKPOINT")) { 271 c = parseCheckpoint(); 272 } else if (readIf("COMMENT")) { 273 c = parseComment(); 274 } 275 break; 276 case 'D': 277 if (readIf("DELETE")) { 278 c = parseDelete(); 279 } else if (readIf("DROP")) { 280 c = parseDrop(); 281 } else if (readIf("DECLARE")) { 282 c = parseCreate(); 284 } 285 break; 286 case 'E': 287 if (readIf("EXPLAIN")) { 288 c = parseExplain(); 289 } 290 break; 291 case 'F': 292 if (isToken("FROM")) { 293 c = parseSelect(); 294 } 295 break; 296 case 'G': 297 if (readIf("GRANT")) { 298 c = parseGrantRevoke(GrantRevoke.GRANT); 299 } 300 break; 301 case 'H': 302 if(readIf("HELP")) { 303 c = parseHelp(); 304 } 305 break; 306 case 'I': 307 if(readIf("INSERT")) { 308 c = parseInsert(); 309 } 310 break; 311 case 'M': 312 if(readIf("MERGE")) { 313 c = parseMerge(); 314 } 315 break; 316 case 'P': 317 if(readIf("PREPARE")) { 318 c = parsePrepareCommit(); 319 } 320 break; 321 case 'R': 322 if(readIf("ROLLBACK")) { 323 c = parseRollback(); 324 } else if (readIf("REVOKE")) { 325 c = parseGrantRevoke(GrantRevoke.REVOKE); 326 } else if(readIf("RUNSCRIPT")) { 327 c = parseRunScript(); 328 } 329 break; 330 case 'S': 331 if (isToken("SELECT")) { 332 c = parseSelect(); 333 } else if (readIf("SET")) { 334 c = parseSet(); 335 } else if (readIf("SAVEPOINT")) { 336 c = parseSavepoint(); 337 } else if (readIf("SCRIPT")) { 338 c = parseScript(); 339 } else if (readIf("SHUTDOWN")) { 340 c = parseShutdown(); 341 } 342 break; 343 case 'T': 344 if(readIf("TRUNCATE")) { 345 c = parseTruncate(); 346 } 347 break; 348 case 'U': 349 if(readIf("UPDATE")) { 350 c = parseUpdate(); 351 } 352 break; 353 case 'V': 354 if(readIf("VALUES")) { 355 c = parserCall(); 356 } 357 break; 358 default: 359 throw getSyntaxError(); 361 } 362 if(indexedParameterList != null) { 363 for(int i=0; i<indexedParameterList.size(); i++) { 364 if(indexedParameterList.get(i) == null) { 365 indexedParameterList.set(i, new Parameter(i)); 366 } 367 } 368 parameters = indexedParameterList; 369 } 370 if(readIf("{")) { 371 do { 372 int index = (int)readLong() - 1; 373 if(index < 0 || index >= parameters.size()) { 374 throw getSyntaxError(); 375 } 376 Parameter p = (Parameter)parameters.get(index); 377 if(p == null) { 378 throw getSyntaxError(); 379 } 380 read(":"); 381 Expression expr = readExpression(); 382 expr = expr.optimize(session); 383 p.setValue(expr.getValue(session)); 384 index++; 385 } while(readIf(",")); 386 read("}"); 387 int len = parameters.size(); 388 for(int i=0; i<len; i++) { 389 Parameter p = (Parameter)parameters.get(i); 390 p.checkSet(); 391 } 392 parameters.clear(); 393 } 394 } 395 if(c==null) { 396 throw getSyntaxError(); 398 } 399 setSQL(c, null, start); 400 return c; 401 } 402 403 private SQLException getSyntaxError() { 404 if(expected == null || expected.size()==0) { 405 return Message.getSyntaxError(sqlCommand, parseIndex); 406 } else { 407 StringBuffer buff = new StringBuffer (); 408 for(int i=0; i<expected.size(); i++) { 409 if(i>0) { 410 buff.append(", "); 411 } 412 buff.append(expected.get(i)); 413 } 414 return Message.getSyntaxError(sqlCommand, parseIndex, buff.toString()); 415 } 416 } 417 418 private Prepared parseAnalyse() throws SQLException { 419 Analyze command = new Analyze(session); 420 if(readIf("SAMPLE_SIZE")) { 421 command.setTop(getPositiveInt()); 422 } 423 return command; 424 } 425 426 private TransactionCommand parseCommit() throws SQLException { 427 TransactionCommand command; 428 if(readIf("TRANSACTION")) { 429 command = new TransactionCommand(session, TransactionCommand.COMMIT_TRANSACTION); 430 command.setTransactionName(readUniqueIdentifier()); 431 return command; 432 } 433 command = new TransactionCommand(session, TransactionCommand.COMMIT); 434 readIf("WORK"); 435 return command; 436 } 437 438 private TransactionCommand parseShutdown() throws SQLException { 439 int type = TransactionCommand.SHUTDOWN; 440 if(readIf("IMMEDIATELY")) { 441 type = TransactionCommand.SHUTDOWN_IMMEDIATELY; 442 } else if(readIf("COMPACT")) { 443 } else if(readIf("SCRIPT")) { 444 } 445 TransactionCommand command = new TransactionCommand(session, type); 446 return command; 447 } 448 449 private TransactionCommand parseRollback() throws SQLException { 450 TransactionCommand command; 451 if(readIf("TRANSACTION")) { 452 command = new TransactionCommand(session, TransactionCommand.ROLLBACK_TRANSACTION); 453 command.setTransactionName(readUniqueIdentifier()); 454 return command; 455 } 456 if(readIf("TO")) { 457 read("SAVEPOINT"); 458 command = new TransactionCommand(session, TransactionCommand.ROLLBACK_TO_SAVEPOINT); 459 command.setSavepointName(readUniqueIdentifier()); 460 } else { 461 readIf("WORK"); 462 command = new TransactionCommand(session, TransactionCommand.ROLLBACK); 463 } 464 return command; 465 } 466 467 private TransactionCommand parsePrepareCommit() throws SQLException { 468 TransactionCommand command = new TransactionCommand(session, TransactionCommand.PREPARE_COMMIT); 469 read("COMMIT"); 470 command.setTransactionName(readUniqueIdentifier()); 471 return command; 472 } 473 474 private TransactionCommand parseSavepoint() throws SQLException { 475 TransactionCommand command = new TransactionCommand(session, TransactionCommand.SAVEPOINT); 476 command.setSavepointName(readUniqueIdentifier()); 477 return command; 478 } 479 480 private Schema getSchema() throws SQLException { 481 if(schemaName == null) { 482 return null; 483 } 484 Schema schema = database.findSchema(schemaName); 485 if(schema == null) { 486 if("SESSION".equals(schemaName)) { 487 schema = database.getSchema(session.getCurrentSchemaName()); 489 } else { 490 throw Message.getSQLException(Message.SCHEMA_NOT_FOUND_1, schemaName); 491 } 492 } 493 return schema; 494 } 495 496 private Column readTableColumn(TableFilter filter) throws SQLException { 497 String tableAlias = null; 498 String columnName = readColumnIdentifier(); 499 if(readIf(".")) { 500 tableAlias = columnName; 501 columnName = readColumnIdentifier(); 502 } 503 if (tableAlias != null && !tableAlias.equals(filter.getTableAlias())) { 504 throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, tableAlias); 505 } 506 return filter.getTable().getColumn(columnName); 507 } 508 509 private Update parseUpdate() throws SQLException { 510 Update command = new Update(session); 511 currentPrepared = command; 512 int start = lastParseIndex; 513 TableFilter filter = readSimpleTableFilter(); 514 command.setTableFilter(filter); 515 read("SET"); 516 if(readIf("(")) { 517 ObjectArray columns = new ObjectArray(); 518 do { 519 Column column = readTableColumn(filter); 520 columns.add(column); 521 } while(readIf(",")); 522 read(")"); 523 read("="); 524 Expression expression = readExpression(); 525 for(int i=0; i<columns.size(); i++) { 526 Column column = (Column) columns.get(i); 527 Function f = Function.getFunction(database, "ARRAY_GET"); 528 f.setParameter(0, expression); 529 f.setParameter(1, ValueExpression.get(ValueInt.get(i+1))); 530 f.doneWithParameters(); 531 command.setAssignment(column, f); 532 } 533 } else { 534 do { 535 Column column = readTableColumn(filter); 536 read("="); 537 Expression expression = readExpression(); 538 command.setAssignment(column, expression); 539 } while(readIf(",")); 540 } 541 if (readIf("WHERE")) { 542 Expression condition = readExpression(); 543 command.setCondition(condition); 544 } 545 setSQL(command, "UPDATE", start); 546 return command; 547 } 548 549 private TableFilter readSimpleTableFilter() throws SQLException { 550 String tableName = readIdentifierWithSchema(); 551 Table table = getSchema().getTableOrView(session, tableName); 552 String alias = null; 553 if(readIf("AS")) { 554 alias = readAliasIdentifier(); 555 } else if(currentTokenType == IDENTIFIER) { 556 if(!"SET".equals(currentToken)) { 557 alias = readAliasIdentifier(); 559 } 560 } 561 TableFilter filter = new TableFilter(session, table, alias, rightsChecked); 562 return filter; 563 } 564 565 private Delete parseDelete() throws SQLException { 566 Delete command = new Delete(session); 567 currentPrepared = command; 568 int start = lastParseIndex; 569 readIf("FROM"); 570 TableFilter filter = readSimpleTableFilter(); 571 command.setTableFilter(filter); 572 if (readIf("WHERE")) { 573 Expression condition = readExpression(); 574 command.setCondition(condition); 575 } 576 setSQL(command, "DELETE", start); 577 return command; 578 } 579 580 private String [] parseColumnList(boolean ascDesc) throws SQLException { 581 ObjectArray columns = new ObjectArray(); 582 do { 583 String columnName = readColumnIdentifier(); 584 columns.add(columnName); 585 if(readIf("ASC")) { 586 } else { 588 readIf("DESC"); 589 } 590 } while(readIf(",")); 591 read(")"); 592 String [] cols = new String [columns.size()]; 593 columns.toArray(cols); 594 return cols; 595 } 596 597 private Column[] parseColumnList(Table table) throws SQLException { 598 ObjectArray columns = new ObjectArray(); 599 if(!readIf(")")) { 600 do { 601 Column column = table.getColumn(readColumnIdentifier()); 602 columns.add(column); 603 } while(readIf(",")); 604 read(")"); 605 } 606 Column[] cols = new Column[columns.size()]; 607 columns.toArray(cols); 608 return cols; 609 } 610 611 private Prepared parseHelp() throws SQLException { 612 StringBuffer buff = new StringBuffer ("SELECT * FROM INFORMATION_SCHEMA.HELP"); 613 int i=0; 614 while (currentTokenType != END) { 615 String s = currentToken; 616 read(); 617 if(i==0) { 618 buff.append(" WHERE "); 619 } else { 620 buff.append(" AND "); 621 } 622 i++; 623 buff.append("UPPER(TOPIC) LIKE "); 624 buff.append(StringUtils.quoteStringSQL("%"+s+"%")); 625 } 626 Prepared command = session.prepare(buff.toString()); 627 return command; 628 } 629 630 private Merge parseMerge() throws SQLException { 631 Merge command = new Merge(session); 632 currentPrepared = command; 633 read("INTO"); 634 String tableName = readIdentifierWithSchema(); 635 Table table = getSchema().getTableOrView(session, tableName); 636 command.setTable(table); 637 if (readIf("(")) { 638 Column[] columns = parseColumnList(table); 639 command.setColumns(columns); 640 } 641 if(readIf("KEY")) { 642 read("("); 643 Column[] keys = parseColumnList(table); 644 command.setKeys(keys); 645 } 646 if (readIf("VALUES")) { 647 do { 648 ObjectArray values = new ObjectArray(); 649 read("("); 650 if(!readIf(")")) { 651 do { 652 if(readIf("DEFAULT")) { 653 values.add(null); 654 } else { 655 values.add(readExpression()); 656 } 657 } while(readIf(",")); 658 read(")"); 659 } 660 Expression[] expr = new Expression[values.size()]; 661 values.toArray(expr); 662 command.addRow(expr); 663 } while(readIf(",")); 664 } else { 665 command.setQuery(parseQueryWithParams()); 666 } 667 return command; 668 } 669 670 private Insert parseInsert() throws SQLException { 671 Insert command = new Insert(session); 672 currentPrepared = command; 673 read("INTO"); 674 String tableName = readIdentifierWithSchema(); 675 Table table = getSchema().getTableOrView(session, tableName); 676 command.setTable(table); 677 if (readIf("(")) { 678 Column[] columns = parseColumnList(table); 679 command.setColumns(columns); 680 } 681 if(readIf("DEFAULT")) { 682 read("VALUES"); 683 Expression[] expr = new Expression[0]; 684 command.addRow(expr); 685 } else if (readIf("VALUES")) { 686 do { 687 ObjectArray values = new ObjectArray(); 688 read("("); 689 if(!readIf(")")) { 690 do { 691 if(readIf("DEFAULT")) { 692 values.add(null); 693 } else { 694 values.add(readExpression()); 695 } 696 } while(readIf(",")); 697 read(")"); 698 } 699 Expression[] expr = new Expression[values.size()]; 700 values.toArray(expr); 701 command.addRow(expr); 702 } while(readIf(",")); 703 } else { 704 command.setQuery(parseQueryWithParams()); 705 } 706 return command; 707 } 708 709 private TableFilter readTableFilter() throws SQLException { 710 Table table; 711 Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN); 712 if(readIf("(")) { 713 if(isToken("SELECT") || isToken("FROM")) { 714 Query query = parseQueryWithParams(); 715 String querySQL = query.getSQL(); 716 table = new TableView(mainSchema, 0, "TEMP_VIEW", querySQL, query.getParameters(), null, session); 717 read(")"); 718 } else { 719 TableFilter top = readTableFilter(); 720 top = readJoin(top, currentSelect); 721 read(")"); 722 return top; 723 } 724 } else { 725 String tableName = readIdentifierWithSchema(); 726 if(readIf("(")) { 727 if(tableName.equals(RangeTable.NAME)) { 728 long min = readLong(); 729 read(","); 730 long max = readLong(); 731 read(")"); 732 table = new RangeTable(mainSchema, min, max); 733 } else { 734 Expression func = readFunction(tableName); 735 if(!(func instanceof FunctionCall)) { 736 throw getSyntaxError(); 737 } 738 table = new FunctionTable(mainSchema, session, (FunctionCall)func); 739 } 740 } else if(tableName.equals("DUAL")) { 741 table = new RangeTable(mainSchema, 1, 1); 742 } else { 743 table = getSchema().getTableOrView(session, tableName); 744 } 745 } 746 String alias = null; 747 if(readIf("AS")) { 748 alias = readAliasIdentifier(); 749 } else if(currentTokenType == IDENTIFIER) { 750 if(!isToken("LEFT") && !isToken("RIGHT")) { 752 alias = readAliasIdentifier(); 753 } 754 } 755 TableFilter filter = new TableFilter(session, table, alias, rightsChecked); 756 return filter; 757 } 758 759 private Prepared parseTruncate() throws SQLException { 760 read("TABLE"); 761 String tableName = readIdentifierWithSchema(); 762 TruncateTable command = new TruncateTable(session, getSchema()); 763 command.setTableName(tableName); 764 return command; 765 } 766 767 private boolean readIfExists(boolean ifExists) throws SQLException { 768 if(readIf("IF")) { 769 read("EXISTS"); 770 ifExists = true; 771 } 772 return ifExists; 773 } 774 775 private Prepared parseComment() throws SQLException { 776 int type = 0; 777 read("ON"); 778 boolean column = false; 779 if(readIf("TABLE") || readIf("VIEW")) { 780 type = DbObject.TABLE_OR_VIEW; 781 } else if(readIf("COLUMN")) { 782 column = true; 783 type = DbObject.TABLE_OR_VIEW; 784 } else if(readIf("CONSTANT")) { 785 type = DbObject.CONSTANT; 786 } else if(readIf("CONSTRAINT")) { 787 type = DbObject.CONSTRAINT; 788 } else if(readIf("ALIAS")) { 789 type = DbObject.FUNCTION_ALIAS; 790 } else if(readIf("INDEX")) { 791 type = DbObject.INDEX; 792 } else if(readIf("ROLE")) { 793 type = DbObject.ROLE; 794 } else if(readIf("SCHEMA")) { 795 type = DbObject.SCHEMA; 796 } else if(readIf("SEQUENCE")) { 797 type = DbObject.SEQUENCE; 798 } else if(readIf("TRIGGER")) { 799 type = DbObject.TRIGGER; 800 } else if(readIf("USER")) { 801 type = DbObject.USER; 802 } else if(readIf("DOMAIN")) { 803 type = DbObject.USER_DATATYPE; 804 } else { 805 throw getSyntaxError(); 806 } 807 SetComment command = new SetComment(session); 808 String objectName = readIdentifierWithSchema(); 809 if(column) { 810 String columnName = objectName; 811 objectName = schemaName; 812 schemaName = session.getCurrentSchemaName(); 813 if(readIf(".")) { 814 schemaName = objectName; 815 objectName = columnName; 816 columnName = readUniqueIdentifier(); 817 } 818 command.setColumn(true); 819 command.setColumnName(columnName); 820 } 821 command.setSchemaName(schemaName); 822 command.setObjectName(objectName); 823 command.setObjectType(type); 824 read("IS"); 825 command.setCommentExpression(readExpression()); 826 return command; 827 } 828 829 private Prepared parseDrop() throws SQLException { 830 if (readIf("TABLE")) { 831 boolean ifExists = readIfExists(false); 832 String tableName = readIdentifierWithSchema(); 833 DropTable command = new DropTable(session, getSchema()); 834 command.setTableName(tableName); 835 while(readIf(",")) { 836 tableName = readIdentifierWithSchema(); 837 DropTable next = new DropTable(session, getSchema()); 838 next.setTableName(tableName); 839 command.addNextDropTable(next); 840 } 841 ifExists = readIfExists(ifExists); 842 command.setIfExists(ifExists); 843 if(readIf("CASCADE")) { 844 readIf("CONSTRAINTS"); 845 } 846 return command; 847 } else if (readIf("INDEX")) { 848 boolean ifExists = readIfExists(false); 849 String indexName = readIdentifierWithSchema(); 850 DropIndex command = new DropIndex(session, getSchema()); 852 command.setIndexName(indexName); 853 ifExists = readIfExists(ifExists); 854 command.setIfExists(ifExists); 855 return command; 856 } else if (readIf("USER")) { 857 boolean ifExists = readIfExists(false); 858 DropUser command = new DropUser(session); 859 command.setUserName(readUniqueIdentifier()); 860 ifExists = readIfExists(ifExists); 861 readIf("CASCADE"); 862 command.setIfExists(ifExists); 863 return command; 864 } else if(readIf("SEQUENCE")) { 865 boolean ifExists = readIfExists(false); 866 String sequenceName = readIdentifierWithSchema(); 867 DropSequence command = new DropSequence(session, getSchema()); 868 command.setSequenceName(sequenceName); 869 ifExists = readIfExists(ifExists); 870 command.setIfExists(ifExists); 871 return command; 872 } else if(readIf("CONSTANT")) { 873 boolean ifExists = readIfExists(false); 874 String constantName = readIdentifierWithSchema(); 875 DropConstant command = new DropConstant(session, getSchema()); 876 command.setConstantName(constantName); 877 ifExists = readIfExists(ifExists); 878 command.setIfExists(ifExists); 879 return command; 880 } else if(readIf("TRIGGER")) { 881 boolean ifExists = readIfExists(false); 882 String triggerName = readIdentifierWithSchema(); 883 DropTrigger command = new DropTrigger(session, getSchema()); 884 command.setTriggerName(triggerName); 885 ifExists = readIfExists(ifExists); 886 command.setIfExists(ifExists); 887 return command; 888 } else if(readIf("VIEW")) { 889 boolean ifExists = readIfExists(false); 890 String viewName = readIdentifierWithSchema(); 891 DropView command = new DropView(session, getSchema()); 892 command.setViewName(viewName); 893 ifExists = readIfExists(ifExists); 894 command.setIfExists(ifExists); 895 return command; 896 } else if(readIf("ROLE")) { 897 boolean ifExists = readIfExists(false); 898 DropRole command = new DropRole(session); 899 command.setRoleName(readUniqueIdentifier()); 900 ifExists = readIfExists(ifExists); 901 command.setIfExists(ifExists); 902 return command; 903 } else if(readIf("ALIAS")) { 905 boolean ifExists = readIfExists(false); 906 DropFunctionAlias command = new DropFunctionAlias(session); 907 command.setAliasName(readUniqueIdentifier()); 908 ifExists = readIfExists(ifExists); 909 command.setIfExists(ifExists); 910 return command; 911 } else if(readIf("SCHEMA")) { 912 boolean ifExists = readIfExists(false); 913 DropSchema command = new DropSchema(session); 914 command.setSchemaName(readUniqueIdentifier()); 915 ifExists = readIfExists(ifExists); 916 command.setIfExists(ifExists); 917 return command; 918 } else if(readIf("ALL")) { 919 read("OBJECTS"); 920 DropDatabase command = new DropDatabase(session); 921 command.setDropAllObjects(true); 922 if(readIf("DELETE")) { 923 read("FILES"); 924 command.setDeleteFiles(true); 925 } 926 return command; 927 } else if(readIf("DOMAIN")) { 928 return parseDropUserDataType(); 929 } else if(readIf("TYPE")) { 930 return parseDropUserDataType(); 931 } else if(readIf("DATATYPE")) { 932 return parseDropUserDataType(); 933 } 934 throw getSyntaxError(); 935 } 936 937 DropUserDataType parseDropUserDataType() throws SQLException { 938 boolean ifExists = readIfExists(false); 939 DropUserDataType command = new DropUserDataType(session); 940 command.setTypeName(readUniqueIdentifier()); 941 ifExists = readIfExists(ifExists); 942 command.setIfExists(ifExists); 943 return command; 944 } 945 946 private TableFilter readJoin(TableFilter top, Select command) throws SQLException { 947 TableFilter last = top; 948 while (true) { 949 if (readIf("RIGHT")) { 950 readIf("OUTER"); 951 read("JOIN"); 952 TableFilter newTop = readTableFilter(); 953 Expression on = null; 954 if(readIf("ON")) { 955 on = readExpression(); 956 } 957 newTop.addJoin(top, true, on); 958 top = newTop; 959 last = newTop; 960 } else if (readIf("LEFT")) { 961 readIf("OUTER"); 962 read("JOIN"); 963 TableFilter join = readTableFilter(); 964 Expression on = null; 965 if(readIf("ON")) { 966 on = readExpression(); 967 } 968 top.addJoin(join, true, on); 969 last = join; 970 } else if (readIf("INNER")) { 971 read("JOIN"); 972 973 TableFilter join = readTableFilter(); 974 Expression on = null; 975 if(readIf("ON")) { 976 on = readExpression(); 977 } 978 top.addJoin(join, false, on); 979 last = join; 980 } else if(readIf("JOIN")) { 981 TableFilter join = readTableFilter(); 982 Expression on = null; 983 if(readIf("ON")) { 984 on = readExpression(); 985 } 986 top.addJoin(join, false, on); 987 last = join; 988 } else if(readIf("CROSS")) { 989 read("JOIN"); 990 TableFilter join = readTableFilter(); 991 top.addJoin(join, false, null); 992 last = join; 993 } else if(readIf("NATURAL")) { 994 read("JOIN"); 995 TableFilter join = readTableFilter(); 996 Column[] tc = last.getTable().getColumns(); 997 Column[] jc = join.getTable().getColumns(); 998 String ts = last.getTable().getSchema().getName(); 999 String js = join.getTable().getSchema().getName(); 1000 Expression on = null; 1001 for(int t=0; t<tc.length; t++) { 1002 String tcn = tc[t].getName(); 1003 for(int j=0; j<jc.length; j++) { 1004 String jcn = jc[j].getName(); 1005 if(tcn.equals(jcn)) { 1006 Expression te = new ExpressionColumn(database, currentSelect, ts, last.getTableAlias(), tcn); 1007 Expression je = new ExpressionColumn(database, currentSelect, js, join.getTableAlias(), jcn); 1008 Expression eq = new Comparison(session, Comparison.EQUAL, te, je); 1009 if(on == null) { 1010 on = eq; 1011 } else { 1012 on = new ConditionAndOr(ConditionAndOr.AND, on, eq); 1013 } 1014 } 1015 } 1016 } 1017 top.addJoin(join, false, on); 1018 last = join; 1019 } else { 1020 break; 1021 } 1022 } 1023 return top; 1024 } 1025 1026 private void parseJoinTableFilter(TableFilter top, Select command) throws SQLException { 1027 top = readJoin(top, command); 1028 command.addTableFilter(top, true); 1029 boolean isOuter = false; 1030 while(true) { 1031 TableFilter join = top.getJoin(); 1032 if(join == null) { 1033 break; 1034 } 1035 isOuter = isOuter | join.isJoinOuter(); 1036 if(isOuter) { 1037 command.addTableFilter(join, false); 1038 } else { 1039 Expression on = join.getJoinCondition(); 1041 if(on != null) { 1042 command.addCondition(on); 1043 } 1044 join.removeJoinCondition(); 1045 top.removeJoin(); 1046 command.addTableFilter(join, true); 1047 } 1048 top = join; 1049 } 1050 } 1051 1052 private ExplainPlan parseExplain() throws SQLException { 1053 ExplainPlan command = new ExplainPlan(session); 1054 readIf("PLAN"); 1055 readIf("FOR"); 1056 if(isToken("SELECT") || isToken("FROM")) { 1057 command.setCommand(parseSelect()); 1058 } else if(isToken("(")) { 1059 command.setCommand(parseSelect()); 1060 } else if(readIf("DELETE")) { 1061 command.setCommand(parseDelete()); 1062 } else if(readIf("UPDATE")) { 1063 command.setCommand(parseUpdate()); 1064 } else if(readIf("INSERT")) { 1065 command.setCommand(parseInsert()); 1066 } else if(readIf("MERGE")) { 1067 command.setCommand(parseMerge()); 1068 } else { 1069 throw getSyntaxError(); 1070 } 1071 return command; 1072 } 1073 1074 private Query parseSelect() throws SQLException { 1075 Query command = parseSelectUnion(); 1076 command.init(); 1077 return command; 1078 } 1079 1080 private Query parseQueryWithParams() throws SQLException { 1081 int paramIndex = parameters.size(); 1082 Query command = parseSelectUnion(); 1083 command.init(); 1084 ObjectArray params = new ObjectArray(); 1085 for(int i=paramIndex; i<parameters.size(); i++) { 1086 params.add(parameters.get(i)); 1087 } 1088 command.setParameterList(params); 1089 return command; 1090 } 1091 1092 private Query parseSelectUnion() throws SQLException { 1093 int start = lastParseIndex; 1094 Query command = parseSelectSub(); 1095 while(true) { 1096 if (readIf("UNION")) { 1097 SelectUnion union = new SelectUnion(session, command); 1098 if(readIf("ALL")) { 1099 union.setUnionType(SelectUnion.UNION_ALL); 1100 } else { 1101 readIf("DISTINCT"); 1102 union.setUnionType(SelectUnion.UNION); 1103 } 1104 union.setRight(parseSelectSub()); 1106 command = union; 1107 } else if(readIf("MINUS") || readIf("EXCEPT")) { 1108 SelectUnion union = new SelectUnion(session, command); 1109 union.setUnionType(SelectUnion.EXCEPT); 1110 union.setRight(parseSelectSub()); 1111 command = union; 1112 } else if(readIf("INTERSECT")) { 1113 SelectUnion union = new SelectUnion(session, command); 1114 union.setUnionType(SelectUnion.INTERSECT); 1115 union.setRight(parseSelectSub()); 1116 command = union; 1117 } else { 1118 break; 1119 } 1120 } 1121 if (readIf("ORDER")) { 1122 read("BY"); 1123 Select oldSelect = currentSelect; 1124 if(command instanceof Select) { 1125 currentSelect = (Select)command; 1126 } 1127 ObjectArray orderList = new ObjectArray(); 1128 do { 1129 boolean canBeNumber = true; 1130 if(readIf("=")) { 1131 canBeNumber = false; 1132 } 1133 SelectOrderBy order = new SelectOrderBy(); 1134 Expression expr = readExpression(); 1135 if(canBeNumber && expr instanceof ValueExpression && expr.getType() == Value.INT) { 1136 int i = expr.getValue(null).getInt(); 1137 order.column = i-1; 1138 } else { 1139 order.expression = expr; 1140 } 1141 if(readIf("DESC")) { 1142 order.descending = true; 1143 } else { 1144 readIf("ASC"); 1145 } 1146 if(readIf("NULLS")) { 1147 if(readIf("FIRST")) { 1148 order.nullsFirst = true; 1149 } else { 1150 read("LAST"); 1151 order.nullsLast = true; 1152 } 1153 } 1154 orderList.add(order); 1155 } while(readIf(",")); 1156 command.setOrder(orderList); 1157 currentSelect = oldSelect; 1158 } 1159 if(readIf("LIMIT")) { 1160 Expression limit = readExpression().optimize(session); 1161 command.setLimit(limit); 1162 if(readIf("OFFSET")) { 1163 Expression offset = readExpression().optimize(session); 1164 command.setOffset(offset); 1165 } else if(readIf(",")) { 1166 Expression offset = limit; 1168 limit = readExpression().optimize(session); 1169 command.setOffset(offset); 1170 command.setLimit(limit); 1171 } 1172 if(readIf("SAMPLE_SIZE")) { 1173 command.setSampleSize(getPositiveInt()); 1174 } 1175 } 1176 if(readIf("FOR")) { 1177 if(readIf("UPDATE")) { 1178 if(readIf("OF")) { 1179 do { 1181 readIdentifierWithSchema(); 1182 } while(readIf(",")); 1183 } else if(readIf("NOWAIT")) { 1184 } else if(readIf("WITH")) { 1186 read("RR"); 1188 } 1189 command.setForUpdate(true); 1190 } else if(readIf("READ")) { 1191 read("ONLY"); 1192 if(readIf("WITH")) { 1193 read("RS"); 1194 } 1195 } 1196 } 1197 setSQL(command, null, start); 1198 return command; 1199 } 1200 1201 private Query parseSelectSub() throws SQLException { 1202 if(readIf("(")) { 1203 Query command = parseSelectUnion(); 1204 read(")"); 1205 return command; 1206 } 1207 Select select = parseSelectSimple(); 1208 return select; 1209 } 1210 1211 private void parseSelectSimpleFromPart(Select command) throws SQLException { 1212 do { 1213 TableFilter filter = readTableFilter(); 1214 parseJoinTableFilter(filter, command); 1215 } while(readIf(",")); 1216 } 1217 1218 private void parseSelectSimpleSelectPart(Select command) throws SQLException { 1219 if(readIf("TOP")) { 1220 Expression limit = readTerm().optimize(session); 1225 command.setLimit(limit); 1226 } else if(readIf("LIMIT")) { 1227 Expression offset = readTerm().optimize(session); 1228 command.setOffset(offset); 1229 Expression limit = readTerm().optimize(session); 1230 command.setLimit(limit); 1231 } 1232 if(readIf("DISTINCT")) { 1233 command.setDistinct(true); 1234 } else { 1235 readIf("ALL"); 1236 } 1237 ObjectArray expressions = new ObjectArray(); 1238 do { 1239 if(readIf("*")) { 1240 expressions.add(new Wildcard(null, null)); 1241 } else { 1242 Expression expr = readExpression(); 1243 if(readIf("AS") || currentTokenType == IDENTIFIER) { 1244 String alias = readAliasIdentifier(); 1245 expr = new Alias(expr, alias); 1246 } 1247 expressions.add(expr); 1248 } 1249 } while(readIf(",")); 1250 command.setExpressions(expressions); 1251 } 1252 1253 private Select parseSelectSimple() throws SQLException { 1254 boolean fromFirst; 1255 if(readIf("SELECT")) { 1256 fromFirst = false; 1257 } else if(readIf("FROM")) { 1258 fromFirst = true; 1259 } else { 1260 throw getSyntaxError(); 1261 } 1262 Select command = new Select(session); 1263 int start = lastParseIndex; 1264 Select oldSelect = currentSelect; 1265 currentSelect = command; 1266 currentPrepared = command; 1267 if(fromFirst) { 1268 parseSelectSimpleFromPart(command); 1269 read("SELECT"); 1270 parseSelectSimpleSelectPart(command); 1271 } else { 1272 parseSelectSimpleSelectPart(command); 1273 if(!readIf("FROM")) { 1274 Schema main = database.findSchema(Constants.SCHEMA_MAIN); 1276 Table dual = new RangeTable(main, 1, 1); 1277 TableFilter filter = new TableFilter(session, dual, null, rightsChecked); 1278 command.addTableFilter(filter, true); 1279 } else { 1280 parseSelectSimpleFromPart(command); 1281 } 1282 } 1283 if (readIf("WHERE")) { 1284 Expression condition = readExpression(); 1285 command.addCondition(condition); 1286 } 1287 currentSelect = oldSelect; 1290 if (readIf("GROUP")) { 1291 read("BY"); 1292 command.setGroupQuery(); 1293 ObjectArray list = new ObjectArray(); 1294 do { 1295 Expression expr = readExpression(); 1296 list.add(expr); 1297 } while(readIf(",")); 1298 command.setGroupBy(list); 1299 } 1300 currentSelect = command; 1301 if(readIf("HAVING")) { 1302 command.setGroupQuery(); 1303 Expression condition = readExpression(); 1304 command.setHaving(condition); 1305 } 1306 currentSelect = oldSelect; 1307 setSQL(command, "SELECT", start); 1308 return command; 1309 } 1310 1311 private void setSQL(Prepared command, String start, int startIndex) { 1312 String sql = originalSQL.substring(startIndex, lastParseIndex).trim(); 1313 if(start != null) { 1314 sql = start + " " + sql; 1315 } 1316 command.setSQL(sql); 1317 } 1318 1319 private Expression readExpression() throws SQLException { 1320 Expression r = readAnd(); 1321 while (readIf("OR")) { 1322 r = new ConditionAndOr(ConditionAndOr.OR, r, readAnd()); 1323 } 1324 return r; 1325 } 1326 1327 private Expression readAnd() throws SQLException { 1328 Expression r = readCondition(); 1329 while (readIf("AND")) { 1330 r = new ConditionAndOr(ConditionAndOr.AND, r, readCondition()); 1331 } 1332 return r; 1333 } 1334 1335 private Expression readCondition() throws SQLException { 1336 if (readIf("NOT")) { 1338 return new ConditionNot(readCondition()); 1339 } 1340 if (readIf("EXISTS")) { 1341 read("("); 1342 Query query = parseQueryWithParams(); 1343 read(")"); 1345 return new ConditionExists(query); 1346 } 1347 Expression r = readConcat(); 1348 while(true) { 1349 int backup = parseIndex; 1351 boolean not = false; 1352 if (readIf("NOT")) { 1353 not = true; 1354 if(isToken("NULL")) { 1355 parseIndex = backup; 1357 currentToken = "NOT"; 1358 break; 1359 } 1360 } 1361 if (readIf("LIKE")) { 1362 Expression b = readConcat(); 1363 Expression esc = null; 1364 if (readIf("ESCAPE")) { 1365 esc = readExpression(); 1366 } 1367 recompileAlways = true; 1368 r = new CompareLike(database.getCompareMode(), r, b, esc); 1369 } else if (readIf("IS")) { 1370 int type; 1371 if (readIf("NOT")) { 1372 type = Comparison.IS_NOT_NULL; 1373 } else { 1374 type = Comparison.IS_NULL; 1375 } 1376 read("NULL"); 1377 r = new Comparison(session, type, r, null); 1378 } else if (readIf("IN")) { 1379 if(Constants.OPTIMIZE_IN) { 1381 recompileAlways = true; 1382 } 1383 read("("); 1384 if(readIf(")")) { 1385 r = ValueExpression.get(ValueBoolean.get(false)); 1386 } else { 1387 if (isToken("SELECT") || isToken("FROM")) { 1388 Query query = parseQueryWithParams(); 1389 r = new ConditionInSelect(database, r, query, false, Comparison.EQUAL); 1390 } else { 1391 ObjectArray v = new ObjectArray(); 1392 Expression last; 1393 do { 1394 last = readExpression(); 1395 v.add(last); 1396 } while(readIf(",")); 1397 if(v.size()==1 && (last instanceof Subquery)) { 1398 Subquery s = (Subquery) last; 1399 Query q = s.getQuery(); 1400 r = new ConditionInSelect(database, r, q, false, Comparison.EQUAL); 1401 } else { 1402 r = new ConditionIn(database, r, v); 1403 } 1404 } 1405 read(")"); 1406 } 1407 } else if (readIf("BETWEEN")) { 1408 Expression low = readConcat(); 1409 read("AND"); 1410 Expression high = readConcat(); 1411 Expression condLow = new Comparison(session, Comparison.SMALLER_EQUAL, low, r); 1412 Expression condHigh = new Comparison(session, Comparison.BIGGER_EQUAL, high, r); 1413 r = new ConditionAndOr(ConditionAndOr.AND, condLow, condHigh); 1414 } else { 1415 int compareType = getCompareType(currentTokenType); 1417 if(compareType < 0) { 1418 break; 1419 } 1420 read(); 1421 if(readIf("ALL")) { 1422 read("("); 1423 Query query = parseQueryWithParams(); 1424 r = new ConditionInSelect(database, r, query, true, compareType); 1425 read(")"); 1426 } else if(readIf("ANY") || readIf("SOME")) { 1427 read("("); 1428 Query query = parseQueryWithParams(); 1429 r = new ConditionInSelect(database, r, query, false, compareType); 1430 read(")"); 1431 } else { 1432 Expression right = readConcat(); 1433 if(readIf("(") && readIf("+") && readIf(")")) { 1434 if(r instanceof ExpressionColumn && right instanceof ExpressionColumn) { 1436 ExpressionColumn lcol = (ExpressionColumn) r; 1437 ExpressionColumn rcol = (ExpressionColumn) right; 1438 ObjectArray filters = currentSelect.getTopFilters(); 1439 for(int i=0; filters != null && i<filters.size(); i++) { 1440 TableFilter f = (TableFilter) filters.get(i); 1441 lcol.mapColumns(f, 0); 1442 rcol.mapColumns(f, 0); 1443 } 1444 TableFilter lfilter = lcol.getTableFilter(); 1445 TableFilter rfilter = rcol.getTableFilter(); 1446 r = new Comparison(session, compareType, r, right); 1447 if(lfilter != null && rfilter != null) { 1448 filters.remove(filters.indexOf(rfilter)); 1449 lfilter.addJoin(rfilter, true, r); 1450 r = ValueExpression.get(ValueBoolean.get(true)); 1451 } 1452 } 1453 } else { 1454 r = new Comparison(session, compareType, r, right); 1455 } 1456 } 1457 } 1458 if (not) { 1459 r = new ConditionNot(r); 1460 } 1461 } 1462 return r; 1463 } 1464 1465 private Expression readConcat() throws SQLException { 1466 Expression r = readSum(); 1467 while (readIf("||")) { 1468 r = new Operation(Operation.CONCAT, r, readSum()); 1469 } 1470 return r; 1471 } 1472 1473 private Expression readSum() throws SQLException { 1474 Expression r = readFactor(); 1475 while(true) { 1476 if(readIf("+")) { 1477 r = new Operation(Operation.PLUS, r, readFactor()); 1478 } else if(readIf("-")) { 1479 r = new Operation(Operation.MINUS, r, readFactor()); 1480 } else { 1481 return r; 1482 } 1483 } 1484 } 1485 1486 private Expression readFactor() throws SQLException { 1487 Expression r = readTerm(); 1488 while(true) { 1489 if(readIf("*")) { 1490 r = new Operation(Operation.MULTIPLY, r, readTerm()); 1491 } else if(readIf("/")) { 1492 r = new Operation(Operation.DIVIDE, r, readTerm()); 1493 } else { 1494 return r; 1495 } 1496 } 1497 } 1498 1499 private Expression readAggregate(int aggregateType) throws SQLException { 1500 if(currentSelect == null) { 1501 throw getSyntaxError(); 1503 } 1504 currentSelect.setGroupQuery(); 1505 Expression r; 1506 if(aggregateType == Aggregate.COUNT) { 1507 if(readIf("*")) { 1508 r = new Aggregate(database, Aggregate.COUNT_ALL, null, currentSelect, false); 1509 } else { 1510 boolean distinct = readIf("DISTINCT"); 1511 r = new Aggregate(database, Aggregate.COUNT, readExpression(), currentSelect, distinct); 1512 } 1513 } else if(aggregateType == Aggregate.GROUP_CONCAT) { 1514 boolean distinct = readIf("DISTINCT"); 1515 Aggregate agg = new Aggregate(database, Aggregate.GROUP_CONCAT, readExpression(), currentSelect, distinct); 1516 if(readIf("ORDER")) { 1517 read("BY"); 1518 agg.setOrder(parseSimpleOrderList()); 1519 } 1520 if(readIf("SEPARATOR")) { 1521 agg.setSeparator(readExpression()); 1522 } 1523 r = agg; 1524 } else { 1525 boolean distinct = readIf("DISTINCT"); 1526 r = new Aggregate(database, aggregateType, readExpression(), currentSelect, distinct); 1527 } 1528 read(")"); 1529 return r; 1530 } 1531 1532 private ObjectArray parseSimpleOrderList() throws SQLException { 1533 ObjectArray orderList = new ObjectArray(); 1534 do { 1535 SelectOrderBy order = new SelectOrderBy(); 1536 Expression expr = readExpression(); 1537 order.expression = expr; 1538 if(readIf("DESC")) { 1539 order.descending = true; 1540 } else { 1541 readIf("ASC"); 1542 } 1543 orderList.add(order); 1544 } while(readIf(",")); 1545 return orderList; 1546 } 1547 1548 private JavaFunction readJavaFunction(String name) throws SQLException { 1549 FunctionAlias functionAlias = database.findFunctionAlias(name); 1550 if(functionAlias == null) { 1551 throw Message.getSQLException(Message.FUNCTION_NOT_FOUND_1, name); 1553 } 1554 int paramCount = functionAlias.getParameterCount(); 1555 Expression[] args = new Expression[paramCount]; 1556 for(int i=0; i<args.length; i++) { 1557 if(i>0) { 1558 read(","); 1559 } 1560 args[i] = readExpression(); 1561 } 1562 read(")"); 1563 JavaFunction func = new JavaFunction(functionAlias, args); 1564 return func; 1565 } 1566 1567 private Expression readFunction(String name) throws SQLException { 1568 int agg = Aggregate.getAggregateType(name); 1569 if(agg >= 0) { 1570 return readAggregate(agg); 1571 } 1572 Function function = Function.getFunction(database, name); 1573 if(function==null) { 1574 return readJavaFunction(name); 1575 } 1576 switch(function.getFunctionType()) { 1577 case Function.CAST: { 1578 function.setParameter(0, readExpression()); 1579 read("AS"); 1580 Column type = parseColumn(null); 1581 function.setDataType(type); 1582 read(")"); 1583 break; 1584 } 1585 case Function.CONVERT: { 1586 function.setParameter(0, readExpression()); 1587 read(","); 1588 Column type = parseColumn(null); 1589 function.setDataType(type); 1590 read(")"); 1591 break; 1592 } 1593 case Function.EXTRACT: { 1594 function.setParameter(0, ValueExpression.get(ValueString.get(currentToken))); 1595 read(); 1596 read("FROM"); 1597 function.setParameter(1, readExpression()); 1598 read(")"); 1599 break; 1600 } 1601 case Function.SUBSTRING: { 1602 function.setParameter(0, readExpression()); 1603 if(!readIf(",")) { 1604 read("FROM"); 1605 } 1606 function.setParameter(1, readExpression()); 1607 if(readIf("FOR") || readIf(",")) { 1608 function.setParameter(2, readExpression()); 1609 } 1610 read(")"); 1611 break; 1612 } 1613 case Function.POSITION: { 1614 function.setParameter(0, readConcat()); 1616 if(!readIf(",")) { 1617 read("IN"); 1618 } 1619 function.setParameter(1, readExpression()); 1620 read(")"); 1621 break; 1622 } 1623 case Function.TRIM: { 1624 Expression space = null; 1625 if(readIf("LEADING")) { 1626 function = Function.getFunction(database, "LTRIM"); 1627 if(!readIf("FROM")) { 1628 space = readExpression(); 1629 read("FROM"); 1630 } 1631 } else if(readIf("TRAILING")) { 1632 function = Function.getFunction(database, "RTRIM"); 1633 if(!readIf("FROM")) { 1634 space = readExpression(); 1635 read("FROM"); 1636 } 1637 } else if(readIf("BOTH")) { 1638 if(!readIf("FROM")) { 1639 space = readExpression(); 1640 read("FROM"); 1641 } 1642 } 1643 Expression p0 = readExpression(); 1644 if(readIf(",")) { 1645 space = readExpression(); 1646 } else if(readIf("FROM")) { 1647 space = p0; 1648 p0 = readExpression(); 1649 } 1650 function.setParameter(0, p0); 1651 if(space != null) { 1652 function.setParameter(1, space); 1653 } 1654 read(")"); 1655 break; 1656 } 1657 default: 1658 if(!readIf(")")) { 1659 int i=0; 1660 do { 1661 function.setParameter(i++, readExpression()); 1662 } while(readIf(",")); 1663 read(")"); 1664 } 1665 } 1666 function.doneWithParameters(); 1667 return function; 1668 } 1669 1670 private Function readFunctionWithoutParameters(String name) throws SQLException { 1671 if(readIf("(")) { 1672 read(")"); 1673 } 1674 Function function = Function.getFunction(database, name); 1675 function.doneWithParameters(); 1676 return function; 1677 } 1678 1679 private Expression readWildcardOrSequenceValue(String schemaName, String objectName) throws SQLException { 1680 if(readIf("*")) { 1681 return new Wildcard(schemaName, objectName); 1682 } 1683 if(schemaName == null) { 1684 schemaName = session.getCurrentSchemaName(); 1685 } 1686 if(readIf("NEXTVAL")) { 1687 Sequence sequence = database.getSchema(schemaName).findSequence(objectName); 1688 if(sequence != null) { 1689 return new SequenceValue(sequence); 1690 } 1691 } else if(readIf("CURRVAL")) { 1692 Sequence sequence = database.getSchema(schemaName).findSequence(objectName); 1693 if(sequence != null) { 1694 Function function = Function.getFunction(database, "CURRVAL"); 1695 function.setParameter(0, ValueExpression.get(ValueString.get(objectName))); 1696 return function; 1697 } 1698 } 1699 return null; 1700 } 1701 1702 private Expression readTermObjectDot(String objectName) throws SQLException { 1703 Expression expr = readWildcardOrSequenceValue(null, objectName); 1704 if(expr != null) { 1705 return expr; 1706 } 1707 String name = readColumnIdentifier(); 1708 if(readIf(".")) { 1709 String schemaName = objectName; 1710 objectName = name; 1711 expr = readWildcardOrSequenceValue(schemaName, objectName); 1712 if(expr != null) { 1713 return expr; 1714 } 1715 name = readColumnIdentifier(); 1716 return new ExpressionColumn(database, currentSelect, schemaName, objectName, name); 1717 } 1718 return new ExpressionColumn(database, currentSelect, null, objectName, name); 1719 } 1720 1721 private Expression readTerm() throws SQLException { 1722 Expression r = null; 1723 switch (currentTokenType) { 1724 case PARAMETER: 1725 boolean indexed = Character.isDigit(sqlCommandChars[parseIndex]); 1727 read(); 1728 if(indexed && currentTokenType == VALUE && currentValue.getType() == Value.INT) { 1729 if(indexedParameterList == null) { 1730 if(parameters.size()>0) { 1731 throw Message.getSQLException(Message.CANT_MIX_INDEXED_AND_UNINDEXED_PARAMS); 1732 } 1733 indexedParameterList = new ObjectArray(); 1734 } 1735 int index = currentValue.getInt() - 1; 1736 if(index < 0 || index >= Constants.MAX_PARAMETER_INDEX) { 1737 throw Message.getInvalidValueException("" + index, "Parameter Index"); 1738 } 1739 if(indexedParameterList.size() <= index) { 1740 indexedParameterList.setSize(index + 1); 1741 } 1742 r = (Parameter) indexedParameterList.get(index); 1743 if(r == null) { 1744 r = new Parameter(index); 1745 indexedParameterList.set(index, r); 1746 } 1747 read(); 1748 } else { 1749 if(indexedParameterList != null) { 1750 throw Message.getSQLException(Message.CANT_MIX_INDEXED_AND_UNINDEXED_PARAMS); 1751 } 1752 r = new Parameter(parameters.size()); 1753 } 1754 parameters.add(r); 1755 break; 1756 case KEYWORD: 1757 if(isToken("SELECT") || isToken("FROM")) { 1758 Query query = parseQueryWithParams(); 1759 return new Subquery(query); 1760 } 1761 throw getSyntaxError(); 1762 case IDENTIFIER: 1763 String name = currentToken; 1764 if(currentTokenQuoted) { 1765 read(); 1766 if(readIf(".")) { 1767 return readTermObjectDot(name); 1768 } 1769 return new ExpressionColumn(database, currentSelect, null, null, name); 1770 } 1771 read(); 1772 if("X".equals(name) && currentTokenType == VALUE && currentValue.getType() == Value.STRING) { 1773 read(); 1774 byte[] buffer = ByteUtils.convertStringToBytes(currentValue.getString()); 1775 r = ValueExpression.get(ValueBytes.getNoCopy(buffer)); 1776 } else if(readIf(".")) { 1777 return readTermObjectDot(name); 1778 } else if (readIf("(")) { 1779 return readFunction(name); 1780 } else if("CURRENT".equals(name)) { 1781 if(readIf("TIMESTAMP")) { 1782 return readFunctionWithoutParameters("CURRENT_TIMESTAMP"); 1783 } else if(readIf("TIME")) { 1784 return readFunctionWithoutParameters("CURRENT_TIME"); 1785 } else if(readIf("DATE")) { 1786 return readFunctionWithoutParameters("CURRENT_DATE"); 1787 } else { 1788 return new ExpressionColumn(database, currentSelect, null, null, name); 1789 } 1790 } else if("NEXT".equals(name) && readIf("VALUE")) { 1791 read("FOR"); 1792 String sequenceName = readIdentifierWithSchema(); 1793 Sequence sequence = getSchema().getSequence(sequenceName); 1794 return new SequenceValue(sequence); 1795 } else if("DATE".equals(name) && currentTokenType == VALUE && currentValue.getType() == Value.STRING) { 1796 String date = currentValue.getString(); 1797 read(); 1798 return ValueExpression.get(ValueDate.get(ValueDate.parseDate(date))); 1799 } else if("TIME".equals(name) && currentTokenType == VALUE && currentValue.getType() == Value.STRING) { 1800 String time = currentValue.getString(); 1801 read(); 1802 return ValueExpression.get(ValueTime.get(ValueTime.parseTime(time))); 1803 } else if("TIMESTAMP".equals(name) && currentTokenType == VALUE && currentValue.getType() == Value.STRING) { 1804 String timestamp = currentValue.getString(); 1805 read(); 1806 return ValueExpression.get(ValueTimestamp.getNoCopy(ValueTimestamp.parseTimestamp(timestamp))); 1807 } else if("CASE".equals(name)) { 1808 if(isToken("WHEN")) { 1809 return readWhen(null); 1810 } else { 1811 Expression left = readExpression(); 1812 return readWhen(left); 1813 } 1814 } else { 1815 return new ExpressionColumn(database, currentSelect, null, null, name); 1816 } 1817 break; 1818 case MINUS: 1819 read(); 1820 if (currentTokenType == VALUE) { 1821 Expression e = ValueExpression.get(currentValue.negate()); 1822 if(e.getType() == Value.LONG && e.getValue(session).getLong() == Integer.MIN_VALUE) { 1824 e = ValueExpression.get(ValueInt.get(Integer.MIN_VALUE)); 1825 } 1826 read(); 1828 return e; 1829 } 1830 return new Operation(Operation.NEGATE, readTerm(), null); 1831 case PLUS: 1832 read(); 1833 return readTerm(); 1834 case OPEN: 1835 read(); 1836 r = readExpression(); 1837 if(readIf(",")) { 1838 ObjectArray list = new ObjectArray(); 1839 list.add(r); 1840 do { 1841 r = readExpression(); 1842 list.add(r); 1843 } while(readIf(",")); 1844 Expression[] array = new Expression[list.size()]; 1845 list.toArray(array); 1846 r = new ExpressionList(array); 1847 } 1848 read(")"); 1849 break; 1850 case TRUE: 1851 read(); 1852 return ValueExpression.get(ValueBoolean.get(true)); 1853 case FALSE: 1854 read(); 1855 return ValueExpression.get(ValueBoolean.get(false)); 1856 case CURRENT_TIME: 1857 read(); 1858 return readFunctionWithoutParameters("CURRENT_TIME"); 1859 case CURRENT_DATE: 1860 read(); 1861 return readFunctionWithoutParameters("CURRENT_DATE"); 1862 case CURRENT_TIMESTAMP: { 1863 Function function = Function.getFunction(database, "CURRENT_TIMESTAMP"); 1864 read(); 1865 if(readIf("(")) { 1866 if(!readIf(")")) { 1867 function.setParameter(0, readExpression()); 1868 read(")"); 1869 } 1870 } 1871 function.doneWithParameters(); 1872 return function; 1873 } 1874 case ROWNUM: 1875 read(); 1876 if(readIf("(")) { 1877 read(")"); 1878 } 1879 return new Rownum(currentSelect == null ? currentPrepared : currentSelect); 1880 case NULL: 1881 read(); 1882 if(readIf("::")) { 1883 parseColumn(null); 1885 } 1886 return ValueExpression.NULL; 1887 case VALUE: 1888 r = ValueExpression.get(currentValue); 1889 read(); 1890 break; 1891 default: 1892 throw getSyntaxError(); 1894 } 1895 return r; 1896 } 1897 1898 private Expression readWhen(Expression left) throws SQLException { 1899 if(readIf("END")) { 1900 readIf("CASE"); 1901 return ValueExpression.NULL; 1902 } 1903 if(readIf("ELSE")) { 1904 Expression elsePart = readExpression(); 1905 read("END"); 1906 readIf("CASE"); 1907 return elsePart; 1908 } 1909 readIf("WHEN"); 1910 Expression when = readExpression(); 1911 if(left != null) { 1912 when = new Comparison(session, Comparison.EQUAL, left, when); 1913 } 1914 read("THEN"); 1915 Expression then = readExpression(); 1916 Expression elsePart = readWhen(left); 1917 Function function = Function.getFunction(session.getDatabase(), "CASEWHEN"); 1918 function.setParameter(0, when); 1919 function.setParameter(1, then); 1920 function.setParameter(2, elsePart); 1921 return function; 1922 } 1923 1924 private int getPositiveInt() throws SQLException { 1925 int v = getInt(); 1926 if(v < 0) { 1927 throw Message.getInvalidValueException("" + v, "positive integer"); 1928 } 1929 return v; 1930 } 1931 1932 private int getInt() throws SQLException { 1933 boolean minus = false; 1934 if(currentTokenType == MINUS) { 1935 minus = true; 1936 read(); 1937 } else if(currentTokenType == PLUS) { 1938 read(); 1939 } 1940 if (currentTokenType != VALUE || currentValue.getType() != Value.INT) { 1941 throw Message.getSyntaxError(sqlCommand, parseIndex, "integer"); 1942 } 1943 int i = currentValue.getInt(); 1944 read(); 1945 return minus ? -i : i; 1946 } 1947 1948 private long readLong() throws SQLException { 1949 boolean minus = false; 1950 if(currentTokenType == MINUS) { 1951 minus = true; 1952 read(); 1953 } 1954 if (currentTokenType != VALUE || (currentValue.getType() != Value.INT && currentValue.getType() != Value.DECIMAL)) { 1955 throw Message.getSyntaxError(sqlCommand, parseIndex, "long"); 1956 } 1957 long i = currentValue.getLong(); 1958 read(); 1959 return minus ? -i : i; 1960 } 1961 1962 private boolean readBooleanSetting() throws SQLException { 1963 if(currentTokenType==VALUE) { 1964 boolean result = currentValue.getBoolean().booleanValue(); 1965 read(); 1966 return result; 1967 } 1968 if(readIf("TRUE") || readIf("ON")) { 1969 return true; 1970 } else if(readIf("FALSE") || readIf("OFF")) { 1971 return false; 1972 } else { 1973 throw getSyntaxError(); 1974 } 1975 } 1976 1977 private String readString() throws SQLException { 1978 Expression expr = readExpression().optimize(session); 1980 if(!(expr instanceof ValueExpression)) { 1981 throw Message.getSyntaxError(sqlCommand, parseIndex, "string"); 1982 } 1983 String s = expr.getValue(session).getString(); 1984 return s; 1985 } 1986 1987 private String readIdentifierWithSchema(String defaultSchemaName) throws SQLException { 1988 if (currentTokenType != IDENTIFIER) { 1989 throw Message.getSyntaxError(sqlCommand, parseIndex, "identifier"); 1990 } 1991 String s = currentToken; 1992 read(); 1993 schemaName = defaultSchemaName; 1994 if (readIf(".")) { 1995 schemaName = s; 1996 if (currentTokenType != IDENTIFIER) { 1997 throw Message.getSyntaxError(sqlCommand, parseIndex, "identifier"); 1998 } 1999 s = currentToken; 2000 read(); 2001 } 2002 return s; 2003 } 2004 2005 private String readIdentifierWithSchema() throws SQLException { 2006 return readIdentifierWithSchema(session.getCurrentSchemaName()); 2007 } 2008 2009 private String readAliasIdentifier() throws SQLException { 2010 return readColumnIdentifier(); 2011 } 2012 2013 private String readUniqueIdentifier() throws SQLException { 2014 return readColumnIdentifier(); 2015 } 2016 2017 private String readColumnIdentifier() throws SQLException { 2018 if (currentTokenType != IDENTIFIER) { 2019 throw Message.getSyntaxError(sqlCommand, parseIndex, "identifier"); 2020 } 2021 String s = currentToken; 2022 read(); 2023 return s; 2024 } 2025 2026 private void read(String expected) throws SQLException { 2027 if (!expected.equals(currentToken) || currentTokenQuoted) { 2028 throw Message.getSyntaxError(sqlCommand, parseIndex, expected); 2029 } 2030 read(); 2031 } 2032 2033 private boolean readIf(String token) throws SQLException { 2034 if(token.equals(currentToken) && !currentTokenQuoted) { 2035 read(); 2036 return true; 2037 } 2038 addExpected(token); 2039 return false; 2040 } 2041 2042 private boolean isToken(String token) { 2043 boolean result = token.equals(currentToken) && !currentTokenQuoted; 2044 if(result) { 2045 return true; 2046 } 2047 addExpected(token); 2048 return false; 2049 } 2050 2051 private void addExpected(String token) { 2052 if(expected != null) { 2053 expected.add(token); 2054 } 2055 } 2056 2057 private void read() throws SQLException { 2058 currentTokenQuoted = false; 2059 if(expected != null) { 2060 expected.clear(); 2061 } 2062 int[] types = characterTypes; 2063 lastParseIndex = parseIndex; 2064 int i = parseIndex; 2065 int type = types[i]; 2066 while (type == 0) { 2067 type = types[++i]; 2068 } 2069 int start = i; 2070 char[] chars = sqlCommandChars; 2071 char c = chars[i++]; 2072 currentToken = ""; 2073 switch (type) { 2074 case CHAR_NAME: 2075 while (true) { 2076 type = types[i]; 2077 if (type != CHAR_NAME && type != CHAR_VALUE) { 2078 c = chars[i]; 2079 break; 2080 } 2081 i++; 2082 } 2083 currentToken = StringCache.getNew(sqlCommand.substring(start, i)); 2084 currentTokenType = getTokenType(currentToken); 2085 parseIndex = i; 2086 return; 2087 case CHAR_QUOTED: { 2088 String result = null; 2089 while(true) { 2090 for(int begin=i; ; i++) { 2091 if(chars[i]=='\"') { 2092 if(result == null) { 2093 result = sqlCommand.substring(begin, i); 2094 } else { 2095 result += sqlCommand.substring(begin-1, i); 2096 } 2097 break; 2098 } 2099 } 2100 if(chars[++i] != '\"') { 2101 break; 2102 } 2103 i++; 2104 } 2105 currentToken = StringCache.getNew(result); 2106 parseIndex = i; 2107 currentTokenQuoted = true; 2108 currentTokenType = IDENTIFIER; 2109 return; 2110 } 2111 case CHAR_SPECIAL_2: 2112 if (types[i] == CHAR_SPECIAL_2) { 2113 i++; 2114 } 2115 case CHAR_SPECIAL_1: 2117 currentToken = sqlCommand.substring(start, i); 2118 currentTokenType = getSpecialType(currentToken); 2119 parseIndex = i; 2120 return; 2121 case CHAR_VALUE: 2122 if(c == '0' && chars[i] == 'X') { 2123 long number = 0; 2125 start += 2; 2126 i++; 2127 while (true) { 2128 c = chars[i]; 2129 if ((c < '0' || c > '9') && (c<'A' || c>'F')) { 2130 checkLiterals(false); 2131 currentValue = ValueInt.get((int) number); 2132 currentTokenType = VALUE; 2133 currentToken = "0"; 2134 parseIndex = i; 2135 return; 2136 } 2137 number = (number << 4) + c - (c >= 'A' ? ('A' - 0xa) : ('0')); 2138 if (number > Integer.MAX_VALUE) { 2139 readHexDecimal(start, i); 2140 return; 2141 } 2142 i++; 2143 } 2144 } 2145 long number = c - '0'; 2146 while (true) { 2147 c = chars[i]; 2148 if (c < '0' || c > '9') { 2149 if (c == '.') { 2150 readDecimal(start, i); 2151 break; 2152 } 2153 if (c == 'E') { 2154 readDecimal(start, i); 2155 break; 2156 } 2157 checkLiterals(false); 2158 currentValue = ValueInt.get((int) number); 2159 currentTokenType = VALUE; 2160 currentToken = "0"; 2161 parseIndex = i; 2162 break; 2163 } 2164 number = number * 10 + (c - '0'); 2165 if (number > Integer.MAX_VALUE) { 2166 readDecimal(start, i); 2167 break; 2168 } 2169 i++; 2170 } 2171 return; 2172 case CHAR_DECIMAL: 2173 if (types[i] != CHAR_VALUE) { 2174 currentTokenType = KEYWORD; 2175 currentToken = "."; 2176 parseIndex = i; 2177 return; 2178 } 2179 readDecimal(i - 1, i); 2180 return; 2181 case CHAR_STRING: { 2182 String result = null; 2183 while(true) { 2184 for(int begin=i; ; i++) { 2185 if(chars[i]=='\'') { 2186 if(result == null) { 2187 result = sqlCommand.substring(begin, i); 2188 } else { 2189 result += sqlCommand.substring(begin-1, i); 2190 } 2191 break; 2192 } 2193 } 2194 if(chars[++i] != '\'') { 2195 break; 2196 } 2197 i++; 2198 } 2199 currentToken = "'"; 2200 checkLiterals(false); 2201 currentValue = ValueString.get(StringCache.getNew(result)); 2202 parseIndex = i; 2203 currentTokenType = VALUE; 2204 return; 2205 } 2206 case CHAR_END: 2207 currentToken = ""; 2208 currentTokenType = END; 2209 parseIndex = i; 2210 return; 2211 default: 2212 throw getSyntaxError(); 2214 } 2215 } 2216 2217 private void checkLiterals(boolean text) throws SQLException { 2218 if(!session.getAllowLiterals()) { 2219 int allowed = database.getAllowLiterals(); 2220 if(allowed == Constants.ALLOW_LITERALS_NONE || (text && allowed != Constants.ALLOW_LITERALS_ALL)) { 2221 throw Message.getSQLException(Message.LITERALS_ARE_NOT_ALLOWED); 2222 } 2223 } 2224 } 2225 2226 private void readHexDecimal(int start, int i) throws SQLException { 2227 char[] chars = sqlCommandChars; 2228 char c; 2229 do { 2230 c = chars[++i]; 2231 } while ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) ; 2232 parseIndex = i; 2233 String sub = sqlCommand.substring(start, i); 2234 BigDecimal bd = new BigDecimal (new BigInteger (sub, 16)); 2235 checkLiterals(false); 2236 currentValue = ValueDecimal.get(bd); 2237 currentTokenType = VALUE; 2238 } 2239 2240 private void readDecimal(int start, int i) throws SQLException { 2241 char[] chars = sqlCommandChars; 2242 int[] types = characterTypes; 2243 while(true) { 2245 int t = types[i]; 2246 if(t != CHAR_DECIMAL && t != CHAR_VALUE) { 2247 break; 2248 } 2249 i++; 2250 } 2251 if (chars[i] == 'E') { 2252 i++; 2253 if (chars[i] == '+' || chars[i] == '-') { 2254 i++; 2255 } 2256 if (types[i] != CHAR_VALUE) { 2257 throw getSyntaxError(); 2259 } 2260 while (types[++i] == CHAR_VALUE) { 2261 } 2263 } 2264 parseIndex = i; 2265 String sub = sqlCommand.substring(start, i); 2266 BigDecimal bd; 2267 try { 2268 bd = new BigDecimal (sub); 2269 } catch (NumberFormatException e) { 2270 throw Message.getSQLException(Message.DATA_CONVERSION_ERROR_1, new String [] { sub }, e); 2271 } 2272 checkLiterals(false); 2273 currentValue = ValueDecimal.get(bd); 2274 currentTokenType = VALUE; 2275 } 2276 2277 public String getOriginalSQL() { 2278 return originalSQL; 2279 } 2280 2281 public Session getSession() { 2282 return session; 2283 } 2284 2285 private void initialize(String sql) throws SQLException { 2286 if(sql == null) { 2287 sql = ""; 2288 } 2289 originalSQL = sql; 2290 sqlCommand = sql; 2291 int len = sql.length() + 1; 2292 char[] command = new char[len]; 2293 int[] types = new int[len]; 2294 len--; 2295 sql.getChars(0, len, command, 0); 2296 boolean changed = false; 2297 command[len] = ' '; 2298 int startLoop = 0; 2299 for (int i = 0; i < len; i++) { 2301 char c = command[i]; 2302 int type = 0; 2303 switch (c) { 2304 case '/': 2305 if (command[i + 1] == '*') { 2306 changed = true; 2308 command[i] = ' '; 2309 command[i + 1] = ' '; 2310 startLoop = i; 2311 i += 2; 2312 checkRunOver(i, len, startLoop); 2313 while (command[i] != '*' || command[i + 1] != '/') { 2314 command[i++] = ' '; 2315 checkRunOver(i, len, startLoop); 2316 } 2317 command[i] = ' '; 2318 command[i + 1] = ' '; 2319 i++; 2320 break; 2321 } else if(command[i + 1] == '/') { 2322 changed = true; 2324 startLoop = i; 2325 while (true) { 2326 c = command[i]; 2327 if (c == '\n' || c == '\r' || i >= len-1) { 2328 break; 2329 } 2330 command[i++] = ' '; 2331 checkRunOver(i, len, startLoop); 2332 } 2333 break; 2334 } 2335 case '-': 2337 if (command[i + 1] == '-') { 2338 changed = true; 2340 startLoop = i; 2341 while (true) { 2342 c = command[i]; 2343 if (c == '\n' || c == '\r' || i >= len-1) { 2344 break; 2345 } 2346 command[i++] = ' '; 2347 checkRunOver(i, len, startLoop); 2348 } 2349 break; 2350 } 2351 case '(': 2353 case ')': 2354 case '{': 2355 case '}': 2356 case '*': 2357 case ',': 2358 case ';': 2359 case '+': 2360 case '%': 2361 case '?': 2362 type = CHAR_SPECIAL_1; 2363 break; 2364 case '!': 2365 case '<': 2366 case '>': 2367 case '|': 2368 case '=': 2369 case ':': 2370 type = CHAR_SPECIAL_2; 2371 break; 2372 case '.': 2373 type = CHAR_DECIMAL; 2374 break; 2375 case '\'': 2376 type = types[i] = CHAR_STRING; 2377 startLoop = i; 2378 while (command[++i] != '\'') { 2379 checkRunOver(i, len, startLoop); 2380 } 2381 break; 2382 case '[': 2383 command[i] = '"'; 2385 changed = true; 2386 type = types[i] = CHAR_QUOTED; 2387 startLoop = i; 2388 while (command[++i] != ']') { 2389 checkRunOver(i, len, startLoop); 2390 } 2391 command[i] = '"'; 2392 break; 2393 case '`': 2394 command[i] = '"'; 2396 changed = true; 2397 type = types[i] = CHAR_QUOTED; 2398 startLoop = i; 2399 while (command[++i] != '`') { 2400 checkRunOver(i, len, startLoop); 2401 c = command[i]; 2402 command[i] = Character.toUpperCase(c); 2403 } 2404 command[i] = '"'; 2405 break; 2406 case '\"': 2407 type = types[i] = CHAR_QUOTED; 2408 startLoop = i; 2409 while (command[++i] != '\"') { 2410 checkRunOver(i, len, startLoop); 2411 } 2412 break; 2413 case '_': 2414 type = CHAR_NAME; 2415 break; 2416 default: 2417 if (c >= 'a' && c <= 'z') { 2418 command[i] = (char) (c - ('a' - 'A')); 2419 changed = true; 2420 type = CHAR_NAME; 2421 } else if (c >= 'A' && c <= 'Z') { 2422 type = CHAR_NAME; 2423 } else if (c >= '0' && c <= '9') { 2424 type = CHAR_VALUE; 2425 } else { 2426 if(Character.isLetterOrDigit(c)) { 2427 type = CHAR_NAME; 2428 char u = Character.toUpperCase(c); 2429 if(u != c) { 2430 command[i] = u; 2431 changed = true; 2432 } 2433 } 2434 } 2435 } 2436 types[i] = (byte)type; 2437 } 2438 sqlCommandChars = command; 2439 types[len] = CHAR_END; 2440 characterTypes = types; 2441 if(changed) { 2442 sqlCommand = new String (command); 2443 } 2444 parseIndex = 0; 2445 } 2446 2447 private void checkRunOver(int i, int len, int startLoop) throws SQLException { 2448 if(i >= len) { 2449 parseIndex = startLoop; 2450 throw getSyntaxError(); 2452 } 2453 } 2454 2455 private int getSpecialType(String s) throws SQLException { 2456 char c0 = s.charAt(0); 2457 if(s.length()==1) { 2458 switch(c0) { 2459 case '?': 2460 return PARAMETER; 2461 case '+': 2462 return PLUS; 2463 case '-': 2464 return MINUS; 2465 case '{': 2466 case '}': 2467 case '*': 2468 case '/': 2469 case ';': 2470 case ',': 2471 case ':': 2472 return KEYWORD; 2473 case '(': 2474 return OPEN; 2475 case ')': 2476 return CLOSE; 2477 case '<': 2478 return SMALLER; 2479 case '>': 2480 return BIGGER; 2481 case '=': 2482 return EQUAL; 2483 } 2484 } else if(s.length()==2) { 2485 switch (c0) { 2486 case ':': 2487 if(s.equals("::")) { 2488 return KEYWORD; 2489 } 2490 break; 2491 case '>': 2492 if(s.equals(">=")) { 2493 return BIGGER_EQUAL; 2494 } 2495 break; 2496 case '<': 2497 if (s.equals("<=")) { 2498 return SMALLER_EQUAL; 2499 } else if (s.equals("<>")) { 2500 return NOT_EQUAL; 2501 } 2502 break; 2503 case '!': 2504 if (s.equals("!=")) { 2505 return NOT_EQUAL; 2506 } 2507 break; 2508 case '|': 2509 if(s.equals("||")) { 2510 return STRINGCONCAT; 2511 } 2512 } 2513 } 2514 throw getSyntaxError(); 2515 } 2516 2517 private int getTokenType(String s) throws SQLException { 2518 int len = s.length(); 2520 if(len == 0) { 2521 throw getSyntaxError(); 2522 } 2523 return getSaveTokenType(s); 2524 } 2525 2526 public static boolean isKeyword(String s) { 2527 if(s == null || s.length() == 0) { 2528 return false; 2529 } 2530 return getSaveTokenType(s) != IDENTIFIER; 2531 } 2532 2533 private static int getSaveTokenType(String s) { 2534 switch (s.charAt(0)) { 2535 case 'C': 2536 if(s.endsWith("CURRENT_TIMESTAMP")) { 2537 return CURRENT_TIMESTAMP; 2538 } else if(s.endsWith("CURRENT_TIME")) { 2539 return CURRENT_TIME; 2540 } else if(s.endsWith("CURRENT_DATE")) { 2541 return CURRENT_DATE; 2542 } 2543 return getKeywordOrIdentifier(s, "CROSS", KEYWORD); 2544 case 'D': 2545 return getKeywordOrIdentifier(s, "DISTINCT", KEYWORD); 2546 case 'E': 2547 if(s.equals("EXCEPT")) { 2548 return KEYWORD; 2549 } 2550 return getKeywordOrIdentifier(s, "EXISTS", KEYWORD); 2551 case 'F': 2552 if(s.equals("FROM")) { 2553 return KEYWORD; 2554 } else if(s.equals("FOR")) { 2555 return KEYWORD; 2556 } else if(s.equals("FULL")) { 2557 return KEYWORD; 2558 } 2559 return getKeywordOrIdentifier(s, "FALSE", FALSE); 2560 case 'G': 2561 return getKeywordOrIdentifier(s, "GROUP", KEYWORD); 2562 case 'H': 2563 return getKeywordOrIdentifier(s, "HAVING", KEYWORD); 2564 case 'I': 2565 if (s.equals("INNER")) { 2566 return KEYWORD; 2567 } else if(s.equals("INTERSECT")) { 2568 return KEYWORD; 2569 } 2570 return getKeywordOrIdentifier(s, "IS", KEYWORD); 2571 case 'J': 2572 return getKeywordOrIdentifier(s, "JOIN", KEYWORD); 2573 case 'L': 2574 if (s.equals("LIMIT")) { 2575 return KEYWORD; 2576 } 2577 return getKeywordOrIdentifier(s, "LIKE", KEYWORD); 2578 case 'M': 2579 if(s.equals("MINUS")) { 2580 return KEYWORD; 2581 } 2582 break; 2583 case 'N': 2584 if(s.equals("NOT")) { 2585 return KEYWORD; 2586 } else if(s.equals("NATURAL")) { 2587 return KEYWORD; 2588 } 2589 return getKeywordOrIdentifier(s, "NULL", NULL); 2590 case 'O': 2591 if (s.equals("ON")) { 2592 return KEYWORD; 2593 } 2594 return getKeywordOrIdentifier(s, "ORDER", KEYWORD); 2595 case 'P': 2596 return getKeywordOrIdentifier(s, "PRIMARY", KEYWORD); 2597 case 'R': 2598 return getKeywordOrIdentifier(s, "ROWNUM", ROWNUM); 2599 case 'S': 2600 if(s.endsWith("SYSTIMESTAMP")) { 2601 return CURRENT_TIMESTAMP; 2602 } else if(s.endsWith("SYSTIME")) { 2603 return CURRENT_TIME; 2604 } else if(s.endsWith("SYSDATE")) { 2605 return CURRENT_DATE; 2606 } 2607 return getKeywordOrIdentifier(s, "SELECT", KEYWORD); 2608 case 'T': 2609 if(s.equals("TODAY")) { 2610 return CURRENT_DATE; 2611 } 2612 return getKeywordOrIdentifier(s, "TRUE", TRUE); 2613 case 'U': 2614 return getKeywordOrIdentifier(s, "UNION", KEYWORD); 2615 case 'W': 2616 return getKeywordOrIdentifier(s, "WHERE", KEYWORD); 2617 } 2618 return IDENTIFIER; 2619 } 2620 2621 private static int getKeywordOrIdentifier(String s1, String s2, int keywordType) { 2622 if (s1.equals(s2)) { 2623 return keywordType; 2624 } 2625 return IDENTIFIER; 2626 } 2627 2628 private Column parseColumnForTable(String columnName) throws SQLException { 2629 Column column; 2630 if(readIf("IDENTITY")) { 2631 column = new Column(columnName, Value.LONG, ValueLong.PRECISION, 0); 2632 column.setOriginalSQL("IDENTITY"); 2633 long start = 1, increment = 1; 2634 if(readIf("(")) { 2635 start = readLong(); 2636 if(readIf(",")) { 2637 increment = readLong(); 2638 } 2639 read(")"); 2640 } 2641 column.setAutoIncrement(true, start, increment); 2642 } else { 2643 column = parseColumn(columnName); 2644 } 2645 if (readIf("NOT")) { 2646 read("NULL"); 2647 column.setNullable(false); 2648 } else { 2649 readIf("NULL"); 2650 column.setNullable(true); 2651 } 2652 if(readIf("AS")) { 2653 Expression expr = readExpression(); 2654 column.setComputed(true, expr); 2655 } else if (readIf("DEFAULT")) { 2656 Expression defaultExpression = readExpression(); 2657 column.setDefaultExpression(session, defaultExpression); 2658 } else if(readIf("GENERATED")) { 2659 read("BY"); 2660 read("DEFAULT"); 2661 read("AS"); 2662 read("IDENTITY"); 2663 long start = 1, increment = 1; 2664 if(readIf("(")) { 2665 read("START"); 2666 read("WITH"); 2667 start = readLong(); 2668 readIf(","); 2669 if(readIf("INCREMENT")) { 2670 read("BY"); 2671 increment = readLong(); 2672 } 2673 read(")"); 2674 } 2675 column.setAutoIncrement(true, start, increment); 2676 } 2677 if (readIf("NOT")) { 2678 read("NULL"); 2679 column.setNullable(false); 2680 } else { 2681 readIf("NULL"); 2682 } 2683 if(readIf("AUTO_INCREMENT") || readIf("IDENTITY")) { 2684 long start = 1, increment = 1; 2685 if(readIf("(")) { 2686 start = readLong(); 2687 if(readIf(",")) { 2688 increment = readLong(); 2689 } 2690 read(")"); 2691 } 2692 column.setAutoIncrement(true, start, increment); 2693 if (readIf("NOT")) { 2694 read("NULL"); 2695 } 2696 } 2697 if(readIf("NULL_TO_DEFAULT")) { 2698 column.setConvertNullToDefault(true); 2699 } 2700 if(readIf("SEQUENCE")) { 2701 String sequenceName = readIdentifierWithSchema(); 2702 Sequence sequence = getSchema().getSequence(sequenceName); 2703 column.setSequence(sequence); 2704 } 2705 if(readIf("SELECTIVITY")) { 2706 int sel = getPositiveInt(); 2707 column.setSelectivity(sel); 2708 } 2709 column.setComment(readCommentIf()); 2710 return column; 2711 } 2712 2713 private String readCommentIf() throws SQLException { 2714 if(readIf("COMMENT")) { 2715 readIf("IS"); 2716 return readString(); 2717 } 2718 return null; 2719 } 2720 2721 private Column parseColumn(String columnName) throws SQLException { 2722 String original = currentToken; 2723 boolean regular = false; 2724 if(readIf("LONG")) { 2725 if(readIf("RAW")) { 2726 original += " RAW"; 2727 } 2728 } else if(readIf("DOUBLE")) { 2729 if(readIf("PRECISION")) { 2730 original += " PRECISION"; 2731 } 2732 } else { 2733 regular = true; 2734 } 2735 DataType dataType = DataType.getTypeByName(original); 2736 long precision = -1; 2737 int scale = -1; 2738 Column templateColumn = null; 2739 if(dataType==null) { 2740 UserDataType userDataType = database.findUserDataType(original); 2741 if(userDataType == null) { 2742 throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, currentToken); 2743 } else { 2744 templateColumn = userDataType.getColumn(); 2745 dataType = DataType.getDataType(templateColumn.getType()); 2746 original = templateColumn.getOriginalSQL(); 2747 precision = templateColumn.getPrecision(); 2748 scale = templateColumn.getScale(); 2749 } 2750 } 2751 if(database.getIgnoreCase() && dataType.type == Value.STRING && !"VARCHAR_CASESENSITIVE".equals(original)) { 2752 original = "VARCHAR_IGNORECASE"; 2753 dataType = DataType.getTypeByName(original); 2754 } 2755 if(regular) { 2756 read(); 2757 } 2758 precision = precision == -1 ? dataType.defaultPrecision : precision; 2759 scale = scale == -1 ? dataType.defaultScale : scale; 2760 if(dataType.supportsPrecision || dataType.supportsScale) { 2761 if(readIf("(")) { 2762 precision = getPositiveInt(); 2763 if(readIf("K")) { 2764 precision *= 1024; 2765 } else if(readIf("M")) { 2766 precision *= 1024 * 1024; 2767 } else if(readIf("G")) { 2768 precision *= 1024 * 1024 * 1024; 2769 } 2770 if(precision > Integer.MAX_VALUE) { 2771 precision = Integer.MAX_VALUE; 2772 } 2773 original += "(" + precision; 2774 readIf("CHAR"); 2776 if(dataType.supportsScale) { 2777 if(readIf(",")) { 2778 scale = getPositiveInt(); 2779 original += ", " + scale; 2780 } else { 2781 scale = 0; 2782 } 2783 } 2784 original += ")"; 2785 read(")"); 2786 } 2787 } else if(readIf("(")) { 2788 getPositiveInt(); 2790 read(")"); 2791 } 2792 if(readIf("FOR")) { 2793 read("BIT"); 2794 read("DATA"); 2795 if(dataType.type == Value.STRING) { 2796 dataType = DataType.getTypeByName("BINARY"); 2797 } 2798 } 2799 int type = dataType.type; 2800 Column column = new Column(columnName, type, precision, scale); 2801 if(templateColumn != null) { 2802 column.setNullable(templateColumn.getNullable()); 2803 column.setDefaultExpression(session, templateColumn.getDefaultExpression()); 2804 int selectivity = templateColumn.getSelectivity(); 2805 if(selectivity != Constants.SELECTIVITY_DEFAULT) { 2806 column.setSelectivity(selectivity); 2807 } 2808 Expression checkConstraint = templateColumn.getCheckConstraint(session, columnName); 2809 if(checkConstraint != null) { 2810 column.addCheckConstraint(session, checkConstraint); 2811 } 2812 } 2813 column.setOriginalSQL(original); 2814 return column; 2815 } 2816 2817 private Prepared parseCreate() throws SQLException { 2818 boolean force = readIf("FORCE"); 2819 if(readIf("LOCAL")) { 2820 read("TEMPORARY"); 2821 read("TABLE"); 2822 return parseCreateTable(true, false, false); 2823 } else if(readIf("GLOBAL")) { 2824 read("TEMPORARY"); 2825 read("TABLE"); 2826 return parseCreateTable(true, true, false); 2827 } else if(readIf("TEMP") || readIf("TEMPORARY")) { 2828 read("TABLE"); 2829 return parseCreateTable(true, true, false); 2830 } else if (readIf("MEMORY")) { 2831 read("TABLE"); 2832 return parseCreateTable(false, false, false); 2833 } else if(readIf("LINKED")) { 2834 return parseCreateLinkedTable(); 2835 } else if (readIf("CACHED")) { 2836 read("TABLE"); 2837 return parseCreateTable(false, false, true); 2838 } else if (readIf("TABLE")) { 2839 int defaultMode; 2840 Setting setting = database.findSetting(SetTypes.getTypeName(SetTypes.DEFAULT_TABLE_TYPE)); 2841 defaultMode = setting == null ? Constants.DEFAULT_TABLE_TYPE : setting.getIntValue(); 2842 return parseCreateTable(false, false, defaultMode==Table.TYPE_CACHED); 2843 } else if(readIf("VIEW")) { 2844 return parseCreateView(force); 2845 } else if (readIf("ALIAS")) { 2846 return parseCreateFunctionAlias(); 2847 } else if (readIf("SEQUENCE")) { 2848 return parseCreateSequence(); 2849 } else if (readIf("USER")) { 2850 return parseCreateUser(); 2851 } else if (readIf("TRIGGER")) { 2852 return parseCreateTrigger(); 2853 } else if (readIf("ROLE")) { 2854 return parseCreateRole(); 2855 } else if(readIf("SCHEMA")) { 2856 return parseCreateSchema(); 2857 } else if(readIf("CONSTANT")) { 2858 return parseCreateConstant(); 2859 } else if(readIf("DOMAIN")) { 2860 return parseCreateUserDataType(); 2861 } else if(readIf("TYPE")) { 2862 return parseCreateUserDataType(); 2863 } else if(readIf("DATATYPE")) { 2864 return parseCreateUserDataType(); 2865 } else { 2866 boolean hash = false, primaryKey = false, unique = false; 2867 String indexName = null; 2868 Schema oldSchema = null; 2869 boolean ifNotExists = false; 2870 if(readIf("PRIMARY")) { 2871 read("KEY"); 2872 if(readIf("HASH")) { 2873 hash = true; 2874 } 2875 primaryKey = true; 2876 } else { 2877 if (readIf("UNIQUE")) { 2878 unique = true; 2879 if(readIf("HASH")) { 2880 hash = true; 2881 } 2882 } if(readIf("INDEX")) { 2883 if(!isToken("ON")) { 2884 ifNotExists = readIfNoExists(); 2885 indexName = readIdentifierWithSchema(null); 2886 oldSchema = getSchema(); 2887 } 2888 } else { 2889 throw getSyntaxError(); 2890 } 2891 } 2892 read("ON"); 2893 String tableName = readIdentifierWithSchema(); 2894 checkSchema(oldSchema); 2895 CreateIndex command = new CreateIndex(session, getSchema()); 2896 command.setIfNotExists(ifNotExists); 2897 command.setHash(hash); 2898 command.setPrimaryKey(primaryKey); 2899 command.setTableName(tableName); 2900 command.setUnique(unique); 2901 command.setIndexName(indexName); 2902 command.setComment(readCommentIf()); 2903 read("("); 2904 command.setColumnNames(parseColumnList(true)); 2905 return command; 2906 } 2907 } 2908 2909 private boolean addRoleOrRight(GrantRevoke command) throws SQLException { 2910 if(readIf("SELECT")) { 2911 command.addRight(Right.SELECT); 2912 return false; 2913 } else if(readIf("DELETE")) { 2914 command.addRight(Right.DELETE); 2915 return false; 2916 } else if(readIf("INSERT")) { 2917 command.addRight(Right.INSERT); 2918 return false; 2919 } else if(readIf("UPDATE")) { 2920 command.addRight(Right.UPDATE); 2921 return false; 2922 } else if(readIf("ALL")) { 2923 command.addRight(Right.ALL); 2924 return false; 2925 } else if(readIf("CONNECT")) { 2926 return false; 2928 } else if(readIf("RESOURCE")) { 2929 return false; 2931 } else { 2932 command.addRoleName(readUniqueIdentifier()); 2933 return true; 2934 } 2935 } 2936 2937 private GrantRevoke parseGrantRevoke(int operationType) throws SQLException { 2938 GrantRevoke command = new GrantRevoke(session); 2939 command.setOperationType(operationType); 2940 boolean isRoleBased = addRoleOrRight(command); 2941 while(readIf(",")) { 2942 boolean next = addRoleOrRight(command); 2943 if(next != isRoleBased) { 2944 throw Message.getSQLException(Message.ROLES_AND_RIGHT_CANNOT_BE_MIXED); 2945 } 2946 } 2947 if(!isRoleBased) { 2948 if(readIf("ON")) { 2949 do { 2950 String tableName = readIdentifierWithSchema(); 2951 Table table = getSchema().getTableOrView(session, tableName); 2952 command.addTable(table); 2953 } while(readIf(",")); 2954 } 2955 } 2956 if(operationType == GrantRevoke.GRANT) { 2957 read("TO"); 2958 } else { 2959 read("FROM"); 2960 } 2961 command.setGranteeName(readUniqueIdentifier()); 2962 return command; 2963 } 2964 2965 private Call parserCall() throws SQLException { 2966 Call command = new Call(session); 2967 currentPrepared = command; 2968 command.setValue(readExpression()); 2969 return command; 2970 } 2971 2972 private CreateRole parseCreateRole() throws SQLException { 2973 CreateRole command = new CreateRole(session); 2974 command.setIfNotExists(readIfNoExists()); 2975 command.setRoleName(readUniqueIdentifier()); 2976 return command; 2977 } 2978 2979 private CreateSchema parseCreateSchema() throws SQLException { 2980 CreateSchema command = new CreateSchema(session); 2981 command.setIfNotExists(readIfNoExists()); 2982 command.setSchemaName(readUniqueIdentifier()); 2983 if(readIf("AUTHORIZATION")) { 2984 command.setAuthorization(readUniqueIdentifier()); 2985 } else { 2986 command.setAuthorization(session.getUser().getName()); 2987 } 2988 return command; 2989 } 2990 2991 private CreateSequence parseCreateSequence() throws SQLException { 2992 boolean ifNotExists = readIfNoExists(); 2993 String sequenceName = readIdentifierWithSchema(); 2994 CreateSequence command = new CreateSequence(session, getSchema()); 2995 command.setIfNotExists(ifNotExists); 2996 command.setSequenceName(sequenceName); 2997 if(readIf("START")) { 2998 read("WITH"); 2999 long start = readLong(); 3000 command.setStartWith(start); 3001 } 3002 if(readIf("INCREMENT")) { 3003 read("BY"); 3004 long increment = readLong(); 3005 command.setIncrement(increment); 3006 } 3007 if(readIf("BELONGS_TO_TABLE")) { 3008 command.setBelongsToTable(true); 3009 } 3010 return command; 3011 } 3012 3013 private boolean readIfNoExists() throws SQLException { 3014 if(readIf("IF")) { 3015 read("NOT"); 3016 read("EXISTS"); 3017 return true; 3018 } 3019 return false; 3020 } 3021 3022 private CreateConstant parseCreateConstant() throws SQLException { 3023 boolean ifNotExists = readIfNoExists(); 3024 String constantName = readIdentifierWithSchema(); 3025 Schema schema = getSchema(); 3026 read("VALUE"); 3027 Expression expr = readExpression(); 3028 CreateConstant command = new CreateConstant(session, schema); 3029 command.setConstantName(constantName); 3030 command.setExpression(expr); 3031 command.setIfNotExists(ifNotExists); 3032 return command; 3033 } 3034 3035 private CreateUserDataType parseCreateUserDataType() throws SQLException { 3036 boolean ifNotExists = readIfNoExists(); 3037 CreateUserDataType command = new CreateUserDataType(session); 3038 command.setTypeName(readUniqueIdentifier()); 3039 read("AS"); 3040 Column col = parseColumnForTable("VALUE"); 3041 if(readIf("CHECK")) { 3042 Expression expr = readExpression(); 3043 col.addCheckConstraint(session, expr); 3044 } 3045 col.rename(null); 3046 command.setColumn(col); 3047 command.setIfNotExists(ifNotExists); 3048 return command; 3049 } 3050 3051 private CreateTrigger parseCreateTrigger() throws SQLException { 3052 boolean ifNotExists = readIfNoExists(); 3053 String triggerName = readIdentifierWithSchema(null); 3054 Schema schema = getSchema(); 3055 boolean isBefore; 3056 if(readIf("BEFORE")) { 3057 isBefore = true; 3058 } else { 3059 read("AFTER"); 3060 isBefore = false; 3061 } 3062 int typeMask = 0; 3063 do { 3064 if(readIf("INSERT")) { 3065 typeMask |= TriggerObject.INSERT; 3066 } else if(readIf("UPDATE")) { 3067 typeMask |= TriggerObject.UPDATE; 3068 } else if(readIf("DELETE")) { 3069 typeMask |= TriggerObject.DELETE; 3070 } else { 3071 throw getSyntaxError(); 3072 } 3073 } while(readIf(",")); 3074 read("ON"); 3075 String tableName = readIdentifierWithSchema(); 3076 checkSchema(schema); 3077 CreateTrigger command = new CreateTrigger(session, getSchema()); 3078 command.setTriggerName(triggerName); 3079 command.setIfNotExists(ifNotExists); 3080 command.setBefore(isBefore); 3081 command.setTypeMask(typeMask); 3082 command.setTableName(tableName); 3083 if(readIf("FOR")) { 3084 read("EACH"); 3085 read("ROW"); 3086 command.setRowBased(true); 3087 } else { 3088 command.setRowBased(false); 3089 } 3090 if(readIf("QUEUE")) { 3091 command.setQueueSize(getPositiveInt()); 3092 } 3093 command.setNoWait(readIf("NOWAIT")); 3094 read("CALL"); 3095 command.setTriggerClassName(readUniqueIdentifier()); 3096 return command; 3097 } 3098 3099 private CreateUser parseCreateUser() throws SQLException { 3100 CreateUser command = new CreateUser(session); 3101 command.setIfNotExists(readIfNoExists()); 3102 command.setUserName(readUniqueIdentifier()); 3103 command.setComment(readCommentIf()); 3104 if(readIf("PASSWORD")) { 3105 command.setPassword(readString()); 3106 } else if(readIf("SALT")) { 3107 command.setSalt(readString()); 3108 read("HASH"); 3109 command.setHash(readString()); 3110 } else if(readIf("IDENTIFIED")) { 3111 read("BY"); 3112 command.setPassword(readColumnIdentifier()); 3114 } else { 3115 throw getSyntaxError(); 3116 } 3117 if(readIf("ADMIN")) { 3118 command.setAdmin(true); 3119 } 3120 return command; 3121 } 3122 3123 private CreateFunctionAlias parseCreateFunctionAlias() throws SQLException { 3124 boolean ifNotExists = readIfNoExists(); 3125 CreateFunctionAlias command = new CreateFunctionAlias(session); 3126 command.setAliasName(readUniqueIdentifier()); 3127 command.setIfNotExists(ifNotExists); 3128 read("FOR"); 3129 command.setJavaClassMethod(readUniqueIdentifier()); 3130 return command; 3131 } 3132 3133 private CreateView parseCreateView(boolean force) throws SQLException { 3134 boolean ifNotExists = readIfNoExists(); 3135 String viewName = readIdentifierWithSchema(); 3136 CreateView command = new CreateView(session, getSchema()); 3137 command.setViewName(viewName); 3138 command.setIfNotExists(ifNotExists); 3139 String select = StringCache.getNew(sqlCommand.substring(parseIndex)); 3140 command.setComment(readCommentIf()); 3141 if(readIf("(")) { 3142 String [] cols = parseColumnList(false); 3143 command.setColumnNames(cols); 3144 } 3145 read("AS"); 3146 try { 3147 Query query = parseSelect(); 3148 query.prepare(); 3149 command.setSelect(query); 3150 } catch(SQLException e) { 3151 if(force) { 3152 command.setSelectSQL(select); 3153 } else { 3154 throw e; 3155 } 3156 } 3157 return command; 3158 } 3159 3160 private TransactionCommand parseCheckpoint() throws SQLException { 3161 TransactionCommand command; 3162 if(readIf("SYNC")) { 3163 command = new TransactionCommand(session, TransactionCommand.CHECKPOINT_SYNC); 3164 } else { 3165 command = new TransactionCommand(session, TransactionCommand.CHECKPOINT); 3166 } 3167 return command; 3168 } 3169 3170 private Prepared parseAlter() throws SQLException { 3171 if(readIf("TABLE")) { 3172 return parseAlterTable(); 3173 } else if(readIf("USER")) { 3174 return parseAlterUser(); 3175 } else if(readIf("INDEX")) { 3176 return parseAlterIndex(); 3177 } else if(readIf("SEQUENCE")) { 3178 return parseAlterSequence(); 3179 } else if(readIf("VIEW")) { 3180 return parseAlterView(); 3181 } 3182 throw getSyntaxError(); 3183 } 3184 3185 private void checkSchema(Schema old) throws SQLException { 3186 if(old != null && getSchema() != old) { 3187 throw Message.getSQLException(Message.SCHEMA_NAME_MUST_MATCH); 3188 } 3189 } 3190 3191 private AlterIndexRename parseAlterIndex() throws SQLException { 3192 String indexName = readIdentifierWithSchema(); 3193 Schema old = getSchema(); 3194 AlterIndexRename command = new AlterIndexRename(session, getSchema()); 3195 command.setOldIndex(getSchema().getIndex(indexName)); 3196 read("RENAME"); 3197 read("TO"); 3198 String newName = readIdentifierWithSchema(old.getSQL()); 3199 checkSchema(old); 3200 command.setNewName(newName); 3201 return command; 3202 } 3203 3204 private AlterView parseAlterView() throws SQLException { 3205 AlterView command = new AlterView(session); 3206 String viewName = readIdentifierWithSchema(); 3207 Table tableView = getSchema().findTableOrView(session, viewName); 3208 if(!(tableView instanceof TableView)) { 3209 throw Message.getSQLException(Message.VIEW_NOT_FOUND_1, viewName); 3210 } 3211 TableView view = (TableView)tableView; 3212 command.setView(view); 3213 read("RECOMPILE"); 3214 return command; 3215 } 3216 3217 private AlterSequence parseAlterSequence() throws SQLException { 3218 AlterSequence command = new AlterSequence(session); 3219 String sequenceName = readIdentifierWithSchema(); 3220 command.setSequence(getSchema().getSequence(sequenceName)); 3221 if(readIf("RESTART")) { 3222 read("WITH"); 3223 long start = readLong(); 3224 command.setStartWith(start); 3225 } 3226 if(readIf("INCREMENT")) { 3227 read("BY"); 3228 long increment = readLong(); 3229 command.setIncrement(increment); 3230 } 3231 return command; 3232 } 3233 3234 private AlterUser parseAlterUser() throws SQLException { 3235 String userName = readUniqueIdentifier(); 3236 if(readIf("SET")) { 3237 AlterUser command = new AlterUser(session); 3238 command.setType(AlterUser.SET_PASSWORD); 3239 User user = database.getUser(userName); 3240 command.setUser(user); 3241 if(readIf("PASSWORD")) { 3242 command.setPassword(readString()); 3243 } else if(readIf("SALT")) { 3244 command.setSalt(readString()); 3245 read("HASH"); 3246 command.setHash(readString()); 3247 } else { 3248 throw getSyntaxError(); 3249 } 3250 return command; 3251 } else if(readIf("RENAME")) { 3252 read("TO"); 3253 AlterUser command = new AlterUser(session); 3254 command.setType(AlterUser.RENAME); 3255 command.setUser(database.getUser(userName)); 3256 String newName = readUniqueIdentifier(); 3257 command.setNewName(newName); 3258 return command; 3259 } else if(readIf("ADMIN")) { 3260 AlterUser command = new AlterUser(session); 3261 command.setType(AlterUser.ADMIN); 3262 User user = database.getUser(userName); 3263 command.setUser(user); 3264 if(readIf("TRUE")) { 3265 command.setAdmin(true); 3266 } else if(readIf("FALSE")) { 3267 command.setAdmin(false); 3268 } else { 3269 throw getSyntaxError(); 3270 } 3271 return command; 3272 } 3273 throw getSyntaxError(); 3274 } 3275 3276 private Prepared parseSet() throws SQLException { 3277 if(readIf("AUTOCOMMIT")) { 3278 boolean value = readBooleanSetting(); 3279 int setting = value ? TransactionCommand.AUTOCOMMIT_TRUE : TransactionCommand.AUTOCOMMIT_FALSE; 3280 return new TransactionCommand(session, setting); 3281 } else if(readIf("IGNORECASE")) { 3282 boolean value = readBooleanSetting(); 3283 Set command = new Set(session, SetTypes.IGNORECASE); 3284 command.setInt(value ? 1 : 0); 3285 return command; 3286 } else if(readIf("PASSWORD")) { 3287 AlterUser command = new AlterUser(session); 3288 command.setType(AlterUser.SET_PASSWORD); 3289 command.setUser(session.getUser()); 3290 command.setPassword(readString()); 3291 return command; 3292 } else if(readIf("SALT")) { 3293 AlterUser command = new AlterUser(session); 3294 command.setType(AlterUser.SET_PASSWORD); 3295 command.setUser(session.getUser()); 3296 command.setSalt(readString()); 3297 read("HASH"); 3298 command.setHash(readString()); 3299 return command; 3300 } else if(readIf("MODE")) { 3301 Set command = new Set(session, SetTypes.MODE); 3302 command.setString(readAliasIdentifier()); 3303 return command; 3304 } else if(readIf("COMPRESS_LOB")) { 3305 Set command = new Set(session, SetTypes.COMPRESS_LOB); 3306 if(currentTokenType == VALUE) { 3307 command.setString(readString()); 3308 } else { 3309 command.setString(readUniqueIdentifier()); 3310 } 3311 return command; 3312 } else if(readIf("DATABASE")) { 3313 read("COLLATION"); 3314 return parseSetCollation(); 3315 } else if(readIf("COLLATION")) { 3316 return parseSetCollation(); 3317 } else if(readIf("CLUSTER")) { 3318 Set command = new Set(session, SetTypes.CLUSTER); 3319 command.setString(readString()); 3320 return command; 3321 } else if(readIf("DATABASE_EVENT_LISTENER")) { 3322 Set command = new Set(session, SetTypes.DATABASE_EVENT_LISTENER); 3323 command.setString(readString()); 3324 return command; 3325 } else if(readIf("ALLOW_LITERALS")) { 3326 Set command = new Set(session, SetTypes.ALLOW_LITERALS); 3327 if(readIf("NONE")) { 3328 command.setInt(Constants.ALLOW_LITERALS_NONE); 3329 } else if(readIf("ALL")) { 3330 command.setInt(Constants.ALLOW_LITERALS_ALL); 3331 } else if(readIf("NUMBERS")){ 3332 command.setInt(Constants.ALLOW_LITERALS_NUMBERS); 3333 } else { 3334 command.setInt(getPositiveInt()); 3335 } 3336 return command; 3337 } else if(readIf("DEFAULT_TABLE_TYPE")) { 3338 Set command = new Set(session, SetTypes.DEFAULT_TABLE_TYPE); 3339 if(readIf("MEMORY")) { 3340 command.setInt(Table.TYPE_MEMORY); 3341 } else if(readIf("CACHED")) { 3342 command.setInt(Table.TYPE_CACHED); 3343 } else { 3344 command.setInt(getPositiveInt()); 3345 } 3346 return command; 3347 } else if(readIf("CREATE")) { 3348 read(); 3350 return new NoOperation(session); 3351 } else if(readIf("HSQLDB.DEFAULT_TABLE_TYPE")) { 3352 read(); 3353 return new NoOperation(session); 3354 } else if(readIf("CACHE_TYPE")) { 3355 read(); 3356 return new NoOperation(session); 3357 } else if(readIf("FILE_LOCK")) { 3358 read(); 3359 return new NoOperation(session); 3360 } else if(readIf("STORAGE")) { 3361 read(); 3362 return new NoOperation(session); 3363 } else if(readIf("DB_CLOSE_ON_EXIT")) { 3364 read(); 3365 return new NoOperation(session); 3366 } else if(readIf("RECOVER")) { 3367 read(); 3368 return new NoOperation(session); 3369 } else if(readIf("SCHEMA")) { 3370 Set command = new Set(session, SetTypes.SCHEMA); 3371 command.setString(readAliasIdentifier()); 3372 return command; 3373 } else { 3374 if(isToken("LOGSIZE")) { 3375 currentToken = SetTypes.getTypeName(SetTypes.MAX_LOG_SIZE); 3377 } 3378 int type = SetTypes.getType(currentToken); 3379 if(type >= 0) { 3380 read(); 3381 Set command = new Set(session, type); 3382 command.setExpression(readExpression()); 3383 return command; 3384 } else { 3385 throw getSyntaxError(); 3386 } 3387 } 3388 } 3389 3390 private Set parseSetCollation() throws SQLException { 3391 Set command = new Set(session, SetTypes.COLLATION); 3392 String name = readAliasIdentifier(); 3393 command.setString(name); 3394 if(name.equals(CompareMode.OFF)) { 3395 return command; 3396 } 3397 Collator coll = CompareMode.getCollator(name); 3398 if(coll == null) { 3399 throw getSyntaxError(); 3400 } 3401 if(readIf("STRENGTH")) { 3402 if(readIf("PRIMARY")) { 3403 command.setInt(Collator.PRIMARY); 3404 } else if(readIf("SECONDARY")) { 3405 command.setInt(Collator.SECONDARY); 3406 } else if(readIf("TERTIARY")) { 3407 command.setInt(Collator.TERTIARY); 3408 } else if(readIf("IDENTICAL")) { 3409 command.setInt(Collator.IDENTICAL); 3410 } 3411 } else { 3412 command.setInt(coll.getStrength()); 3413 } 3414 return command; 3415 } 3416 3417 private RunScript parseRunScript() throws SQLException { 3418 RunScript command = new RunScript(session); 3419 read("FROM"); 3420 command.setFileName(readString()); 3421 if(readIf("COMPRESSION")) { 3422 command.setCompressionAlgorithm(readUniqueIdentifier()); 3423 } 3424 if(readIf("CIPHER")) { 3425 command.setCipher(readUniqueIdentifier()); 3426 if(readIf("PASSWORD")) { 3427 command.setPassword(readString().toCharArray()); 3428 } 3429 } 3430 if(readIf("CHARSET")) { 3431 command.setCharset(readString()); 3432 } 3433 return command; 3434 } 3435 3436 private Script parseScript() throws SQLException { 3437 Script command = new Script(session); 3438 boolean data = true, passwords = true, settings = true, dropTables = false; 3439 if(readIf("NODATA")) { 3440 data = false; 3441 } 3442 if(readIf("NOPASSWORDS")) { 3443 passwords = false; 3444 } 3445 if(readIf("NOSETTINGS")) { 3446 settings = false; 3447 } 3448 if(readIf("DROP")) { 3449 dropTables = true; 3450 } 3451 if(readIf("BLOCKSIZE")) { 3452 long blockSize = readLong(); 3453 command.setLobBlockSize(blockSize); 3454 } 3455 command.setData(data); 3456 command.setPasswords(passwords); 3457 command.setSettings(settings); 3458 command.setDrop(dropTables); 3459 if(readIf("TO")) { 3460 command.setFileName(readString()); 3461 if(readIf("COMPRESSION")) { 3462 command.setCompressionAlgorithm(readUniqueIdentifier()); 3463 } 3464 if(readIf("CIPHER")) { 3465 command.setCipher(readUniqueIdentifier()); 3466 if(readIf("PASSWORD")) { 3467 command.setPassword(readString().toCharArray()); 3468 } 3469 } 3470 } 3471 return command; 3472 } 3473 3474 private Prepared parseAlterTable() throws SQLException { 3475 String tableName = readIdentifierWithSchema(); 3476 Schema tableSchema = getSchema(); 3477 Table table = getSchema().getTableOrView(session, tableName); 3478 if(readIf("ADD")) { 3479 Prepared command = parseAlterTableAddConstraintIf(getSchema(), tableName); 3480 if(command != null) { 3481 return command; 3482 } 3483 return parseAlterTableAddColumn(table); 3484 } else if(readIf("SET")) { 3485 read("REFERENTIAL_INTEGRITY"); 3486 int type; 3487 if(readIf("TRUE")) { 3488 type = AlterTableAddConstraint.REFERENTIAL_INTEGRITY_TRUE; 3489 } else { 3490 read("FALSE"); 3491 type = AlterTableAddConstraint.REFERENTIAL_INTEGRITY_FALSE; 3492 } 3493 AlterTableAddConstraint command = new AlterTableAddConstraint(session, getSchema()); 3494 command.setTableName(tableName); 3495 command.setType(type); 3496 return command; 3497 } else if(readIf("RENAME")) { 3498 read("TO"); 3499 String newName = readIdentifierWithSchema(tableSchema.getSQL()); 3500 checkSchema(tableSchema); 3501 AlterTableRename command = new AlterTableRename(session, getSchema()); 3502 command.setOldTable(table); 3503 command.setNewTableName(newName); 3504 return command; 3505 } else if(readIf("DROP")) { 3506 if(readIf("CONSTRAINT")) { 3507 String constraintName = readIdentifierWithSchema(tableSchema.getSQL()); 3508 checkSchema(tableSchema); 3509 AlterTableDropConstraint command = new AlterTableDropConstraint(session, getSchema()); 3510 command.setConstraintName(constraintName); 3511 return command; 3512 } else if(readIf("PRIMARY")) { 3513 read("KEY"); 3514 Index idx = table.getPrimaryKey(); 3515 DropIndex command = new DropIndex(session, tableSchema); 3516 command.setIndexName(idx.getName()); 3517 return command; 3518 } else { 3519 readIf("COLUMN"); 3520 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3521 command.setType(AlterTableAlterColumn.DROP); 3522 String columnName = readColumnIdentifier(); 3523 command.setTable(table); 3524 command.setOldColumn(table.getColumn(columnName)); 3525 return command; 3526 } 3527 } else if(readIf("ALTER")) { 3528 readIf("COLUMN"); 3529 String columnName = readColumnIdentifier(); 3530 Column column = table.getColumn(columnName); 3531 if(readIf("RENAME")) { 3532 read("TO"); 3533 AlterTableRenameColumn command = new AlterTableRenameColumn(session); 3534 command.setTable(table); 3535 command.setColumn(column); 3536 String newName = readColumnIdentifier(); 3537 command.setNewColumnName(newName); 3538 return command; 3539 } else if(readIf("SET")) { 3540 if(readIf("DATA")) { 3541 read("TYPE"); 3543 Column newColumn = parseColumnForTable(columnName); 3544 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3545 command.setTable(table); 3546 command.setType(AlterTableAlterColumn.CHANGE_TYPE); 3547 command.setOldColumn(column); 3548 command.setNewColumn(newColumn); 3549 return command; 3550 } 3551 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3552 command.setTable(table); 3553 command.setOldColumn(column); 3554 if(readIf("NULL")) { 3555 command.setType(AlterTableAlterColumn.NULL); 3556 return command; 3557 } else if(readIf("NOT")) { 3558 read("NULL"); 3559 command.setType(AlterTableAlterColumn.NOT_NULL); 3560 return command; 3561 } else if(readIf("DEFAULT")) { 3562 Expression defaultExpression = readExpression(); 3563 command.setType(AlterTableAlterColumn.DEFAULT); 3564 command.setDefaultExpression(defaultExpression); 3565 return command; 3566 } 3567 } else if(readIf("RESTART")) { 3568 readIf("WITH"); 3569 long start = readLong(); 3570 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3571 command.setTable(table); 3572 command.setType(AlterTableAlterColumn.RESTART); 3573 command.setOldColumn(column); 3574 command.setStartWith(start); 3575 return command; 3576 } else if(readIf("SELECTIVITY")) { 3577 int sel = getPositiveInt(); 3578 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3579 command.setTable(table); 3580 command.setType(AlterTableAlterColumn.SELECTIVITY); 3581 command.setOldColumn(column); 3582 command.setStartWith(sel); 3583 return command; 3584 } else { 3585 Column newColumn = parseColumnForTable(columnName); 3586 AlterTableAlterColumn command = new AlterTableAlterColumn(session, tableSchema); 3587 command.setTable(table); 3588 command.setType(AlterTableAlterColumn.CHANGE_TYPE); 3589 command.setOldColumn(column); 3590 command.setNewColumn(newColumn); 3591 return command; 3592 } 3593 } 3594 throw getSyntaxError(); 3595 } 3596 3597 private AlterTableAlterColumn parseAlterTableAddColumn(Table table) throws SQLException { 3598 readIf("COLUMN"); 3599 Schema schema = table.getSchema(); 3600 AlterTableAlterColumn command = new AlterTableAlterColumn(session, schema); 3601 command.setType(AlterTableAlterColumn.ADD); 3602 command.setTable(table); 3603 String columnName = readColumnIdentifier(); 3604 Column column = parseColumnForTable(columnName); 3605 command.setNewColumn(column); 3606 if(readIf("BEFORE")) { 3607 command.setAddBefore(readColumnIdentifier()); 3608 } 3609 return command; 3610 } 3611 3612 private int parseAction() throws SQLException { 3613 if(readIf("CASCADE")) { 3614 return ConstraintReferential.CASCADE; 3615 } else if(readIf("RESTRICT")) { 3616 return ConstraintReferential.RESTRICT; 3617 } else if(readIf("NO")) { 3618 read("ACTION"); 3619 return ConstraintReferential.RESTRICT; 3620 } else { 3621 read("SET"); 3622 if(readIf("NULL")) { 3623 return ConstraintReferential.SET_NULL; 3624 } else { 3625 read("DEFAULT"); 3626 return ConstraintReferential.SET_DEFAULT; 3627 } 3628 } 3629 } 3630 3631 private Prepared parseAlterTableAddConstraintIf(Schema schema, String tableName) throws SQLException { 3632 String name = null, comment = null; 3633 if(readIf("CONSTRAINT")) { 3634 name = readIdentifierWithSchema(schema.getName()); 3635 checkSchema(schema); 3636 comment = readCommentIf(); 3637 } 3638 if(readIf("PRIMARY")) { 3639 read("KEY"); 3640 CreateIndex command = new CreateIndex(session, schema); 3641 command.setComment(comment); 3642 command.setTableName(tableName); 3643 command.setPrimaryKey(true); 3644 if(readIf("HASH")) { 3645 command.setHash(true); 3646 } 3647 read("("); 3648 command.setColumnNames(parseColumnList(true)); 3649 return command; 3650 } else if(Mode.getCurrentMode().indexDefinitionInCreateTable && (readIf("INDEX") || readIf("KEY"))) { 3651 CreateIndex command = new CreateIndex(session, schema); 3653 command.setComment(comment); 3654 command.setTableName(tableName); 3655 if(!readIf("(")) { 3656 command.setIndexName(readUniqueIdentifier()); 3657 read("("); 3658 } 3659 command.setColumnNames(parseColumnList(true)); 3660 return command; 3661 } 3662 AlterTableAddConstraint command; 3663 if(readIf("CHECK")) { 3664 command = new AlterTableAddConstraint(session, schema); 3665 command.setType(AlterTableAddConstraint.CHECK); 3666 command.setCheckExpression(readExpression()); 3667 } else if(readIf("UNIQUE")) { 3668 readIf("INDEX"); 3669 command = new AlterTableAddConstraint(session, schema); 3670 command.setType(AlterTableAddConstraint.UNIQUE); 3671 if(!readIf("(")) { 3672 name = readUniqueIdentifier(); 3673 read("("); 3674 } 3675 command.setColumnNames(parseColumnList(true)); 3676 if(readIf("INDEX")) { 3677 String indexName = readIdentifierWithSchema(); 3678 command.setIndex(getSchema().findIndex(indexName)); 3679 } 3680 } else if(readIf("FOREIGN")) { 3681 command = new AlterTableAddConstraint(session, schema); 3682 command.setType(AlterTableAddConstraint.REFERENTIAL); 3683 read("KEY"); 3684 read("("); 3685 String [] cols = parseColumnList(true); 3686 command.setColumnNames(cols); 3687 if(readIf("INDEX")) { 3688 String indexName = readIdentifierWithSchema(); 3689 command.setIndex(schema.findIndex(indexName)); 3690 } 3691 read("REFERENCES"); 3692 if(readIf("(")) { 3693 command.setRefTableName(schema, tableName); 3694 cols = parseColumnList(false); 3695 command.setRefColumnNames(cols); 3696 } else { 3697 String refTableName = readIdentifierWithSchema(schema.getName()); 3698 command.setRefTableName(getSchema(), refTableName); 3699 if(readIf("(")) { 3700 cols = parseColumnList(false); 3701 command.setRefColumnNames(cols); 3702 } 3703 } 3704 if(readIf("INDEX")) { 3705 String indexName = readIdentifierWithSchema(); 3706 command.setRefIndex(getSchema().findIndex(indexName)); 3707 } 3708 while(readIf("ON")) { 3709 if(readIf("DELETE")) { 3710 command.setDeleteAction(parseAction()); 3711 } else { 3712 read("UPDATE"); 3713 command.setUpdateAction(parseAction()); 3714 } 3715 } 3716 if(readIf("NOT")) { 3717 read("DEFERRABLE"); 3718 } else { 3719 readIf("DEFERRABLE"); 3720 } 3721 } else { 3722 if(name != null) { 3723 throw getSyntaxError(); 3724 } 3725 return null; 3726 } 3727 command.setTableName(tableName); 3728 command.setConstraintName(name); 3729 command.setComment(comment); 3730 return command; 3731 } 3732 3733 private CreateLinkedTable parseCreateLinkedTable() throws SQLException { 3734 read("TABLE"); 3735 boolean ifNotExists = readIfNoExists(); 3736 String tableName = readIdentifierWithSchema(); 3737 CreateLinkedTable command = new CreateLinkedTable(session, getSchema()); 3738 command.setIfNotExists(ifNotExists); 3739 command.setTableName(tableName); 3740 command.setComment(readCommentIf()); 3741 read("("); 3742 command.setDriver(readString()); 3743 read(","); 3744 command.setUrl(readString()); 3745 read(","); 3746 command.setUser(readString()); 3747 read(","); 3748 command.setPassword(readString()); 3749 read(","); 3750 command.setOriginalTable(readString()); 3751 read(")"); 3752 return command; 3753 } 3754 3755 private CreateTable parseCreateTable(boolean temp, boolean globalTemp, boolean persistent) throws SQLException { 3756 boolean ifNotExists = readIfNoExists(); 3757 String tableName = readIdentifierWithSchema(); 3758 if(temp && globalTemp && "SESSION".equals(schemaName)) { 3759 schemaName = session.getCurrentSchemaName(); 3761 globalTemp = false; 3762 } 3763 Schema schema = getSchema(); 3764 CreateTable command = new CreateTable(session, schema); 3765 command.setPersistent(persistent); 3766 command.setTemporary(temp); 3767 command.setGlobalTemporary(globalTemp); 3768 command.setIfNotExists(ifNotExists); 3769 command.setTableName(tableName); 3770 command.setComment(readCommentIf()); 3771 if(readIf("AS")) { 3772 Query query = parseQueryWithParams(); 3773 command.setQuery(query); 3774 } else { 3775 read("("); 3776 if(!readIf(")")) { 3777 do { 3778 Prepared c = parseAlterTableAddConstraintIf(schema, tableName); 3779 if(c != null) { 3780 command.addConstraintCommand(c); 3781 } else { 3782 String columnName = readColumnIdentifier(); 3783 Column column = parseColumnForTable(columnName); 3784 if(column.getAutoIncrement()) { 3785 command.setPrimaryKeyColumnNames(new String []{column.getName()}); 3786 } 3787 command.addColumn(column); 3788 String constraintName = null; 3789 if(readIf("CONSTRAINT")) { 3790 constraintName = readColumnIdentifier(); 3791 } 3792 if (readIf("PRIMARY")) { 3793 read("KEY"); 3794 if(readIf("HASH")) { 3795 command.setHashPrimaryKey(true); 3796 } 3797 command.setPrimaryKeyColumnNames(new String []{column.getName()}); 3798 } else if(readIf("UNIQUE")) { 3799 AlterTableAddConstraint unique = new AlterTableAddConstraint(session, schema); 3800 unique.setConstraintName(constraintName); 3801 unique.setType(AlterTableAddConstraint.UNIQUE); 3802 unique.setColumnNames(new String []{columnName}); 3803 unique.setTableName(tableName); 3804 command.addConstraintCommand(unique); 3805 } else if(readIf("CHECK")) { 3806 Expression expr = readExpression(); 3807 column.addCheckConstraint(session, expr); 3808 } else if(readIf("REFERENCES")) { 3809 AlterTableAddConstraint ref = new AlterTableAddConstraint(session, schema); 3810 ref.setConstraintName(constraintName); 3811 ref.setType(AlterTableAddConstraint.REFERENTIAL); 3812 ref.setColumnNames(new String []{columnName}); 3813 ref.setTableName(tableName); 3814 String refTableName = readIdentifierWithSchema(schema.getName()); 3815 ref.setRefTableName(getSchema(), refTableName); 3816 if(readIf("(")) { 3817 String [] cols = parseColumnList(false); 3818 ref.setRefColumnNames(cols); 3819 } 3820 command.addConstraintCommand(ref); 3821 } 3822 } 3823 } while(readIf(",")); 3824 read(")"); 3825 } 3826 } 3827 if(temp) { 3828 if(readIf("ON")) { 3829 read("COMMIT"); 3830 if(readIf("DROP")) { 3831 command.setOnCommitDrop(); 3832 } else if(readIf("DELETE")) { 3833 read("ROWS"); 3834 command.setOnCommitTruncate(); 3835 } 3836 } else if(readIf("NOT")) { 3837 read("LOGGED"); 3838 } 3839 } 3840 return command; 3841 } 3842 3843 private int getCompareType(int tokenType) { 3844 switch (tokenType) { 3845 case EQUAL: 3846 return Comparison.EQUAL; 3847 case BIGGER_EQUAL: 3848 return Comparison.BIGGER_EQUAL; 3849 case BIGGER: 3850 return Comparison.BIGGER; 3851 case SMALLER: 3852 return Comparison.SMALLER; 3853 case SMALLER_EQUAL: 3854 return Comparison.SMALLER_EQUAL; 3855 case NOT_EQUAL: 3856 return Comparison.NOT_EQUAL; 3857 default: 3858 return -1; 3859 } 3860 } 3861 3862 public static String quoteIdentifier(String s) { 3863 if(s == null || s.length()==0) { 3864 return "\"\""; 3865 } 3866 char c = s.charAt(0); 3867 if((!Character.isLetter(c) && c != '_') || Character.isLowerCase(c)) { 3869 return StringUtils.quoteIdentifier(s); 3870 } 3871 for(int i=0; i<s.length(); i++) { 3872 c = s.charAt(i); 3873 if((!Character.isLetterOrDigit(c) && c != '_') || Character.isLowerCase(c)) { 3874 return StringUtils.quoteIdentifier(s); 3875 } 3876 } 3877 if(Parser.isKeyword(s)) { 3878 return StringUtils.quoteIdentifier(s); 3879 } 3880 return s; 3881 } 3882 3883 public void setRightsChecked(boolean rightsChecked) { 3884 this.rightsChecked = rightsChecked; 3885 } 3886 3887 public Expression parseExpression(String sql) throws SQLException { 3888 initialize(sql); 3889 read(); 3890 return readExpression(); 3891 } 3892 3893} 3894 | Popular Tags |