/h2/src/main/org/h2/command/Parser.java
Java | 5949 lines | 5553 code | 169 blank | 227 comment | 1681 complexity | a58dfe4f8c1c65b9913b805a6bc30771 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
- * Version 1.0, and under the Eclipse Public License, Version 1.0
- * (http://h2database.com/html/license.html).
- * Initial Developer: H2 Group
- *
- * Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
- * Support for the operator "&&" as an alias for SPATIAL_INTERSECTS
- */
- package org.h2.command;
- import java.math.BigDecimal;
- import java.math.BigInteger;
- import java.nio.charset.Charset;
- import java.text.Collator;
- import java.util.ArrayList;
- import java.util.HashSet;
- import org.h2.api.ErrorCode;
- import org.h2.api.Trigger;
- import org.h2.command.ddl.AlterIndexRename;
- import org.h2.command.ddl.AlterSchemaRename;
- import org.h2.command.ddl.AlterTableAddConstraint;
- import org.h2.command.ddl.AlterTableAlterColumn;
- import org.h2.command.ddl.AlterTableDropConstraint;
- import org.h2.command.ddl.AlterTableRename;
- import org.h2.command.ddl.AlterTableRenameColumn;
- import org.h2.command.ddl.AlterUser;
- import org.h2.command.ddl.AlterView;
- import org.h2.command.ddl.Analyze;
- import org.h2.command.ddl.CreateAggregate;
- import org.h2.command.ddl.CreateConstant;
- import org.h2.command.ddl.CreateFunctionAlias;
- import org.h2.command.ddl.CreateIndex;
- import org.h2.command.ddl.CreateLinkedTable;
- import org.h2.command.ddl.CreateRole;
- import org.h2.command.ddl.CreateSchema;
- import org.h2.command.ddl.CreateSequence;
- import org.h2.command.ddl.CreateTable;
- import org.h2.command.ddl.CreateTableData;
- import org.h2.command.ddl.CreateTrigger;
- import org.h2.command.ddl.CreateUser;
- import org.h2.command.ddl.CreateUserDataType;
- import org.h2.command.ddl.CreateView;
- import org.h2.command.ddl.DeallocateProcedure;
- import org.h2.command.ddl.DefineCommand;
- import org.h2.command.ddl.DropAggregate;
- import org.h2.command.ddl.DropConstant;
- import org.h2.command.ddl.DropDatabase;
- import org.h2.command.ddl.DropFunctionAlias;
- import org.h2.command.ddl.DropIndex;
- import org.h2.command.ddl.DropRole;
- import org.h2.command.ddl.DropSchema;
- import org.h2.command.ddl.DropSequence;
- import org.h2.command.ddl.DropTable;
- import org.h2.command.ddl.DropTrigger;
- import org.h2.command.ddl.DropUser;
- import org.h2.command.ddl.DropUserDataType;
- import org.h2.command.ddl.DropView;
- import org.h2.command.ddl.GrantRevoke;
- import org.h2.command.ddl.PrepareProcedure;
- import org.h2.command.ddl.SetComment;
- import org.h2.command.ddl.TruncateTable;
- import org.h2.command.dml.AlterSequence;
- import org.h2.command.dml.AlterTableSet;
- import org.h2.command.dml.BackupCommand;
- import org.h2.command.dml.Call;
- import org.h2.command.dml.Delete;
- import org.h2.command.dml.ExecuteProcedure;
- import org.h2.command.dml.Explain;
- import org.h2.command.dml.Insert;
- import org.h2.command.dml.Merge;
- import org.h2.command.dml.NoOperation;
- import org.h2.command.dml.Query;
- import org.h2.command.dml.Replace;
- import org.h2.command.dml.RunScriptCommand;
- import org.h2.command.dml.ScriptCommand;
- import org.h2.command.dml.Select;
- import org.h2.command.dml.SelectOrderBy;
- import org.h2.command.dml.SelectUnion;
- import org.h2.command.dml.Set;
- import org.h2.command.dml.SetTypes;
- import org.h2.command.dml.TransactionCommand;
- import org.h2.command.dml.Update;
- import org.h2.constraint.ConstraintReferential;
- import org.h2.engine.Constants;
- import org.h2.engine.Database;
- import org.h2.engine.DbObject;
- import org.h2.engine.FunctionAlias;
- import org.h2.engine.Procedure;
- import org.h2.engine.Right;
- import org.h2.engine.Session;
- import org.h2.engine.SysProperties;
- import org.h2.engine.User;
- import org.h2.engine.UserAggregate;
- import org.h2.engine.UserDataType;
- import org.h2.expression.Aggregate;
- import org.h2.expression.Alias;
- import org.h2.expression.CompareLike;
- import org.h2.expression.Comparison;
- import org.h2.expression.ConditionAndOr;
- import org.h2.expression.ConditionExists;
- import org.h2.expression.ConditionIn;
- import org.h2.expression.ConditionInSelect;
- import org.h2.expression.ConditionNot;
- import org.h2.expression.Expression;
- import org.h2.expression.ExpressionColumn;
- import org.h2.expression.ExpressionList;
- import org.h2.expression.Function;
- import org.h2.expression.FunctionCall;
- import org.h2.expression.JavaAggregate;
- import org.h2.expression.JavaFunction;
- import org.h2.expression.Operation;
- import org.h2.expression.Parameter;
- import org.h2.expression.Rownum;
- import org.h2.expression.SequenceValue;
- import org.h2.expression.Subquery;
- import org.h2.expression.TableFunction;
- import org.h2.expression.ValueExpression;
- import org.h2.expression.Variable;
- import org.h2.expression.Wildcard;
- import org.h2.index.Index;
- import org.h2.message.DbException;
- import org.h2.result.SortOrder;
- import org.h2.schema.Schema;
- import org.h2.schema.Sequence;
- import org.h2.table.Column;
- import org.h2.table.FunctionTable;
- import org.h2.table.IndexColumn;
- import org.h2.table.RangeTable;
- import org.h2.table.Table;
- import org.h2.table.TableFilter;
- import org.h2.table.TableView;
- import org.h2.table.TableFilter.TableFilterVisitor;
- import org.h2.util.MathUtils;
- import org.h2.util.New;
- import org.h2.util.StatementBuilder;
- import org.h2.util.StringUtils;
- import org.h2.value.CompareMode;
- import org.h2.value.DataType;
- import org.h2.value.Value;
- import org.h2.value.ValueBoolean;
- import org.h2.value.ValueBytes;
- import org.h2.value.ValueDate;
- import org.h2.value.ValueDecimal;
- import org.h2.value.ValueInt;
- import org.h2.value.ValueLong;
- import org.h2.value.ValueNull;
- import org.h2.value.ValueString;
- import org.h2.value.ValueTime;
- import org.h2.value.ValueTimestamp;
- /**
- * The parser is used to convert a SQL statement string to an command object.
- *
- * @author Thomas Mueller
- * @author Noel Grandin
- * @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
- */
- public class Parser {
- // used during the tokenizer phase
- private static final int CHAR_END = 1, CHAR_VALUE = 2, CHAR_QUOTED = 3;
- private static final int CHAR_NAME = 4, CHAR_SPECIAL_1 = 5,
- CHAR_SPECIAL_2 = 6;
- private static final int CHAR_STRING = 7, CHAR_DOT = 8,
- CHAR_DOLLAR_QUOTED_STRING = 9;
- // this are token types
- private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3,
- END = 4, VALUE = 5;
- private static final int EQUAL = 6, BIGGER_EQUAL = 7, BIGGER = 8;
- private static final int SMALLER = 9, SMALLER_EQUAL = 10, NOT_EQUAL = 11,
- AT = 12;
- private static final int MINUS = 13, PLUS = 14, STRING_CONCAT = 15;
- private static final int OPEN = 16, CLOSE = 17, NULL = 18, TRUE = 19,
- FALSE = 20;
- private static final int CURRENT_TIMESTAMP = 21, CURRENT_DATE = 22,
- CURRENT_TIME = 23, ROWNUM = 24;
- private static final int SPATIAL_INTERSECTS = 25;
- private final Database database;
- private final Session session;
- /**
- * @see org.h2.engine.DbSettings#databaseToUpper
- */
- private final boolean identifiersToUpper;
- /** indicates character-type for each char in sqlCommand */
- private int[] characterTypes;
- private int currentTokenType;
- private String currentToken;
- private boolean currentTokenQuoted;
- private Value currentValue;
- private String originalSQL;
- /** copy of originalSQL, with comments blanked out */
- private String sqlCommand;
- /** cached array if chars from sqlCommand */
- private char[] sqlCommandChars;
- /** index into sqlCommand of previous token */
- private int lastParseIndex;
- /** index into sqlCommand of current token */
- private int parseIndex;
- private CreateView createView;
- private Prepared currentPrepared;
- private Select currentSelect;
- private ArrayList<Parameter> parameters;
- private String schemaName;
- private ArrayList<String> expectedList;
- private boolean rightsChecked;
- private boolean recompileAlways;
- private ArrayList<Parameter> indexedParameterList;
- public Parser(Session session) {
- this.database = session.getDatabase();
- this.identifiersToUpper = database.getSettings().databaseToUpper;
- this.session = session;
- }
- /**
- * Parse the statement and prepare it for execution.
- *
- * @param sql the SQL statement to parse
- * @return the prepared object
- */
- public Prepared prepare(String sql) {
- Prepared p = parse(sql);
- p.prepare();
- if (currentTokenType != END) {
- throw getSyntaxError();
- }
- return p;
- }
- /**
- * Parse a statement or a list of statements, and prepare it for execution.
- *
- * @param sql the SQL statement to parse
- * @return the command object
- */
- public Command prepareCommand(String sql) {
- try {
- Prepared p = parse(sql);
- boolean hasMore = isToken(";");
- if (!hasMore && currentTokenType != END) {
- throw getSyntaxError();
- }
- p.prepare();
- Command c = new CommandContainer(this, sql, p);
- if (hasMore) {
- String remaining = originalSQL.substring(parseIndex);
- if (remaining.trim().length() != 0) {
- CommandList list = new CommandList(this, sql, c, remaining);
- // list.addCommand(c);
- // do {
- // c = parseCommand();
- // list.addCommand(c);
- // } while (currentToken.equals(";"));
- c = list;
- }
- }
- return c;
- } catch (DbException e) {
- throw e.addSQL(originalSQL);
- }
- }
- /**
- * Parse the statement, but don't prepare it for execution.
- *
- * @param sql the SQL statement to parse
- * @return the prepared object
- */
- Prepared parse(String sql) {
- Prepared p;
- try {
- // first, try the fast variant
- p = parse(sql, false);
- } catch (DbException e) {
- if (e.getErrorCode() == ErrorCode.SYNTAX_ERROR_1) {
- // now, get the detailed exception
- p = parse(sql, true);
- } else {
- throw e.addSQL(sql);
- }
- }
- p.setPrepareAlways(recompileAlways);
- p.setParameterList(parameters);
- return p;
- }
- private Prepared parse(String sql, boolean withExpectedList) {
- initialize(sql);
- if (withExpectedList) {
- expectedList = New.arrayList();
- } else {
- expectedList = null;
- }
- parameters = New.arrayList();
- currentSelect = null;
- currentPrepared = null;
- createView = null;
- recompileAlways = false;
- indexedParameterList = null;
- read();
- return parsePrepared();
- }
- private Prepared parsePrepared() {
- int start = lastParseIndex;
- Prepared c = null;
- String token = currentToken;
- if (token.length() == 0) {
- c = new NoOperation(session);
- } else {
- char first = token.charAt(0);
- switch (first) {
- case '?':
- // read the ? as a parameter
- readTerm();
- // this is an 'out' parameter - set a dummy value
- parameters.get(0).setValue(ValueNull.INSTANCE);
- read("=");
- read("CALL");
- c = parseCall();
- break;
- case '(':
- c = parseSelect();
- break;
- case 'a':
- case 'A':
- if (readIf("ALTER")) {
- c = parseAlter();
- } else if (readIf("ANALYZE")) {
- c = parseAnalyze();
- }
- break;
- case 'b':
- case 'B':
- if (readIf("BACKUP")) {
- c = parseBackup();
- } else if (readIf("BEGIN")) {
- c = parseBegin();
- }
- break;
- case 'c':
- case 'C':
- if (readIf("COMMIT")) {
- c = parseCommit();
- } else if (readIf("CREATE")) {
- c = parseCreate();
- } else if (readIf("CALL")) {
- c = parseCall();
- } else if (readIf("CHECKPOINT")) {
- c = parseCheckpoint();
- } else if (readIf("COMMENT")) {
- c = parseComment();
- }
- break;
- case 'd':
- case 'D':
- if (readIf("DELETE")) {
- c = parseDelete();
- } else if (readIf("DROP")) {
- c = parseDrop();
- } else if (readIf("DECLARE")) {
- // support for DECLARE GLOBAL TEMPORARY TABLE...
- c = parseCreate();
- } else if (readIf("DEALLOCATE")) {
- c = parseDeallocate();
- }
- break;
- case 'e':
- case 'E':
- if (readIf("EXPLAIN")) {
- c = parseExplain();
- } else if (readIf("EXECUTE")) {
- c = parseExecute();
- }
- break;
- case 'f':
- case 'F':
- if (isToken("FROM")) {
- c = parseSelect();
- }
- break;
- case 'g':
- case 'G':
- if (readIf("GRANT")) {
- c = parseGrantRevoke(CommandInterface.GRANT);
- }
- break;
- case 'h':
- case 'H':
- if (readIf("HELP")) {
- c = parseHelp();
- }
- break;
- case 'i':
- case 'I':
- if (readIf("INSERT")) {
- c = parseInsert();
- }
- break;
- case 'm':
- case 'M':
- if (readIf("MERGE")) {
- c = parseMerge();
- }
- break;
- case 'p':
- case 'P':
- if (readIf("PREPARE")) {
- c = parsePrepare();
- }
- break;
- case 'r':
- case 'R':
- if (readIf("ROLLBACK")) {
- c = parseRollback();
- } else if (readIf("REVOKE")) {
- c = parseGrantRevoke(CommandInterface.REVOKE);
- } else if (readIf("RUNSCRIPT")) {
- c = parseRunScript();
- } else if (readIf("RELEASE")) {
- c = parseReleaseSavepoint();
- } else if (readIf("REPLACE")) {
- c = parseReplace();
- }
- break;
- case 's':
- case 'S':
- if (isToken("SELECT")) {
- c = parseSelect();
- } else if (readIf("SET")) {
- c = parseSet();
- } else if (readIf("SAVEPOINT")) {
- c = parseSavepoint();
- } else if (readIf("SCRIPT")) {
- c = parseScript();
- } else if (readIf("SHUTDOWN")) {
- c = parseShutdown();
- } else if (readIf("SHOW")) {
- c = parseShow();
- }
- break;
- case 't':
- case 'T':
- if (readIf("TRUNCATE")) {
- c = parseTruncate();
- }
- break;
- case 'u':
- case 'U':
- if (readIf("UPDATE")) {
- c = parseUpdate();
- }
- break;
- case 'v':
- case 'V':
- if (readIf("VALUES")) {
- c = parseValues();
- }
- break;
- case 'w':
- case 'W':
- if (readIf("WITH")) {
- c = parseWith();
- }
- break;
- case ';':
- c = new NoOperation(session);
- break;
- default:
- throw getSyntaxError();
- }
- if (indexedParameterList != null) {
- for (int i = 0, size = indexedParameterList.size();
- i < size; i++) {
- if (indexedParameterList.get(i) == null) {
- indexedParameterList.set(i, new Parameter(i));
- }
- }
- parameters = indexedParameterList;
- }
- if (readIf("{")) {
- do {
- int index = (int) readLong() - 1;
- if (index < 0 || index >= parameters.size()) {
- throw getSyntaxError();
- }
- Parameter p = parameters.get(index);
- if (p == null) {
- throw getSyntaxError();
- }
- read(":");
- Expression expr = readExpression();
- expr = expr.optimize(session);
- p.setValue(expr.getValue(session));
- } while (readIf(","));
- read("}");
- for (Parameter p : parameters) {
- p.checkSet();
- }
- parameters.clear();
- }
- }
- if (c == null) {
- throw getSyntaxError();
- }
- setSQL(c, null, start);
- return c;
- }
- private DbException getSyntaxError() {
- if (expectedList == null || expectedList.size() == 0) {
- return DbException.getSyntaxError(sqlCommand, parseIndex);
- }
- StatementBuilder buff = new StatementBuilder();
- for (String e : expectedList) {
- buff.appendExceptFirst(", ");
- buff.append(e);
- }
- return DbException.getSyntaxError(sqlCommand, parseIndex,
- buff.toString());
- }
- private Prepared parseBackup() {
- BackupCommand command = new BackupCommand(session);
- read("TO");
- command.setFileName(readExpression());
- return command;
- }
- private Prepared parseAnalyze() {
- Analyze command = new Analyze(session);
- if (readIf("SAMPLE_SIZE")) {
- command.setTop(getPositiveInt());
- }
- return command;
- }
- private TransactionCommand parseBegin() {
- TransactionCommand command;
- if (!readIf("WORK")) {
- readIf("TRANSACTION");
- }
- command = new TransactionCommand(session, CommandInterface.BEGIN);
- return command;
- }
- private TransactionCommand parseCommit() {
- TransactionCommand command;
- if (readIf("TRANSACTION")) {
- command = new TransactionCommand(session,
- CommandInterface.COMMIT_TRANSACTION);
- command.setTransactionName(readUniqueIdentifier());
- return command;
- }
- command = new TransactionCommand(session,
- CommandInterface.COMMIT);
- readIf("WORK");
- return command;
- }
- private TransactionCommand parseShutdown() {
- int type = CommandInterface.SHUTDOWN;
- if (readIf("IMMEDIATELY")) {
- type = CommandInterface.SHUTDOWN_IMMEDIATELY;
- } else if (readIf("COMPACT")) {
- type = CommandInterface.SHUTDOWN_COMPACT;
- } else if (readIf("DEFRAG")) {
- type = CommandInterface.SHUTDOWN_DEFRAG;
- } else {
- readIf("SCRIPT");
- }
- return new TransactionCommand(session, type);
- }
- private TransactionCommand parseRollback() {
- TransactionCommand command;
- if (readIf("TRANSACTION")) {
- command = new TransactionCommand(session,
- CommandInterface.ROLLBACK_TRANSACTION);
- command.setTransactionName(readUniqueIdentifier());
- return command;
- }
- if (readIf("TO")) {
- read("SAVEPOINT");
- command = new TransactionCommand(session,
- CommandInterface.ROLLBACK_TO_SAVEPOINT);
- command.setSavepointName(readUniqueIdentifier());
- } else {
- readIf("WORK");
- command = new TransactionCommand(session,
- CommandInterface.ROLLBACK);
- }
- return command;
- }
- private Prepared parsePrepare() {
- if (readIf("COMMIT")) {
- TransactionCommand command = new TransactionCommand(session,
- CommandInterface.PREPARE_COMMIT);
- command.setTransactionName(readUniqueIdentifier());
- return command;
- }
- String procedureName = readAliasIdentifier();
- if (readIf("(")) {
- ArrayList<Column> list = New.arrayList();
- for (int i = 0;; i++) {
- Column column = parseColumnForTable("C" + i, true);
- list.add(column);
- if (readIf(")")) {
- break;
- }
- read(",");
- }
- }
- read("AS");
- Prepared prep = parsePrepared();
- PrepareProcedure command = new PrepareProcedure(session);
- command.setProcedureName(procedureName);
- command.setPrepared(prep);
- return command;
- }
- private TransactionCommand parseSavepoint() {
- TransactionCommand command = new TransactionCommand(session,
- CommandInterface.SAVEPOINT);
- command.setSavepointName(readUniqueIdentifier());
- return command;
- }
- private Prepared parseReleaseSavepoint() {
- Prepared command = new NoOperation(session);
- readIf("SAVEPOINT");
- readUniqueIdentifier();
- return command;
- }
- private Schema getSchema(String schemaName) {
- if (schemaName == null) {
- return null;
- }
- Schema schema = database.findSchema(schemaName);
- if (schema == null) {
- if (equalsToken("SESSION", schemaName)) {
- // for local temporary tables
- schema = database.getSchema(session.getCurrentSchemaName());
- } else if (database.getMode().sysDummy1 &&
- "SYSIBM".equals(schemaName)) {
- // IBM DB2 and Apache Derby compatibility: SYSIBM.SYSDUMMY1
- } else {
- throw DbException.get(ErrorCode.SCHEMA_NOT_FOUND_1, schemaName);
- }
- }
- return schema;
- }
- private Schema getSchema() {
- return getSchema(schemaName);
- }
- private Column readTableColumn(TableFilter filter) {
- String tableAlias = null;
- String columnName = readColumnIdentifier();
- if (readIf(".")) {
- tableAlias = columnName;
- columnName = readColumnIdentifier();
- if (readIf(".")) {
- String schema = tableAlias;
- tableAlias = columnName;
- columnName = readColumnIdentifier();
- if (readIf(".")) {
- String catalogName = schema;
- schema = tableAlias;
- tableAlias = columnName;
- columnName = readColumnIdentifier();
- if (!equalsToken(catalogName, database.getShortName())) {
- throw DbException.get(ErrorCode.DATABASE_NOT_FOUND_1,
- catalogName);
- }
- }
- if (!equalsToken(schema, filter.getTable().getSchema()
- .getName())) {
- throw DbException.get(ErrorCode.SCHEMA_NOT_FOUND_1, schema);
- }
- }
- if (!equalsToken(tableAlias, filter.getTableAlias())) {
- throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1,
- tableAlias);
- }
- }
- if (database.getSettings().rowId) {
- if (Column.ROWID.equals(columnName)) {
- return filter.getRowIdColumn();
- }
- }
- return filter.getTable().getColumn(columnName);
- }
- private Update parseUpdate() {
- Update command = new Update(session);
- currentPrepared = command;
- int start = lastParseIndex;
- TableFilter filter = readSimpleTableFilter();
- command.setTableFilter(filter);
- read("SET");
- if (readIf("(")) {
- ArrayList<Column> columns = New.arrayList();
- do {
- Column column = readTableColumn(filter);
- columns.add(column);
- } while (readIf(","));
- read(")");
- read("=");
- Expression expression = readExpression();
- if (columns.size() == 1) {
- // the expression is parsed as a simple value
- command.setAssignment(columns.get(0), expression);
- } else {
- for (int i = 0, size = columns.size(); i < size; i++) {
- Column column = columns.get(i);
- Function f = Function.getFunction(database, "ARRAY_GET");
- f.setParameter(0, expression);
- f.setParameter(1, ValueExpression.get(ValueInt.get(i + 1)));
- f.doneWithParameters();
- command.setAssignment(column, f);
- }
- }
- } else {
- do {
- Column column = readTableColumn(filter);
- read("=");
- Expression expression;
- if (readIf("DEFAULT")) {
- expression = ValueExpression.getDefault();
- } else {
- expression = readExpression();
- }
- command.setAssignment(column, expression);
- } while (readIf(","));
- }
- if (readIf("WHERE")) {
- Expression condition = readExpression();
- command.setCondition(condition);
- }
- if (readIf("LIMIT")) {
- Expression limit = readTerm().optimize(session);
- command.setLimit(limit);
- }
- setSQL(command, "UPDATE", start);
- return command;
- }
- private TableFilter readSimpleTableFilter() {
- Table table = readTableOrView();
- String alias = null;
- if (readIf("AS")) {
- alias = readAliasIdentifier();
- } else if (currentTokenType == IDENTIFIER) {
- if (!equalsToken("SET", currentToken)) {
- // SET is not a keyword (PostgreSQL supports it as a table name)
- alias = readAliasIdentifier();
- }
- }
- return new TableFilter(session, table, alias, rightsChecked,
- currentSelect);
- }
- private Delete parseDelete() {
- Delete command = new Delete(session);
- Expression limit = null;
- if (readIf("TOP")) {
- limit = readTerm().optimize(session);
- }
- currentPrepared = command;
- int start = lastParseIndex;
- readIf("FROM");
- TableFilter filter = readSimpleTableFilter();
- command.setTableFilter(filter);
- if (readIf("WHERE")) {
- Expression condition = readExpression();
- command.setCondition(condition);
- }
- if (readIf("LIMIT") && limit == null) {
- limit = readTerm().optimize(session);
- }
- command.setLimit(limit);
- setSQL(command, "DELETE", start);
- return command;
- }
- private IndexColumn[] parseIndexColumnList() {
- ArrayList<IndexColumn> columns = New.arrayList();
- do {
- IndexColumn column = new IndexColumn();
- column.columnName = readColumnIdentifier();
- columns.add(column);
- if (readIf("ASC")) {
- // ignore
- } else if (readIf("DESC")) {
- column.sortType = SortOrder.DESCENDING;
- }
- if (readIf("NULLS")) {
- if (readIf("FIRST")) {
- column.sortType |= SortOrder.NULLS_FIRST;
- } else {
- read("LAST");
- column.sortType |= SortOrder.NULLS_LAST;
- }
- }
- } while (readIf(","));
- read(")");
- return columns.toArray(new IndexColumn[columns.size()]);
- }
- private String[] parseColumnList() {
- ArrayList<String> columns = New.arrayList();
- do {
- String columnName = readColumnIdentifier();
- columns.add(columnName);
- } while (readIfMore());
- return columns.toArray(new String[columns.size()]);
- }
- private Column[] parseColumnList(Table table) {
- ArrayList<Column> columns = New.arrayList();
- HashSet<Column> set = New.hashSet();
- if (!readIf(")")) {
- do {
- Column column = parseColumn(table);
- if (!set.add(column)) {
- throw DbException.get(ErrorCode.DUPLICATE_COLUMN_NAME_1,
- column.getSQL());
- }
- columns.add(column);
- } while (readIfMore());
- }
- return columns.toArray(new Column[columns.size()]);
- }
- private Column parseColumn(Table table) {
- String id = readColumnIdentifier();
- if (database.getSettings().rowId && Column.ROWID.equals(id)) {
- return table.getRowIdColumn();
- }
- return table.getColumn(id);
- }
- private boolean readIfMore() {
- if (readIf(",")) {
- return !readIf(")");
- }
- read(")");
- return false;
- }
- private Prepared parseHelp() {
- StringBuilder buff = new StringBuilder(
- "SELECT * FROM INFORMATION_SCHEMA.HELP");
- int i = 0;
- ArrayList<Value> paramValues = New.arrayList();
- while (currentTokenType != END) {
- String s = currentToken;
- read();
- if (i == 0) {
- buff.append(" WHERE ");
- } else {
- buff.append(" AND ");
- }
- i++;
- buff.append("UPPER(TOPIC) LIKE ?");
- paramValues.add(ValueString.get("%" + s + "%"));
- }
- return prepare(session, buff.toString(), paramValues);
- }
- private Prepared parseShow() {
- ArrayList<Value> paramValues = New.arrayList();
- StringBuilder buff = new StringBuilder("SELECT ");
- if (readIf("CLIENT_ENCODING")) {
- // for PostgreSQL compatibility
- buff.append("'UNICODE' AS CLIENT_ENCODING FROM DUAL");
- } else if (readIf("DEFAULT_TRANSACTION_ISOLATION")) {
- // for PostgreSQL compatibility
- buff.append("'read committed' AS DEFAULT_TRANSACTION_ISOLATION " +
- "FROM DUAL");
- } else if (readIf("TRANSACTION")) {
- // for PostgreSQL compatibility
- read("ISOLATION");
- read("LEVEL");
- buff.append("'read committed' AS TRANSACTION_ISOLATION " +
- "FROM DUAL");
- } else if (readIf("DATESTYLE")) {
- // for PostgreSQL compatibility
- buff.append("'ISO' AS DATESTYLE FROM DUAL");
- } else if (readIf("SERVER_VERSION")) {
- // for PostgreSQL compatibility
- buff.append("'8.1.4' AS SERVER_VERSION FROM DUAL");
- } else if (readIf("SERVER_ENCODING")) {
- // for PostgreSQL compatibility
- buff.append("'UTF8' AS SERVER_ENCODING FROM DUAL");
- } else if (readIf("TABLES")) {
- // for MySQL compatibility
- String schema = Constants.SCHEMA_MAIN;
- if (readIf("FROM")) {
- schema = readUniqueIdentifier();
- }
- buff.append("TABLE_NAME, TABLE_SCHEMA FROM "
- + "INFORMATION_SCHEMA.TABLES "
- + "WHERE TABLE_SCHEMA=? ORDER BY TABLE_NAME");
- paramValues.add(ValueString.get(schema));
- } else if (readIf("COLUMNS")) {
- // for MySQL compatibility
- read("FROM");
- String tableName = readIdentifierWithSchema();
- String schemaName = getSchema().getName();
- paramValues.add(ValueString.get(tableName));
- if (readIf("FROM")) {
- schemaName = readUniqueIdentifier();
- }
- buff.append("C.COLUMN_NAME FIELD, "
- + "C.TYPE_NAME || '(' || C.NUMERIC_PRECISION || ')' TYPE, "
- + "C.IS_NULLABLE \"NULL\", "
- + "CASE (SELECT MAX(I.INDEX_TYPE_NAME) FROM "
- + "INFORMATION_SCHEMA.INDEXES I "
- + "WHERE I.TABLE_SCHEMA=C.TABLE_SCHEMA "
- + "AND I.TABLE_NAME=C.TABLE_NAME "
- + "AND I.COLUMN_NAME=C.COLUMN_NAME)"
- + "WHEN 'PRIMARY KEY' THEN 'PRI' "
- + "WHEN 'UNIQUE INDEX' THEN 'UNI' ELSE '' END KEY, "
- + "IFNULL(COLUMN_DEFAULT, 'NULL') DEFAULT "
- + "FROM INFORMATION_SCHEMA.COLUMNS C "
- + "WHERE C.TABLE_NAME=? AND C.TABLE_SCHEMA=? "
- + "ORDER BY C.ORDINAL_POSITION");
- paramValues.add(ValueString.get(schemaName));
- } else if (readIf("DATABASES") || readIf("SCHEMAS")) {
- // for MySQL compatibility
- buff.append("SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA");
- }
- boolean b = session.getAllowLiterals();
- try {
- // need to temporarily enable it, in case we are in
- // ALLOW_LITERALS_NUMBERS mode
- session.setAllowLiterals(true);
- return prepare(session, buff.toString(), paramValues);
- } finally {
- session.setAllowLiterals(b);
- }
- }
- private static Prepared prepare(Session s, String sql,
- ArrayList<Value> paramValues) {
- Prepared prep = s.prepare(sql);
- ArrayList<Parameter> params = prep.getParameters();
- if (params != null) {
- for (int i = 0, size = params.size(); i < size; i++) {
- Parameter p = params.get(i);
- p.setValue(paramValues.get(i));
- }
- }
- return prep;
- }
- private boolean isSelect() {
- int start = lastParseIndex;
- while (readIf("(")) {
- // need to read ahead, it could be a nested union:
- // ((select 1) union (select 1))
- }
- boolean select = isToken("SELECT") || isToken("FROM");
- parseIndex = start;
- read();
- return select;
- }
- private Merge parseMerge() {
- Merge command = new Merge(session);
- currentPrepared = command;
- read("INTO");
- Table table = readTableOrView();
- command.setTable(table);
- if (readIf("(")) {
- if (isSelect()) {
- command.setQuery(parseSelect());
- read(")");
- return command;
- }
- Column[] columns = parseColumnList(table);
- command.setColumns(columns);
- }
- if (readIf("KEY")) {
- read("(");
- Column[] keys = parseColumnList(table);
- command.setKeys(keys);
- }
- if (readIf("VALUES")) {
- do {
- ArrayList<Expression> values = New.arrayList();
- read("(");
- if (!readIf(")")) {
- do {
- if (readIf("DEFAULT")) {
- values.add(null);
- } else {
- values.add(readExpression());
- }
- } while (readIfMore());
- }
- command.addRow(values.toArray(new Expression[values.size()]));
- } while (readIf(","));
- } else {
- command.setQuery(parseSelect());
- }
- return command;
- }
- private Insert parseInsert() {
- Insert command = new Insert(session);
- currentPrepared = command;
- read("INTO");
- Table table = readTableOrView();
- command.setTable(table);
- Column[] columns = null;
- if (readIf("(")) {
- if (isSelect()) {
- command.setQuery(parseSelect());
- read(")");
- return command;
- }
- columns = parseColumnList(table);
- command.setColumns(columns);
- }
- if (readIf("DIRECT")) {
- command.setInsertFromSelect(true);
- }
- if (readIf("SORTED")) {
- command.setSortedInsertMode(true);
- }
- if (readIf("DEFAULT")) {
- read("VALUES");
- Expression[] expr = {};
- command.addRow(expr);
- } else if (readIf("VALUES")) {
- read("(");
- do {
- ArrayList<Expression> values = New.arrayList();
- if (!readIf(")")) {
- do {
- if (readIf("DEFAULT")) {
- values.add(null);
- } else {
- values.add(readExpression());
- }
- } while (readIfMore());
- }
- command.addRow(values.toArray(new Expression[values.size()]));
- // the following condition will allow (..),; and (..);
- } while (readIf(",") && readIf("("));
- } else if (readIf("SET")) {
- if (columns != null) {
- throw getSyntaxError();
- }
- ArrayList<Column> columnList = New.arrayList();
- ArrayList<Expression> values = New.arrayList();
- do {
- columnList.add(parseColumn(table));
- read("=");
- Expression expression;
- if (readIf("DEFAULT")) {
- expression = ValueExpression.getDefault();
- } else {
- expression = readExpression();
- }
- values.add(expression);
- } while (readIf(","));
- command.setColumns(columnList.toArray(new Column[columnList.size()]));
- command.addRow(values.toArray(new Expression[values.size()]));
- } else {
- command.setQuery(parseSelect());
- }
- if (database.getMode().onDuplicateKeyUpdate) {
- if (readIf("ON")) {
- read("DUPLICATE");
- read("KEY");
- read("UPDATE");
- do {
- Column column = parseColumn(table);
- read("=");
- Expression expression;
- if (readIf("DEFAULT")) {
- expression = ValueExpression.getDefault();
- } else {
- expression = readExpression();
- }
- command.addAssignmentForDuplicate(column, expression);
- } while (readIf(","));
- }
- }
- if (database.getMode().isolationLevelInSelectOrInsertStatement) {
- parseIsolationClause();
- }
- return command;
- }
- /**
- * MySQL compatibility. REPLACE is similar to MERGE.
- */
- private Replace parseReplace() {
- Replace command = new Replace(session);
- currentPrepared = command;
- read("INTO");
- Table table = readTableOrView();
- command.setTable(table);
- if (readIf("(")) {
- if (isSelect()) {
- command.setQuery(parseSelect());
- read(")");
- return command;
- }
- Column[] columns = parseColumnList(table);
- command.setColumns(columns);
- }
- if (readIf("VALUES")) {
- do {
- ArrayList<Expression> values = New.arrayList();
- read("(");
- if (!readIf(")")) {
- do {
- if (readIf("DEFAULT")) {
- values.add(null);
- } else {
- values.add(readExpression());
- }
- } while (readIfMore());
- }
- command.addRow(values.toArray(new Expression[values.size()]));
- } while (readIf(","));
- } else {
- command.setQuery(parseSelect());
- }
- return command;
- }
- private TableFilter readTableFilter(boolean fromOuter) {
- Table table;
- String alias = null;
- if (readIf("(")) {
- if (isSelect()) {
- Query query = parseSelectUnion();
- read(")");
- query.setParameterList(New.arrayList(parameters));
- query.init();
- Session s;
- if (createView != null) {
- s = database.getSystemSession();
- } else {
- s = session;
- }
- alias = session.getNextSystemIdentifier(sqlCommand);
- table = TableView.createTempView(s, session.getUser(), alias,
- query, currentSelect);
- } else {
- TableFilter top;
- if (database.getSettings().nestedJoins) {
- top = readTableFilter(false);
- top = readJoin(top, currentSelect, false, false);
- top = getNested(top);
- } else {
- top = readTableFilter(fromOuter);
- top = readJoin(top, currentSelect, false, fromOuter);
- }
- read(")");
- alias = readFromAlias(null);
- if (alias != null) {
- top.setAlias(alias);
- }
- return top;
- }
- } else if (readIf("VALUES")) {
- table = parseValuesTable().getTable();
- } else {
- String tableName = readIdentifierWithSchema(null);
- Schema schema = getSchema();
- boolean foundLeftBracket = readIf("(");
- if (foundLeftBracket && readIf("INDEX")) {
- // Sybase compatibility with
- // "select * from test (index table1_index)"
- readIdentifierWithSchema(null);
- read(")");
- foundLeftBracket = false;
- }
- if (foundLeftBracket) {
- Schema mainSchema = database.getSchema(Constants.SCHEMA_MAIN);
- if (equalsToken(tableName, RangeTable.NAME)) {
- Expression min = readExpression();
- read(",");
- Expression max = readExpression();
- read(")");
- table = new RangeTable(mainSchema, min, max, false);
- } else {
- Expression expr = readFunction(schema, tableName);
- if (!(expr instanceof FunctionCall)) {
- throw getSyntaxError();
- }
- FunctionCall call = (FunctionCall) expr;
- if (!call.isDeterministic()) {
- recompileAlways = true;
- }
- table = new FunctionTable(mainSchema, session, expr, call);
- }
- } else if (equalsToken("DUAL", tableName)) {
- table = getDualTable(false);
- } else if (database.getMode().sysDummy1 &&
- equalsToken("SYSDUMMY1", tableName)) {
- table = getDualTable(false);
- } else {
- table = readTableOrView(tableName);
- }
- }
- alias = readFromAlias(alias);
- return new TableFilter(session, table, alias, rightsChecked,
- currentSelect);
- }
- private String readFromAlias(String alias) {
- if (readIf("AS")) {
- alias = readAliasIdentifier();
- } else if (currentTokenType == IDENTIFIER) {
- // left and right are not keywords (because they are functions as
- // well)
- if (!isToken("LEFT") && !isToken("RIGHT") && !isToken("FULL")) {
- alias = readAliasIdentifier();
- }
- }
- return alias;
- }
- private Prepared parseTruncate() {
- read("TABLE");
- Table table = readTableOrView();
- TruncateTable command = new TruncateTable(session);
- command.setTable(table);
- return command;
- }
- private boolean readIfExists(boolean ifExists) {
- if (readIf("IF")) {
- read("EXISTS");
- ifExists = true;
- }
- return ifExists;
- }
- private Prepared parseComment() {
- int type = 0;
- read("ON");
- boolean column = false;
- if (readIf("TABLE") || readIf("VIEW")) {
- type = DbObject.TABLE_OR_VIEW;
- } else if (readIf("COLUMN")) {
- column = true;
- type = DbObject.TABLE_OR_VIEW;
- } else if (readIf("CONSTANT")) {
- type = DbObject.CONSTANT;
- } else if (readIf("CONSTRAINT")) {
- type = DbObject.CONSTRAINT;
- } else if (readIf("ALIAS")) {
- type = DbObject.FUNCTION_ALIAS;
- } else if (readIf("INDEX")) {
- type = DbObject.INDEX;
- } else if (readIf("ROLE")) {
- type = DbObject.ROLE;
- } else if (readIf("SCHEMA")) {
- type = DbObject.SCHEMA;
- } else if (readIf("SEQUENCE")) {
- type = DbObject.SEQUENCE;
- } else if (readIf("TRIGGER")) {
- type = DbObject.TRIGGER;
- } else if (readIf("USER")) {
- type = DbObject.USER;
- } else if (readIf("DOMAIN")) {
- type = DbObject.USER_DATATYPE;
- } else {
- throw getSyntaxError();
- }
- SetComment command = new SetComment(session);
- String objectName;
- if (column) {
- // can't use readIdentifierWithSchema() because
- // it would not read schema.table.column correctly
- // if the db name is equal to the schema name
- ArrayList<String> list = New.arrayList();
- do {
- list.add(readUniqueIdentifier());
- } while (readIf("."));
- schemaName = session.getCurrentSchemaName();
- if (list.size() == 4) {
- if (!equalsToken(database.getShortName(), list.get(0))) {
- throw DbException.getSyntaxError(sqlCommand, parseIndex,
- "database name");
- }
- list.remove(0);
- }
- if (list.size() == 3) {
- schemaName = list.get(0);
- list.remove(0);
- }
- if (list.size() != 2) {
- throw DbException.getSyntaxError(sqlCommand, parseIndex,
- "table.column");
- }
- objectName = list.get(0);
- command.setColumn(true);
- command.setColumnName(list.get(1));
- } else {
- objectName = readIdentifierWithSchema();
- }
- command.setSchemaName(schemaName);
- command.setObjectName(objectName);
- command.setObjectType(type);
- read("IS");
- command.setCommentExpression(readExpression());
- return command;
- }
- private Prepared parseDrop() {
- if (readIf("TABLE")) {
- boolean ifExists = readIfExists(false);
- String tableName = readIdentifierWithSchema();
- DropTable command = new DropTable(session, getSchema());
- command.setTableName(tableName);
- while (readIf(",")) {
- tableName = readIdentifierWithSchema();
- DropTable next = new DropTable(session, getSchema());
- next.setTableName(tableName);
- command.addNextDropTable(next);
- }
- ifExists = readIfExists(ifExists);
- command.setIfExists(ifExists);
- if (readIf("CASCADE")) {
- command.setDropAction(ConstraintReferential.CASCADE);
- readIf("CONSTRAINTS");
- } else if (readIf("RESTRICT")) {
- command.setDropAction(ConstraintReferential.RESTRICT);
- } else if (readIf("IGNORE")) {
- command.setDropAction(ConstraintReferential.SET_DEFAULT);
- }
- return command;
- } else if (readIf("INDEX")) {
- boolean ifExists = readIfExists(false);
- String indexName = readIdentifierWithSchema();
- DropIndex command = new DropIndex(session, getSchema());
- command.setIndexName(indexName);
- ifExists = readIfExists(ifExists);
- command.setIfExists(ifExists);
- return command;
- } else if (readIf("USER")) {
- boolean ifExists = readIfExists(false);
- DropUser command = new DropUser(session);
- command.setUserName(readUniqueIdentifier());
- ifExists = readIfExists(ifExists);
- readIf("CASCADE");
- command.setIfExists(ifExists);
- return command;
- } else if (readIf("SEQUENCE")) {
- boolean ifExists = readIfExists(false);
- String sequenceName = readIdentifierWithSchema();
- DropSequence command = new DropSequence(session, getSchema());
- command.setSequenceName(sequenceName);
- ifExists = readIfExists(ifExists);
- command.setIfExists(ifExists);
- return command;
- } else if (readIf("CONSTANT")) {
- boolean ifExists = readIfExists(false);
- String constantName = readIdentifierWithSchema();
- DropConstant command = new DropConstant(session, getSchema());
- command.setConstantName(constantName);
- ifExists = readIfExists(ifExists);
- command.setIfExists(ifExists);
- return command;
- } else if (readIf("TRIGGER")) {
- boolean ifExists = readIfExists(false);
- …
Large files files are truncated, but you can click here to view the full file