You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by ji...@apache.org on 2013/12/26 05:49:21 UTC

git commit: TAJO-439: Time literal support. (DaeMyung Kang via jihoon)

Updated Branches:
  refs/heads/master 9d86ff7bc -> 3a5a617c6


TAJO-439: Time literal support. (DaeMyung Kang via jihoon)


Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/3a5a617c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/3a5a617c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/3a5a617c

Branch: refs/heads/master
Commit: 3a5a617c6bb1dd10d026ab0735f9031623a66d30
Parents: 9d86ff7
Author: Jihoon Son <ji...@apache.org>
Authored: Thu Dec 26 13:48:37 2013 +0900
Committer: Jihoon Son <ji...@apache.org>
Committed: Thu Dec 26 13:48:37 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 .../java/org/apache/tajo/algebra/OpType.java    |   3 +-
 .../org/apache/tajo/algebra/TimeLiteral.java    |  51 ++++++++
 .../org/apache/tajo/datum/DatumFactory.java     |   4 +-
 .../java/org/apache/tajo/datum/TimeDatum.java   |  10 ++
 .../org/apache/tajo/engine/parser/SQLParser.g4  |   7 +-
 .../apache/tajo/engine/parser/SQLAnalyzer.java  |  12 +-
 .../tajo/engine/planner/AlgebraVisitor.java     |   1 +
 .../tajo/engine/planner/BaseAlgebraVisitor.java |   5 +
 .../tajo/engine/planner/LogicalPlanner.java     | 129 +++++++++++++------
 .../tajo/engine/eval/TestSQLDateTimeTypes.java  |   6 +
 .../storage/TextSerializerDeserializer.java     |   5 +
 12 files changed, 193 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8fbc6bb..385ef9f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,8 @@ Release 0.8.0 - unreleased
 
   NEW FEATURES
 
+    TAJO-439: Time literal support. (DaeMyung Kang via jihoon)
+
     TAJO-437: Timestamp literal support. (hyunsik)
 
     TAJO-382: Implement encode/decode functions. (Seungun Choe via jihoon)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
