You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by ja...@apache.org on 2014/06/11 05:52:25 UTC

[40/61] [abbrv] git commit: DRILL-736: Fix DESCRIBE issues when the selected table exists in more than one schema.

DRILL-736: Fix DESCRIBE issues when the selected table exists in more than one schema.


Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/299d1bf1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/299d1bf1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/299d1bf1

Branch: refs/heads/master
Commit: 299d1bf1c053da7bcf9902e7bf1ad870b9337c61
Parents: 0c3bad9
Author: vkorukanti <ve...@gmail.com>
Authored: Mon Jun 9 15:48:55 2014 -0700
Committer: vkorukanti <ve...@gmail.com>
Committed: Mon Jun 9 15:48:55 2014 -0700

----------------------------------------------------------------------
 .../sql/handlers/AbstractSqlHandler.java        |  4 +
 .../sql/handlers/DescribeTableHandler.java      | 81 ++++++++++++--------
 .../apache/drill/jdbc/test/TestMetadataDDL.java | 43 ++++++++++-
 3 files changed, 93 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/299d1bf1/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/AbstractSqlHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/AbstractSqlHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/AbstractSqlHandler.java
index 4a3584c..3504505 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/AbstractSqlHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/AbstractSqlHandler.java
@@ -79,6 +79,10 @@ public abstract class AbstractSqlHandler {
     throw new Exception(String.format("Invalid schema path '%s'.", Joiner.on(".").join(schemaPath)));
   }
 
