From 7a50e92716a4f03f71d5f16b054b6f31c6b4753c Mon Sep 17 00:00:00 2001 From: Prasad Nagaraj Subramanya Date: Thu, 16 Nov 2017 23:03:43 -0800 Subject: [PATCH 1/3] DRILL-5952: Implement "CREATE TABLE IF NOT EXISTS and CREATE VIEW IF NOT EXISTS" --- .../src/main/codegen/includes/parserImpls.ftl | 25 ++++-- .../drill/exec/planner/sql/SqlConverter.java | 3 + .../sql/handlers/CreateTableHandler.java | 41 ++++------ .../planner/sql/handlers/ViewHandler.java | 79 +++++++++++-------- .../parser/CompoundIdentifierConverter.java | 2 +- .../planner/sql/parser/SqlCreateTable.java | 22 ++++-- .../planner/sql/parser/SqlCreateView.java | 37 +++++---- .../org/apache/drill/exec/sql/TestCTAS.java | 61 ++++++++++++++ .../org/apache/drill/exec/sql/TestCTTAS.java | 60 ++++++++++++++ .../drill/exec/sql/TestViewSupport.java | 69 ++++++++++++++++ 10 files changed, 309 insertions(+), 90 deletions(-) diff --git a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl index d9ceed91e88..b38a36221b4 100644 --- a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl +++ b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl @@ -172,26 +172,34 @@ SqlNodeList ParseRequiredFieldList(String relType) : /** * Parses a create view or replace existing view statement. - * CREATE [OR REPLACE] VIEW view_name [ (field1, field2 ...) ] AS select_statement + * CREATE { [OR REPLACE] VIEW | VIEW [IF NOT EXISTS] | VIEW } view_name [ (field1, field2 ...) ] AS select_statement */ SqlNode SqlCreateOrReplaceView() : { SqlParserPos pos; - boolean replaceView = false; SqlIdentifier viewName; SqlNode query; SqlNodeList fieldList; + String createViewType = "0"; } { { pos = getPos(); } - [ { replaceView = true; } ] + [ { createViewType = "1"; } ] + [ + { + if (createViewType == "1") { + throw new ParseException("Create view statement cannot have both and clause"); + } + createViewType = "2"; + } + ] viewName = CompoundIdentifier() fieldList = ParseOptionalFieldList("View") query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) { - return new SqlCreateView(pos, viewName, fieldList, query, replaceView); + return new SqlCreateView(pos, viewName, fieldList, query, SqlLiteral.createExactNumeric(createViewType, getPos())); } } @@ -215,11 +223,12 @@ SqlNode SqlDropView() : /** * Parses a CTAS or CTTAS statement. - * CREATE [TEMPORARY] TABLE tblname [ (field1, field2, ...) ] AS select_statement. + * CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tblname [ (field1, field2, ...) ] AS select_statement. */ SqlNode SqlCreateTable() : { SqlParserPos pos; + boolean tableNonExistenceCheck = false; SqlIdentifier tblName; SqlNodeList fieldList; SqlNodeList partitionFieldList; @@ -233,6 +242,7 @@ SqlNode SqlCreateTable() : { pos = getPos(); } ( { isTemporary = true; } )? + ( { tableNonExistenceCheck = true; } )? tblName = CompoundIdentifier() fieldList = ParseOptionalFieldList("Table") ( @@ -241,8 +251,9 @@ SqlNode SqlCreateTable() : query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) { - return new SqlCreateTable(pos,tblName, fieldList, partitionFieldList, query, - SqlLiteral.createBoolean(isTemporary, getPos())); + return new SqlCreateTable(pos, tblName, fieldList, partitionFieldList, query, + SqlLiteral.createBoolean(isTemporary, getPos()), + SqlLiteral.createBoolean(tableNonExistenceCheck, getPos())); } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java index 798e3a4479d..dbe16bd5904 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java @@ -382,6 +382,9 @@ public int getInSubqueryThreshold() { * @return The sql with a ^ character under the error */ static String formatSQLParsingError(String sql, SqlParserPos pos) { + if (pos == null) { + return sql; + } StringBuilder sb = new StringBuilder(); String[] lines = sql.split("\n"); for (int i = 0; i < lines.length; i++) { diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java index d232a7116b8..74e77ab8c3b 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java @@ -40,6 +40,7 @@ import org.apache.drill.exec.ExecConstants; import org.apache.drill.exec.physical.PhysicalPlan; import org.apache.drill.exec.physical.base.PhysicalOperator; +import org.apache.drill.exec.planner.sql.DirectPlan; import org.apache.drill.exec.rpc.user.UserSession; import org.apache.drill.exec.store.StorageStrategy; import org.apache.drill.exec.planner.logical.DrillRel; @@ -83,7 +84,20 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv final DrillConfig drillConfig = context.getConfig(); final AbstractSchema drillSchema = resolveSchema(sqlCreateTable, config.getConverter().getDefaultSchema(), drillConfig); - checkDuplicatedObjectExistence(drillSchema, originalTableName, drillConfig, context.getSession()); + String schemaPath = drillSchema.getFullSchemaName(); + + // Check duplicate object existence + boolean isTemporaryTable = context.getSession().isTemporaryTable(drillSchema, drillConfig, originalTableName); + if (isTemporaryTable || SqlHandlerUtil.getTableFromSchema(drillSchema, originalTableName) != null) { + if (sqlCreateTable.checkTableNonExistence()) { + return DirectPlan.createDirectPlan(context, false, + String.format("A table or view with given name [%s] already exists in schema [%s]", originalTableName, schemaPath)); + } else { + throw UserException.validationError() + .message("A table or view with given name [%s] already exists in schema [%s]", originalTableName, schemaPath) + .build(logger); + } + } final RelNode newTblRelNodeWithPCol = SqlHandlerUtil.qualifyPartitionCol(newTblRelNode, sqlCreateTable.getPartitionColumns()); @@ -288,29 +302,4 @@ private AbstractSchema resolveSchema(SqlCreateTable sqlCreateTable, SchemaPlus d return resolvedSchema; } - /** - * Checks if any object (persistent table / temporary table / view) - * with the same name as table to be created exists in indicated schema. - * - * @param drillSchema schema where table will be created - * @param tableName table name - * @param config drill config - * @param userSession current user session - * @throws UserException if duplicate is found - */ - private void checkDuplicatedObjectExistence(AbstractSchema drillSchema, - String tableName, - DrillConfig config, - UserSession userSession) { - String schemaPath = drillSchema.getFullSchemaName(); - boolean isTemporaryTable = userSession.isTemporaryTable(drillSchema, config, tableName); - - if (isTemporaryTable || SqlHandlerUtil.getTableFromSchema(drillSchema, tableName) != null) { - throw UserException - .validationError() - .message("A table or view with given name [%s] already exists in schema [%s]", - tableName, schemaPath) - .build(logger); - } - } } \ No newline at end of file diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java index 495e8b5105a..0886612e52c 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java @@ -78,47 +78,58 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv final View view = new View(newViewName, viewSql, newViewRelNode.getRowType(), SchemaUtilites.getSchemaPathAsList(defaultSchema)); - validateViewCreationPossibility(drillSchema, createView, context); + final String schemaPath = drillSchema.getFullSchemaName(); + final String viewName = view.getName(); + final Table table = SqlHandlerUtil.getTableFromSchema(drillSchema, viewName); + + // check table/view existence + final boolean isTable = (table != null && table.getJdbcTableType() != Schema.TableType.VIEW) + || context.getSession().isTemporaryTable(drillSchema, context.getConfig(), viewName); + final boolean isView = (table != null && table.getJdbcTableType() == Schema.TableType.VIEW); + + switch (createView.getcreateViewType()) { + case 0 : + // create view + if (isTable) { + throw UserException + .validationError() + .message("A non-view table with given name [%s] already exists in schema [%s]", viewName, schemaPath) + .build(logger); + } else if (isView) { + throw UserException + .validationError() + .message("A view with given name [%s] already exists in schema [%s]", viewName, schemaPath) + .build(logger); + } + break; + case 1 : + // create or replace view + if (isTable) { + throw UserException + .validationError() + .message("A non-view table with given name [%s] already exists in schema [%s]", viewName, schemaPath) + .build(logger); + } + break; + case 2 : + // create view if not exists + if (isTable) { + return DirectPlan + .createDirectPlan(context, false, String.format("A non-view table with given name [%s] already exists in schema [%s]", viewName, schemaPath)); + } else if (isView) { + return DirectPlan + .createDirectPlan(context, false, String.format("A view with given name [%s] already exists in schema [%s]", viewName, schemaPath)); + } + break; + } final boolean replaced = drillSchema.createView(view); final String summary = String.format("View '%s' %s successfully in '%s' schema", - createView.getName(), replaced ? "replaced" : "created", drillSchema.getFullSchemaName()); + createView.getName(), replaced ? "replaced" : "created", schemaPath); return DirectPlan.createDirectPlan(context, true, summary); } - /** - * Validates if view can be created in indicated schema: - * checks if object (persistent / temporary table) with the same name exists - * or if view with the same name exists but replace flag is not set. - * - * @param drillSchema schema where views will be created - * @param view create view call - * @param context query context - * @throws UserException if views can be created in indicated schema - */ - private void validateViewCreationPossibility(AbstractSchema drillSchema, SqlCreateView view, QueryContext context) { - final String schemaPath = drillSchema.getFullSchemaName(); - final String viewName = view.getName(); - final Table existingTable = SqlHandlerUtil.getTableFromSchema(drillSchema, viewName); - - if ((existingTable != null && existingTable.getJdbcTableType() != Schema.TableType.VIEW) || - context.getSession().isTemporaryTable(drillSchema, context.getConfig(), viewName)) { - // existing table is not a view - throw UserException - .validationError() - .message("A non-view table with given name [%s] already exists in schema [%s]", viewName, schemaPath) - .build(logger); - } - - if ((existingTable != null && existingTable.getJdbcTableType() == Schema.TableType.VIEW) && !view.getReplace()) { - // existing table is a view and create view has no "REPLACE" clause - throw UserException - .validationError() - .message("A view with given name [%s] already exists in schema [%s]", viewName, schemaPath) - .build(logger); - } - } } /** Handler for Drop View [If Exists] DDL command. */ diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java index db934e27486..e9d0dca71eb 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/CompoundIdentifierConverter.java @@ -161,7 +161,7 @@ RewriteType[] should be R(D, E, D, D). //SqlNode offset, //SqlNode fetch, rules.put(SqlSelect.class, R(D, E, D, E, E, E, E, E, D, D)); - rules.put(SqlCreateTable.class, R(D, D, D, E, D)); + rules.put(SqlCreateTable.class, R(D, D, D, E, D, D)); rules.put(SqlCreateView.class, R(D, E, E, D)); rules.put(SqlDescribeTable.class, R(D, D, E)); rules.put(SqlDropView.class, R(D, D)); diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateTable.java index bba60b2bc4c..457e78cc01b 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateTable.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateTable.java @@ -20,14 +20,10 @@ import java.util.List; import com.google.common.base.Preconditions; -import org.apache.calcite.tools.Planner; -import org.apache.drill.common.expression.SchemaPath; -import org.apache.drill.exec.ops.QueryContext; import org.apache.drill.exec.planner.sql.handlers.AbstractSqlHandler; import org.apache.drill.exec.planner.sql.handlers.CreateTableHandler; import org.apache.drill.exec.planner.sql.handlers.SqlHandlerConfig; -import org.apache.calcite.plan.hep.HepPlanner; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -48,13 +44,14 @@ public class SqlCreateTable extends DrillSqlCall { public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("CREATE_TABLE", SqlKind.OTHER) { @Override public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNode... operands) { - Preconditions.checkArgument(operands.length == 5, "SqlCreateTable.createCall() has to get 5 operands!"); + Preconditions.checkArgument(operands.length == 6, "SqlCreateTable.createCall() has to get 6 operands!"); return new SqlCreateTable(pos, (SqlIdentifier) operands[0], (SqlNodeList) operands[1], (SqlNodeList) operands[2], operands[3], - (SqlLiteral) operands[4]); + (SqlLiteral) operands[4], + (SqlLiteral) operands[5]); } }; @@ -63,19 +60,22 @@ public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNod private final SqlNodeList partitionColumns; private final SqlNode query; private final SqlLiteral isTemporary; + private final SqlLiteral tableNonExistenceCheck; public SqlCreateTable(SqlParserPos pos, SqlIdentifier tblName, SqlNodeList fieldList, SqlNodeList partitionColumns, SqlNode query, - SqlLiteral isTemporary) { + SqlLiteral isTemporary, + SqlLiteral tableNonExistenceCheck) { super(pos); this.tblName = tblName; this.fieldList = fieldList; this.partitionColumns = partitionColumns; this.query = query; this.isTemporary = isTemporary; + this.tableNonExistenceCheck = tableNonExistenceCheck; } @Override @@ -91,6 +91,7 @@ public List getOperandList() { ops.add(partitionColumns); ops.add(query); ops.add(isTemporary); + ops.add(tableNonExistenceCheck); return ops; } @@ -101,6 +102,11 @@ public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { writer.keyword("TEMPORARY"); } writer.keyword("TABLE"); + if (tableNonExistenceCheck.booleanValue()) { + writer.keyword("IF"); + writer.keyword("NOT"); + writer.keyword("EXISTS"); + } tblName.unparse(writer, leftPrec, rightPrec); if (fieldList.size() > 0) { SqlHandlerUtil.unparseSqlNodeList(writer, leftPrec, rightPrec, fieldList); @@ -160,4 +166,6 @@ public List getPartitionColumns() { public boolean isTemporary() { return isTemporary.booleanValue(); } + public boolean checkTableNonExistence() { return tableNonExistenceCheck.booleanValue(); } + } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java index cc6118a4324..a918ef07f66 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java @@ -23,6 +23,7 @@ import org.apache.drill.exec.planner.sql.handlers.SqlHandlerConfig; import org.apache.drill.exec.planner.sql.handlers.SqlHandlerUtil; import org.apache.drill.exec.planner.sql.handlers.ViewHandler; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; @@ -32,7 +33,6 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.parser.SqlParserPos; import java.util.List; @@ -47,20 +47,15 @@ public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNod private SqlIdentifier viewName; private SqlNodeList fieldList; private SqlNode query; - private boolean replaceView; - - public SqlCreateView(SqlParserPos pos, SqlIdentifier viewName, SqlNodeList fieldList, - SqlNode query, SqlLiteral replaceView) { - this(pos, viewName, fieldList, query, replaceView.booleanValue()); - } + private SqlLiteral createViewType; public SqlCreateView(SqlParserPos pos, SqlIdentifier viewName, SqlNodeList fieldList, - SqlNode query, boolean replaceView) { + SqlNode query, SqlLiteral createViewType) { super(pos); this.viewName = viewName; this.query = query; - this.replaceView = replaceView; this.fieldList = fieldList; + this.createViewType = createViewType; } @Override @@ -74,18 +69,29 @@ public List getOperandList() { ops.add(viewName); ops.add(fieldList); ops.add(query); - ops.add(SqlLiteral.createBoolean(replaceView, SqlParserPos.ZERO)); + ops.add(createViewType); return ops; } @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { writer.keyword("CREATE"); - if (replaceView) { - writer.keyword("OR"); - writer.keyword("REPLACE"); + switch (createViewType.intValue(true)) { + case 0 : + writer.keyword("VIEW"); + break; + case 1 : + writer.keyword("OR"); + writer.keyword("REPLACE"); + writer.keyword("VIEW"); + break; + case 2 : + writer.keyword("VIEW"); + writer.keyword("IF"); + writer.keyword("NOT"); + writer.keyword("EXISTS"); + break; } - writer.keyword("VIEW"); viewName.unparse(writer, leftPrec, rightPrec); if (fieldList.size() > 0) { SqlHandlerUtil.unparseSqlNodeList(writer, leftPrec, rightPrec, fieldList); @@ -124,6 +130,7 @@ public List getFieldNames() { } public SqlNode getQuery() { return query; } - public boolean getReplace() { return replaceView; } + + public int getcreateViewType() { return createViewType.intValue(true); } } diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java index 764cef4faf2..63c44982ea3 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java @@ -32,6 +32,7 @@ import java.util.Map; +import static org.apache.drill.exec.util.StoragePluginTestUtils.DFS_TMP_SCHEMA; import static org.junit.Assert.assertEquals; @Category(SqlTest.class) @@ -254,6 +255,66 @@ public void createTableWithCustomUmask() throws Exception { } } + @Test // DRILL-5952 + public void testCreateTableIfNotExistsWhenTableWithSameNameAlreadyExists() throws Exception{ + final String newTblName = "createTableIfNotExistsWhenATableWithSameNameAlreadyExists"; + + try { + String ctasQuery = String.format("CREATE TABLE %s.%s AS SELECT * from cp.`region.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + ctasQuery = + String.format("CREATE TABLE IF NOT EXISTS %s.%s AS SELECT * FROM cp.`employee.json`", DFS_TMP_SCHEMA, newTblName); + + testBuilder() + .sqlQuery(ctasQuery) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) + .go(); + } finally { + test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + + @Test // DRILL-5952 + public void testCreateTableIfNotExistsWhenViewWithSameNameAlreadyExists() throws Exception{ + final String newTblName = "createTableIfNotExistsWhenAViewWithSameNameAlreadyExists"; + + try { + String ctasQuery = String.format("CREATE VIEW %s.%s AS SELECT * from cp.`region.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + ctasQuery = + String.format("CREATE TABLE IF NOT EXISTS %s.%s AS SELECT * FROM cp.`employee.json`", DFS_TMP_SCHEMA, newTblName); + + testBuilder() + .sqlQuery(ctasQuery) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) + .go(); + } finally { + test(String.format("DROP VIEW IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + + @Test // DRILL-5952 + public void testCreateTableIfNotExistsWhenTableWithSameNameDoesNotExist() throws Exception{ + final String newTblName = "createTableIfNotExistsWhenATableWithSameNameDoesNotExist"; + + try { + String ctasQuery = String.format("CREATE TABLE IF NOT EXISTS %s.%s AS SELECT * FROM cp.`employee.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + } finally { + test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + private static void ctasErrorTestHelper(final String ctasSql, final String expErrorMsg) throws Exception { final String createTableSql = String.format(ctasSql, "testTableName"); errorMsgTestHelper(createTableSql, expErrorMsg); diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTTAS.java b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTTAS.java index bc06af3eac5..e83fa377db3 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTTAS.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTTAS.java @@ -383,6 +383,66 @@ public void testTemporaryTablesInViewExpansionLogic() throws Exception { } } + @Test // DRILL-5952 + public void testCreateTemporaryTableIfNotExistsWhenTableWithSameNameAlreadyExists() throws Exception{ + final String newTblName = "createTemporaryTableIfNotExistsWhenATableWithSameNameAlreadyExists"; + + try { + String ctasQuery = String.format("CREATE TEMPORARY TABLE %s.%s AS SELECT * from cp.`region.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + ctasQuery = + String.format("CREATE TEMPORARY TABLE IF NOT EXISTS %s AS SELECT * FROM cp.`employee.json`", newTblName); + + testBuilder() + .sqlQuery(ctasQuery) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) + .go(); + } finally { + test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + + @Test // DRILL-5952 + public void testCreateTemporaryTableIfNotExistsWhenViewWithSameNameAlreadyExists() throws Exception{ + final String newTblName = "createTemporaryTableIfNotExistsWhenAViewWithSameNameAlreadyExists"; + + try { + String ctasQuery = String.format("CREATE VIEW %s.%s AS SELECT * from cp.`region.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + ctasQuery = + String.format("CREATE TEMPORARY TABLE IF NOT EXISTS %s.%s AS SELECT * FROM cp.`employee.json`", DFS_TMP_SCHEMA, newTblName); + + testBuilder() + .sqlQuery(ctasQuery) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) + .go(); + } finally { + test(String.format("DROP VIEW IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + + @Test // DRILL-5952 + public void testCreateTemporaryTableIfNotExistsWhenTableWithSameNameDoesNotExist() throws Exception{ + final String newTblName = "createTemporaryTableIfNotExistsWhenATableWithSameNameDoesNotExist"; + + try { + String ctasQuery = String.format("CREATE TEMPORARY TABLE IF NOT EXISTS %s.%s AS SELECT * FROM cp.`employee.json`", DFS_TMP_SCHEMA, newTblName); + + test(ctasQuery); + + } finally { + test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + } + } + @Test public void testManualDropWithoutSchema() throws Exception { String temporaryTableName = "temporary_table_to_drop_without_schema"; diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java index d571c664d1c..26ea12319ff 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java @@ -311,6 +311,75 @@ public void createViewWhenViewAlreadyExists() throws Exception { } } + @Test // DRILL-5952 + public void createViewIfNotExistsWhenTableAlreadyExists() throws Exception { + final String tableName = generateViewName(); + + try { + final String tableDef = "SELECT region_id, sales_city FROM cp.`region.json` ORDER BY `region_id` LIMIT 2"; + + test("CREATE TABLE %s.%s as %s", DFS_TMP_SCHEMA, tableName, tableDef); + + // Try to create the view with same name in same schema with if not exists clause. + final String createViewSql = String.format("CREATE VIEW IF NOT EXISTS %s.`%s` AS %s", DFS_TMP_SCHEMA, tableName, tableDef); + + testBuilder() + .sqlQuery(createViewSql) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, + String.format("A non-view table with given name [%s] already exists in schema [%s]", tableName, DFS_TMP_SCHEMA)) + .go(); + + } finally { + FileUtils.deleteQuietly(new File(dirTestWatcher.getDfsTestTmpDir(), tableName)); + } + } + + @Test // DRILL-5952 + public void createViewIfNotExistsWhenViewAlreadyExists() throws Exception { + final String viewName = generateViewName(); + + try { + final String viewDef1 = "SELECT region_id, sales_city FROM cp.`region.json` ORDER BY `region_id` LIMIT 2"; + + // Create the view + createViewHelper(DFS_TMP_SCHEMA, viewName, DFS_TMP_SCHEMA, null, viewDef1); + + // Try to create the view with same name in same schema with if not exists clause. + final String viewDef2 = "SELECT sales_state_province FROM cp.`region.json` ORDER BY `region_id`"; + final String createViewSql = String.format("CREATE VIEW IF NOT EXISTS %s.`%s` AS %s", DFS_TMP_SCHEMA, viewName, viewDef2); + + testBuilder() + .sqlQuery(createViewSql) + .unOrdered() + .baselineColumns("ok", "summary") + .baselineValues(false, + String.format("A view with given name [%s] already exists in schema [%s]", viewName, DFS_TMP_SCHEMA)) + .go(); + + // Make sure the view created returns the data expected. + queryViewHelper(String.format("SELECT * FROM %s.`%s` LIMIT 1", DFS_TMP_SCHEMA, viewName), + new String[]{"region_id", "sales_city"}, + ImmutableList.of(new Object[]{0L, "None"}) + ); + } finally { + dropViewHelper(DFS_TMP_SCHEMA, viewName, DFS_TMP_SCHEMA); + } + } + + @Test // DRILL-5952 + public void createViewWithBothOrReplaceAndIfNotExists() throws Exception { + final String viewName = generateViewName(); + + final String viewDef = "SELECT region_id, sales_city FROM cp.`region.json`"; + + // Try to create the view with both and clause. + final String createViewSql = String.format("CREATE OR REPLACE VIEW IF NOT EXISTS %s.`%s` AS %s", DFS_TMP_SCHEMA, viewName, viewDef); + + errorMsgTestHelper(createViewSql, "Create view statement cannot have both and clause"); + } + @Test // DRILL-2422 @Category(UnlikelyTest.class) public void createViewWhenATableWithSameNameAlreadyExists() throws Exception { From 6acff92371fcab88103c3c2322990b87f9aa8c94 Mon Sep 17 00:00:00 2001 From: Prasad Nagaraj Subramanya Date: Thu, 23 Nov 2017 21:33:01 -0800 Subject: [PATCH 2/3] Addressed review comments --- .../src/main/codegen/includes/parserImpls.ftl | 12 ++-- .../sql/handlers/CreateTableHandler.java | 56 +++++++++++++----- .../planner/sql/handlers/ViewHandler.java | 58 ++++++++++++------- .../planner/sql/parser/SqlCreateView.java | 14 +++-- .../org/apache/drill/exec/sql/TestCTAS.java | 6 +- .../drill/exec/sql/TestViewSupport.java | 25 +++++++- 6 files changed, 118 insertions(+), 53 deletions(-) diff --git a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl index b38a36221b4..e4bdabe4452 100644 --- a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl +++ b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl @@ -180,18 +180,18 @@ SqlNode SqlCreateOrReplaceView() : SqlIdentifier viewName; SqlNode query; SqlNodeList fieldList; - String createViewType = "0"; + String createViewType = "SIMPLE"; } { { pos = getPos(); } - [ { createViewType = "1"; } ] + [ { createViewType = "ORREPLACE"; } ] [ { - if (createViewType == "1") { + if (createViewType == "ORREPLACE") { throw new ParseException("Create view statement cannot have both and clause"); } - createViewType = "2"; + createViewType = "IFNOTEXISTS"; } ] viewName = CompoundIdentifier() @@ -199,7 +199,7 @@ SqlNode SqlCreateOrReplaceView() : query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) { - return new SqlCreateView(pos, viewName, fieldList, query, SqlLiteral.createExactNumeric(createViewType, getPos())); + return new SqlCreateView(pos, viewName, fieldList, query, SqlLiteral.createCharString(createViewType, getPos())); } } @@ -228,12 +228,12 @@ SqlNode SqlDropView() : SqlNode SqlCreateTable() : { SqlParserPos pos; - boolean tableNonExistenceCheck = false; SqlIdentifier tblName; SqlNodeList fieldList; SqlNodeList partitionFieldList; SqlNode query; boolean isTemporary = false; + boolean tableNonExistenceCheck = false; } { { diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java index 74e77ab8c3b..4491bff3613 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/CreateTableHandler.java @@ -71,8 +71,8 @@ public CreateTableHandler(SqlHandlerConfig config, Pointer textPlan) { @Override public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConversionException, IOException, ForemanSetupException { - SqlCreateTable sqlCreateTable = unwrap(sqlNode, SqlCreateTable.class); - String originalTableName = sqlCreateTable.getName(); + final SqlCreateTable sqlCreateTable = unwrap(sqlNode, SqlCreateTable.class); + final String originalTableName = sqlCreateTable.getName(); final ConvertedRelNode convertedRelNode = validateAndConvert(sqlCreateTable.getQuery()); final RelDataType validatedRowType = convertedRelNode.getValidatedRowType(); @@ -83,20 +83,13 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv final DrillConfig drillConfig = context.getConfig(); final AbstractSchema drillSchema = resolveSchema(sqlCreateTable, config.getConverter().getDefaultSchema(), drillConfig); + final boolean checkTableNonExistence = sqlCreateTable.checkTableNonExistence(); + final String schemaPath = drillSchema.getFullSchemaName(); - String schemaPath = drillSchema.getFullSchemaName(); - - // Check duplicate object existence - boolean isTemporaryTable = context.getSession().isTemporaryTable(drillSchema, drillConfig, originalTableName); - if (isTemporaryTable || SqlHandlerUtil.getTableFromSchema(drillSchema, originalTableName) != null) { - if (sqlCreateTable.checkTableNonExistence()) { - return DirectPlan.createDirectPlan(context, false, - String.format("A table or view with given name [%s] already exists in schema [%s]", originalTableName, schemaPath)); - } else { - throw UserException.validationError() - .message("A table or view with given name [%s] already exists in schema [%s]", originalTableName, schemaPath) - .build(logger); - } + // Check table creation possibility + if(!checkTableCreationPossibility(drillSchema, originalTableName, drillConfig, context.getSession(), schemaPath, checkTableNonExistence)) { + return DirectPlan.createDirectPlan(context, false, + String.format("A table or view with given name [%s] already exists in schema [%s]", originalTableName, schemaPath)); } final RelNode newTblRelNodeWithPCol = SqlHandlerUtil.qualifyPartitionCol(newTblRelNode, @@ -302,4 +295,37 @@ private AbstractSchema resolveSchema(SqlCreateTable sqlCreateTable, SchemaPlus d return resolvedSchema; } + /** + * Validates if table can be created in indicated schema + * Checks if any object (persistent table / temporary table / view) with the same name exists + * or if object with the same name exists but if not exists flag is set. + * + * @param drillSchema schema where table will be created + * @param tableName table name + * @param config drill config + * @param userSession current user session + * @param schemaPath schema path + * @param checkTableNonExistence whether duplicate check is requested + * @return if duplicate found in indicated schema + * @throws UserException if duplicate found in indicated schema and no duplicate check requested + */ + private boolean checkTableCreationPossibility(AbstractSchema drillSchema, + String tableName, + DrillConfig config, + UserSession userSession, + String schemaPath, + boolean checkTableNonExistence) { + boolean isTemporaryTable = userSession.isTemporaryTable(drillSchema, config, tableName); + + if (isTemporaryTable || SqlHandlerUtil.getTableFromSchema(drillSchema, tableName) != null) { + if (checkTableNonExistence) { + return false; + } else { + throw UserException.validationError() + .message("A table or view with given name [%s] already exists in schema [%s]", tableName, schemaPath) + .build(logger); + } + } + return true; + } } \ No newline at end of file diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java index 0886612e52c..651c70c3527 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java @@ -1,4 +1,4 @@ -/** +/* * 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 @@ -77,19 +77,44 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv final View view = new View(newViewName, viewSql, newViewRelNode.getRowType(), SchemaUtilites.getSchemaPathAsList(defaultSchema)); + final String schemaPath = drillSchema.getFullSchemaName(); + + // check view creation possibility + if(!checkViewCreationPossibility(drillSchema, createView, context)) { + return DirectPlan + .createDirectPlan(context, false, String.format("A table or view with given name [%s] already exists in schema [%s]", view.getName(), schemaPath)); + } + + final boolean replaced = drillSchema.createView(view); + final String summary = String.format("View '%s' %s successfully in '%s' schema", + createView.getName(), replaced ? "replaced" : "created", drillSchema.getFullSchemaName()); + + return DirectPlan.createDirectPlan(context, true, summary); + } + /** + * Validates if view can be created in indicated schema: + * checks if object (persistent / temporary table) with the same name exists + * or if view with the same name exists but replace flag is not set + * or if object with the same name exists but if not exists flag is set. + * + * @param drillSchema schema where views will be created + * @param view create view call + * @param context query context + * @return if view can be created in indicated schema + * @throws UserException if view cannot be created in indicated schema and no duplicate check requested + */ + private boolean checkViewCreationPossibility(AbstractSchema drillSchema, SqlCreateView view, QueryContext context) { final String schemaPath = drillSchema.getFullSchemaName(); final String viewName = view.getName(); final Table table = SqlHandlerUtil.getTableFromSchema(drillSchema, viewName); - // check table/view existence final boolean isTable = (table != null && table.getJdbcTableType() != Schema.TableType.VIEW) - || context.getSession().isTemporaryTable(drillSchema, context.getConfig(), viewName); + || context.getSession().isTemporaryTable(drillSchema, context.getConfig(), viewName); final boolean isView = (table != null && table.getJdbcTableType() == Schema.TableType.VIEW); - switch (createView.getcreateViewType()) { - case 0 : - // create view + switch (view.getcreateViewType()) { + case SIMPLE: if (isTable) { throw UserException .validationError() @@ -102,8 +127,7 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv .build(logger); } break; - case 1 : - // create or replace view + case ORREPLACE: if (isTable) { throw UserException .validationError() @@ -111,23 +135,13 @@ public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConv .build(logger); } break; - case 2 : - // create view if not exists - if (isTable) { - return DirectPlan - .createDirectPlan(context, false, String.format("A non-view table with given name [%s] already exists in schema [%s]", viewName, schemaPath)); - } else if (isView) { - return DirectPlan - .createDirectPlan(context, false, String.format("A view with given name [%s] already exists in schema [%s]", viewName, schemaPath)); + case IFNOTEXISTS: + if (isTable || isView) { + return false; } break; } - - final boolean replaced = drillSchema.createView(view); - final String summary = String.format("View '%s' %s successfully in '%s' schema", - createView.getName(), replaced ? "replaced" : "created", schemaPath); - - return DirectPlan.createDirectPlan(context, true, summary); + return true; } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java index a918ef07f66..f125a6efc70 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java @@ -49,6 +49,10 @@ public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNod private SqlNode query; private SqlLiteral createViewType; + public enum SqlCreateViewType { + SIMPLE, ORREPLACE, IFNOTEXISTS + } + public SqlCreateView(SqlParserPos pos, SqlIdentifier viewName, SqlNodeList fieldList, SqlNode query, SqlLiteral createViewType) { super(pos); @@ -76,16 +80,16 @@ public List getOperandList() { @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { writer.keyword("CREATE"); - switch (createViewType.intValue(true)) { - case 0 : + switch (SqlCreateViewType.valueOf(createViewType.toValue())) { + case SIMPLE: writer.keyword("VIEW"); break; - case 1 : + case ORREPLACE: writer.keyword("OR"); writer.keyword("REPLACE"); writer.keyword("VIEW"); break; - case 2 : + case IFNOTEXISTS: writer.keyword("VIEW"); writer.keyword("IF"); writer.keyword("NOT"); @@ -131,6 +135,6 @@ public List getFieldNames() { public SqlNode getQuery() { return query; } - public int getcreateViewType() { return createViewType.intValue(true); } + public SqlCreateViewType getcreateViewType() { return SqlCreateViewType.valueOf(createViewType.toValue()); } } diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java index 63c44982ea3..2315a0321a8 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestCTAS.java @@ -274,7 +274,7 @@ public void testCreateTableIfNotExistsWhenTableWithSameNameAlreadyExists() throw .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) .go(); } finally { - test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + test("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName); } } @@ -297,7 +297,7 @@ public void testCreateTableIfNotExistsWhenViewWithSameNameAlreadyExists() throws .baselineValues(false, String.format("A table or view with given name [%s] already exists in schema [%s]", newTblName, DFS_TMP_SCHEMA)) .go(); } finally { - test(String.format("DROP VIEW IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + test("DROP VIEW IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName); } } @@ -311,7 +311,7 @@ public void testCreateTableIfNotExistsWhenTableWithSameNameDoesNotExist() throws test(ctasQuery); } finally { - test(String.format("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName)); + test("DROP TABLE IF EXISTS %s.%s", DFS_TMP_SCHEMA, newTblName); } } diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java index 26ea12319ff..6efa5ce51aa 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/sql/TestViewSupport.java @@ -328,7 +328,7 @@ public void createViewIfNotExistsWhenTableAlreadyExists() throws Exception { .unOrdered() .baselineColumns("ok", "summary") .baselineValues(false, - String.format("A non-view table with given name [%s] already exists in schema [%s]", tableName, DFS_TMP_SCHEMA)) + String.format("A table or view with given name [%s] already exists in schema [%s]", tableName, DFS_TMP_SCHEMA)) .go(); } finally { @@ -355,7 +355,7 @@ public void createViewIfNotExistsWhenViewAlreadyExists() throws Exception { .unOrdered() .baselineColumns("ok", "summary") .baselineValues(false, - String.format("A view with given name [%s] already exists in schema [%s]", viewName, DFS_TMP_SCHEMA)) + String.format("A table or view with given name [%s] already exists in schema [%s]", viewName, DFS_TMP_SCHEMA)) .go(); // Make sure the view created returns the data expected. @@ -368,6 +368,27 @@ public void createViewIfNotExistsWhenViewAlreadyExists() throws Exception { } } + @Test // DRILL-5952 + public void testCreateViewIfNotExists() throws Exception { + final String viewName = generateViewName(); + + try { + final String viewDef = "SELECT region_id, sales_city FROM cp.`region.json` ORDER BY `region_id` LIMIT 2"; + + final String createViewSql = String.format("CREATE VIEW IF NOT EXISTS %s.`%s` AS %s", DFS_TMP_SCHEMA, viewName, viewDef); + + test(createViewSql); + + // Make sure the view created returns the data expected. + queryViewHelper(String.format("SELECT * FROM %s.`%s` LIMIT 1", DFS_TMP_SCHEMA, viewName), + new String[]{"region_id", "sales_city"}, + ImmutableList.of(new Object[]{0L, "None"}) + ); + } finally { + dropViewHelper(DFS_TMP_SCHEMA, viewName, DFS_TMP_SCHEMA); + } + } + @Test // DRILL-5952 public void createViewWithBothOrReplaceAndIfNotExists() throws Exception { final String viewName = generateViewName(); From 60aac1f387804c95d56bbf1016a57844cf343afe Mon Sep 17 00:00:00 2001 From: Prasad Nagaraj Subramanya Date: Fri, 24 Nov 2017 08:45:24 -0800 Subject: [PATCH 3/3] Fixed enum names --- exec/java-exec/src/main/codegen/includes/parserImpls.ftl | 6 +++--- .../apache/drill/exec/planner/sql/handlers/ViewHandler.java | 4 ++-- .../apache/drill/exec/planner/sql/parser/SqlCreateView.java | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl index e4bdabe4452..67d15015efc 100644 --- a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl +++ b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl @@ -184,14 +184,14 @@ SqlNode SqlCreateOrReplaceView() : } { { pos = getPos(); } - [ { createViewType = "ORREPLACE"; } ] + [ { createViewType = "OR_REPLACE"; } ] [ { - if (createViewType == "ORREPLACE") { + if (createViewType == "OR_REPLACE") { throw new ParseException("Create view statement cannot have both and clause"); } - createViewType = "IFNOTEXISTS"; + createViewType = "IF_NOT_EXISTS"; } ] viewName = CompoundIdentifier() diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java index 651c70c3527..e86b90a091a 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java @@ -127,7 +127,7 @@ private boolean checkViewCreationPossibility(AbstractSchema drillSchema, SqlCrea .build(logger); } break; - case ORREPLACE: + case OR_REPLACE: if (isTable) { throw UserException .validationError() @@ -135,7 +135,7 @@ private boolean checkViewCreationPossibility(AbstractSchema drillSchema, SqlCrea .build(logger); } break; - case IFNOTEXISTS: + case IF_NOT_EXISTS: if (isTable || isView) { return false; } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java index f125a6efc70..e7ee9c90a75 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java @@ -50,7 +50,7 @@ public SqlCall createCall(SqlLiteral functionQualifier, SqlParserPos pos, SqlNod private SqlLiteral createViewType; public enum SqlCreateViewType { - SIMPLE, ORREPLACE, IFNOTEXISTS + SIMPLE, OR_REPLACE, IF_NOT_EXISTS } public SqlCreateView(SqlParserPos pos, SqlIdentifier viewName, SqlNodeList fieldList, @@ -84,12 +84,12 @@ public void unparse(SqlWriter writer, int leftPrec, int rightPrec) { case SIMPLE: writer.keyword("VIEW"); break; - case ORREPLACE: + case OR_REPLACE: writer.keyword("OR"); writer.keyword("REPLACE"); writer.keyword("VIEW"); break; - case IFNOTEXISTS: + case IF_NOT_EXISTS: writer.keyword("VIEW"); writer.keyword("IF"); writer.keyword("NOT");