index a58f103..3022ea1 100644
--- a/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/OpType.java
@@ -97,6 +97,7 @@ public enum OpType {
   Cast(CastExpr.class),
   Literal(LiteralValue.class),
   NullLiteral(NullLiteral.class),
+  TimeLiteral(TimeLiteral.class),
   TimestampLiteral(TimestampLiteral.class);
 
   private Class baseClass;
@@ -128,4 +129,4 @@ public enum OpType {
       return OpType.valueOf(json.getAsString());
     }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-algebra/src/main/java/org/apache/tajo/algebra/TimeLiteral.java
----------------------------------------------------------------------
diff --git a/tajo-algebra/src/main/java/org/apache/tajo/algebra/TimeLiteral.java b/tajo-algebra/src/main/java/org/apache/tajo/algebra/TimeLiteral.java
new file mode 100644
index 0000000..e939128
--- /dev/null
+++ b/tajo-algebra/src/main/java/org/apache/tajo/algebra/TimeLiteral.java
@@ -0,0 +1,51 @@
+/**
+ * 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.tajo.algebra;
+
+import com.google.common.base.Objects;
+
+public class TimeLiteral extends Expr {
+  private TimeValue time;
+
+  public TimeLiteral(TimeValue time) {
+    super(OpType.TimeLiteral);
+    this.time = time;
+  }
+
+  public TimeValue getTime() {
+    return time;
+  }
+
+  public String toString() {
+    return time.toString();
+  }
+
+  public int hashCode() {
+    return Objects.hashCode(time);
+  }
+
+  @Override
+  boolean equalsTo(Expr expr) {
+    if (expr instanceof TimeLiteral) {
+      TimeLiteral another = (TimeLiteral) expr;
+      return time.equals(another.time);
+    }
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java b/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
index 0c98084..de645c1 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/DatumFactory.java
@@ -299,8 +299,10 @@ public class DatumFactory {
       return new TimeDatum(datum.asInt8());
     case TEXT:
       return new TimeDatum(datum.asChars());
+    case TIME:
+      return (TimeDatum) datum;
     default:
-      throw new InvalidCastException(datum.type() + " cannot be casted to TIMESTAMP type");
+      throw new InvalidCastException(datum.type() + " cannot be casted to TIME type");
     }
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-common/src/main/java/org/apache/tajo/datum/TimeDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/TimeDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/TimeDatum.java
index f6fac63..9f67249 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/TimeDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/TimeDatum.java
@@ -38,6 +38,16 @@ public class TimeDatum extends Datum {
     time = new LocalTime(value);
   }
 
+  public TimeDatum(int hour, int minute, int second) {
+    super(TajoDataTypes.Type.TIME);
+    time = new LocalTime(hour, minute, second);
+  }
+
+  public TimeDatum(int hour, int minute, int second, int millis) {
+    super(TajoDataTypes.Type.TIME);
+    time = new LocalTime(hour, minute, second, millis);
+  }
+
   public TimeDatum(String timeStr) {
     super(TajoDataTypes.Type.TIME);
     time = LocalTime.parse(timeStr, DEFAULT_FORMATTER);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4 b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
index 1a7f903..06a2b7a 100644
--- a/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
+++ b/tajo-core/tajo-core-backend/src/main/antlr4/org/apache/tajo/engine/parser/SQLParser.g4
@@ -188,6 +188,11 @@ general_literal
 
 datetime_literal
   : timestamp_literal
+  | time_literal
+  ;
+
+time_literal
+  : TIME time_string=Character_String_Literal
   ;
 
 timestamp_literal
@@ -1138,4 +1143,4 @@ null_ordering
 insert_statement
   : INSERT (OVERWRITE)? INTO table_name (LEFT_PAREN column_name_list RIGHT_PAREN)? query_expression
   | INSERT (OVERWRITE)? INTO LOCATION path=Character_String_Literal (USING file_type=Identifier (param_clause)?)? query_expression
-  ;
\ No newline at end of file
+  ;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
index a2777c5..54a90da 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/parser/SQLAnalyzer.java
@@ -1263,7 +1263,17 @@ public class SQLAnalyzer extends SQLParserBaseVisitor<Expr> {
 
   @Override
   public Expr visitDatetime_literal(@NotNull SQLParser.Datetime_literalContext ctx) {
-    return visitTimestamp_literal(ctx.timestamp_literal());
+    if (checkIfExist(ctx.time_literal())) {
+      return visitTime_literal(ctx.time_literal());
+    } else { 
+      return visitTimestamp_literal(ctx.timestamp_literal());
+    }
+  }
+
+  @Override
+  public Expr visitTime_literal(SQLParser.Time_literalContext ctx) {
+    String timePart = stripQuote(ctx.time_string.getText());
+    return new TimeLiteral(parseTime(timePart));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
index 385158e..dcfc6fc 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/AlgebraVisitor.java
@@ -99,5 +99,6 @@ public interface AlgebraVisitor<CONTEXT, RESULT> {
   RESULT visitLiteral(CONTEXT ctx, Stack<OpType> stack, LiteralValue expr) throws PlanningException;
   RESULT visitNullLiteral(CONTEXT ctx, Stack<OpType> stack, NullLiteral expr) throws PlanningException;
   RESULT visitTimestampLiteral(CONTEXT ctx, Stack<OpType> stack, TimestampLiteral expr) throws PlanningException;
+  RESULT visitTimeLiteral(CONTEXT ctx, Stack<OpType> stack, TimeLiteral expr) throws PlanningException;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
index f2cf1f8..1aeef5f 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/BaseAlgebraVisitor.java
@@ -636,4 +636,9 @@ public class BaseAlgebraVisitor<CONTEXT, RESULT> implements AlgebraVisitor<CONTE
   public RESULT visitTimestampLiteral(CONTEXT ctx, Stack<OpType> stack, TimestampLiteral expr) throws PlanningException {
     return null;
   }
+
+  @Override
+  public RESULT visitTimeLiteral(CONTEXT ctx, Stack<OpType> stack, TimeLiteral expr) throws PlanningException {
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
index 6581c66..11da7b7 100644
--- a/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
+++ b/tajo-core/tajo-core-backend/src/main/java/org/apache/tajo/engine/planner/LogicalPlanner.java
@@ -39,6 +39,7 @@ import org.apache.tajo.datum.Datum;
 import org.apache.tajo.datum.DatumFactory;
 import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.datum.TimestampDatum;
+import org.apache.tajo.datum.TimeDatum;
 import org.apache.tajo.engine.eval.*;
 import org.apache.tajo.engine.exception.InvalidQueryException;
 import org.apache.tajo.engine.exception.UndefinedFunctionException;
@@ -1040,6 +1041,69 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
     return dropTableNode;
   }
 
+  public static int [] dateToIntArray(String years, String months, String days) 
+    throws PlanningException { 
+    int year = Integer.valueOf(years);
+    int month = Integer.valueOf(months);
+    int day = Integer.valueOf(days);
+
+    if (!(1 <= year && year <= 9999)) {
+      throw new PlanningException(String.format("Years (%d) must be between 1 and 9999 integer value", year));
+    }
+
+    if (!(1 <= month && month <= 12)) {
+      throw new PlanningException(String.format("Months (%d) must be between 1 and 12 integer value", month));
+    }
+
+    if (!(1<= day && day <= 31)) {
+      throw new PlanningException(String.format("Days (%d) must be between 1 and 31 integer value", day));
+    }
+
+    int [] results = new int[3];
+    results[0] = year;
+    results[1] = month;
+    results[2] = day;
+
+    return results;
+  }
+
+  public static int [] timeToIntArray(String hours, String minutes, String seconds, String fractionOfSecond) 
+    throws PlanningException { 
+    int hour = Integer.valueOf(hours);
+    int minute = Integer.valueOf(minutes);
+    int second = Integer.valueOf(seconds);
+    int fraction = 0;
+    if (fractionOfSecond != null) {
+      fraction = Integer.valueOf(fractionOfSecond);
+    }
+
+    if (!(0 <= hour && hour <= 23)) {
+      throw new PlanningException(String.format("Hours (%d) must be between 0 and 24 integer value", hour));
+    }
+
+    if (!(0 <= minute && minute <= 59)) {
+      throw new PlanningException(String.format("Minutes (%d) must be between 0 and 59 integer value", minute));
+    }
+
+    if (!(0 <= second && second <= 59)) {
+      throw new PlanningException(String.format("Seconds (%d) must be between 0 and 59 integer value", second));
+    }
+
+    if (fraction != 0) {
+      if (!(0 <= fraction && fraction <= 999)) {
+        throw new PlanningException(String.format("Seconds (%d) must be between 0 and 999 integer value", fraction));
+      }
+    }
+
+    int [] results = new int[4];
+    results[0] = hour;
+    results[1] = minute;
+    results[2] = second;
+    results[3] = fraction;
+
+    return results;
+  }
+    
   /*===============================================================================================
     Expression SECTION
    ===============================================================================================*/
@@ -1068,51 +1132,40 @@ public class LogicalPlanner extends BaseAlgebraVisitor<LogicalPlanner.PlanContex
             throw new RuntimeException("Unsupported type: " + literal.getValueType());
         }
 
