| <#-- |
| |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| --> |
| <#-- |
| Add implementations of additional parser statements here. |
| Each implementation should return an object of SqlNode type. |
| |
| Example of SqlShowTables() implementation: |
| SqlNode SqlShowTables() |
| { |
| ...local variables... |
| } |
| { |
| <SHOW> <TABLES> |
| ... |
| { |
| return SqlShowTables(...) |
| } |
| } |
| --> |
| |
| /** |
| * Parses statement |
| * SHOW TABLES [{FROM | IN} db_name] [LIKE 'pattern' | WHERE expr] |
| */ |
| SqlNode SqlShowTables() : |
| { |
| SqlParserPos pos; |
| SqlIdentifier db = null; |
| SqlNode likePattern = null; |
| SqlNode where = null; |
| } |
| { |
| <SHOW> { pos = getPos(); } |
| <TABLES> |
| [ |
| (<FROM> | <IN>) { db = CompoundIdentifier(); } |
| ] |
| [ |
| <LIKE> { likePattern = StringLiteral(); } |
| | |
| <WHERE> { where = Expression(ExprContext.ACCEPT_SUBQUERY); } |
| ] |
| { |
| return new SqlShowTables(pos, db, likePattern, where); |
| } |
| } |
| |
| /** |
| * Parses statement |
| * SHOW FILES [{FROM | IN} schema] |
| */ |
| SqlNode SqlShowFiles() : |
| { |
| SqlParserPos pos = null; |
| SqlIdentifier db = null; |
| } |
| { |
| <SHOW> { pos = getPos(); } |
| <FILES> |
| [ |
| (<FROM> | <IN>) { db = CompoundIdentifier(); } |
| ] |
| { |
| return new SqlShowFiles(pos, db); |
| } |
| } |
| |
| |
| /** |
| * Parses statement SHOW {DATABASES | SCHEMAS} [LIKE 'pattern' | WHERE expr] |
| */ |
| SqlNode SqlShowSchemas() : |
| { |
| SqlParserPos pos; |
| SqlNode likePattern = null; |
| SqlNode where = null; |
| } |
| { |
| <SHOW> { pos = getPos(); } |
| (<DATABASES> | <SCHEMAS>) |
| [ |
| <LIKE> { likePattern = StringLiteral(); } |
| | |
| <WHERE> { where = Expression(ExprContext.ACCEPT_SUBQUERY); } |
| ] |
| { |
| return new SqlShowSchemas(pos, likePattern, where); |
| } |
| } |
| |
| /** |
| * Parses statement |
| * { DESCRIBE | DESC } [TABLE] tblname [col_name | wildcard ] |
| */ |
| SqlNode SqlDescribeTable() : |
| { |
| SqlParserPos pos; |
| SqlIdentifier table; |
| SqlIdentifier column = null; |
| SqlNode columnPattern = null; |
| } |
| { |
| (<DESCRIBE> | <DESC>) { pos = getPos(); } |
| (<TABLE>)? |
| table = CompoundIdentifier() |
| ( |
| column = CompoundIdentifier() |
| | |
| columnPattern = StringLiteral() |
| | |
| E() |
| ) |
| { |
| return new DrillSqlDescribeTable(pos, table, column, columnPattern); |
| } |
| } |
| |
| SqlNode SqlUseSchema(): |
| { |
| SqlIdentifier schema; |
| SqlParserPos pos; |
| } |
| { |
| <USE> { pos = getPos(); } |
| schema = CompoundIdentifier() |
| { |
| return new SqlUseSchema(pos, schema); |
| } |
| } |
| |
| /** Parses an optional field list and makes sure no field is a "*". */ |
| SqlNodeList ParseOptionalFieldList(String relType) : |
| { |
| SqlNodeList fieldList; |
| } |
| { |
| fieldList = ParseRequiredFieldList(relType) |
| { |
| return fieldList; |
| } |
| | |
| { |
| return SqlNodeList.EMPTY; |
| } |
| } |
| |
| /** Parses a required field list and makes sure no field is a "*". */ |
| SqlNodeList ParseRequiredFieldList(String relType) : |
| { |
| Pair<SqlNodeList, SqlNodeList> fieldList; |
| } |
| { |
| fieldList = ParenthesizedCompoundIdentifierList() |
| { |
| for(SqlNode node : fieldList.left) |
| { |
| if (((SqlIdentifier) node).isStar()) |
| throw new ParseException(String.format("%s's field list has a '*', which is invalid.", relType)); |
| } |
| return fieldList.left; |
| } |
| } |
| |
| /** |
| * Parses CREATE [OR REPLACE] command for VIEW, TABLE or SCHEMA. |
| */ |
| SqlNode SqlCreateOrReplace() : |
| { |
| SqlParserPos pos; |
| String createType = "SIMPLE"; |
| boolean isTemporary = false; |
| boolean isPublic = false; |
| } |
| { |
| <CREATE> { pos = getPos(); } |
| [ <OR> <REPLACE> { createType = "OR_REPLACE"; } ] |
| [ <TEMPORARY> { isTemporary = true; } ] |
| ( |
| <VIEW> |
| { |
| if (isTemporary) { |
| throw new ParseException("Create view statement does not allow <TEMPORARY> keyword."); |
| } |
| return SqlCreateView(pos, createType); |
| } |
| | |
| <TABLE> |
| { |
| if (createType == "OR_REPLACE") { |
| throw new ParseException("Create table statement does not allow <OR><REPLACE>."); |
| } |
| return SqlCreateTable(pos, isTemporary); |
| |
| } |
| | |
| <SCHEMA> |
| { |
| if (isTemporary) { |
| throw new ParseException("Create schema statement does not allow <TEMPORARY> keyword."); |
| } |
| return SqlCreateSchema(pos, createType); |
| } |
| | |
| [ <PUBLIC> { isPublic = true; } ] |
| <ALIAS> |
| { |
| if (isTemporary) { |
| throw new ParseException("Create alias statement does not allow <TEMPORARY> keyword."); |
| } |
| return SqlCreateAlias(pos, createType.equals("OR_REPLACE"), isPublic); |
| } |
| ) |
| } |
| |
| /** |
| * Parses a create view or replace existing view statement. |
| * after CREATE OR REPLACE VIEW statement which is handled in the SqlCreateOrReplace method. |
| * |
| * CREATE { [OR REPLACE] VIEW | VIEW [IF NOT EXISTS] | VIEW } view_name [ (field1, field2 ...) ] AS select_statement |
| */ |
| SqlNode SqlCreateView(SqlParserPos pos, String createType) : |
| { |
| SqlIdentifier viewName; |
| SqlNode query; |
| SqlNodeList fieldList; |
| } |
| { |
| [ |
| <IF> <NOT> <EXISTS> { |
| if (createType == "OR_REPLACE") { |
| throw new ParseException("Create view statement cannot have both <OR REPLACE> and <IF NOT EXISTS> clause"); |
| } |
| createType = "IF_NOT_EXISTS"; |
| } |
| ] |
| viewName = CompoundIdentifier() |
| fieldList = ParseOptionalFieldList("View") |
| <AS> |
| query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) |
| { |
| return new SqlCreateView(pos, viewName, fieldList, query, SqlLiteral.createCharString(createType, getPos())); |
| } |
| } |
| |
| /** |
| * Parses a CTAS or CTTAS statement after CREATE [TEMPORARY] TABLE statement |
| * which is handled in the SqlCreateOrReplace method. |
| * |
| * CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tblname [ (field1, field2, ...) ] AS select_statement. |
| */ |
| SqlNode SqlCreateTable(SqlParserPos pos, boolean isTemporary) : |
| { |
| SqlIdentifier tblName; |
| SqlNodeList fieldList; |
| SqlNodeList partitionFieldList; |
| SqlNode query; |
| boolean tableNonExistenceCheck = false; |
| } |
| { |
| { |
| partitionFieldList = SqlNodeList.EMPTY; |
| } |
| ( <IF> <NOT> <EXISTS> { tableNonExistenceCheck = true; } )? |
| tblName = CompoundIdentifier() |
| fieldList = ParseOptionalFieldList("Table") |
| ( <PARTITION> <BY> |
| partitionFieldList = ParseRequiredFieldList("Partition") |
| )? |
| <AS> |
| query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) |
| { |
| return new SqlCreateTable(pos, tblName, fieldList, partitionFieldList, query, |
| SqlLiteral.createBoolean(isTemporary, getPos()), |
| SqlLiteral.createBoolean(tableNonExistenceCheck, getPos())); |
| } |
| } |
| |
| /** |
| * Parses create table schema statement after CREATE OR REPLACE SCHEMA statement |
| * which is handled in the SqlCreateOrReplace method. |
| * |
| * CREATE [OR REPLACE] SCHEMA |
| * [ |
| * LOAD 'file:///path/to/raw_schema' |
| * | |
| * ( |
| * col1 int, |
| * col2 varchar(10) not null |
| * ) |
| * ] |
| * [FOR TABLE dfs.my_table] |
| * [PATH 'file:///path/to/schema'] |
| * [PROPERTIES ('prop1'='val1', 'prop2'='val2')] |
| */ |
| SqlNode SqlCreateSchema(SqlParserPos pos, String createType) : |
| { |
| SqlCharStringLiteral schema = null; |
| SqlNode load = null; |
| SqlIdentifier table = null; |
| SqlNode path = null; |
| SqlNodeList properties = null; |
| } |
| { |
| { |
| token_source.pushState(); |
| token_source.SwitchTo(SCH); |
| } |
| ( |
| <SCH_LOAD> |
| { |
| load = StringLiteral(); |
| } |
| | |
| <SCH_PAREN_STRING> |
| { |
| schema = SqlLiteral.createCharString(token.image, getPos()); |
| } |
| ) |
| ( |
| <FOR> <TABLE> { table = CompoundIdentifier(); } |
| | |
| <PATH> |
| { |
| path = StringLiteral(); |
| if (createType == "OR_REPLACE") { |
| throw new ParseException("<OR REPLACE> cannot be used with <PATH> property."); |
| } |
| } |
| ) |
| [ |
| <PROPERTIES> <LPAREN> |
| { |
| properties = new SqlNodeList(getPos()); |
| addProperty(properties); |
| } |
| ( |
| <COMMA> |
| { addProperty(properties); } |
| )* |
| <RPAREN> |
| ] |
| { |
| return new SqlSchema.Create(pos, schema, load, table, path, properties, |
| SqlLiteral.createCharString(createType, getPos())); |
| } |
| } |
| |
| /** |
| * Helper method to add string literals divided by equals into SqlNodeList. |
| */ |
| void addProperty(SqlNodeList properties) : |
| {} |
| { |
| { properties.add(StringLiteral()); } |
| <EQ> |
| { properties.add(StringLiteral()); } |
| } |
| |
| <SCH> SKIP : |
| { |
| " " |
| | "\t" |
| | "\n" |
| | "\r" |
| } |
| |
| <SCH> TOKEN : { |
| < SCH_LOAD: "LOAD" > { popState(); } |
| | < SCH_NUM: <DIGIT> (" " | "\t" | "\n" | "\r")* > |
| // once schema is found, switch back to initial lexical state |
| // must be enclosed in the parentheses |
| // inside may have left parenthesis only if number precedes (covers cases with varchar(10)), |
| // if left parenthesis is present in column name, it must be escaped with backslash |
| | < SCH_PAREN_STRING: <LPAREN> ((~[")"]) | (<SCH_NUM> ")") | ("\\)"))* <RPAREN> > { popState(); } |
| } |
| |
| /** |
| * Parses DROP command for VIEW, TABLE and SCHEMA. |
| */ |
| SqlNode SqlDrop() : |
| { |
| SqlParserPos pos; |
| } |
| { |
| <DROP> { pos = getPos(); } |
| ( |
| <VIEW> |
| { |
| return SqlDropView(pos); |
| } |
| | |
| <TABLE> |
| { |
| return SqlDropTable(pos); |
| } |
| | |
| <SCHEMA> |
| { |
| return SqlDropSchema(pos); |
| } |
| ) |
| } |
| |
| /** |
| * Parses a drop view or drop view if exists statement |
| * after DROP VIEW statement which is handled in SqlDrop method. |
| * |
| * DROP VIEW [IF EXISTS] view_name; |
| */ |
| SqlNode SqlDropView(SqlParserPos pos) : |
| { |
| boolean viewExistenceCheck = false; |
| } |
| { |
| [ <IF> <EXISTS> { viewExistenceCheck = true; } ] |
| { |
| return new SqlDropView(pos, CompoundIdentifier(), viewExistenceCheck); |
| } |
| } |
| |
| /** |
| * Parses a drop table or drop table if exists statement |
| * after DROP TABLE statement which is handled in SqlDrop method. |
| * |
| * DROP TABLE [IF EXISTS] table_name; |
| */ |
| SqlNode SqlDropTable(SqlParserPos pos) : |
| { |
| boolean tableExistenceCheck = false; |
| } |
| { |
| [ <IF> <EXISTS> { tableExistenceCheck = true; } ] |
| { |
| return new SqlDropTable(pos, CompoundIdentifier(), tableExistenceCheck); |
| } |
| } |
| |
| /** |
| * Parses drop schema or drop schema if exists statement |
| * after DROP SCHEMA statement which is handled in SqlDrop method. |
| * |
| * DROP SCHEMA [IF EXISTS] |
| * FOR TABLE dfs.my_table |
| */ |
| SqlNode SqlDropSchema(SqlParserPos pos) : |
| { |
| SqlIdentifier table = null; |
| boolean existenceCheck = false; |
| } |
| { |
| [ <IF> <EXISTS> { existenceCheck = true; } ] |
| <FOR> <TABLE> { table = CompoundIdentifier(); } |
| { |
| return new SqlSchema.Drop(pos, table, SqlLiteral.createBoolean(existenceCheck, getPos())); |
| } |
| } |
| |
| /** |
| * Parse refresh table metadata statement. |
| * REFRESH TABLE METADATA [COLUMNS ((field1, field2,..) | NONE)] table_name |
| */ |
| SqlNode SqlRefreshMetadata() : |
| { |
| SqlParserPos pos; |
| SqlIdentifier tblName; |
| SqlNodeList fieldList = null; |
| SqlNode query; |
| boolean allColumnsInteresting = true; |
| } |
| { |
| <REFRESH> { pos = getPos(); } |
| <TABLE> |
| <METADATA> |
| [ |
| <COLUMNS> { allColumnsInteresting = false; } |
| ( fieldList = ParseRequiredFieldList("Table") |
| | |
| <NONE> |
| ) |
| ] |
| tblName = CompoundIdentifier() |
| { |
| return new SqlRefreshMetadata(pos, tblName, SqlLiteral.createBoolean(allColumnsInteresting, getPos()), fieldList); |
| } |
| } |
| |
| /** |
| * Parses statement |
| * { DESCRIBE | DESC } { SCHEMA | DATABASE } name |
| * { DESCRIBE | DESC } SCHEMA FOR TABLE dfs.my_table [AS (JSON | STATEMENT)] |
| */ |
| SqlNode SqlDescribeSchema() : |
| { |
| SqlParserPos pos; |
| SqlIdentifier table; |
| String format = "JSON"; |
| } |
| { |
| (<DESCRIBE> | <DESC>) { pos = getPos(); } |
| ( |
| <SCHEMA> |
| ( |
| <FOR> <TABLE> { table = CompoundIdentifier(); } |
| [ |
| <AS> |
| ( |
| <JSON> { format = "JSON"; } |
| | |
| <STATEMENT> { format = "STATEMENT"; } |
| ) |
| ] |
| { |
| return new SqlSchema.Describe(pos, table, SqlLiteral.createCharString(format, getPos())); |
| } |
| |
| | |
| { |
| return new SqlDescribeSchema(pos, CompoundIdentifier()); |
| } |
| ) |
| | |
| <DATABASE> |
| { |
| return new SqlDescribeSchema(pos, CompoundIdentifier()); |
| } |
| ) |
| } |
| |
| /** |
| * Parses ALTER SCHEMA statements: |
| * |
| * ALTER SCHEMA |
| * (FOR TABLE dfs.tmp.nation | PATH '/tmp/schema.json') |
| * ADD [OR REPLACE] |
| * [COLUMNS (col1 int, col2 varchar)] |
| * [PROPERTIES ('prop1'='val1', 'prop2'='val2')] |
| * |
| * ALTER SCHEMA |
| * (FOR TABLE dfs.tmp.nation | PATH '/tmp/schema.json') |
| * REMOVE |
| * [COLUMNS (`col1`, `col2`)] |
| * [PROPERTIES ('prop1', 'prop2')] |
| */ |
| SqlNode SqlAlterSchema() : |
| { |
| SqlParserPos pos; |
| SqlIdentifier table = null; |
| SqlNode path = null; |
| } |
| { |
| <ALTER> { pos = getPos(); } |
| <SCHEMA> |
| ( |
| <FOR> <TABLE> { table = CompoundIdentifier(); } |
| | |
| <PATH> { path = StringLiteral(); } |
| ) |
| ( |
| <ADD> { return SqlAlterSchemaAdd(pos, table, path); } |
| | |
| <REMOVE> { return SqlAlterSchemaRemove(pos, table, path); } |
| ) |
| } |
| |
| SqlNode SqlAlterSchemaAdd(SqlParserPos pos, SqlIdentifier table, SqlNode path) : |
| { |
| boolean replace = false; |
| SqlCharStringLiteral schema = null; |
| SqlNodeList properties = null; |
| } |
| { |
| [ <OR> <REPLACE> { replace = true; } ] |
| [ <COLUMNS> { schema = ParseSchema(); } ] |
| [ |
| <PROPERTIES> <LPAREN> |
| { |
| properties = new SqlNodeList(getPos()); |
| addProperty(properties); |
| } |
| ( |
| <COMMA> { addProperty(properties); } |
| )* |
| <RPAREN> |
| ] |
| { |
| if (schema == null && properties == null) { |
| throw new ParseException("ALTER SCHEMA ADD command must have at least <COLUMNS> or <PROPERTIES> keyword indicated."); |
| } |
| return new SqlSchema.Add(pos, table, path, SqlLiteral.createBoolean(replace, getPos()), schema, properties); |
| } |
| } |
| |
| SqlCharStringLiteral ParseSchema() : |
| {} |
| { |
| { |
| token_source.pushState(); |
| token_source.SwitchTo(SCH); |
| } |
| <SCH_PAREN_STRING> |
| { |
| return SqlLiteral.createCharString(token.image, getPos()); |
| } |
| } |
| |
| SqlNode SqlAlterSchemaRemove(SqlParserPos pos, SqlIdentifier table, SqlNode path) : |
| { |
| SqlNodeList columns = null; |
| SqlNodeList properties = null; |
| } |
| { |
| [ <COLUMNS> { columns = ParseRequiredFieldList("Schema"); } ] |
| [ |
| <PROPERTIES> <LPAREN> |
| { |
| properties = new SqlNodeList(getPos()); |
| properties.add(StringLiteral()); |
| } |
| ( |
| <COMMA> |
| { properties.add(StringLiteral()); } |
| )* |
| <RPAREN> |
| ] |
| { |
| if (columns == null && properties == null) { |
| throw new ParseException("ALTER SCHEMA REMOVE command must have at least <COLUMNS> or <PROPERTIES> keyword indicated."); |
| } |
| return new SqlSchema.Remove(pos, table, path, columns, properties); |
| } |
| } |
| |
| /** |
| * Parse create UDF statement |
| * CREATE FUNCTION USING JAR 'jar_name' |
| */ |
| SqlNode SqlCreateFunction() : |
| { |
| SqlParserPos pos; |
| SqlNode jar; |
| } |
| { |
| <CREATE> { pos = getPos(); } |
| <FUNCTION> |
| <USING> |
| <JAR> |
| jar = StringLiteral() |
| { |
| return new SqlCreateFunction(pos, jar); |
| } |
| } |
| |
| /** |
| * Parse drop UDF statement |
| * DROP FUNCTION USING JAR 'jar_name' |
| */ |
| SqlNode SqlDropFunction() : |
| { |
| SqlParserPos pos; |
| SqlNode jar; |
| } |
| { |
| <DROP> { pos = getPos(); } |
| <FUNCTION> |
| <USING> |
| <JAR> |
| jar = StringLiteral() |
| { |
| return new SqlDropFunction(pos, jar); |
| } |
| } |
| |
| /** |
| * Parses a analyze statements: |
| * <ul> |
| * <li>ANALYZE TABLE [table_name | table({table function name}(parameters))] [COLUMNS {(col1, col2, ...) | NONE}] REFRESH METADATA ['level' LEVEL] [{COMPUTE | ESTIMATE} | STATISTICS [ SAMPLE number PERCENT ]] |
| * <li>ANALYZE TABLE [table_name] DROP [METADATA|STATISTICS] [IF EXISTS] |
| * <li>ANALYZE TABLE [table_name | table({table function name}(parameters))] {COMPUTE | ESTIMATE} | STATISTICS [(column1, column2, ...)] [ SAMPLE numeric PERCENT ] |
| * </ul> |
| */ |
| SqlNode SqlAnalyzeTable() : |
| { |
| SqlParserPos pos; |
| SqlNode tableRef; |
| Span s = null; |
| SqlNodeList fieldList = null; |
| SqlNode level = null; |
| SqlLiteral estimate = null; |
| SqlLiteral dropMetadata = null; |
| SqlLiteral checkMetadataExistence = null; |
| SqlNumericLiteral percent = null; |
| } |
| { |
| <ANALYZE> { pos = getPos(); } |
| <TABLE> |
| ( |
| tableRef = CompoundIdentifier() |
| | |
| tableRef = TableFunctionCall() |
| ) |
| [ |
| ( |
| ( |
| <COMPUTE> { estimate = SqlLiteral.createBoolean(false, pos); } |
| | |
| <ESTIMATE> { |
| if (true) { |
| throw new ParseException("ESTIMATE statistics collecting is not supported. See DRILL-7438."); |
| } |
| estimate = SqlLiteral.createBoolean(true, pos); |
| } |
| ) |
| <STATISTICS> |
| [ |
| (fieldList = ParseRequiredFieldList("Table")) |
| ] |
| [ |
| <SAMPLE> percent = UnsignedNumericLiteral() <PERCENT> |
| { |
| BigDecimal rate = percent.bigDecimalValue(); |
| if (rate.compareTo(BigDecimal.ZERO) <= 0 || |
| rate.compareTo(BigDecimal.valueOf(100L)) > 0) |
| { |
| throw new ParseException("Invalid percentage for ANALYZE TABLE"); |
| } |
| } |
| ] |
| { |
| if (percent == null) { percent = SqlLiteral.createExactNumeric("100.0", pos); } |
| return new SqlAnalyzeTable(pos, tableRef, estimate, fieldList, percent); |
| } |
| ) |
| | |
| ( |
| [ |
| <COLUMNS> |
| ( |
| fieldList = ParseRequiredFieldList("Table") |
| | |
| <NONE> {fieldList = SqlNodeList.EMPTY;} |
| ) |
| ] |
| <REFRESH> |
| <METADATA> |
| [ |
| level = StringLiteral() |
| <LEVEL> |
| ] |
| [ |
| ( |
| <COMPUTE> { estimate = SqlLiteral.createBoolean(false, pos); } |
| | |
| <ESTIMATE> { |
| if (true) { |
| throw new ParseException("ESTIMATE statistics collecting is not supported. See DRILL-7438."); |
| } |
| estimate = SqlLiteral.createBoolean(true, pos); |
| } |
| ) |
| <STATISTICS> |
| ] |
| [ |
| <SAMPLE> percent = UnsignedNumericLiteral() <PERCENT> |
| { |
| BigDecimal rate = percent.bigDecimalValue(); |
| if (rate.compareTo(BigDecimal.ZERO) <= 0 || |
| rate.compareTo(BigDecimal.valueOf(100L)) > 0) { |
| throw new ParseException("Invalid percentage for ANALYZE TABLE"); |
| } |
| } |
| ] |
| { |
| return new SqlMetastoreAnalyzeTable(pos, tableRef, fieldList, level, estimate, percent); |
| } |
| ) |
| | |
| ( |
| <DROP> |
| [ |
| <METADATA> { dropMetadata = SqlLiteral.createCharString("METADATA", pos); } |
| | |
| <STATISTICS> { |
| if (true) { |
| throw new ParseException("DROP STATISTICS is not supported."); |
| } |
| dropMetadata = SqlLiteral.createCharString("STATISTICS", pos); |
| } |
| ] |
| [ |
| <IF> |
| <EXISTS> { checkMetadataExistence = SqlLiteral.createBoolean(false, pos); } |
| ] |
| { |
| if (checkMetadataExistence == null) { |
| checkMetadataExistence = SqlLiteral.createBoolean(true, pos); |
| } |
| if (s != null) { |
| throw new ParseException("Table functions shouldn't be used in DROP METADATA statement."); |
| } |
| return new SqlDropTableMetadata(pos, (SqlIdentifier) tableRef, dropMetadata, checkMetadataExistence); |
| } |
| ) |
| ] |
| { throw generateParseException(); } |
| } |
| |
| |
| /** |
| * Parses a SET statement without a leading "ALTER <SCOPE>": |
| * |
| * SET <NAME> [ = VALUE ] |
| * <p> |
| * Statement handles in: {@link SetAndResetOptionHandler} |
| */ |
| DrillSqlSetOption DrillSqlSetOption(Span s, String scope) : |
| { |
| SqlParserPos pos; |
| SqlIdentifier name; |
| SqlNode val = null; |
| } |
| { |
| <SET> { |
| s.add(this); |
| } |
| name = CompoundIdentifier() |
| ( |
| <EQ> |
| ( |
| val = Literal() |
| | |
| val = SimpleIdentifier() |
| ) |
| )? |
| { |
| pos = (val == null) ? s.end(name) : s.end(val); |
| |
| return new DrillSqlSetOption(pos, scope, name, val); |
| } |
| } |
| |
| /** |
| * Parses a RESET statement without a leading "ALTER <SCOPE>": |
| * |
| * RESET { <NAME> | ALL } |
| * <p> |
| * Statement handles in: {@link SetAndResetOptionHandler} |
| */ |
| DrillSqlResetOption DrillSqlResetOption(Span s, String scope) : |
| { |
| SqlIdentifier name; |
| } |
| { |
| <RESET> { |
| s.add(this); |
| } |
| ( |
| name = CompoundIdentifier() |
| | |
| <ALL> { |
| name = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT), getPos()); |
| } |
| ) |
| { |
| return new DrillSqlResetOption(s.end(name), scope, name); |
| } |
| } |
| |
| /** |
| * Parses CREATE ALIAS statement |
| * CREATE [OR REPLACE] [PUBLIC] ALIAS `alias` FOR [TABLE | STORAGE] `table/storage` [AS USER 'username'] |
| */ |
| SqlNode SqlCreateAlias(SqlParserPos pos, boolean replace, boolean isPublic) : |
| { |
| SqlIdentifier alias = null; |
| String aliasTarget = "TABLE"; |
| SqlIdentifier source = null; |
| SqlNode user = null; |
| } |
| { |
| { alias = CompoundIdentifier(); } |
| <FOR> |
| [ |
| <TABLE> { aliasTarget = "TABLE"; } |
| | |
| <STORAGE> { aliasTarget = "STORAGE"; } |
| ] |
| { source = CompoundIdentifier(); } |
| [ <AS> <USER> { user = StringLiteral(); } ] |
| { |
| return SqlCreateAlias.builder() |
| .pos(pos) |
| .alias(alias) |
| .source(source) |
| .aliasKind(SqlLiteral.createCharString(aliasTarget, pos)) |
| .replace(SqlLiteral.createBoolean(replace, pos)) |
| .isPublic(SqlLiteral.createBoolean(isPublic, pos)) |
| .user(user) |
| .build(); |
| } |
| } |
| |
| /** |
| * Parses DROP ALIAS statement |
| * DROP [PUBLIC] ALIAS [IF EXISTS] `employee-alias` [FOR (TABLE | STORAGE)] [AS USER 'username'] |
| */ |
| SqlNode SqlDropAlias() : |
| { |
| SqlParserPos pos; |
| boolean isPublic = false; |
| boolean ifExists = false; |
| SqlIdentifier alias = null; |
| String aliasTarget = "TABLE"; |
| SqlNode user = null; |
| } |
| { |
| <DROP> { pos = getPos(); } |
| [ <PUBLIC> { isPublic = true; } ] |
| <ALIAS> |
| [ <IF> <EXISTS> { ifExists = true; } ] |
| { alias = CompoundIdentifier(); } |
| [ <FOR> |
| ( |
| <TABLE> { aliasTarget = "TABLE"; } |
| | |
| <STORAGE> { aliasTarget = "STORAGE"; } |
| ) |
| ] |
| [ <AS> <USER> { user = StringLiteral(); } ] |
| { |
| return SqlDropAlias.builder() |
| .pos(pos) |
| .alias(alias) |
| .aliasKind(SqlLiteral.createCharString(aliasTarget, pos)) |
| .ifExists(SqlLiteral.createBoolean(ifExists, pos)) |
| .isPublic(SqlLiteral.createBoolean(isPublic, pos)) |
| .user(user) |
| .build(); |
| } |
| } |
| |
| /** |
| * Parses DROP ALL ALIASES statement |
| * DROP ALL [PUBLIC] ALIASES [FOR (TABLE | STORAGE)] [AS USER 'username'] |
| */ |
| SqlNode SqlDropAllAliases() : |
| { |
| SqlParserPos pos; |
| boolean isPublic = false; |
| String aliasTarget = "TABLE"; |
| SqlNode user = null; |
| } |
| { |
| <DROP> { pos = getPos(); } |
| <ALL> |
| [ <PUBLIC> { isPublic = true; } ] |
| <ALIASES> |
| [ <FOR> |
| ( |
| <TABLE> { aliasTarget = "TABLE"; } |
| | |
| <STORAGE> { aliasTarget = "STORAGE"; } |
| ) |
| ] |
| [ <AS> <USER> { user = StringLiteral(); } ] |
| { |
| return SqlDropAllAliases.builder() |
| .pos(pos) |
| .aliasKind(SqlLiteral.createCharString(aliasTarget, pos)) |
| .isPublic(SqlLiteral.createBoolean(isPublic, pos)) |
| .user(user) |
| .build(); |
| } |
| } |