+  public static boolean isRootSchema(SchemaPlus schema) {
+    return schema.getParentSchema() == null;
+  }
+
   private static SchemaPlus searchSchemaTree(SchemaPlus schema, List<String> schemaPath) {
     for (String schemaName : schemaPath) {
       schema = schema.getSubSchema(schemaName);

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/299d1bf1/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DescribeTableHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DescribeTableHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DescribeTableHandler.java
index d6849f4..1020757 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DescribeTableHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DescribeTableHandler.java
@@ -19,11 +19,13 @@
 package org.apache.drill.exec.planner.sql.handlers;
 
 import com.google.common.collect.ImmutableList;
+import net.hydromatic.optiq.SchemaPlus;
 import net.hydromatic.optiq.tools.Planner;
 import net.hydromatic.optiq.tools.RelConversionException;
 import org.apache.drill.exec.ops.QueryContext;
 import org.apache.drill.exec.planner.sql.parser.DrillParserUtil;
 import org.apache.drill.exec.planner.sql.parser.SqlDescribeTable;
+import org.apache.drill.exec.store.AbstractSchema;
 import org.eigenbase.sql.*;
 import org.eigenbase.sql.fun.SqlStdOperatorTable;
 import org.eigenbase.sql.parser.SqlParserPos;
@@ -39,50 +41,61 @@ public class DescribeTableHandler extends DefaultSqlHandler {
 
   /** Rewrite the parse tree as SELECT ... FROM INFORMATION_SCHEMA.COLUMNS ... */
   @Override
-  public SqlNode rewrite(SqlNode sqlNode) throws RelConversionException{
+  public SqlNode rewrite(SqlNode sqlNode) throws RelConversionException {
     SqlDescribeTable node = unwrap(sqlNode, SqlDescribeTable.class);
 
-    List<SqlNode> selectList = ImmutableList.of((SqlNode)new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
-        new SqlIdentifier("DATA_TYPE", SqlParserPos.ZERO),
-        new SqlIdentifier("IS_NULLABLE", SqlParserPos.ZERO));
+    try {
+      List<SqlNode> selectList = ImmutableList.of((SqlNode) new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
+          new SqlIdentifier("DATA_TYPE", SqlParserPos.ZERO),
+          new SqlIdentifier("IS_NULLABLE", SqlParserPos.ZERO));
 
-    SqlNode fromClause = new SqlIdentifier(
-        ImmutableList.of("INFORMATION_SCHEMA", "COLUMNS"), null, SqlParserPos.ZERO, null);
+      SqlNode fromClause = new SqlIdentifier(
+          ImmutableList.of("INFORMATION_SCHEMA", "COLUMNS"), null, SqlParserPos.ZERO, null);
 
-    final SqlIdentifier table = node.getTable();
-    final int numLevels = table.names.size();
+      final SqlIdentifier table = node.getTable();
+      final SchemaPlus schema = findSchema(context.getRootSchema(), context.getNewDefaultSchema(),
+          Util.skipLast(table.names));
+      final String tableName = Util.last(table.names);
 
-    SqlNode schemaCondition = null;
-    if (numLevels > 1) {
-      schemaCondition = DrillParserUtil.createCondition(
-          new SqlIdentifier("TABLE_SCHEMA", SqlParserPos.ZERO),
-          SqlStdOperatorTable.EQUALS,
-          SqlLiteral.createCharString(Util.sepList(table.names.subList(0, numLevels - 1), "."),
-              CHARSET, SqlParserPos.ZERO)
-      );
-    }
+      if (schema.getTable(tableName) == null) {
+        throw new RelConversionException(String.format("Table %s is not valid", Util.sepList(table.names, ".")));
+      }
 
-    SqlNode where = DrillParserUtil.createCondition(
-        new SqlIdentifier("TABLE_NAME", SqlParserPos.ZERO),
-        SqlStdOperatorTable.EQUALS,
-        SqlLiteral.createCharString(table.names.get(numLevels-1), CHARSET, SqlParserPos.ZERO));
+      SqlNode schemaCondition = null;
+      if (!isRootSchema(schema)) {
+        AbstractSchema drillSchema = getDrillSchema(schema);
 
-    where = DrillParserUtil.createCondition(schemaCondition, SqlStdOperatorTable.AND, where);
+        schemaCondition = DrillParserUtil.createCondition(
+            new SqlIdentifier("TABLE_SCHEMA", SqlParserPos.ZERO),
+            SqlStdOperatorTable.EQUALS,
+            SqlLiteral.createCharString(drillSchema.getFullSchemaName(), CHARSET, SqlParserPos.ZERO)
+        );
+      }
 
-    SqlNode columnFilter = null;
-    if (node.getColumn() != null) {
-      columnFilter = DrillParserUtil.createCondition(new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
+      SqlNode where = DrillParserUtil.createCondition(
+          new SqlIdentifier("TABLE_NAME", SqlParserPos.ZERO),
           SqlStdOperatorTable.EQUALS,
-          SqlLiteral.createCharString(node.getColumn().toString(), CHARSET, SqlParserPos.ZERO));
-    } else if (node.getColumnQualifier() != null) {
-      columnFilter = DrillParserUtil.createCondition(new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
-          SqlStdOperatorTable.LIKE, node.getColumnQualifier());
+          SqlLiteral.createCharString(tableName, CHARSET, SqlParserPos.ZERO));
+
+      where = DrillParserUtil.createCondition(schemaCondition, SqlStdOperatorTable.AND, where);
+
+      SqlNode columnFilter = null;
+      if (node.getColumn() != null) {
+        columnFilter = DrillParserUtil.createCondition(new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
+            SqlStdOperatorTable.EQUALS,
+            SqlLiteral.createCharString(node.getColumn().toString(), CHARSET, SqlParserPos.ZERO));
+      } else if (node.getColumnQualifier() != null) {
+        columnFilter = DrillParserUtil.createCondition(new SqlIdentifier("COLUMN_NAME", SqlParserPos.ZERO),
+            SqlStdOperatorTable.LIKE, node.getColumnQualifier());
+      }
+
+      where = DrillParserUtil.createCondition(where, SqlStdOperatorTable.AND, columnFilter);
+
+      return new SqlSelect(SqlParserPos.ZERO, null, new SqlNodeList(selectList, SqlParserPos.ZERO),
+          fromClause, where, null, null, null, null, null, null);
+    } catch (Exception ex) {
+      throw new RelConversionException("Error while rewriting DESCRIBE query: " + ex.getMessage(), ex);
     }
-
-    where = DrillParserUtil.createCondition(where, SqlStdOperatorTable.AND, columnFilter);
-
-    return new SqlSelect(SqlParserPos.ZERO, null, new SqlNodeList(selectList, SqlParserPos.ZERO),
-        fromClause, where, null, null, null, null, null, null);
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/299d1bf1/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestMetadataDDL.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestMetadataDDL.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestMetadataDDL.java
index 59e2d03..06a671d 100644
--- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestMetadataDDL.java
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestMetadataDDL.java
@@ -129,7 +129,7 @@ public class TestMetadataDDL extends TestJdbcQuery {
 
   @Test
   public void testDescribeTable() throws Exception{
-    JdbcAssert.withNoDefaultSchema()
+    JdbcAssert.withFull("INFORMATION_SCHEMA")
         .sql("DESCRIBE CATALOGS")
         .returns(
             "COLUMN_NAME=CATALOG_NAME; DATA_TYPE=VARCHAR; IS_NULLABLE=NO\n"+
@@ -149,6 +149,47 @@ public class TestMetadataDDL extends TestJdbcQuery {
   }
 
   @Test
+  public void testDescribeSameTableInMultipleSchemas() throws Exception{
+    JdbcAssert.withNoDefaultSchema().withConnection(new Function<Connection, Void>() {
+      public Void apply(Connection connection) {
+        try {
+          Statement statement = connection.createStatement();
+          statement.executeQuery("USE dfs.tmp").close();
+
+          // INFORMATION_SCHEMA already has a table named "TABLES". Now create a table with same name in "dfs.tmp" schema
+          statement.executeQuery("CREATE OR REPLACE VIEW `TABLES` AS SELECT key FROM hive.kv").close();
+
+          // Test describe of `TABLES` with no schema qualifier
+          ResultSet resultSet = statement.executeQuery("DESCRIBE `TABLES`");
+          String result = JdbcAssert.toString(resultSet).trim();
+          resultSet.close();
+          String expected = "COLUMN_NAME=key; DATA_TYPE=INTEGER; IS_NULLABLE=NO";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
+
+          // Test describe of `TABLES` with a schema qualifier which is not in default schema
+          resultSet = statement.executeQuery("DESCRIBE INFORMATION_SCHEMA.`TABLES`");
+          result = JdbcAssert.toString(resultSet).trim();
+          resultSet.close();
+          expected =
+              "COLUMN_NAME=TABLE_CATALOG; DATA_TYPE=VARCHAR; IS_NULLABLE=NO\n" +
+              "COLUMN_NAME=TABLE_SCHEMA; DATA_TYPE=VARCHAR; IS_NULLABLE=NO\n" +
+              "COLUMN_NAME=TABLE_NAME; DATA_TYPE=VARCHAR; IS_NULLABLE=NO\n" +
+              "COLUMN_NAME=TABLE_TYPE; DATA_TYPE=VARCHAR; IS_NULLABLE=NO";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
+
+          // drop created view
+          statement.executeQuery("DROP VIEW `TABLES`").close();
+
+          statement.close();
+          return null;
+        } catch (Exception e) {
+          throw new RuntimeException(e);
+        }
+      }
+    });
+  }
+
+  @Test
   public void testDescribeTableWithColumnName() throws Exception{
     JdbcAssert.withFull("INFORMATION_SCHEMA")
         .sql("DESCRIBE `TABLES` TABLE_CATALOG")