drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From par...@apache.org
Subject [3/6] drill git commit: DRILL-2461: Fix: INTERVAL in view makes INFORMATION_SCHEMA.COLUMN fail.
Date Fri, 27 Mar 2015 17:49:21 GMT
DRILL-2461: Fix: INTERVAL in view makes INFORMATION_SCHEMA.COLUMN fail.

- Created test.
- Handled INTERVAL data types in View:
  - Added <interval qualifier> data to FieldType.
  - Switch calling of createSqlType to createSqlIntervalType for interval types


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

Branch: refs/heads/master
Commit: 8796fd1e13f07ac84df1c466dce83456dfa22950
Parents: 9a5b50e
Author: dbarclay <dbarclay@maprtech.com>
Authored: Sun Mar 22 13:05:38 2015 -0700
Committer: Parth Chandra <pchandra@maprtech.com>
Committed: Fri Mar 27 10:19:32 2015 -0700

----------------------------------------------------------------------
 .../org/apache/drill/exec/dotdrill/View.java    | 160 +++++++++++++++----
 ...rill2461IntervalsBreakInfoSchemaBugTest.java |  91 +++++++++++
 2 files changed, 222 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/8796fd1e/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java b/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
index a7b496b..c5c62d8 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
@@ -22,9 +22,13 @@ import java.util.List;
 import org.apache.drill.exec.planner.StarColumnHelper;
 import org.apache.drill.exec.planner.types.RelDataTypeDrillImpl;
 import org.apache.drill.exec.planner.types.RelDataTypeHolder;
+
 import org.eigenbase.reltype.RelDataType;
 import org.eigenbase.reltype.RelDataTypeFactory;
 import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.sql.SqlIntervalQualifier;
+import org.eigenbase.sql.parser.SqlParserPos;
+import org.eigenbase.sql.type.SqlTypeFamily;
 import org.eigenbase.sql.type.SqlTypeName;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
