From 1ec3edf01575f302b765b62317ca16c1547dbe10 Mon Sep 17 00:00:00 2001 From: Arina Ielchiieva Date: Thu, 2 Feb 2017 11:47:19 +0000 Subject: [PATCH] DRILL-5238: CTTAS: unable to resolve temporary table if workspace is indicated without schema This closes #736 --- .../apache/drill/exec/ops/QueryContext.java | 4 +- .../drill/exec/planner/sql/SqlConverter.java | 46 +++++++++++++++---- .../drill/exec/rpc/user/UserSession.java | 8 +--- .../org/apache/drill/exec/sql/TestCTTAS.java | 14 ++++++ 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java index 101600ccdbd..4ee8a9d7dc1 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.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 @@ -93,7 +93,7 @@ public QueryContext(final UserSession session, final DrillbitContext drillbitCon plannerSettings.setNumEndPoints(drillbitContext.getBits().size()); table = new DrillOperatorTable(getFunctionRegistry(), drillbitContext.getOptionManager()); - queryContextInfo = Utilities.createQueryContextInfo(session.getDefaultSchemaName(), session.getSessionId()); + queryContextInfo = Utilities.createQueryContextInfo(session.getDefaultSchemaPath(), session.getSessionId()); contextInformation = new ContextInformation(session.getCredentials(), queryContextInfo); allocator = drillbitContext.getAllocator().newChildAllocator( 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 d20fc060e5a..3e3226d3e4f 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 @@ -480,25 +480,27 @@ private class DrillCalciteCatalogReader extends CalciteCatalogReader { private boolean allowTemporaryTables; DrillCalciteCatalogReader(CalciteSchema rootSchema, - boolean caseSensitive, - List defaultSchema, - JavaTypeFactory typeFactory, - DrillConfig drillConfig, - UserSession session) { + boolean caseSensitive, + List defaultSchema, + JavaTypeFactory typeFactory, + DrillConfig drillConfig, + UserSession session) { super(rootSchema, caseSensitive, defaultSchema, typeFactory); this.drillConfig = drillConfig; this.session = session; this.allowTemporaryTables = true; } - /** Disallow temporary tables presence in sql statement (ex: in view definitions) */ + /** + * Disallow temporary tables presence in sql statement (ex: in view definitions) + */ public void disallowTemporaryTables() { this.allowTemporaryTables = false; } /** * If schema is not indicated (only one element in the list) or schema is default temporary workspace, - * we need to check among session temporary tables first in default temporary workspace. + * we need to check among session temporary tables in default temporary workspace first. * If temporary table is found and temporary tables usage is allowed, its table instance will be returned, * otherwise search will be conducted in original workspace. * @@ -509,8 +511,8 @@ public void disallowTemporaryTables() { @Override public RelOptTableImpl getTable(final List names) { RelOptTableImpl temporaryTable = null; - String schemaPath = SchemaUtilites.getSchemaPath(names.subList(0, names.size() - 1)); - if (names.size() == 1 || SchemaUtilites.isTemporaryWorkspace(schemaPath, drillConfig)) { + + if (mightBeTemporaryTable(names, session.getDefaultSchemaPath(), drillConfig)) { String temporaryTableName = session.resolveTemporaryTableName(names.get(names.size() - 1)); if (temporaryTableName != null) { List temporaryNames = Lists.newArrayList(temporarySchema, temporaryTableName); @@ -528,5 +530,31 @@ public RelOptTableImpl getTable(final List names) { } return super.getTable(names); } + + /** + * We should check if passed table is temporary or not if: + *
  • schema is not indicated (only one element in the names list)
  • + *
  • current schema or indicated schema is default temporary workspace
  • + * + * Examples (where dfs.tmp is default temporary workspace): + *
  • select * from t
  • + *
  • select * from dfs.tmp.t
  • + *
  • use dfs; select * from tmp.t
  • + * + * @param names list of schema and table names, table name is always the last element + * @param defaultSchemaPath current schema path set using USE command + * @param drillConfig drill config + * @return true if check for temporary table should be done, false otherwise + */ + private boolean mightBeTemporaryTable(List names, String defaultSchemaPath, DrillConfig drillConfig) { + if (names.size() == 1) { + return true; + } + + String schemaPath = SchemaUtilites.getSchemaPath(names.subList(0, names.size() - 1)); + return SchemaUtilites.isTemporaryWorkspace(schemaPath, drillConfig) || + SchemaUtilites.isTemporaryWorkspace( + SchemaUtilites.SCHEMA_PATH_JOINER.join(defaultSchemaPath, schemaPath), drillConfig); + } } } diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java index 27bf3e9a975..c1e577df912 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java @@ -65,8 +65,8 @@ public class UserSession implements Closeable { private boolean supportComplexTypes = false; private UserCredentials credentials; - private Map properties; private OptionManager sessionOptions; + private final Map properties; private final AtomicInteger queryCount; private final String sessionId; @@ -121,7 +121,6 @@ public Builder withOptionManager(OptionManager systemOptions) { } public Builder withUserProperties(UserProperties properties) { - userSession.properties = Maps.newHashMap(); if (properties != null) { for (int i = 0; i < properties.getPropertiesCount(); i++) { final Property property = properties.getProperties(i); @@ -157,6 +156,7 @@ private UserSession() { sessionId = UUID.randomUUID().toString(); temporaryTables = Maps.newConcurrentMap(); temporaryLocations = Maps.newConcurrentMap(); + properties = Maps.newHashMap(); } public boolean isSupportComplexTypes() { @@ -189,10 +189,6 @@ public String getTargetUserName() { return properties.get(IMPERSONATION_TARGET); } - public String getDefaultSchemaName() { - return getProp(SCHEMA); - } - public void incrementQueryCount(final QueryCountIncrementer incrementer) { assert incrementer != null; queryCount.incrementAndGet(); 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 5d83beb260e..b38af4acda0 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 @@ -142,6 +142,20 @@ public void testTemporaryTablesCaseInsensitivity() throws Exception { } } + @Test + public void testResolveTemporaryTableWithPartialSchema() throws Exception { + String temporaryTableName = "temporary_table_with_partial_schema"; + test("use %s", test_schema); + test("create temporary table tmp.%s as select 'A' as c1 from (values(1))", temporaryTableName); + + testBuilder() + .sqlQuery("select * from tmp.%s", temporaryTableName) + .unOrdered() + .baselineColumns("c1") + .baselineValues("A") + .go(); + } + @Test public void testPartitionByWithTemporaryTables() throws Exception { String temporaryTableName = "temporary_table_with_partitions";