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) {