This is an automated email from the ASF dual-hosted git repository.

dkuzmenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 99aa3995609 HIVE-26995: Iceberg: Enhance time travel syntax with 
expressions (Denys Kuzmenko, reviewed by Krisztian Kasa)
99aa3995609 is described below

commit 99aa3995609a47be7f6f34c644c73e50f36dfd24
Author: Denys Kuzmenko <denisk...@gmail.com>
AuthorDate: Mon Jan 30 11:31:48 2023 +0200

    HIVE-26995: Iceberg: Enhance time travel syntax with expressions (Denys 
Kuzmenko, reviewed by Krisztian Kasa)
    
    Closes #3988
---
 .../iceberg/mr/hive/TestHiveIcebergTimeTravel.java | 24 ++++++++++++++++++++++
 .../apache/hadoop/hive/ql/parse/FromClauseParser.g |  2 +-
 .../apache/hadoop/hive/ql/io/HiveInputFormat.java  |  4 +---
 .../hadoop/hive/ql/parse/SemanticAnalyzer.java     | 13 +++++++++++-
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git 
a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergTimeTravel.java
 
b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergTimeTravel.java
index 13cfd975f4d..be865817d13 100644
--- 
a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergTimeTravel.java
+++ 
b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergTimeTravel.java
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.util.List;
 import org.apache.iceberg.HistoryEntry;
 import org.apache.iceberg.Table;
+import org.apache.iceberg.types.Types;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -117,6 +118,29 @@ public class TestHiveIcebergTimeTravel extends 
HiveIcebergStorageHandlerWithEngi
     Assert.assertEquals(7, rows.size());
   }
 
+  @Test
+  public void testSelectAsOfCurrentTimestampAndInterval() throws IOException, 
InterruptedException {
+    testTables.createTableWithVersions(shell, "customers",
+        HiveIcebergStorageHandlerTestUtils.CUSTOMER_SCHEMA, fileFormat,
+        HiveIcebergStorageHandlerTestUtils.CUSTOMER_RECORDS, 3);
+
+    List<Object[]> rows = shell.executeStatement("SELECT * FROM " +
+        "customers FOR SYSTEM_TIME AS OF CURRENT_TIMESTAMP + interval '10' 
hours");
+
+    Assert.assertEquals(5, rows.size());
+  }
+
+  @Test
+  public void testInvalidSelectAsOfTimestampExpression() throws IOException, 
InterruptedException {
+    Table icebergTable = testTables.createTableWithVersions(shell, "customers",
+        HiveIcebergStorageHandlerTestUtils.CUSTOMER_SCHEMA, fileFormat,
+        HiveIcebergStorageHandlerTestUtils.CUSTOMER_RECORDS, 3);
+    icebergTable.updateSchema().addColumn("create_time", 
Types.TimestampType.withZone()).commit();
+
+    Assert.assertThrows(IllegalArgumentException.class, () -> 
shell.executeStatement("SELECT * FROM " +
+        "customers FOR SYSTEM_TIME AS OF create_time - interval '10' hours"));
+  }
+
   @Test
   public void testAsOfWithJoins() throws IOException, InterruptedException {
     Table table = testTables.createTableWithVersions(shell, "customers",
diff --git a/parser/src/java/org/apache/hadoop/hive/ql/parse/FromClauseParser.g 
b/parser/src/java/org/apache/hadoop/hive/ql/parse/FromClauseParser.g
index dbad0f7f33b..abeb38305dc 100644
--- a/parser/src/java/org/apache/hadoop/hive/ql/parse/FromClauseParser.g
+++ b/parser/src/java/org/apache/hadoop/hive/ql/parse/FromClauseParser.g
@@ -217,7 +217,7 @@ asOfClause
 @init { gParent.pushMsg("as of system_time / system_version clause for table", 
state); }
 @after { gParent.popMsg(state); }
     :
-    (KW_FOR KW_SYSTEM_TIME KW_AS KW_OF asOfTime=StringLiteral)
+    (KW_FOR KW_SYSTEM_TIME KW_AS KW_OF asOfTime=expression)
     -> ^(TOK_AS_OF_TIME $asOfTime)
     |
     (KW_FOR KW_SYSTEM_VERSION KW_AS KW_OF asOfVersion=Number)
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/io/HiveInputFormat.java 
b/ql/src/java/org/apache/hadoop/hive/ql/io/HiveInputFormat.java
index de93573e303..951e20687a0 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/io/HiveInputFormat.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/io/HiveInputFormat.java
@@ -52,7 +52,6 @@ import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;
 import org.apache.hadoop.hive.ql.plan.MapWork;
 import org.apache.hadoop.hive.ql.plan.OperatorDesc;
 import org.apache.hadoop.hive.ql.plan.PartitionDesc;
-import org.apache.hadoop.hive.ql.plan.PlanUtils;
 import org.apache.hadoop.hive.ql.plan.TableDesc;
 import org.apache.hadoop.hive.ql.plan.TableScanDesc;
 import org.apache.hadoop.hive.ql.session.SessionState;
@@ -987,8 +986,7 @@ public class HiveInputFormat<K extends WritableComparable, 
V extends Writable>
     if (scanDesc.getAsOfTimestamp() != null) {
       ZoneId timeZone = SessionState.get() == null ? new 
HiveConf().getLocalTimeZone() :
           SessionState.get().getConf().getLocalTimeZone();
-      TimestampTZ time = 
TimestampTZUtil.parse(PlanUtils.stripQuotes(scanDesc.getAsOfTimestamp()), 
timeZone);
-
+      TimestampTZ time = TimestampTZUtil.parse(scanDesc.getAsOfTimestamp(), 
timeZone);
       jobConf.set(TableScanDesc.AS_OF_TIMESTAMP, 
Long.toString(time.toEpochMilli()));
     }
 
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
index 6053f3bc90e..e460ae1df8c 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
@@ -1133,7 +1133,18 @@ public class SemanticAnalyzer extends 
BaseSemanticAnalyzer {
 
     if (asOfTimeIndex != -1 || asOfVersionIndex != -1) {
       String asOfVersion = asOfVersionIndex == -1 ? null : 
tabref.getChild(asOfVersionIndex).getChild(0).getText();
-      String asOfTime = asOfTimeIndex == -1 ? null : 
tabref.getChild(asOfTimeIndex).getChild(0).getText();
+      String asOfTime = null;
+      
+      if (asOfTimeIndex != -1) {
+        ASTNode expr = (ASTNode) tabref.getChild(asOfTimeIndex).getChild(0);
+        if (expr.getChildCount() > 0) {
+          ExprNodeDesc desc = genExprNodeDesc(expr, new RowResolver(), false, 
true);
+          ExprNodeConstantDesc c = (ExprNodeConstantDesc) desc;
+          asOfTime = String.valueOf(c.getValue());
+        } else {
+          asOfTime = stripQuotes(expr.getText());
+        }
+      }
       Pair<String, String> asOf = Pair.of(asOfVersion, asOfTime);
       qb.setAsOf(alias, asOf);
     }

Reply via email to