@@ -48,36 +52,50 @@ public class View {
 
   @JsonInclude(Include.NON_NULL)
   public static class FieldType {
-    public final String name;
-    public final SqlTypeName type;
-    public final Integer precision;
-    public final Integer scale;
-    public final Boolean isNullable;
+
+    private final String name;
+    private final SqlTypeName type;
+    private final Integer precision;
+    private final Integer scale;
+    private SqlIntervalQualifier intervalQualifier;
+    private final Boolean isNullable;
+
 
     @JsonCreator
     public FieldType(
-        @JsonProperty("name") String name,
-        @JsonProperty("type") SqlTypeName type,
-        @JsonProperty("precision") Integer precision,
-        @JsonProperty("scale") Integer scale,
-        @JsonProperty("isNullable") Boolean isNullable){
+        @JsonProperty("name")                       String name,
+        @JsonProperty("type")                       SqlTypeName type,
+        @JsonProperty("precision")                  Integer precision,
+        @JsonProperty("scale")                      Integer scale,
+        @JsonProperty("startUnit")                  SqlIntervalQualifier.TimeUnit startUnit,
+        @JsonProperty("endUnit")                    SqlIntervalQualifier.TimeUnit endUnit,
+        @JsonProperty("fractionalSecondPrecision")  Integer fractionalSecondPrecision,
+        @JsonProperty("isNullable")                 Boolean isNullable) {
       this.name = name;
       this.type = type;
       this.precision = precision;
       this.scale = scale;
+      this.intervalQualifier =
+          null == startUnit
+          ? null
+          : new SqlIntervalQualifier(
+              startUnit, precision, endUnit, fractionalSecondPrecision, SqlParserPos.ZERO
);
 
-      // Property "isNullable" is not part of the initial view definition and added in DRILL-2342.
If the
-      // default value is null, consider it as "true". It is safe to default to "nullable"
than "required" type.
-      this.isNullable = (isNullable == null) ? true : isNullable;
+      // Property "isNullable" is not part of the initial view definition and
+      // was added in DRILL-2342.  If the default value is null, consider it as
+      // "true".  It is safe to default to "nullable" than "required" type.
+      this.isNullable = isNullable == null ? true : isNullable;
     }
 
-    public FieldType(String name, RelDataType dataType){
+    public FieldType(String name, RelDataType dataType) {
       this.name = name;
       this.type = dataType.getSqlTypeName();
+
       Integer p = null;
       Integer s = null;
+      Integer fractionalSecondPrecision = null;
 
-      switch(dataType.getSqlTypeName()){
+      switch (dataType.getSqlTypeName()) {
       case CHAR:
       case BINARY:
       case VARBINARY:
@@ -88,19 +106,100 @@ public class View {
         p = dataType.getPrecision();
         s = dataType.getScale();
         break;
+      case INTERVAL_YEAR_MONTH:
+      case INTERVAL_DAY_TIME:
+        p = dataType.getIntervalQualifier().getStartPrecision();
+      default:
+        break;
       }
 
       this.precision = p;
       this.scale = s;
+      this.intervalQualifier = dataType.getIntervalQualifier();
       this.isNullable = dataType.isNullable();
     }
+
+    /**
+     * Gets the name of this field.
+     */
+    public String getName() {
+      return name;
+    }
+
+    /**
+     * Gets the data type of this field.
+     * (Data type only; not full datatype descriptor.)
+     */
+    public SqlTypeName getType() {
+      return type;
+    }
+
+    /**
+     * Gets the precision of the data type descriptor of this field.
+     * The precision is the precision for a numeric type, the length for a
+     * string type, or the start unit precision for an interval type.
+     * */
+    public Integer getPrecision() {
+      return precision;
+    }
+
+    /**
+     * Gets the numeric scale of the data type descriptor of this field,
+     * for numeric types.
+     */
+    public Integer getScale() {
+      return scale;
+    }
+
+    /**
+     * Gets the interval type qualifier of the interval data type descriptor of
+     * this field (<i>iff</i> interval type). */
+    @JsonIgnore
+    public SqlIntervalQualifier getIntervalQualifier() {
+      return intervalQualifier;
+    }
+
+    /**
+     * Gets the time range start unit of the type qualifier of the interval data
+     * type descriptor of this field (<i>iff</i> interval type).
+     */
+    public SqlIntervalQualifier.TimeUnit getStartUnit() {
+      return null == intervalQualifier ? null : intervalQualifier.getStartUnit();
+    }
+
+    /**
+     * Gets the time range end unit of the type qualifier of the interval data
+     * type descriptor of this field (<i>iff</i> interval type).
+     */
+    public SqlIntervalQualifier.TimeUnit getEndUnit() {
+      return null == intervalQualifier ? null : intervalQualifier.getEndUnit();
+    }
+
+    /**
+     * Gets the fractional second precision of the type qualifier of the interval
+     * data type descriptor of this field (<i>iff</i> interval type).
+     * Gets the interval type descriptor's fractional second precision
+     * (<i>iff</i> interval type).
+     */
+    public Integer getFractionalSecondPrecision() {
+      return null == intervalQualifier ? null : intervalQualifier.getFractionalSecondPrecision();
+    }
+
+    /**
+     * Gets the nullability of the data type desription of this field.
+     */
+    public Boolean getIsNullable() {
+      return isNullable;
+    }
+
   }
 
-  public View(String name, String sql, RelDataType rowType, List<String> workspaceSchemaPath){
+
+  public View(String name, String sql, RelDataType rowType, List<String> workspaceSchemaPath)
{
     this.name = name;
     this.sql = sql;
     fields = Lists.newArrayList();
-    for(RelDataTypeField f : rowType.getFieldList()){
+    for (RelDataTypeField f : rowType.getFieldList()) {
       fields.add(new FieldType(f.getName(), f.getType()));
     }
     this.workspaceSchemaPath =
@@ -119,28 +218,31 @@ public class View {
         workspaceSchemaPath == null ? ImmutableList.<String>of() : ImmutableList.copyOf(workspaceSchemaPath);
   }
 
-  public RelDataType getRowType(RelDataTypeFactory factory){
+  public RelDataType getRowType(RelDataTypeFactory factory) {
 
     // if there are no fields defined, this is a dynamic view.
-    if(isDynamic()){
+    if (isDynamic()) {
       return new RelDataTypeDrillImpl(new RelDataTypeHolder(), factory);
     }
 
     List<RelDataType> types = Lists.newArrayList();
     List<String> names = Lists.newArrayList();
 
-    for(FieldType field : fields){
-      names.add(field.name);
+    for (FieldType field : fields) {
+      names.add(field.getName());
       RelDataType type;
-      if(field.precision == null && field.scale == null){
-        type = factory.createSqlType(field.type);
-      }else if(field.precision != null && field.scale == null){
-        type = factory.createSqlType(field.type, field.precision);
-      }else{
-        type = factory.createSqlType(field.type, field.precision, field.scale);
+      if (   SqlTypeFamily.INTERVAL_YEAR_MONTH == field.getType().getFamily()
+          || SqlTypeFamily.INTERVAL_DAY_TIME   == field.getType().getFamily() ) {
+       type = factory.createSqlIntervalType( field.getIntervalQualifier() );
+      } else if (field.getPrecision() == null && field.getScale() == null) {
+        type = factory.createSqlType(field.getType());
+      } else if (field.getPrecision() != null && field.getScale() == null) {
+        type = factory.createSqlType(field.getType(), field.getPrecision());
+      } else {
+        type = factory.createSqlType(field.getType(), field.getPrecision(), field.getScale());
       }
 
-      if (field.isNullable) {
+      if (field.getIsNullable()) {
         types.add(factory.createTypeWithNullability(type, true));
       } else {
         types.add(type);
@@ -157,7 +259,7 @@ public class View {
   @JsonIgnore
   public boolean hasStar() {
     for (FieldType field : fields) {
-      if (StarColumnHelper.isNonPrefixedStarColumn(field.name)) {
+      if (StarColumnHelper.isNonPrefixedStarColumn(field.getName())) {
         return true;
       }
     }

http://git-wip-us.apache.org/repos/asf/drill/blob/8796fd1e/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2461IntervalsBreakInfoSchemaBugTest.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2461IntervalsBreakInfoSchemaBugTest.java
b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2461IntervalsBreakInfoSchemaBugTest.java
new file mode 100644
index 0000000..fce7923
--- /dev/null
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/Drill2461IntervalsBreakInfoSchemaBugTest.java
@@ -0,0 +1,91 @@
+/**
+ * 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.
+ */
+package org.apache.drill.jdbc.test;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.hamcrest.CoreMatchers.*;
+
+import org.apache.drill.common.util.TestTools;
+import org.apache.drill.jdbc.Driver;
+import org.apache.drill.jdbc.JdbcTest;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+
+
+public class Drill2461IntervalsBreakInfoSchemaBugTest extends JdbcTest {
+
+  private static final String VIEW_NAME =
+      Drill2461IntervalsBreakInfoSchemaBugTest.class.getSimpleName() + "_View";
+
+  private static Connection connection;
+
+
+  @BeforeClass
+  public static void setUpConnection() throws Exception {
+    connection = connect( "jdbc:drill:zk=local" );
+  }
+
+  @AfterClass
+  public static void tearDownConnection() throws Exception {
+    connection.close();
+  }
+
+
+  @Test
+  public void testIntervalInViewDoesntCrashInfoSchema() throws Exception {
+    final Statement stmt = connection.createStatement();
+    ResultSet util;
+
+    // Create a view using an INTERVAL type:
+    util = stmt.executeQuery( "USE dfs.tmp" );
+    assert util.next();
+    assert util.getBoolean( 1 )
+        : "Error setting schema to dfs.tmp: " + util.getString( 2 );
+    util = stmt.executeQuery(
+        "CREATE OR REPLACE VIEW " + VIEW_NAME + " AS "
+      + "\n  SELECT CAST( NULL AS INTERVAL HOUR(4) TO MINUTE ) AS optINTERVAL_HM "
+      + "\n  FROM INFORMATION_SCHEMA.CATALOGS "
+      + "\n  LIMIT 1 " );
+    assert util.next();
+    assert util.getBoolean( 1 )
+        : "Error creating temporary test-columns view " + VIEW_NAME + ": "
+          + util.getString( 2 );
+
+    // Test whether query INFORMATION_SCHEMA.COLUMNS works (doesn't crash):
+    util = stmt.executeQuery( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS" );
+    assert util.next();
+
+    // Clean up the test view:
+    util = connection.createStatement().executeQuery( "DROP VIEW " + VIEW_NAME );
+    assert util.next();
+    assert util.getBoolean( 1 )
+       : "Error dropping temporary test-columns view " + VIEW_NAME + ": "
+         + util.getString( 2 );
+  }
+
+}


Mime
View raw message