This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ty/OptTypeMismatchErrorMsg in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 62aaf7943c8fea2966c08df25ee84740e4dfc974 Author: JackieTien97 <[email protected]> AuthorDate: Wed Aug 21 21:35:39 2024 +0800 Opt type mismatch error msg --- .../org/apache/iotdb/db/it/utils/TestUtils.java | 2 +- .../scalar/IoTDBScalarFunctionTableIT.java | 49 +++++++++++++++++ .../fragment/FragmentInstanceContext.java | 10 +++- .../execution/schedule/AbstractDriverThread.java | 10 +++- .../queryengine/plan/execution/QueryExecution.java | 6 +++ .../relational/metadata/TableMetadataImpl.java | 11 ++-- .../binary/CompareBinaryColumnTransformer.java | 3 +- .../scalar/CastFunctionColumnTransformer.java | 62 +++++++++++++--------- 8 files changed, 117 insertions(+), 36 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/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBScalarFunctionTableIT.java index dd67aa726d1..908eab95e1e 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 TimeStamp, 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/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/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..59056f5c2b5 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; @@ -478,6 +479,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/relational/metadata/TableMetadataImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java index bfe07f693f4..01ce776d4f3 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..41bc76a0ff5 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,6 +19,7 @@ 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; @@ -30,6 +31,9 @@ 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.format.DateTimeParseException; public class CastFunctionColumnTransformer extends UnaryColumnTransformer { @@ -237,31 +241,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())); } } }