+      case TimeLiteral: {
+        TimeLiteral timeLiteral = (TimeLiteral) expr;
+        TimeValue timeValue = timeLiteral.getTime();
+        int [] times = LogicalPlanner.timeToIntArray(timeValue.getHours(),
+                                         timeValue.getMinutes(),
+                                         timeValue.getSeconds(),
+                                         timeValue.getSecondsFraction());
+
+        TimeDatum datum;
+        if (times[3] == 0) {
+          datum = new TimeDatum(times[0], times[1], times[2]);
+        } else {
+          datum = new TimeDatum(times[0], times[1], times[2], times[3]);
+        }
+        return new ConstEval(datum);
+      }
+
       case TimestampLiteral: {
         TimestampLiteral timestampLiteral = (TimestampLiteral) expr;
         DateValue dateValue = timestampLiteral.getDate();
         TimeValue timeValue = timestampLiteral.getTime();
-        int years;
-        int months;
-        int days;
-        int hours;
-        int minutes;
-        int seconds;
-
-        years = Integer.valueOf(dateValue.getYears());
-        if (!(1 <= years && years <= 9999)) {
-          throw new PlanningException(String.format("Years (%d) must be between 1 and 9999 integer value", years));
-        }
-        months = Integer.valueOf(dateValue.getMonths());
-        if (!(1 <= months && months <= 12)) {
-          throw new PlanningException(String.format("Months (%d) must be between 1 and 12 integer value", months));
-        }
-        days = Integer.valueOf(dateValue.getDays());
-        if (!(1<= days && days <= 31)) {
-          throw new PlanningException(String.format("Days (%d) must be between 1 and 31 integer value", days));
-        }
-
-        hours = Integer.valueOf(timeValue.getHours());
-        if (!(0 <= hours && hours <= 23)) {
-          throw new PlanningException(String.format("Hours (%d) must be between 0 and 24 integer value", hours));
-        }
-        minutes = Integer.valueOf(timeValue.getMinutes());
-        if (!(0 <= minutes && minutes <= 59)) {
-          throw new PlanningException(String.format("Minutes (%d) must be between 0 and 59 integer value", minutes));
-        }
-        seconds = Integer.valueOf(timeValue.getSeconds());
-        if (!(0 <= seconds && seconds <= 59)) {
-          throw new PlanningException(String.format("Seconds (%d) must be between 0 and 59 integer value", seconds));
-        }
 
+        int [] dates = LogicalPlanner.dateToIntArray(dateValue.getYears(),
+                                        dateValue.getMonths(),
+                                        dateValue.getDays());
+        int [] times = LogicalPlanner.timeToIntArray(timeValue.getHours(),
+                                        timeValue.getMinutes(),
+                                        timeValue.getSeconds(),
+                                        timeValue.getSecondsFraction());
         DateTime dateTime;
-        if (timeValue.hasSecondsFraction()) {
-          int secondsFraction = Integer.valueOf(timeValue.getSecondsFraction());
-          if (!(0 <= secondsFraction && secondsFraction <= 999))
-          throw new PlanningException(String.format("Seconds (%d) must be between 0 and 999 integer value", seconds));
-          dateTime = new DateTime(years, months, days, hours, minutes, seconds, secondsFraction);
+        if (times[3] == 0) {
+          dateTime = new DateTime(dates[0], dates[1], dates[2], times[0], times[1], times[2]);
         } else {
-          dateTime = new DateTime(years, months, days, hours, minutes, seconds);
+          dateTime = new DateTime(dates[0], dates[1], dates[2], times[0], times[1], times[3]);
         }
 
         return new ConstEval(new TimestampDatum(dateTime));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java
index fb1699f..9eb4d1d 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/eval/TestSQLDateTimeTypes.java
@@ -29,4 +29,10 @@ public class TestSQLDateTimeTypes extends ExprTestBase {
     testSimpleEval("select to_char(TIMESTAMP '1970-01-17 10:09:37', 'yyyy-MM-dd HH:mm:ss');",
         new String[]{"1970-01-17 10:09:37"});
   }
+
+  @Test
+  public void testTimeLiteral() throws IOException {
+    testSimpleEval("select TIME '10:09:37';",
+        new String[]{"10:09:37"});
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/3a5a617c/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TextSerializerDeserializer.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TextSerializerDeserializer.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TextSerializerDeserializer.java
index b80b461..9995a4a 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TextSerializerDeserializer.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/TextSerializerDeserializer.java
@@ -77,6 +77,7 @@ public class TextSerializerDeserializer implements SerializerDeserializer {
       case FLOAT8:
       case INET4:
       case DATE:
+      case TIME:
       case TIMESTAMP:
         bytes = datum.asTextBytes();
         length = bytes.length;
@@ -149,6 +150,10 @@ public class TextSerializerDeserializer implements SerializerDeserializer {
         datum = isNull(bytes, offset, length, nullCharacters) ? NullDatum.get()
             : DatumFactory.createDate(new String(bytes, offset, length));
         break;
+      case TIME:
+        datum = isNull(bytes, offset, length, nullCharacters) ? NullDatum.get()
+            : DatumFactory.createTime(new String(bytes, offset, length));
+        break;
       case TIMESTAMP:
         datum = isNull(bytes, offset, length, nullCharacters) ? NullDatum.get()
             : DatumFactory.createTimeStamp(new String(bytes, offset, length));