This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ty/TableModelGrammar in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit fca8c61b4b053469ea9a4da903c13f6f7dd1ea6c Author: JackieTien97 <[email protected]> AuthorDate: Tue Apr 9 17:18:49 2024 +0800 Add support for builtin scalar and aggregation function --- .../java/org/apache/iotdb/rpc/TSStatusCode.java | 1 + .../relational/analyzer/ExpressionAnalyzer.java | 277 ++++++++------------- .../metadata/BuiltinFunctionResolver.java} | 20 +- .../plan/relational/metadata/Metadata.java | 15 ++ .../relational/metadata/TableMetadataImpl.java | 226 +++++++++++++++++ .../plan/relational/planner/PlannerContext.java} | 28 ++- .../plan/relational/type/InternalTypeManager.java | 67 +++++ .../queryengine/plan/relational/type/TypeId.java | 66 +++++ .../plan/relational/type/TypeManager.java} | 27 +- .../relational/type/TypeNotFoundException.java} | 27 +- .../relational/type/TypeSignatureTranslator.java | 107 ++++++++ .../binary/CompareBinaryColumnTransformer.java | 2 +- .../ternary/CompareTernaryColumnTransformer.java | 6 +- .../dag/column/unary/InColumnTransformer.java | 4 +- .../dag/column/unary/RegularColumnTransformer.java | 2 +- .../scalar/CastFunctionColumnTransformer.java | 14 +- .../plan/relational/analyzer/TestMatadata.java | 30 +++ .../iotdb/tsfile/read/common/type/BinaryType.java | 2 +- .../iotdb/tsfile/read/common/type/TypeEnum.java | 2 +- .../iotdb/tsfile/read/common/type/TypeFactory.java | 2 +- 20 files changed, 674 insertions(+), 251 deletions(-) diff --git a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java index ba6a7f06681..5e7fcb543c6 100644 --- a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java +++ b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java @@ -82,6 +82,7 @@ public enum TSStatusCode { DATABASE_CONFIG_ERROR(525), SCHEMA_QUOTA_EXCEEDED(526), MEASUREMENT_ALREADY_EXISTS_IN_TEMPLATE(527), + TYPE_NOT_FOUND(528), // Storage Engine SYSTEM_READ_ONLY(600), diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java index 64bd4a98952..cb76bf10504 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java @@ -23,13 +23,13 @@ import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector; import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider; -import org.apache.iotdb.db.queryengine.plan.relational.function.BoundSignature; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; import org.apache.iotdb.db.queryengine.plan.relational.metadata.OperatorNotFoundException; import org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName; import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException; import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression; import org.apache.iotdb.db.relational.sql.tree.ArithmeticUnaryExpression; import org.apache.iotdb.db.relational.sql.tree.BetweenPredicate; @@ -103,6 +103,7 @@ import static java.lang.String.format; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; import static java.util.Objects.requireNonNull; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature; import static org.apache.iotdb.db.relational.sql.tree.DereferenceExpression.isQualifiedAllFieldsReference; import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT; import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN; @@ -145,6 +146,10 @@ public class ExpressionAnalyzer { private final List<Field> sourceFields = new ArrayList<>(); + // Record fields prefixed with labels in row pattern recognition context + private final Map<NodeRef<DereferenceExpression>, LabelPrefixedReference> labelDereferences = + new LinkedHashMap<>(); + private ExpressionAnalyzer( Metadata metadata, AccessControl accessControl, @@ -615,10 +620,7 @@ public class ExpressionAnalyzer { case PLUS: Type type = process(node.getValue(), context); - if (!type.equals(DOUBLE) - && !type.equals(FLOAT) - && !type.equals(INT32) - && !type.equals(INT64)) { + if (!isNumericType(type)) { // TODO: figure out a type-agnostic way of dealing with this. Maybe add a special unary // operator // that types can chose to implement, or piggyback on the existence of the negation @@ -731,106 +733,64 @@ public class ExpressionAnalyzer { @Override protected Type visitFunctionCall( FunctionCall node, StackableAstVisitorContext<Context> context) { - // TODO implememt function call - throw new SemanticException("FunctionCall is not implemented yet."); - // boolean isAggregation = functionResolver.isAggregationFunction(session, - // node.getName(), accessControl); - // // argument of the form `label.*` is only allowed for row pattern count function - // node.getArguments().stream() - // .filter(DereferenceExpression::isQualifiedAllFieldsReference) - // .findAny() - // .ifPresent(allRowsReference -> { - // if (node.getArguments().size() > 1) { - // throw new SemanticException( - // "label.* syntax is only supported as the only argument of row pattern - // count function"); - // } - // }); - // - // if (node.isDistinct() && !isAggregation) { - // throw new SemanticException("DISTINCT is not supported for non-aggregation - // functions"); - // } - // - // List<TypeSignatureProvider> argumentTypes = getCallArgumentTypes(node.getArguments(), - // context); - // - // ResolvedFunction function; - // try { - // function = functionResolver.resolveFunction(session, node.getName(), argumentTypes, - // accessControl); - // } catch (TrinoException e) { - // if (e.getLocation().isPresent()) { - // // If analysis of any of the argument types (which is done lazily to deal with - // lambda - // // expressions) fails, we want to report the original reason for the failure - // throw e; - // } - // - // // otherwise, it must have failed due to a missing function or other reason, so we - // report an error at the - // // current location - // - // throw new TrinoException(e::getErrorCode, extractLocation(node), e.getMessage(), e); - // } - // - // if (node.getArguments().size() > 127) { - // throw new SemanticException(String.format("Too many arguments for function call - // %s()", - // function.getSignature().getName().getFunctionName())); - // } - // - // BoundSignature signature = function.getSignature(); - // for (int i = 0; i < argumentTypes.size(); i++) { - // Expression expression = node.getArguments().get(i); - // Type expectedType = signature.getArgumentTypes().get(i); - // if (expectedType == null) { - // throw new NullPointerException(format("Type '%s' not found", - // signature.getArgumentTypes().get(i))); - // } - // if (node.isDistinct() && !expectedType.isComparable()) { - // throw new SemanticException(String.format("DISTINCT can only be applied to - // comparable types (actual: %s)", - // expectedType)); - // } - // Type actualType = - // plannerContext.getTypeManager().getType(argumentTypes.get(i).getTypeSignature()); - // - // coerceType(expression, actualType, expectedType, String.format("Function %s argument - // %d", function, i)); - // } - // resolvedFunctions.put(NodeRef.of(node), function); - // - // Type type = signature.getReturnType(); - // return setExpressionType(node, type); + String functionName = node.getName().getSuffix(); + boolean isAggregation = metadata.isAggregationFunction(session, functionName, accessControl); + // argument of the form `label.*` is only allowed for row pattern count function + node.getArguments().stream() + .filter(DereferenceExpression::isQualifiedAllFieldsReference) + .findAny() + .ifPresent( + allRowsReference -> { + if (node.getArguments().size() > 1) { + throw new SemanticException( + "label.* syntax is only supported as the only argument of row pattern count function"); + } + }); + + if (node.isDistinct() && !isAggregation) { + throw new SemanticException("DISTINCT is not supported for non-aggregation functions"); + } + + List<Type> argumentTypes = getCallArgumentTypes(node.getArguments(), context); + + if (node.getArguments().size() > 127) { + throw new SemanticException( + String.format("Too many arguments for function call %s()", functionName)); + } + + for (Type argumentType : argumentTypes) { + if (node.isDistinct() && !argumentType.isComparable()) { + throw new SemanticException( + String.format( + "DISTINCT can only be applied to comparable types (actual: %s)", argumentType)); + } + } + + Type type = metadata.getFunctionReturnType(functionName, argumentTypes); + return setExpressionType(node, type); } - // public List<TypeSignatureProvider> getCallArgumentTypes(List<Expression> arguments, - // - // StackableAstVisitorContext<Context> context) { - // ImmutableList.Builder<TypeSignatureProvider> argumentTypesBuilder = - // ImmutableList.builder(); - // for (Expression argument : arguments) { - // if (isQualifiedAllFieldsReference(argument)) { - // // to resolve `count(label.*)` correctly, we should skip the argument, like for - // `count(*)` - // // process the argument but do not include it in the list - // DereferenceExpression allRowsDereference = (DereferenceExpression) argument; - // String label = label((Identifier) allRowsDereference.getBase()); - // if (!context.getContext().getLabels().contains(label)) { - // throw semanticException(INVALID_FUNCTION_ARGUMENT, allRowsDereference.getBase(), - // "%s is not a primary pattern variable or subset name", label); - // } - // labelDereferences.put(NodeRef.of(allRowsDereference), new - // LabelPrefixedReference(label)); - // } else { - // argumentTypesBuilder.add(new TypeSignatureProvider(process(argument, - // context).getTypeSignature())); - // } - // } - // - // return argumentTypesBuilder.build(); - // } + public List<Type> getCallArgumentTypes( + List<Expression> arguments, StackableAstVisitorContext<Context> context) { + ImmutableList.Builder<Type> argumentTypesBuilder = ImmutableList.builder(); + for (Expression argument : arguments) { + if (isQualifiedAllFieldsReference(argument)) { + // to resolve `count(label.*)` correctly, we should skip the argument, like for `count(*)` + // process the argument but do not include it in the list + DereferenceExpression allRowsDereference = (DereferenceExpression) argument; + String label = label((Identifier) allRowsDereference.getBase()); + if (!context.getContext().getLabels().contains(label)) { + throw new SemanticException( + String.format("%s is not a primary pattern variable or subset name", label)); + } + labelDereferences.put(NodeRef.of(allRowsDereference), new LabelPrefixedReference(label)); + } else { + argumentTypesBuilder.add(process(argument, context)); + } + } + + return argumentTypesBuilder.build(); + } private String label(Identifier identifier) { return identifier.getCanonicalValue(); @@ -849,38 +809,17 @@ public class ExpressionAnalyzer { @Override protected Type visitTrim(Trim node, StackableAstVisitorContext<Context> context) { - // TODO implement TRIM - throw new SemanticException("Trim is not implemented yet"); - // ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder(); - // - // argumentTypes.add(process(node.getTrimSource(), context)); - // node.getTrimCharacter().ifPresent(trimChar -> argumentTypes.add(process(trimChar, - // context))); - // List<Type> actualTypes = argumentTypes.build(); - // - // String functionName = node.getSpecification().getFunctionName(); - // ResolvedFunction function = - // plannerContext.getMetadata().resolveBuiltinFunction(functionName, - // fromTypes(actualTypes)); - // - // List<Type> expectedTypes = function.getSignature().getArgumentTypes(); - // checkState(expectedTypes.size() == actualTypes.size(), "wrong argument number in the - // resolved signature"); - // - // Type actualTrimSourceType = actualTypes.get(0); - // Type expectedTrimSourceType = expectedTypes.get(0); - // coerceType(node.getTrimSource(), actualTrimSourceType, expectedTrimSourceType, - // "source argument of trim function"); - // - // if (node.getTrimCharacter().isPresent()) { - // Type actualTrimCharType = actualTypes.get(1); - // Type expectedTrimCharType = expectedTypes.get(1); - // coerceType(node.getTrimCharacter().get(), actualTrimCharType, expectedTrimCharType, - // "trim character argument of trim function"); - // } - // resolvedFunctions.put(NodeRef.of(node), function); - // - // return setExpressionType(node, function.getSignature().getReturnType()); + ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder(); + + argumentTypes.add(process(node.getTrimSource(), context)); + node.getTrimCharacter().ifPresent(trimChar -> argumentTypes.add(process(trimChar, context))); + List<Type> actualTypes = argumentTypes.build(); + + String functionName = node.getSpecification().getFunctionName(); + + Type returnType = metadata.getFunctionReturnType(functionName, actualTypes); + + return setExpressionType(node, returnType); } @Override @@ -926,31 +865,26 @@ public class ExpressionAnalyzer { @Override public Type visitCast(Cast node, StackableAstVisitorContext<Context> context) { - // TODO implement cast - throw new SemanticException("Cast is not implemented yet"); - // - // Type type; - // try { - // type = plannerContext.getTypeManager().getType(toTypeSignature(node.getType())); - // } catch (TypeNotFoundException e) { - // throw semanticException(TYPE_MISMATCH, node, "Unknown type: %s", node.getType()); - // } - // - // if (type.equals(UnknownType.UNKNOWN)) { - // throw new SemanticException("UNKNOWN is not a valid type"); - // } - // - // Type value = process(node.getExpression(), context); - // if (!value.equals(UnknownType.UNKNOWN) && !node.isTypeOnly()) { - // // TODO implement cast - // try { - // plannerContext.getMetadata().getCoercion(value, type); - // } catch (OperatorNotFoundException e) { - // throw semanticException(TYPE_MISMATCH, node, "Cannot cast %s to %s", value, type); - // } - // } - // - // return setExpressionType(node, type); + + Type type; + try { + type = metadata.getType(toTypeSignature(node.getType())); + } catch (TypeNotFoundException e) { + throw new SemanticException(String.format("Unknown type: %s", node.getType())); + } + + if (type.equals(UnknownType.UNKNOWN)) { + throw new SemanticException("UNKNOWN is not a valid type"); + } + + Type value = process(node.getExpression(), context); + if (!value.equals(UnknownType.UNKNOWN) + && !node.isTypeOnly() + && (!metadata.canCoerce(value, type))) { + throw new SemanticException(String.format("Cannot cast %s to %s", value, type)); + } + + return setExpressionType(node, type); } @Override @@ -1158,25 +1092,13 @@ public class ExpressionAnalyzer { argumentTypes.add(process(expression, context)); } - BoundSignature operatorSignature; + Type type; try { - operatorSignature = - metadata.resolveOperator(operatorType, argumentTypes.build()).getSignature(); + type = metadata.getOperatorReturnType(operatorType, argumentTypes.build()); } catch (OperatorNotFoundException e) { throw new SemanticException(e.getMessage()); } - for (int i = 0; i < arguments.length; i++) { - Expression expression = arguments[i]; - Type type = operatorSignature.getArgumentTypes().get(i); - coerceType( - context, - expression, - type, - String.format("Operator %s argument %d", operatorSignature, i)); - } - - Type type = operatorSignature.getReturnType(); return setExpressionType(node, type); } @@ -1382,10 +1304,9 @@ public class ExpressionAnalyzer { return functionInputTypes; } - // public Set<String> getLabels() { - // checkState(isPatternRecognition()); - // return labels; - // } + public Set<String> getLabels() { + return labels; + } public CorrelationSupport getCorrelationSupport() { return correlationSupport; diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java similarity index 83% copy from iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java index ed3e7b99fe5..991b38d18b3 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/BuiltinFunctionResolver.java @@ -17,22 +17,6 @@ * under the License. */ -package org.apache.iotdb.tsfile.read.common.type; +package org.apache.iotdb.db.queryengine.plan.relational.metadata; -public enum TypeEnum { - INT32, - - INT64, - - FLOAT, - - DOUBLE, - - BOOLEAN, - - BINARY, - - ROW, - - UNKNOWN -} +public class BuiltinFunctionResolver {} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java index 5e708b9c9f0..00843f38201 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java @@ -21,6 +21,9 @@ package org.apache.iotdb.db.queryengine.plan.relational.metadata; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature; import org.apache.iotdb.tsfile.read.common.type.Type; import java.util.List; @@ -61,4 +64,16 @@ public interface Metadata { ResolvedFunction resolveOperator(OperatorType operatorType, List<? extends Type> argumentTypes) throws OperatorNotFoundException; + + Type getOperatorReturnType(OperatorType operatorType, List<? extends Type> argumentTypes) + throws OperatorNotFoundException; + + Type getFunctionReturnType(String functionName, List<? extends Type> argumentTypes); + + boolean isAggregationFunction( + SessionInfo session, String functionName, AccessControl accessControl); + + Type getType(TypeSignature signature) throws TypeNotFoundException; + + boolean canCoerce(Type from, Type to); } 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 95fcfcaacbe..f040a086142 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 @@ -19,15 +19,35 @@ package org.apache.iotdb.db.queryengine.plan.relational.metadata; +import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction; +import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction; +import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeManager; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature; +import org.apache.iotdb.db.utils.constant.SqlConstant; import org.apache.iotdb.tsfile.read.common.type.Type; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; +import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT; +import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN; +import static org.apache.iotdb.tsfile.read.common.type.DoubleType.DOUBLE; +import static org.apache.iotdb.tsfile.read.common.type.FloatType.FLOAT; +import static org.apache.iotdb.tsfile.read.common.type.IntType.INT32; +import static org.apache.iotdb.tsfile.read.common.type.LongType.INT64; + public class TableMetadataImpl implements Metadata { + + private final TypeManager typeManager = new InternalTypeManager(); + @Override public boolean tableExists(QualifiedObjectName name) { return false; @@ -59,4 +79,210 @@ public class TableMetadataImpl implements Metadata { throws OperatorNotFoundException { return null; } + + @Override + public Type getOperatorReturnType(OperatorType operatorType, List<? extends Type> argumentTypes) + throws OperatorNotFoundException { + + switch (operatorType) { + case ADD: + case SUBTRACT: + case MULTIPLY: + case DIVIDE: + case MODULUS: + if (!isTwoNumericType(argumentTypes)) { + throw new OperatorNotFoundException( + operatorType, + argumentTypes, + new IllegalArgumentException("Should have two numeric operands.")); + } + return DOUBLE; + case NEGATION: + if (!isOneNumericType(argumentTypes)) { + throw new OperatorNotFoundException( + operatorType, + argumentTypes, + new IllegalArgumentException("Should have one numeric operands.")); + } + return DOUBLE; + case EQUAL: + case LESS_THAN: + case LESS_THAN_OR_EQUAL: + if (!isTwoTypeComparable(argumentTypes)) { + throw new OperatorNotFoundException( + operatorType, + argumentTypes, + new IllegalArgumentException("Should have two comparable operands.")); + } + return BOOLEAN; + default: + throw new OperatorNotFoundException( + operatorType, argumentTypes, new UnsupportedOperationException()); + } + } + + @Override + public Type getFunctionReturnType(String functionName, List<? extends Type> argumentTypes) { + + // builtin scalar function + if (BuiltinScalarFunction.DIFF.getFunctionName().equalsIgnoreCase(functionName) + || BuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) { + if (!isOneNumericType(argumentTypes)) { + throw new SemanticException( + "Scalar function" + + functionName.toLowerCase(Locale.ENGLISH) + + " only supports numeric data types [INT32, INT64, FLOAT, DOUBLE]"); + } + return DOUBLE; + } else if (BuiltinScalarFunction.REPLACE.getFunctionName().equalsIgnoreCase(functionName) + || BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName)) { + if (!isOneTextType(argumentTypes)) { + throw new SemanticException( + "Scalar function" + + functionName.toLowerCase(Locale.ENGLISH) + + " only supports text data type."); + } + return TEXT; + } + + // builtin aggregation function + // check argument type + switch (functionName.toLowerCase()) { + case SqlConstant.AVG: + case SqlConstant.SUM: + case SqlConstant.EXTREME: + case SqlConstant.MIN_VALUE: + case SqlConstant.MAX_VALUE: + case SqlConstant.STDDEV: + case SqlConstant.STDDEV_POP: + case SqlConstant.STDDEV_SAMP: + case SqlConstant.VARIANCE: + case SqlConstant.VAR_POP: + case SqlConstant.VAR_SAMP: + if (!isOneNumericType(argumentTypes)) { + throw new SemanticException( + String.format( + "Aggregate functions [%s] only support numeric data types [INT32, INT64, FLOAT, DOUBLE]", + functionName)); + } + break; + case SqlConstant.MIN_TIME: + case SqlConstant.MAX_TIME: + case SqlConstant.FIRST_VALUE: + case SqlConstant.LAST_VALUE: + case SqlConstant.TIME_DURATION: + case SqlConstant.MODE: + if (argumentTypes.size() != 1) { + throw new SemanticException( + String.format( + "Aggregate functions [%s] should only have one argument", functionName)); + } + break; + case SqlConstant.MAX_BY: + case SqlConstant.MIN_BY: + if (argumentTypes.size() != 2) { + throw new SemanticException( + String.format( + "Aggregate functions [%s] should only have two arguments", functionName)); + } else if (!argumentTypes.get(1).isOrderable()) { + throw new SemanticException( + String.format( + "Second argument of Aggregate functions [%s] should be orderable", functionName)); + } + + break; + case SqlConstant.COUNT: + break; + default: + // ignore + } + + // get return type + switch (functionName.toLowerCase()) { + case SqlConstant.MIN_TIME: + case SqlConstant.MAX_TIME: + case SqlConstant.COUNT: + case SqlConstant.TIME_DURATION: + return INT64; + case SqlConstant.MIN_VALUE: + case SqlConstant.LAST_VALUE: + case SqlConstant.FIRST_VALUE: + case SqlConstant.MAX_VALUE: + case SqlConstant.EXTREME: + case SqlConstant.MODE: + case SqlConstant.MAX_BY: + case SqlConstant.MIN_BY: + return argumentTypes.get(0); + case SqlConstant.AVG: + case SqlConstant.SUM: + case SqlConstant.STDDEV: + case SqlConstant.STDDEV_POP: + case SqlConstant.STDDEV_SAMP: + case SqlConstant.VARIANCE: + case SqlConstant.VAR_POP: + case SqlConstant.VAR_SAMP: + return DOUBLE; + default: + // ignore + } + + // TODO scalar UDF function + + // TODO UDAF + + throw new SemanticException("Unknown function: " + functionName); + } + + @Override + public boolean isAggregationFunction( + SessionInfo session, String functionName, AccessControl accessControl) { + return BuiltinAggregationFunction.getNativeFunctionNames() + .contains(functionName.toLowerCase(Locale.ENGLISH)); + } + + @Override + public Type getType(TypeSignature signature) throws TypeNotFoundException { + return typeManager.getType(signature); + } + + @Override + public boolean canCoerce(Type from, Type to) { + return true; + } + + public static boolean isTwoNumericType(List<? extends Type> argumentTypes) { + return argumentTypes.size() == 2 + && isNumericType(argumentTypes.get(0)) + && isNumericType(argumentTypes.get(1)); + } + + public static boolean isOneNumericType(List<? extends Type> argumentTypes) { + return argumentTypes.size() == 1 && isNumericType(argumentTypes.get(0)); + } + + public static boolean isOneBooleanType(List<? extends Type> argumentTypes) { + return argumentTypes.size() == 1 && BOOLEAN.equals(argumentTypes.get(0)); + } + + public static boolean isOneTextType(List<? extends Type> argumentTypes) { + return argumentTypes.size() == 1 && TEXT.equals(argumentTypes.get(0)); + } + + public static boolean isNumericType(Type type) { + return DOUBLE.equals(type) || FLOAT.equals(type) || INT32.equals(type) || INT64.equals(type); + } + + public static boolean isTwoTypeComparable(List<? extends Type> argumentTypes) { + if (argumentTypes.size() != 2) { + return false; + } + Type left = argumentTypes.get(0); + Type right = argumentTypes.get(1); + if (left.equals(right)) { + return true; + } + + // Boolean type and Binary Type can not be compared with other types + return isNumericType(left) && isNumericType(right); + } } diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java similarity index 53% copy from iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java index ed3e7b99fe5..b8090df85d4 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java @@ -17,22 +17,24 @@ * under the License. */ -package org.apache.iotdb.tsfile.read.common.type; +package org.apache.iotdb.db.queryengine.plan.relational.planner; -public enum TypeEnum { - INT32, +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeManager; - INT64, - - FLOAT, - - DOUBLE, - - BOOLEAN, +/** + * A carrier of core, global, non-derived services for planner and analyzer. This is used to ease + * the addition of new services in the future without having to modify large portions the planner + * and analyzer just to pass around the service. + */ +public class PlannerContext { - BINARY, + private final Metadata metadata; - ROW, + private final TypeManager typeManager; - UNKNOWN + public PlannerContext(Metadata metadata, TypeManager typeManager) { + this.metadata = metadata; + this.typeManager = typeManager; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java new file mode 100644 index 00000000000..3b3cdf32bc3 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/InternalTypeManager.java @@ -0,0 +1,67 @@ +/* + * 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.iotdb.db.queryengine.plan.relational.type; + +import org.apache.iotdb.tsfile.read.common.type.Type; +import org.apache.iotdb.tsfile.read.common.type.TypeEnum; + +import java.util.Locale; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.apache.iotdb.tsfile.read.common.type.BinaryType.TEXT; +import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN; +import static org.apache.iotdb.tsfile.read.common.type.DoubleType.DOUBLE; +import static org.apache.iotdb.tsfile.read.common.type.FloatType.FLOAT; +import static org.apache.iotdb.tsfile.read.common.type.IntType.INT32; +import static org.apache.iotdb.tsfile.read.common.type.LongType.INT64; + +public class InternalTypeManager implements TypeManager { + + private final ConcurrentMap<TypeSignature, Type> types = new ConcurrentHashMap<>(); + + public InternalTypeManager() { + types.put(new TypeSignature(TypeEnum.DOUBLE.name().toLowerCase(Locale.ENGLISH)), DOUBLE); + types.put(new TypeSignature(TypeEnum.FLOAT.name().toLowerCase(Locale.ENGLISH)), FLOAT); + types.put(new TypeSignature(TypeEnum.INT64.name().toLowerCase(Locale.ENGLISH)), INT64); + types.put(new TypeSignature(TypeEnum.INT32.name().toLowerCase(Locale.ENGLISH)), INT32); + types.put(new TypeSignature(TypeEnum.BOOLEAN.name().toLowerCase(Locale.ENGLISH)), BOOLEAN); + types.put(new TypeSignature(TypeEnum.TEXT.name().toLowerCase(Locale.ENGLISH)), TEXT); + } + + @Override + public Type getType(TypeSignature signature) throws TypeNotFoundException { + Type type = types.get(signature); + if (type == null) { + throw new TypeNotFoundException(signature); + } + return type; + } + + @Override + public Type fromSqlType(String type) { + throw new UnsupportedOperationException(); + } + + @Override + public Type getType(TypeId id) { + throw new UnsupportedOperationException(); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java new file mode 100644 index 00000000000..9f445377fbb --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeId.java @@ -0,0 +1,66 @@ +/* + * 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.iotdb.db.queryengine.plan.relational.type; + +import java.util.Objects; + +import static java.util.Objects.requireNonNull; + +/** + * Represents an opaque identifier for a Type than can be used for serialization or storage in + * external systems. + */ +public class TypeId { + private final String id; + + private TypeId(String id) { + this.id = requireNonNull(id, "id is null"); + } + + public static TypeId of(String id) { + return new TypeId(id); + } + + public String getId() { + return id; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TypeId typeId = (TypeId) o; + return id.equals(typeId.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public String toString() { + return "type:[" + getId() + "]"; + } +} diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java similarity index 62% copy from iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java index ed3e7b99fe5..ed6dd267e0b 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java @@ -17,22 +17,21 @@ * under the License. */ -package org.apache.iotdb.tsfile.read.common.type; +package org.apache.iotdb.db.queryengine.plan.relational.type; -public enum TypeEnum { - INT32, +import org.apache.iotdb.tsfile.read.common.type.Type; - INT64, +public interface TypeManager { + /** + * Gets the type with the specified signature. + * + * @throws TypeNotFoundException if not found + */ + Type getType(TypeSignature signature) throws TypeNotFoundException; - FLOAT, + /** Gets a type given it's SQL representation */ + Type fromSqlType(String type); - DOUBLE, - - BOOLEAN, - - BINARY, - - ROW, - - UNKNOWN + /** Gets the type with the give (opaque) id */ + Type getType(TypeId id); } diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java similarity index 55% copy from iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java index ed3e7b99fe5..20d7281abf8 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java @@ -17,22 +17,27 @@ * under the License. */ -package org.apache.iotdb.tsfile.read.common.type; +package org.apache.iotdb.db.queryengine.plan.relational.type; -public enum TypeEnum { - INT32, +import org.apache.iotdb.commons.exception.IoTDBException; - INT64, +import static java.util.Objects.requireNonNull; +import static org.apache.iotdb.rpc.TSStatusCode.TYPE_NOT_FOUND; - FLOAT, +public class TypeNotFoundException extends IoTDBException { - DOUBLE, + private final TypeSignature type; - BOOLEAN, + public TypeNotFoundException(TypeSignature type) { + this(type, null); + } - BINARY, + public TypeNotFoundException(TypeSignature type, Throwable cause) { + super("Unknown type: " + type, cause, TYPE_NOT_FOUND.getStatusCode()); + this.type = requireNonNull(type, "type is null"); + } - ROW, - - UNKNOWN + public TypeSignature getType() { + return type; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java new file mode 100644 index 00000000000..5a65111666e --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeSignatureTranslator.java @@ -0,0 +1,107 @@ +/* + * 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.iotdb.db.queryengine.plan.relational.type; + +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.relational.sql.tree.DataType; +import org.apache.iotdb.db.relational.sql.tree.DataTypeParameter; +import org.apache.iotdb.db.relational.sql.tree.GenericDataType; +import org.apache.iotdb.db.relational.sql.tree.Identifier; +import org.apache.iotdb.db.relational.sql.tree.NumericParameter; +import org.apache.iotdb.db.relational.sql.tree.TypeParameter; + +import com.google.common.collect.ImmutableList; + +import java.util.Collections; +import java.util.Locale; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.numericParameter; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.typeParameter; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureParameter.typeVariable; + +public class TypeSignatureTranslator { + + private TypeSignatureTranslator() {} + + public static TypeSignature toTypeSignature(DataType type) { + return toTypeSignature(type, Collections.emptySet()); + } + + private static TypeSignature toTypeSignature(DataType type, Set<String> typeVariables) { + if (type instanceof GenericDataType) { + return toTypeSignature((GenericDataType) type, typeVariables); + } + + throw new UnsupportedOperationException("Unsupported DataType: " + type.getClass().getName()); + } + + private static TypeSignature toTypeSignature(GenericDataType type, Set<String> typeVariables) { + ImmutableList.Builder<TypeSignatureParameter> parameters = ImmutableList.builder(); + + // if (type.getName().getValue().equalsIgnoreCase(VARCHAR) && type.getArguments().isEmpty()) + // { + // // We treat VARCHAR specially because currently, the unbounded VARCHAR type is modeled + // in the system as a VARCHAR(n) with a "magic" length + // // TODO: Eventually, we should split the types into VARCHAR and VARCHAR(n) + // return VarcharType.VARCHAR.getTypeSignature(); + // } + + checkArgument( + !typeVariables.contains(type.getName().getValue()), + "Base type name cannot be a type variable"); + + for (DataTypeParameter parameter : type.getArguments()) { + if (parameter instanceof NumericParameter) { + String value = ((NumericParameter) parameter).getValue(); + try { + parameters.add(numericParameter(Long.parseLong(value))); + } catch (NumberFormatException e) { + throw new SemanticException(String.format("Invalid type parameter: %s", value)); + } + } else if (parameter instanceof TypeParameter) { + DataType value = ((TypeParameter) parameter).getValue(); + if (value instanceof GenericDataType + && ((GenericDataType) value).getArguments().isEmpty() + && typeVariables.contains(((GenericDataType) value).getName().getValue())) { + parameters.add(typeVariable(((GenericDataType) value).getName().getValue())); + } else { + parameters.add(typeParameter(toTypeSignature(value, typeVariables))); + } + } else { + throw new UnsupportedOperationException( + "Unsupported type parameter kind: " + parameter.getClass().getName()); + } + } + + return new TypeSignature(canonicalize(type.getName()), parameters.build()); + } + + private static String canonicalize(Identifier identifier) { + if (identifier.isDelimited()) { + return identifier.getValue(); + } + + return identifier + .getValue() + .toLowerCase(Locale.ENGLISH); // TODO: make this toUpperCase to match standard SQL semantics + } +} 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 15c481c5cea..a352ac017be 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 @@ -48,7 +48,7 @@ public abstract class CompareBinaryColumnTransformer extends BinaryColumnTransfo if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) { boolean flag = false; // compare binary type - if (TypeEnum.BINARY.equals(leftTransformer.getType().getTypeEnum())) { + if (TypeEnum.TEXT.equals(leftTransformer.getType().getTypeEnum())) { flag = transform( TransformUtils.compare( diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java index 6379ae04e9f..e7b31815f62 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java @@ -54,9 +54,9 @@ public abstract class CompareTernaryColumnTransformer extends TernaryColumnTrans if (firstColumnTransformer.isReturnTypeNumeric() && secondColumnTransformer.isReturnTypeNumeric() && thirdColumnTransformer.isReturnTypeNumeric() - || firstColumnTransformer.typeEquals(TypeEnum.BINARY) - && secondColumnTransformer.typeEquals(TypeEnum.BINARY) - && thirdColumnTransformer.typeEquals(TypeEnum.BINARY)) { + || firstColumnTransformer.typeEquals(TypeEnum.TEXT) + && secondColumnTransformer.typeEquals(TypeEnum.TEXT) + && thirdColumnTransformer.typeEquals(TypeEnum.TEXT)) { return; } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java index 23c7e6a5298..6aa7e0797c8 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java @@ -76,7 +76,7 @@ public class InColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, satisfy.of(column.getBoolean(i))); break; - case BINARY: + case TEXT: returnType.writeBoolean( columnBuilder, satisfy.of(column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET))); @@ -142,7 +142,7 @@ public class InColumnTransformer extends UnaryColumnTransformer { booleanSet.add(strictCastToBool(value)); } break; - case BINARY: + case TEXT: stringSet = values; break; default: diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java index eb48fa3ef79..f010008b695 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/RegularColumnTransformer.java @@ -58,7 +58,7 @@ public class RegularColumnTransformer extends UnaryColumnTransformer { @Override protected void checkType() { - if (!childColumnTransformer.typeEquals(TypeEnum.BINARY)) { + if (!childColumnTransformer.typeEquals(TypeEnum.TEXT)) { throw new UnsupportedOperationException( "Unsupported Type: " + childColumnTransformer.getType().getTypeEnum()); } 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 b1b9dac06fc..2d76882f42f 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 @@ -60,7 +60,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: cast(columnBuilder, childType.getBoolean(column, i)); break; - case BINARY: + case TEXT: cast(columnBuilder, childType.getBinary(column, i)); break; default: @@ -92,7 +92,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, value != 0); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, BytesUtils.valueOf(String.valueOf(value))); break; default: @@ -117,7 +117,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, value != 0L); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, BytesUtils.valueOf(String.valueOf(value))); break; default: @@ -142,7 +142,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, value != 0.0f); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, BytesUtils.valueOf(String.valueOf(value))); break; default: @@ -167,7 +167,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, value != 0.0); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, BytesUtils.valueOf(String.valueOf(value))); break; default: @@ -192,7 +192,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, value); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, BytesUtils.valueOf(String.valueOf(value))); break; default: @@ -218,7 +218,7 @@ public class CastFunctionColumnTransformer extends UnaryColumnTransformer { case BOOLEAN: returnType.writeBoolean(columnBuilder, CastFunctionHelper.castTextToBoolean(stringValue)); break; - case BINARY: + case TEXT: returnType.writeBinary(columnBuilder, value); break; default: diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java index 62ac6cae73c..486f18c761b 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java @@ -12,6 +12,9 @@ import org.apache.iotdb.db.queryengine.plan.relational.metadata.ResolvedFunction import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableHandle; import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadata; import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature; import org.apache.iotdb.tsfile.read.common.type.BinaryType; import org.apache.iotdb.tsfile.read.common.type.DoubleType; import org.apache.iotdb.tsfile.read.common.type.Type; @@ -106,4 +109,31 @@ public class TestMatadata implements Metadata { throws OperatorNotFoundException { return null; } + + @Override + public Type getOperatorReturnType(OperatorType operatorType, List<? extends Type> argumentTypes) + throws OperatorNotFoundException { + return null; + } + + @Override + public Type getFunctionReturnType(String functionName, List<? extends Type> argumentTypes) { + return null; + } + + @Override + public boolean isAggregationFunction( + SessionInfo session, String functionName, AccessControl accessControl) { + return false; + } + + @Override + public Type getType(TypeSignature signature) throws TypeNotFoundException { + return null; + } + + @Override + public boolean canCoerce(Type from, Type to) { + return false; + } } diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java index 19c9551942e..47febb3315e 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java +++ b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/BinaryType.java @@ -49,7 +49,7 @@ public class BinaryType implements Type { @Override public TypeEnum getTypeEnum() { - return TypeEnum.BINARY; + return TypeEnum.TEXT; } @Override diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java index ed3e7b99fe5..6d38bf6f1e8 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java +++ b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeEnum.java @@ -30,7 +30,7 @@ public enum TypeEnum { BOOLEAN, - BINARY, + TEXT, ROW, diff --git a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java index 7a82fdb8ae2..751e25a2169 100644 --- a/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java +++ b/iotdb-core/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/type/TypeFactory.java @@ -59,7 +59,7 @@ public class TypeFactory { return DoubleType.getInstance(); case BOOLEAN: return BooleanType.getInstance(); - case BINARY: + case TEXT: return BinaryType.getInstance(); case UNKNOWN: return UnknownType.getInstance();
