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

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


The following commit(s) were added to refs/heads/master by this push:
     new c0ad8400ce9 Opt type mismatch error msg & fix Blob and date compare bug
c0ad8400ce9 is described below

commit c0ad8400ce94cae60ef76e997d48c1ff1a6347c3
Author: Jackie Tien <[email protected]>
AuthorDate: Thu Aug 22 18:18:14 2024 +0800

    Opt type mismatch error msg & fix Blob and date compare bug
---
 .../org/apache/iotdb/db/it/utils/TestUtils.java    |   2 +-
 .../it/query/old/IoTDBNestedQueryTableIT.java      |  19 +--
 .../scalar/IoTDBScalarFunctionTableIT.java         |  49 +++++++
 .../IoTDBQueryWithComplexValueFilterTableIT.java   |  14 +-
 .../execution/exchange/source/SourceHandle.java    |  12 ++
 .../fragment/FragmentInstanceContext.java          |  10 +-
 .../relational/ColumnTransformerBuilder.java       |   3 +-
 .../execution/schedule/AbstractDriverThread.java   |  10 +-
 .../queryengine/plan/execution/QueryExecution.java |  12 ++
 .../multi/builtin/helper/CastFunctionHelper.java   |   6 +-
 .../relational/metadata/TableMetadataImpl.java     |  11 +-
 .../binary/CompareBinaryColumnTransformer.java     |   3 +-
 .../scalar/CastFunctionColumnTransformer.java      | 149 +++++++++++++++++----
 .../org/apache/iotdb/db/utils/DateTimeUtils.java   |  38 +++++-
 14 files changed, 277 insertions(+), 61 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java 
