This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ty/IrExpressionInterpreter in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit fbea5bdbeb6114aa8724dbd53d5cd868da05941b Author: JackieTien97 <[email protected]> AuthorDate: Tue Aug 27 21:12:28 2024 +0800 init --- .../relational/ColumnTransformerBuilder.java | 38 +- .../InterpretedFunctionInvoker.java} | 18 +- .../FunctionManager.java} | 21 +- .../planner/IrExpressionInterpreter.java | 93 ++++ .../plan/relational/planner/IrTypeAnalyzer.java | 491 +++++++++++++++++++++ .../plan/relational/planner/LiteralEncoder.java | 126 ++++++ .../relational/planner/LiteralInterpreter.java | 112 +++++ .../plan/relational/planner/PlannerContext.java | 4 + .../AllowAllAccessControl.java} | 18 +- .../plan/relational/sql/ast/BinaryLiteral.java | 9 + .../plan/relational/sql/ast/DoubleLiteral.java | 5 + .../type/{TypeManager.java => TypeCoercion.java} | 20 +- .../plan/relational/type/TypeManager.java | 2 +- .../relational/type/TypeNotFoundException.java | 4 +- .../relational/type/TypeSignatureTranslator.java | 7 + 15 files changed, 907 insertions(+), 61 deletions(-) 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 bdaa1f2ea1c..0a0bae7629a 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 @@ -41,6 +41,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DecimalLiteral; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate; @@ -152,6 +153,8 @@ import org.apache.tsfile.read.common.block.column.BooleanColumn; import org.apache.tsfile.read.common.block.column.DoubleColumn; import org.apache.tsfile.read.common.block.column.IntColumn; import org.apache.tsfile.read.common.block.column.LongColumn; +import org.apache.tsfile.read.common.type.DateType; +import org.apache.tsfile.read.common.type.TimestampType; import org.apache.tsfile.read.common.type.Type; import org.apache.tsfile.read.common.type.TypeEnum; import org.apache.tsfile.utils.Binary; @@ -427,6 +430,37 @@ public class ColumnTransformerBuilder throw new UnsupportedOperationException(); } + @Override + protected ColumnTransformer visitGenericLiteral(GenericLiteral node, Context context) { + ColumnTransformer res = + context.cache.computeIfAbsent( + node, + e -> { + ConstantColumnTransformer columnTransformer = getColumnTransformerForGenericLiteral(node); + context.leafList.add(columnTransformer); + return columnTransformer; + }); + res.addReferenceCount(); + return res; + } + + // currently, we only support Date and Timestamp + // for Date, GenericLiteral.value is an int value + // for Timestamp, GenericLiteral.value is a long value + private static ConstantColumnTransformer getColumnTransformerForGenericLiteral(GenericLiteral literal) { + if (DateType.DATE.getTypeEnum().name().equals(literal.getType())) { + return new ConstantColumnTransformer( + DateType.DATE, + new IntColumn(1, Optional.empty(), new int[] {Integer.parseInt(literal.getValue())})); + } else if (TimestampType.TIMESTAMP.getTypeEnum().name().equals(literal.getType())) { + return new ConstantColumnTransformer( + TimestampType.TIMESTAMP, + new LongColumn(1, Optional.empty(), new long[] {Long.parseLong(literal.getValue())})); + } else { + throw new IllegalArgumentException("Unsupported type in GenericLiteral: " + literal.getType()); + } + } + @Override protected ColumnTransformer visitNullLiteral(NullLiteral node, Context context) { ColumnTransformer res = @@ -982,7 +1016,7 @@ public class ColumnTransformerBuilder case DATE: Set<Integer> dateSet = new HashSet<>(); for (Literal value : values) { - dateSet.add(DateUtils.parseDateExpressionToInt(((StringLiteral) value).getValue())); + dateSet.add(Integer.parseInt(((GenericLiteral) value).getValue())); } return new InInt32MultiColumnTransformer(dateSet, valueColumnTransformerList); case INT64: @@ -990,7 +1024,7 @@ public class ColumnTransformerBuilder Set<Long> longSet = new HashSet<>(); for (Literal value : values) { try { - longSet.add((((LongLiteral) value).getParsedValue())); + longSet.add(Long.parseLong(((GenericLiteral) value).getValue())); } catch (IllegalArgumentException e) { throw new SemanticException(String.format(errorMsg, value, childType)); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java similarity index 62% copy from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java index 1830db19e19..6f370c35e46 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/function/InterpretedFunctionInvoker.java @@ -17,21 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.queryengine.plan.relational.type; +package org.apache.iotdb.db.queryengine.plan.relational.function; -import org.apache.tsfile.read.common.type.Type; - -public interface TypeManager { - /** - * Gets the type with the specified signature. - * - * @throws TypeNotFoundException if not found - */ - Type getType(TypeSignature signature) throws TypeNotFoundException; - - /** Gets a type given it's SQL representation */ - Type fromSqlType(String type); - - /** Gets the type with the give (opaque) id */ - Type getType(TypeId id); +public class InterpretedFunctionInvoker { } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java similarity index 62% copy from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java index 1830db19e19..8d8819f8f5b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/FunctionManager.java @@ -17,21 +17,16 @@ * under the License. */ -package org.apache.iotdb.db.queryengine.plan.relational.type; +package org.apache.iotdb.db.queryengine.plan.relational.metadata; -import org.apache.tsfile.read.common.type.Type; +import static java.util.Objects.requireNonNull; -public interface TypeManager { - /** - * Gets the type with the specified signature. - * - * @throws TypeNotFoundException if not found - */ - Type getType(TypeSignature signature) throws TypeNotFoundException; +public class FunctionManager { - /** Gets a type given it's SQL representation */ - Type fromSqlType(String type); + private final FunctionManager functionManager; + + public InterpretedFunctionInvoker(FunctionManager functionManager) { + this.functionManager = requireNonNull(functionManager, "functionManager is null"); + } - /** Gets the type with the give (opaque) id */ - Type getType(TypeId id); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java new file mode 100644 index 00000000000..4afe56c93c9 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java @@ -0,0 +1,93 @@ +/* + * 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.planner; + +import com.google.common.collect.ImmutableMap; +import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider; +import org.apache.iotdb.db.queryengine.plan.relational.analyzer.NodeRef; +import org.apache.iotdb.db.queryengine.plan.relational.function.InterpretedFunctionInvoker; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression; +import org.apache.iotdb.db.queryengine.plan.relational.type.TypeCoercion; +import org.apache.tsfile.read.common.type.Type; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Verify.verify; +import static java.util.Objects.requireNonNull; + +public class IrExpressionInterpreter { + + private final Expression expression; + private final PlannerContext plannerContext; + private final Metadata metadata; + private final LiteralInterpreter literalInterpreter; + private final LiteralEncoder literalEncoder; + private final SessionInfo session; + private final Map<NodeRef<Expression>, Type> expressionTypes; + private final InterpretedFunctionInvoker functionInvoker; + private final TypeCoercion typeCoercion; + + private final IdentityHashMap<InListExpression, Set<?>> inListCache = new IdentityHashMap<>(); + + + public IrExpressionInterpreter(Expression expression, PlannerContext plannerContext, SessionInfo session, Map<NodeRef<Expression>, Type> expressionTypes) + { + this.expression = requireNonNull(expression, "expression is null"); + this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); + this.metadata = plannerContext.getMetadata(); + this.literalInterpreter = new LiteralInterpreter(plannerContext, session); + this.literalEncoder = new LiteralEncoder(plannerContext); + this.session = requireNonNull(session, "session is null"); + this.expressionTypes = ImmutableMap.copyOf(requireNonNull(expressionTypes, "expressionTypes is null")); + verify(expressionTypes.containsKey(NodeRef.of(expression))); + this.functionInvoker = new InterpretedFunctionInvoker(plannerContext.getFunctionManager()); + this.typeCoercion = new TypeCoercion(plannerContext.getTypeManager()::getType); + } + + public static Object evaluateConstantExpression(Expression expression, PlannerContext plannerContext, SessionInfo session) + { + Map<NodeRef<Expression>, Type> types = new IrTypeAnalyzer(plannerContext).getTypes(session, TypeProvider.empty(), expression); + return new IrExpressionInterpreter(expression, plannerContext, session, types).evaluate(); + } + + public Object evaluate() + { + Object result = new Visitor(false).processWithExceptionHandling(expression, null); + verify(!(result instanceof Expression), "Expression interpreter returned an unresolved expression"); + return result; + } + + public Object evaluate(SymbolResolver inputs) + { + Object result = new Visitor(false).processWithExceptionHandling(expression, inputs); + verify(!(result instanceof Expression), "Expression interpreter returned an unresolved expression"); + return result; + } + + public Object optimize(SymbolResolver inputs) + { + return new Visitor(true).processWithExceptionHandling(expression, inputs); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java new file mode 100644 index 00000000000..f9c58c5e7ef --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java @@ -0,0 +1,491 @@ +/* + * 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.planner; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +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.analyzer.NodeRef; +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.OperatorNotFoundException; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.security.AllowAllAccessControl; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticBinaryExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticUnaryExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BetweenPredicate; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Cast; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CoalesceExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNotNullPredicate; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNullPredicate; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullIfExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SearchedCaseExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SimpleCaseExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference; +import org.apache.tsfile.read.common.type.BlobType; +import org.apache.tsfile.read.common.type.StringType; +import org.apache.tsfile.read.common.type.Type; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.collect.ImmutableList.toImmutableList; +import static java.lang.Math.toIntExact; +import static java.util.Objects.requireNonNull; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature; +import static org.apache.tsfile.read.common.type.BooleanType.BOOLEAN; +import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE; +import static org.apache.tsfile.read.common.type.IntType.INT32; +import static org.apache.tsfile.read.common.type.LongType.INT64; +import static org.apache.tsfile.read.common.type.UnknownType.UNKNOWN; + +public class IrTypeAnalyzer { + + private final PlannerContext plannerContext; + + public IrTypeAnalyzer(PlannerContext plannerContext) { + this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); + } + + + public Map<NodeRef<Expression>, Type> getTypes(SessionInfo session, TypeProvider inputTypes, Iterable<Expression> expressions) + { + Visitor visitor = new Visitor(plannerContext, session, inputTypes); + + for (Expression expression : expressions) { + visitor.process(expression, new Context(ImmutableMap.of())); + } + + return visitor.getTypes(); + } + + public Map<NodeRef<Expression>, Type> getTypes(SessionInfo session, TypeProvider inputTypes, Expression expression) + { + return getTypes(session, inputTypes, ImmutableList.of(expression)); + } + + public Type getType(SessionInfo session, TypeProvider inputTypes, Expression expression) + { + return getTypes(session, inputTypes, expression).get(NodeRef.of(expression)); + } + + private static class Visitor + extends AstVisitor<Type, Context> + { + private static final AccessControl ALLOW_ALL_ACCESS_CONTROL = new AllowAllAccessControl(); + + private final PlannerContext plannerContext; + private final SessionInfo session; + private final TypeProvider symbolTypes; + private final FunctionResolver functionResolver; + + // Cache from SQL type name to Type; every Type in the cache has a CAST defined from VARCHAR + private final Cache<String, Type> varcharCastableTypeCache = buildNonEvictableCache(CacheBuilder.newBuilder().maximumSize(1000)); + + private final Map<NodeRef<Expression>, Type> expressionTypes = new LinkedHashMap<>(); + + public Visitor(PlannerContext plannerContext, SessionInfo session, TypeProvider symbolTypes) + { + this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); + this.session = requireNonNull(session, "session is null"); + this.symbolTypes = requireNonNull(symbolTypes, "symbolTypes is null"); + this.functionResolver = plannerContext.getFunctionResolver(WarningCollector.NOOP); + } + + public Map<NodeRef<Expression>, Type> getTypes() + { + return expressionTypes; + } + + private Type setExpressionType(Expression expression, Type type) + { + requireNonNull(expression, "expression cannot be null"); + requireNonNull(type, "type cannot be null"); + + expressionTypes.put(NodeRef.of(expression), type); + return type; + } + + @Override + public Type process(Node node, Context context) + { + if (node instanceof Expression) { + // don't double process a node + Type type = expressionTypes.get(NodeRef.of(((Expression) node))); + if (type != null) { + return type; + } + } + return super.process(node, context); + } + + + @Override + protected Type visitSymbolReference(SymbolReference node, Context context) + { + Symbol symbol = Symbol.from(node); + Type type = context.getArgumentTypes().get(symbol); + if (type == null) { + type = symbolTypes.getTableModelType(symbol); + } + checkArgument(type != null, "No type for: %s", node.getName()); + return setExpressionType(node, type); + } + + @Override + protected Type visitNotExpression(NotExpression node, Context context) + { + process(node.getValue(), context); + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitLogicalExpression(LogicalExpression node, Context context) + { + node.getTerms().forEach(term -> process(term, context)); + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitComparisonExpression(ComparisonExpression node, Context context) + { + process(node.getLeft(), context); + process(node.getRight(), context); + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitIsNullPredicate(IsNullPredicate node, Context context) + { + process(node.getValue(), context); + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitIsNotNullPredicate(IsNotNullPredicate node, Context context) + { + process(node.getValue(), context); + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitNullIfExpression(NullIfExpression node, Context context) + { + Type firstType = process(node.getFirst(), context); + Type ignored = process(node.getSecond(), context); + + // TODO: + // NULLIF(v1, v2) = IF(v1 = v2, v1) + // In order to compare v1 and v2, they need to have the same (coerced) type, but + // the result of NULLIF should be the same as v1. It's currently not possible + // to represent this in the IR, so we allow the types to be different for now and + // rely on the execution layer to insert the necessary casts. + + return setExpressionType(node, firstType); + } + + @Override + protected Type visitIfExpression(IfExpression node, Context context) + { + Type conditionType = process(node.getCondition(), context); + checkArgument(conditionType.equals(BOOLEAN), "Condition must be boolean: %s", conditionType); + + Type trueType = process(node.getTrueValue(), context); + if (node.getFalseValue().isPresent()) { + Type falseType = process(node.getFalseValue().get(), context); + checkArgument(trueType.equals(falseType), "Types must be equal: %s vs %s", trueType, falseType); + } + + return setExpressionType(node, trueType); + } + + @Override + protected Type visitSearchedCaseExpression(SearchedCaseExpression node, Context context) + { + Set<Type> resultTypes = node.getWhenClauses().stream() + .map(clause -> { + Type operandType = process(clause.getOperand(), context); + checkArgument(operandType.equals(BOOLEAN), "When clause operand must be boolean: %s", operandType); + return setExpressionType(clause, process(clause.getResult(), context)); + }) + .collect(Collectors.toSet()); + + checkArgument(resultTypes.size() == 1, "All result types must be the same: %s", resultTypes); + Type resultType = resultTypes.iterator().next(); + node.getDefaultValue().ifPresent(defaultValue -> { + Type defaultType = process(defaultValue, context); + checkArgument(defaultType.equals(resultType), "Default result type must be the same as WHEN result types: %s vs %s", defaultType, resultType); + }); + + return setExpressionType(node, resultType); + } + + @Override + protected Type visitSimpleCaseExpression(SimpleCaseExpression node, Context context) + { + Type operandType = process(node.getOperand(), context); + + Set<Type> resultTypes = node.getWhenClauses().stream() + .map(clause -> { + Type clauseOperandType = process(clause.getOperand(), context); + checkArgument(clauseOperandType.equals(operandType), "WHEN clause operand type must match CASE operand type: %s vs %s", clauseOperandType, operandType); + return setExpressionType(clause, process(clause.getResult(), context)); + }) + .collect(Collectors.toSet()); + + checkArgument(resultTypes.size() == 1, "All result types must be the same: %s", resultTypes); + Type resultType = resultTypes.iterator().next(); + node.getDefaultValue().ifPresent(defaultValue -> { + Type defaultType = process(defaultValue, context); + checkArgument(defaultType.equals(resultType), "Default result type must be the same as WHEN result types: %s vs %s", defaultType, resultType); + }); + + return setExpressionType(node, resultType); + } + + @Override + protected Type visitCoalesceExpression(CoalesceExpression node, Context context) + { + Set<Type> types = node.getOperands().stream() + .map(operand -> process(operand, context)) + .collect(Collectors.toSet()); + + checkArgument(types.size() == 1, "All operands must have the same type: %s", types); + return setExpressionType(node, types.iterator().next()); + } + + @Override + protected Type visitArithmeticUnary(ArithmeticUnaryExpression node, Context context) + { + return setExpressionType(node, process(node.getValue(), context)); + } + + @Override + protected Type visitArithmeticBinary(ArithmeticBinaryExpression node, Context context) + { + ImmutableList.Builder<Type> argumentTypes = ImmutableList.builder(); + argumentTypes.add(process(node.getLeft(), context)); + argumentTypes.add(process(node.getRight(), context)); + + try { + return setExpressionType(node, plannerContext.getMetadata().getOperatorReturnType(OperatorType.valueOf(node.getOperator().name()), argumentTypes.build())); + } catch (OperatorNotFoundException e) { + throw new SemanticException(e.getMessage()); + } + } + + @Override + protected Type visitStringLiteral(StringLiteral node, Context context) + { + return setExpressionType(node, StringType.STRING); + } + + @Override + protected Type visitBinaryLiteral(BinaryLiteral node, Context context) + { + return setExpressionType(node, BlobType.BLOB); + } + + @Override + protected Type visitLongLiteral(LongLiteral node, Context context) + { + if (node.getParsedValue() >= Integer.MIN_VALUE && node.getParsedValue() <= Integer.MAX_VALUE) { + return setExpressionType(node, INT32); + } + + return setExpressionType(node, INT64); + } + + @Override + protected Type visitDoubleLiteral(DoubleLiteral node, Context context) + { + return setExpressionType(node, DOUBLE); + } + + @Override + protected Type visitBooleanLiteral(BooleanLiteral node, Context context) + { + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitGenericLiteral(GenericLiteral node, Context context) + { + return setExpressionType( + node, + switch (node.getType()) { + case String name when name.equalsIgnoreCase("CHAR") -> CharType.createCharType(node.getValue().length()); + case String name when name.equalsIgnoreCase("TIMESTAMP") && timestampHasTimeZone(node.getValue()) -> createTimestampWithTimeZoneType(extractTimestampPrecision(node.getValue())); + case String name when name.equalsIgnoreCase("TIMESTAMP") -> createTimestampType(extractTimestampPrecision(node.getValue())); + case String name when name.equalsIgnoreCase("TIME") && timeHasTimeZone(node.getValue()) -> createTimeWithTimeZoneType(extractTimePrecision(node.getValue())); + case String name when name.equalsIgnoreCase("TIME") -> createTimeType(extractTimePrecision(node.getValue())); + default -> uncheckedCacheGet(varcharCastableTypeCache, node.getType(), () -> plannerContext.getTypeManager().fromSqlType(node.getType())); + }); + } + + @Override + protected Type visitNullLiteral(NullLiteral node, Context context) + { + return setExpressionType(node, UNKNOWN); + } + + @Override + protected Type visitFunctionCall(FunctionCall node, Context context) + { + // Function should already be resolved in IR + ResolvedFunction function = functionResolver.resolveFunction(session, node.getName(), null, ALLOW_ALL_ACCESS_CONTROL); + + BoundSignature signature = function.getSignature(); + for (int i = 0; i < node.getArguments().size(); i++) { + Expression argument = node.getArguments().get(i); + Type formalType = signature.getArgumentTypes().get(i); + + Type unused = switch (argument) { + case LambdaExpression lambda -> processLambdaExpression(lambda, ((FunctionType) formalType).getArgumentTypes()); + case BindExpression bind -> processBindExpression(bind, (FunctionType) formalType, context); + default -> process(argument, context); + }; + + // TODO + // checkArgument(actualType.equals(formalType), "Actual and formal argument types do not match: %s vs %s", actualType, formalType); + } + + return setExpressionType(node, signature.getReturnType()); + } + + private Type processBindExpression(BindExpression bind, FunctionType formalType, Context context) + { + List<Type> argumentTypes = new ArrayList<>(); + + argumentTypes.addAll(bind.getValues().stream() + .map(value -> process(value, context)) + .collect(toImmutableList())); + + argumentTypes.addAll(formalType.getArgumentTypes()); + + if (bind.getFunction() instanceof LambdaExpression) { + Type unused = processLambdaExpression((LambdaExpression) bind.getFunction(), argumentTypes); + // TODO: validate actual type and expected type are the same + return setExpressionType(bind, formalType); + } + + throw new UnsupportedOperationException("not yet implemented"); + } + + private Type processLambdaExpression(LambdaExpression lambda, List<Type> argumentTypes) + { + ImmutableMap.Builder<Symbol, Type> typeBindings = ImmutableMap.builder(); + for (int i = 0; i < argumentTypes.size(); i++) { + typeBindings.put( + new Symbol(lambda.getArguments().get(i).getName().getValue()), + argumentTypes.get(i)); + } + + Type returnType = process(lambda.getBody(), new Context(typeBindings.buildOrThrow())); + return setExpressionType(lambda, new FunctionType(argumentTypes, returnType)); + } + + @Override + protected Type visitBetweenPredicate(BetweenPredicate node, Context context) + { + process(node.getValue(), context); + process(node.getMin(), context); + process(node.getMax(), context); + + return setExpressionType(node, BOOLEAN); + } + + @Override + public Type visitCast(Cast node, Context context) + { + process(node.getExpression(), context); + return setExpressionType(node, plannerContext.getTypeManager().getType(toTypeSignature(node.getType()))); + } + + @Override + protected Type visitInPredicate(InPredicate node, Context context) + { + Expression value = node.getValue(); + InListExpression valueList = (InListExpression) node.getValueList(); + + Type type = process(value, context); + for (Expression item : valueList.getValues()) { + Type itemType = process(item, context); + checkArgument(itemType.equals(type), "Types must be equal: %s vs %s", itemType, type); + } + + setExpressionType(valueList, type); + + return setExpressionType(node, BOOLEAN); + } + + @Override + protected Type visitExpression(Expression node, Context context) + { + throw new UnsupportedOperationException("Not a valid IR expression: " + node.getClass().getName()); + } + + @Override + protected Type visitNode(Node node, Context context) + { + throw new UnsupportedOperationException("Not a valid IR expression: " + node.getClass().getName()); + } + } + + private static class Context { + private final Map<Symbol, Type> argumentTypes; + + public Context(Map<Symbol, Type> argumentTypes) { + this.argumentTypes = argumentTypes; + } + + public Map<Symbol, Type> getArgumentTypes() { + return argumentTypes; + } + } + +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java new file mode 100644 index 00000000000..c8d88f66be8 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralEncoder.java @@ -0,0 +1,126 @@ +/* + * 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.planner; + +import com.google.common.collect.ImmutableList; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Cast; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral; +import org.apache.tsfile.common.conf.TSFileConfig; +import org.apache.tsfile.read.common.type.DateType; +import org.apache.tsfile.read.common.type.TimestampType; +import org.apache.tsfile.read.common.type.Type; +import org.apache.tsfile.read.common.type.UnknownType; +import org.apache.tsfile.utils.Binary; + +import java.util.List; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; +import static org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isBlobType; +import static org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isBool; +import static org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl.isCharType; +import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toSqlType; +import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE; +import static org.apache.tsfile.read.common.type.FloatType.FLOAT; +import static org.apache.tsfile.read.common.type.IntType.INT32; +import static org.apache.tsfile.read.common.type.LongType.INT64; + +public final class LiteralEncoder { + + private final PlannerContext plannerContext; + + public LiteralEncoder(PlannerContext plannerContext) { + this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); + } + + public List<Expression> toExpressions(List<?> objects, List<? extends Type> types) { + requireNonNull(objects, "objects is null"); + requireNonNull(types, "types is null"); + checkArgument(objects.size() == types.size(), "objects and types do not have the same size"); + + ImmutableList.Builder<Expression> expressions = ImmutableList.builder(); + for (int i = 0; i < objects.size(); i++) { + Object object = objects.get(i); + Type type = types.get(i); + expressions.add(toExpression(object, type)); + } + return expressions.build(); + } + + public Expression toExpression(@Nullable Object object, Type type) { + requireNonNull(type, "type is null"); + + if (object instanceof Expression) { + return (Expression) object; + } + + if (object == null) { + if (type.equals(UnknownType.UNKNOWN)) { + return new NullLiteral(); + } + return new Cast(new NullLiteral(), toSqlType(type), false); + } + + + if (type.equals(INT32) || type.equals(INT64)) { + return new LongLiteral(object.toString()); + } + + + if (type.equals(FLOAT) || type.equals(DOUBLE)) { + Double value = (Double) object; + return new DoubleLiteral(value); + } + + if (isBool(type)) { + return new BooleanLiteral(object.toString()); + } + + if (isCharType(type)) { + Binary value = (Binary) object; + return new StringLiteral(value.getStringValue(TSFileConfig.STRING_CHARSET)); + } + + if (isBlobType(type)) { + Binary value = (Binary) object; + return new BinaryLiteral(value.getValues()); + } + + + if (type.equals(DateType.DATE)) { + return new GenericLiteral(DateType.DATE.getTypeEnum().name(), ((Integer) object).toString()); + } + + if (type.equals(TimestampType.TIMESTAMP)) { + return new GenericLiteral(TimestampType.TIMESTAMP.getTypeEnum().name(), object.toString()); + } + + throw new IllegalArgumentException("Unknown type: " + type); + } + +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java new file mode 100644 index 00000000000..0e2e5936129 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/LiteralInterpreter.java @@ -0,0 +1,112 @@ +/* + * 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.planner; + +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.GenericLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral; +import org.apache.tsfile.common.conf.TSFileConfig; +import org.apache.tsfile.read.common.type.DateType; +import org.apache.tsfile.read.common.type.TimestampType; +import org.apache.tsfile.read.common.type.Type; +import org.apache.tsfile.utils.Binary; + +import static java.util.Objects.requireNonNull; + +public class LiteralInterpreter { + + private final PlannerContext plannerContext; + private final SessionInfo session; + + public LiteralInterpreter(PlannerContext plannerContext, SessionInfo session) { + this.plannerContext = requireNonNull(plannerContext, "plannerContext is null"); + this.session = session; + } + + public Object evaluate(Expression node, Type type) { + if (!(node instanceof Literal)) { + throw new IllegalArgumentException("node must be a Literal"); + } + return new LiteralVisitor(type).process(node, null); + } + + private class LiteralVisitor extends AstVisitor<Object, Void> { + private final Type type; + + private LiteralVisitor(Type type) { + this.type = requireNonNull(type, "type is null"); + } + + @Override + protected Object visitLiteral(Literal node, Void context) { + throw new UnsupportedOperationException("Unhandled literal type: " + node); + } + + @Override + protected Object visitBooleanLiteral(BooleanLiteral node, Void context) { + return node.getValue(); + } + + @Override + protected Long visitLongLiteral(LongLiteral node, Void context) { + return node.getParsedValue(); + } + + @Override + protected Double visitDoubleLiteral(DoubleLiteral node, Void context) { + return node.getValue(); + } + + @Override + protected Binary visitStringLiteral(StringLiteral node, Void context) { + return new Binary(node.getValue(), TSFileConfig.STRING_CHARSET); + } + + @Override + protected Binary visitBinaryLiteral(BinaryLiteral node, Void context) { + return new Binary(node.getValue()); + } + + @Override + protected Object visitGenericLiteral(GenericLiteral node, Void context) { + if (type.equals(TimestampType.TIMESTAMP)) { + return Long.parseLong(node.getValue()); + } else if (type.equals(DateType.DATE)) { + return Integer.parseInt(node.getValue()); + } else { + throw new SemanticException(String.format("No literal form for type %s", type)); + } + } + + @Override + protected Object visitNullLiteral(NullLiteral node, Void context) { + return null; + } + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java index 7fb3a2cb59e..094d417a74b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlannerContext.java @@ -41,4 +41,8 @@ public class PlannerContext { public Metadata getMetadata() { return metadata; } + + public TypeManager getTypeManager() { + return typeManager; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java similarity index 62% copy from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java index 1830db19e19..947d553c508 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java @@ -17,21 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.queryengine.plan.relational.type; +package org.apache.iotdb.db.queryengine.plan.relational.security; -import org.apache.tsfile.read.common.type.Type; - -public interface TypeManager { - /** - * Gets the type with the specified signature. - * - * @throws TypeNotFoundException if not found - */ - Type getType(TypeSignature signature) throws TypeNotFoundException; - - /** Gets a type given it's SQL representation */ - Type fromSqlType(String type); - - /** Gets the type with the give (opaque) id */ - Type getType(TypeId id); +public class AllowAllAccessControl implements AccessControl { } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java index 22aa5c8107b..c7011205960 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/BinaryLiteral.java @@ -55,6 +55,15 @@ public class BinaryLiteral extends Literal { this.value = BaseEncoding.base16().decode(hexString); } + public BinaryLiteral(byte[] value) { + super(null); + requireNonNull(value, "value is null"); + if (value.length % 2 != 0) { + throw new ParsingException("Binary literal must contain an even number of digits"); + } + this.value = value; + } + public BinaryLiteral(NodeLocation location, String value) { super(requireNonNull(location, "location is null")); requireNonNull(value, "value is null"); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java index d7916148a6c..cf2fa708326 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DoubleLiteral.java @@ -36,6 +36,11 @@ public class DoubleLiteral extends Literal { this.value = Double.parseDouble(requireNonNull(value, "value is null")); } + public DoubleLiteral(double value) { + super(null); + this.value = value; + } + public DoubleLiteral(NodeLocation location, String value) { super(requireNonNull(location, "location is null")); this.value = Double.parseDouble(requireNonNull(value, "value is null")); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java similarity index 71% copy from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java copy to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java index 1830db19e19..f6105f579b1 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeCoercion.java @@ -21,17 +21,15 @@ package org.apache.iotdb.db.queryengine.plan.relational.type; import org.apache.tsfile.read.common.type.Type; -public interface TypeManager { - /** - * Gets the type with the specified signature. - * - * @throws TypeNotFoundException if not found - */ - Type getType(TypeSignature signature) throws TypeNotFoundException; +import java.util.function.Function; - /** Gets a type given it's SQL representation */ - Type fromSqlType(String type); +import static java.util.Objects.requireNonNull; + +public class TypeCoercion { + private final Function<TypeSignature, Type> lookupType; + + public TypeCoercion(Function<TypeSignature, Type> lookupType) { + this.lookupType = requireNonNull(lookupType, "lookupType is null"); + } - /** Gets the type with the give (opaque) id */ - Type getType(TypeId id); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java index 1830db19e19..a39947aa4d3 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeManager.java @@ -27,7 +27,7 @@ public interface TypeManager { * * @throws TypeNotFoundException if not found */ - Type getType(TypeSignature signature) throws TypeNotFoundException; + Type getType(TypeSignature signature); /** Gets a type given it's SQL representation */ Type fromSqlType(String type); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java index 20d7281abf8..99df1101bda 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/type/TypeNotFoundException.java @@ -19,12 +19,12 @@ package org.apache.iotdb.db.queryengine.plan.relational.type; -import org.apache.iotdb.commons.exception.IoTDBException; +import org.apache.iotdb.commons.exception.IoTDBRuntimeException; import static java.util.Objects.requireNonNull; import static org.apache.iotdb.rpc.TSStatusCode.TYPE_NOT_FOUND; -public class TypeNotFoundException extends IoTDBException { +public class TypeNotFoundException extends IoTDBRuntimeException { private final TypeSignature 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 index 6cfcc5d81a8..03eff294b31 100644 --- 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 @@ -28,9 +28,11 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NumericParameter; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.TypeParameter; import com.google.common.collect.ImmutableList; +import org.apache.tsfile.read.common.type.Type; import java.util.Collections; import java.util.Locale; +import java.util.Optional; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; @@ -42,6 +44,11 @@ public class TypeSignatureTranslator { private TypeSignatureTranslator() {} + public static DataType toSqlType(Type type) + { + return new GenericDataType(new Identifier(type.getTypeEnum().name(), false), Collections.emptyList()); + } + public static TypeSignature toTypeSignature(DataType type) { return toTypeSignature(type, Collections.emptySet()); }