b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
index 2e6f975dac9..b4d8a521bd4 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
@@ -278,7 +278,7 @@ public class TestUtils {
       statement.executeQuery(sql);
       fail("No exception!");
     } catch (SQLException e) {
-      Assert.assertTrue(e.getMessage().contains(errMsg));
+      Assert.assertTrue(e.getMessage(), e.getMessage().contains(errMsg));
     }
   }
 
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryTableIT.java
index 8c0127e5f3b..48077696c5b 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/IoTDBNestedQueryTableIT.java
@@ -426,15 +426,16 @@ public class IoTDBNestedQueryTableIT {
       //      }
       statement.execute("USE " + DATABASE_NAME);
 
-      String query3 =
-          "SELECT time,s1 FROM vehicle1 where device_id='d1' and s5 IN 
('2024-01-01', '2024-01-02', '2024-01-03')";
-      try (ResultSet rs = statement.executeQuery(query3)) {
-        for (int i = 1; i <= 3; i++) {
-          Assert.assertTrue(rs.next());
-          Assert.assertEquals(i, rs.getLong(1));
-        }
-        Assert.assertFalse(rs.next());
-      }
+      //      String query3 =
+      //          "SELECT time,s1 FROM vehicle1 where device_id='d1' and s5 IN 
('2024-01-01',
+      // '2024-01-02', '2024-01-03')";
+      //      try (ResultSet rs = statement.executeQuery(query3)) {
+      //        for (int i = 1; i <= 3; i++) {
+      //          Assert.assertTrue(rs.next());
+      //          Assert.assertEquals(i, rs.getLong(1));
+      //        }
+      //        Assert.assertFalse(rs.next());
+      //      }
 
       String query4 = "SELECT time,s1 FROM vehicle1 where device_id='d1' and 
s6 IN (1, 2, 3)";
       try (ResultSet rs = statement.executeQuery(query4)) {
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
index 8d33e0c1376..247a0325e26 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java
@@ -366,6 +366,43 @@ public class IoTDBScalarFunctionTableIT {
         DATABASE_NAME);
   }
 
+  @Test
+  public void testBlobCompare() {
+    // case 1: support INT32, INT64, FLOAT, DOUBLE
+    String[] expectedHeader = new String[] {"s10", "res1", "res2", "res3"};
+    String[] expectedAns =
+        new String[] {
+          "0xabcd,true,true,true,",
+        };
+    tableResultSetEqualTest(
+        "select s10, s10 > x'2d' as res1, s10 <> x'2d' as res2, s10 = X'abcd' 
as res3 from absTable",
+        expectedHeader,
+        expectedAns,
+        DATABASE_NAME);
+  }
+
+  @Test
+  public void testDateCompare() {
+    // case 1: support INT32, INT64, FLOAT, DOUBLE
+    String[] expectedHeader = new String[] {"s7", "res1", "res2", "res3"};
+    String[] expectedAns =
+        new String[] {
+          "2021-10-01,true,true,true,",
+        };
+    // add it back while supporting Implicit conversion
+    //    tableResultSetEqualTest(
+    //        "select s7, s7 < '2022-12-12' as res1, s7 <> '2022-12-12' as 
res2, s7 = '2021-10-01'
+    // as res3 from absTable",
+    //        expectedHeader,
+    //        expectedAns,
+    //        DATABASE_NAME);
+    tableResultSetEqualTest(
+        "select s7, s7 < CAST('2022-12-12' AS DATE) as res1, s7 <> 
CAST('2022-12-12' AS DATE) AS res2, s7 = CAST('2021-10-01' AS DATE) as res3 
from absTable",
+        expectedHeader,
+        expectedAns,
+        DATABASE_NAME);
+  }
+
   @Test
   public void absTestFail() {
     // case 1: more than one argument
@@ -409,6 +446,18 @@ public class IoTDBScalarFunctionTableIT {
         TSStatusCode.SEMANTIC_ERROR.getStatusCode()
             + ": Scalar function abs only accepts one argument and it must be 
Double, Float, Int32 or Int64 data type.",
         DATABASE_NAME);
+
+    // case 7: wrong data type
+    tableAssertTestFail(
+        "select s7, s7 < '2022-12-12', s7 <> '2022-12-12', s7 = '2021-10-01' 
from absTable",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode() + ": Cannot apply 
operator: DATE < STRING",
+        DATABASE_NAME);
+
+    // case 7: wrong data type
+    tableAssertTestFail(
+        "select CAST(s1 AS INT32) from absTable",
+        TSStatusCode.SEMANTIC_ERROR.getStatusCode() + ": Cannot cast abcd to 
INT32 type",
+        DATABASE_NAME);
   }
 
   @Test
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBQueryWithComplexValueFilterTableIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBQueryWithComplexValueFilterTableIT.java
index 292d4f14d41..578b7e4d87b 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBQueryWithComplexValueFilterTableIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBQueryWithComplexValueFilterTableIT.java
@@ -125,7 +125,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 = 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 = 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -150,7 +150,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 != 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 != 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -185,7 +185,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 > 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 > 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -210,7 +210,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 < 
'2024-01-02'")) {
+          statement.executeQuery("select s1 from sg1 where s4 < 
CAST('2024-01-02' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -235,7 +235,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 >= 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 >= 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -260,7 +260,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 <= 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 <= 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -303,7 +303,7 @@ public class IoTDBQueryWithComplexValueFilterTableIT {
       }
 
       try (ResultSet resultSet =
-          statement.executeQuery("select s1 from sg1 where s4 = 
'2024-01-01'")) {
+          statement.executeQuery("select s1 from sg1 where s4 = 
CAST('2024-01-01' AS DATE)")) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/exchange/source/SourceHandle.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/exchange/source/SourceHandle.java
index 2d1a06fcd32..7e0a56405db 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/exchange/source/SourceHandle.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/exchange/source/SourceHandle.java
@@ -51,6 +51,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 
 import static 
com.google.common.util.concurrent.Futures.nonCancellationPropagating;
@@ -466,6 +467,17 @@ public class SourceHandle implements ISourceHandle {
 
   private void checkState() {
     if (aborted) {
+      if (blocked.isDone()) {
+        // try throw underlying exception instead of "Source handle is 
aborted."
+        try {
+          blocked.get();
+        } catch (InterruptedException e) {
+          Thread.currentThread().interrupt();
+          throw new IllegalStateException(e);
+        } catch (ExecutionException e) {
+          throw new IllegalStateException(e);
+        }
+      }
       throw new IllegalStateException("Source handle is aborted.");
     } else if (closed) {
       throw new IllegalStateException("SourceHandle is closed.");
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
index 9648b1701fb..9519ecb0212 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/fragment/FragmentInstanceContext.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.queryengine.execution.fragment;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
 import org.apache.iotdb.commons.path.IFullPath;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -316,11 +317,16 @@ public class FragmentInstanceContext extends QueryContext 
{
 
   public Optional<TSStatus> getErrorCode() {
     return stateMachine.getFailureCauses().stream()
-        .filter(IoTDBException.class::isInstance)
+        .filter(e -> e instanceof IoTDBException || e instanceof 
IoTDBRuntimeException)
         .findFirst()
         .flatMap(
             t -> {
-              TSStatus status = new TSStatus(((IoTDBException) 
t).getErrorCode());
+              TSStatus status;
+              if (t instanceof IoTDBException) {
+                status = new TSStatus(((IoTDBException) t).getErrorCode());
+              } else {
+                status = new TSStatus(((IoTDBRuntimeException) 
t).getErrorCode());
+              }
               status.setMessage(t.getMessage());
               return Optional.of(status);
             });
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
index 883efecec1c..a1b853ad1b7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
@@ -304,7 +304,8 @@ public class ColumnTransformerBuilder
         } catch (TypeNotFoundException e) {
           throw new SemanticException(String.format("Unknown type: %s", 
node.getType()));
         }
-        context.cache.put(node, new CastFunctionColumnTransformer(type, 
child));
+        context.cache.put(
+            node, new CastFunctionColumnTransformer(type, child, 
context.sessionInfo.getZoneId()));
       }
     }
     ColumnTransformer res = context.cache.get(node);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/schedule/AbstractDriverThread.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/schedule/AbstractDriverThread.java
index 381c9b9378a..b4664703b45 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/schedule/AbstractDriverThread.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/schedule/AbstractDriverThread.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.execution.schedule;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.queryengine.exception.MemoryNotEnoughException;
 import 
org.apache.iotdb.db.queryengine.execution.schedule.queue.IndexedBlockingQueue;
 import org.apache.iotdb.db.queryengine.execution.schedule.task.DriverTask;
@@ -78,8 +79,13 @@ public abstract class AbstractDriverThread extends Thread 
implements Closeable {
           // reset the thread name here
           try (SetThreadName driverTaskName =
               new 
SetThreadName(next.getDriver().getDriverTaskId().getFullId())) {
-            logger.warn("[ExecuteFailed]", e);
-            next.setAbortCause(getAbortCause(e));
+            Throwable rootCause = ErrorHandlingUtils.getRootCause(e);
+            if (rootCause instanceof SemanticException) {
+              next.setAbortCause(e.getMessage());
+            } else {
+              logger.warn("[ExecuteFailed]", e);
+              next.setAbortCause(getAbortCause(e));
+            }
             scheduler.toAborted(next);
           }
         } finally {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/QueryExecution.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/QueryExecution.java
index d7cfc4bc240..108b117298c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/QueryExecution.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/QueryExecution.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.common.rpc.thrift.TEndPoint;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.commons.exception.IoTDBRuntimeException;
 import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -431,6 +432,12 @@ public class QueryExecution implements IQueryExecution {
             throw new IoTDBException(
                 stateMachine.getFailureStatus().getMessage(), 
stateMachine.getFailureStatus().code);
           } else {
+            Throwable rootCause = stateMachine.getFailureException();
+            if (rootCause instanceof IoTDBRuntimeException) {
+              throw (IoTDBRuntimeException) rootCause;
+            } else if (rootCause instanceof IoTDBException) {
+              throw (IoTDBException) rootCause;
+            }
             throw new IoTDBException(
                 stateMachine.getFailureMessage(),
                 TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
@@ -478,6 +485,11 @@ public class QueryExecution implements IQueryExecution {
           stateMachine.getFailureStatus().getMessage(), 
stateMachine.getFailureStatus().code);
     } else if (stateMachine.getFailureException() != null) {
       Throwable rootCause = stateMachine.getFailureException();
+      if (rootCause instanceof IoTDBRuntimeException) {
+        throw (IoTDBRuntimeException) rootCause;
+      } else if (rootCause instanceof IoTDBException) {
+        throw (IoTDBException) rootCause;
+      }
       throw new IoTDBException(rootCause, 
TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode());
     } else {
       throwIfUnchecked(t);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/CastFunctionHelper.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/CastFunctionHelper.java
index a7a480c644e..ca4e3fed37c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/CastFunctionHelper.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/multi/builtin/helper/CastFunctionHelper.java
@@ -31,6 +31,7 @@ import 
org.apache.iotdb.db.queryengine.transformation.dag.transformer.unary.scal
 import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.read.common.type.TypeFactory;
 
+import java.time.ZoneId;
 import java.util.Map;
 
 import static org.apache.iotdb.db.utils.constant.SqlConstant.CAST_TYPE;
@@ -56,7 +57,8 @@ public class CastFunctionHelper implements 
BuiltInScalarFunctionHelper {
       FunctionExpression expression, ColumnTransformer columnTransformer) {
     return new CastFunctionColumnTransformer(
         
TypeFactory.getType(this.getBuiltInScalarFunctionReturnType(expression)),
-        columnTransformer);
+        columnTransformer,
+        ZoneId.systemDefault());
   }
 
   @Override
@@ -131,7 +133,7 @@ public class CastFunctionHelper implements 
BuiltInScalarFunctionHelper {
     return f;
   }
 
-  public static Double castTextToDouble(String value) {
+  public static double castTextToDouble(String value) {
     double d = Double.parseDouble(value);
     if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY) {
       throw new SemanticException(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
index 9c644ef3908..12b88a7948f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
@@ -44,7 +44,7 @@ import 
org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
 import org.apache.iotdb.db.utils.constant.SqlConstant;
 
 import org.apache.tsfile.file.metadata.IDeviceID;
-import org.apache.tsfile.read.common.type.DateType;
+import org.apache.tsfile.read.common.type.BlobType;
 import org.apache.tsfile.read.common.type.StringType;
 import org.apache.tsfile.read.common.type.TimestampType;
 import org.apache.tsfile.read.common.type.Type;
@@ -667,6 +667,10 @@ public class TableMetadataImpl implements Metadata {
     return TEXT.equals(type) || StringType.STRING.equals(type);
   }
 
+  public static boolean isBlobType(Type type) {
+    return BlobType.BLOB.equals(type);
+  }
+
   public static boolean isSupportedMathNumericType(Type type) {
     return DOUBLE.equals(type) || FLOAT.equals(type) || INT32.equals(type) || 
INT64.equals(type);
   }
@@ -694,9 +698,6 @@ public class TableMetadataImpl implements Metadata {
     }
 
     // Boolean type and Binary Type can not be compared with other types
-    return (isNumericType(left) && isNumericType(right))
-        || (isCharType(left) && isCharType(right))
-        || (isCharType(left) && DateType.DATE.equals(right))
-        || (DateType.DATE.equals(left) && isCharType(right));
+    return (isNumericType(left) && isNumericType(right)) || (isCharType(left) 
&& isCharType(right));
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
index 17c4abe41e7..04f6f87436f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/binary/CompareBinaryColumnTransformer.java
@@ -28,6 +28,7 @@ import 
org.apache.tsfile.read.common.block.column.RunLengthEncodedColumn;
 import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.read.common.type.TypeEnum;
 
+import static 
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isBlobType;
 import static 
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isCharType;
 
 public abstract class CompareBinaryColumnTransformer extends 
BinaryColumnTransformer {
@@ -51,7 +52,7 @@ public abstract class CompareBinaryColumnTransformer extends 
BinaryColumnTransfo
       if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
         boolean flag = false;
         // compare binary type
-        if (isCharType(leftTransformer.getType())) {
+        if (isCharType(leftTransformer.getType()) || 
isBlobType(leftTransformer.getType())) {
           flag =
               transform(
                   TransformUtils.compare(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
index 7ef2b156935..cb69d887e70 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/CastFunctionColumnTransformer.java
@@ -19,9 +19,11 @@
 
 package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
 
+import org.apache.iotdb.db.exception.sql.SemanticException;
 import 
org.apache.iotdb.db.queryengine.plan.expression.multi.builtin.helper.CastFunctionHelper;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.UnaryColumnTransformer;
+import org.apache.iotdb.db.utils.DateTimeUtils;
 
 import org.apache.tsfile.block.column.Column;
 import org.apache.tsfile.block.column.ColumnBuilder;
@@ -30,13 +32,21 @@ import org.apache.tsfile.read.common.type.Type;
 import org.apache.tsfile.read.common.type.TypeEnum;
 import org.apache.tsfile.utils.Binary;
 import org.apache.tsfile.utils.BytesUtils;
+import org.apache.tsfile.utils.DateUtils;
+
+import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
 
 public class CastFunctionColumnTransformer extends UnaryColumnTransformer {
 
   private static final String ERROR_MSG = "Unsupported target dataType: %s";
 
-  public CastFunctionColumnTransformer(Type returnType, ColumnTransformer 
childColumnTransformer) {
+  private final ZoneId zoneId;
+
+  public CastFunctionColumnTransformer(
+      Type returnType, ColumnTransformer childColumnTransformer, ZoneId 
zoneId) {
     super(returnType, childColumnTransformer);
+    this.zoneId = zoneId;
   }
 
   @Override
@@ -47,13 +57,17 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
       if (!column.isNull(i)) {
         switch (sourceType) {
           case INT32:
-          case DATE:
             cast(columnBuilder, childType.getInt(column, i));
             break;
+          case DATE:
+            castDate(columnBuilder, childType.getInt(column, i));
+            break;
           case INT64:
-          case TIMESTAMP:
             cast(columnBuilder, childType.getLong(column, i));
             break;
+          case TIMESTAMP:
+            castTimestamp(columnBuilder, childType.getLong(column, i));
+            break;
           case FLOAT:
             cast(columnBuilder, childType.getFloat(column, i));
             break;
@@ -111,6 +125,77 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
     }
   }
 
+  private void castDate(ColumnBuilder columnBuilder, int value) {
+    switch (returnType.getTypeEnum()) {
+      case INT32:
+      case DATE:
+        returnType.writeInt(columnBuilder, value);
+        break;
+      case INT64:
+        returnType.writeLong(columnBuilder, value);
+        break;
+      case TIMESTAMP:
+        returnType.writeLong(
+            columnBuilder,
+            
DateTimeUtils.correctPrecision(DateUtils.parseIntToDate(value).getTime()));
+        break;
+      case FLOAT:
+        returnType.writeFloat(columnBuilder, value);
+        break;
+      case DOUBLE:
+        returnType.writeDouble(columnBuilder, value);
+        break;
+      case BOOLEAN:
+        returnType.writeBoolean(columnBuilder, value != 0);
+        break;
+      case TEXT:
+      case STRING:
+        returnType.writeBinary(columnBuilder, 
BytesUtils.valueOf(DateUtils.formatDate(value)));
+        break;
+      case BLOB:
+        returnType.writeBinary(columnBuilder, new 
Binary(BytesUtils.intToBytes(value)));
+        break;
+      default:
+        throw new UnsupportedOperationException(String.format(ERROR_MSG, 
returnType.getTypeEnum()));
+    }
+  }
+
+  private void castTimestamp(ColumnBuilder columnBuilder, long value) {
+    switch (returnType.getTypeEnum()) {
+      case INT32:
+        returnType.writeInt(columnBuilder, 
(CastFunctionHelper.castLongToInt(value)));
+        break;
+      case DATE:
+        returnType.writeInt(
+            columnBuilder,
+            
DateUtils.parseDateExpressionToInt(DateTimeUtils.convertToLocalDate(value, 
zoneId)));
+        break;
+      case INT64:
+      case TIMESTAMP:
+        returnType.writeLong(columnBuilder, value);
+        break;
+      case FLOAT:
+        returnType.writeFloat(columnBuilder, value);
+        break;
+      case DOUBLE:
+        returnType.writeDouble(columnBuilder, value);
+        break;
+      case BOOLEAN:
+        returnType.writeBoolean(columnBuilder, value != 0L);
+        break;
+      case TEXT:
+      case STRING:
+        returnType.writeBinary(
+            columnBuilder, 
BytesUtils.valueOf(DateTimeUtils.convertLongToDate(value, zoneId)));
+        break;
+      case BLOB:
+        returnType.writeBinary(columnBuilder, new 
Binary(BytesUtils.longToBytes(value)));
+        break;
+      default:
+        throw new UnsupportedOperationException(String.format(ERROR_MSG, 
returnType.getTypeEnum()));
+    }
+  }
+
   private void cast(ColumnBuilder columnBuilder, long value) {
     switch (returnType.getTypeEnum()) {
       case INT32:
@@ -237,31 +322,39 @@ public class CastFunctionColumnTransformer extends 
UnaryColumnTransformer {
 
   private void cast(ColumnBuilder columnBuilder, Binary value) {
     String stringValue = value.getStringValue(TSFileConfig.STRING_CHARSET);
-    switch (returnType.getTypeEnum()) {
-      case INT32:
-      case DATE:
-        returnType.writeInt(columnBuilder, Integer.parseInt(stringValue));
-        break;
-      case INT64:
-      case TIMESTAMP:
-        returnType.writeLong(columnBuilder, Long.parseLong(stringValue));
-        break;
-      case FLOAT:
-        returnType.writeFloat(columnBuilder, 
CastFunctionHelper.castTextToFloat(stringValue));
-        break;
-      case DOUBLE:
-        returnType.writeDouble(columnBuilder, 
CastFunctionHelper.castTextToDouble(stringValue));
-        break;
-      case BOOLEAN:
-        returnType.writeBoolean(columnBuilder, 
CastFunctionHelper.castTextToBoolean(stringValue));
-        break;
-      case TEXT:
-      case STRING:
-      case BLOB:
-        returnType.writeBinary(columnBuilder, value);
-        break;
-      default:
-        throw new UnsupportedOperationException(String.format(ERROR_MSG, 
returnType.getTypeEnum()));
+    try {
+      switch (returnType.getTypeEnum()) {
+        case INT32:
+          returnType.writeInt(columnBuilder, Integer.parseInt(stringValue));
+          break;
+        case DATE:
+          returnType.writeInt(columnBuilder, 
DateUtils.parseDateExpressionToInt(stringValue));
+          break;
+        case INT64:
+        case TIMESTAMP:
+          returnType.writeLong(columnBuilder, Long.parseLong(stringValue));
+          break;
+        case FLOAT:
+          returnType.writeFloat(columnBuilder, 
CastFunctionHelper.castTextToFloat(stringValue));
+          break;
+        case DOUBLE:
+          returnType.writeDouble(columnBuilder, 
CastFunctionHelper.castTextToDouble(stringValue));
+          break;
+        case BOOLEAN:
+          returnType.writeBoolean(columnBuilder, 
CastFunctionHelper.castTextToBoolean(stringValue));
+          break;
+        case TEXT:
+        case STRING:
+        case BLOB:
+          returnType.writeBinary(columnBuilder, value);
+          break;
+        default:
+          throw new UnsupportedOperationException(
+              String.format(ERROR_MSG, returnType.getTypeEnum()));
+      }
+    } catch (DateTimeParseException | NumberFormatException e) {
+      throw new SemanticException(
+          String.format("Cannot cast %s to %s type", stringValue, 
returnType.getDisplayName()));
     }
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java
index 98e0a6f09aa..089aafa0106 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java
@@ -35,6 +35,7 @@ import org.apache.tsfile.utils.TimeDuration;
 
 import java.time.DateTimeException;
 import java.time.Instant;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
@@ -56,6 +57,22 @@ public class DateTimeUtils {
 
   private static final String TIMESTAMP_PRECISION =
       CommonDescriptor.getInstance().getConfig().getTimestampPrecision();
+
+  public static long correctPrecision(long millis) {
+    switch (TIMESTAMP_PRECISION) {
+      case "us":
+      case "microsecond":
+        return millis * 1_000L;
+      case "ns":
+      case "nanosecond":
+        return millis * 1_000_000L;
+      case "ms":
+      case "millisecond":
+      default:
+        return millis;
+    }
+  }
+
   private static Function<Long, Long> CAST_TIMESTAMP_TO_MS;
 
   static {
@@ -716,10 +733,21 @@ public class DateTimeUtils {
 
   public static String convertLongToDate(long timestamp) {
     return convertLongToDate(
-        timestamp, 
CommonDescriptor.getInstance().getConfig().getTimestampPrecision());
+        timestamp,
+        CommonDescriptor.getInstance().getConfig().getTimestampPrecision(),
+        ZoneId.systemDefault());
+  }
+
+  public static String convertLongToDate(long timestamp, ZoneId zoneId) {
+    return convertLongToDate(
+        timestamp, 
CommonDescriptor.getInstance().getConfig().getTimestampPrecision(), zoneId);
   }
 
   public static String convertLongToDate(long timestamp, String 
sourcePrecision) {
+    return convertLongToDate(timestamp, sourcePrecision, 
ZoneId.systemDefault());
+  }
+
+  public static String convertLongToDate(long timestamp, String 
sourcePrecision, ZoneId zoneId) {
     switch (sourcePrecision) {
       case "ns":
       case "nanosecond":
@@ -730,8 +758,12 @@ public class DateTimeUtils {
         timestamp /= 1000;
         break;
     }
-    return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), 
ZoneId.systemDefault())
-        .toString();
+    return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), 
zoneId).toString();
+  }
+
+  public static LocalDate convertToLocalDate(long timestamp, ZoneId zoneId) {
+    timestamp = CAST_TIMESTAMP_TO_MS.apply(timestamp);
+    return Instant.ofEpochMilli(timestamp).atZone(zoneId).toLocalDate();
   }
 
   public static ZoneOffset toZoneOffset(ZoneId zoneId) {

Reply via email to