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 821f72ee78f9365f9fd7facc690868deef2ecc01 Merge: ae8e5fa6bbf c149aad8acb Author: JackieTien97 <[email protected]> AuthorDate: Tue Apr 9 18:22:24 2024 +0800 resolve conflicts .../common/header/ColumnHeaderConstant.java | 7 ++ .../common/header/DatasetHeaderFactory.java | 4 + .../iotdb/db/queryengine/plan/Coordinator.java | 2 - .../execution/config/TableConfigTaskVisitor.java | 14 +++- .../config/executor/ClusterConfigTaskExecutor.java | 97 ++++++++++++++++++++-- .../config/metadata/relational/CreateDBTask.java | 42 ++++++++++ .../config/metadata/relational/DropDBTask.java | 42 ++++++++++ .../config/metadata/relational/ShowDBTask.java | 82 ++++++++++++++++++ .../plan/relational/planner/LogicalPlanner.java | 29 ++++--- .../plan/relational/planner/QueryPlanner.java | 8 +- .../plan/relational/planner/RelationPlan.java | 7 +- .../plan/relational/planner/RelationPlanner.java | 4 +- .../relational/planner/RelationalModelPlanner.java | 24 ++++-- .../distribute/RelationalDistributionPlanner.java | 32 +++++++ .../plan/relational/analyzer/AnalyzerTest.java | 40 +++------ .../plan/relational/analyzer/TestMatadata.java | 34 ++++++-- 16 files changed, 396 insertions(+), 72 deletions(-) diff --cc iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java index 95436deea9e,e1b5f3af7d5..c42342c16cd --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java @@@ -22,14 -23,21 +23,17 @@@ import org.apache.iotdb.commons.excepti import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.QueryId; import org.apache.iotdb.db.queryengine.common.SessionInfo; + import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector; + import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan; -import org.apache.iotdb.db.queryengine.plan.relational.function.BoundSignature; -import org.apache.iotdb.db.queryengine.plan.relational.function.FunctionId; -import org.apache.iotdb.db.queryengine.plan.relational.function.FunctionKind; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnHandle; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema; 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.metadata.ResolvedFunction; import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableHandle; import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema; + import org.apache.iotdb.db.queryengine.plan.relational.planner.LogicalPlanner; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; import org.apache.iotdb.db.relational.sql.parser.SqlParser; import org.apache.iotdb.db.relational.sql.tree.Statement; diff --cc iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java index 993ed00ebda,1c37929bee0..0a8b6635ee7 --- 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 @@@ -1,9 -1,9 +1,12 @@@ package org.apache.iotdb.db.queryengine.plan.relational.analyzer; +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.BoundSignature; + import org.apache.iotdb.db.queryengine.plan.relational.function.FunctionId; + import org.apache.iotdb.db.queryengine.plan.relational.function.FunctionKind; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnHandle; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnMetadata; @@@ -15,14 -15,8 +18,14 @@@ import org.apache.iotdb.db.queryengine. 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.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.BinaryType; - import org.apache.iotdb.tsfile.read.common.type.DoubleType; + import org.apache.iotdb.tsfile.read.common.type.BooleanType; import org.apache.iotdb.tsfile.read.common.type.Type; import org.mockito.Mockito; @@@ -120,212 -107,27 +123,233 @@@ public class TestMatadata implements Me public ResolvedFunction resolveOperator( OperatorType operatorType, List<? extends Type> argumentTypes) throws OperatorNotFoundException { - return null; + if (operatorType == OperatorType.LESS_THAN) { + return new ResolvedFunction( + new BoundSignature("less_than", BooleanType.BOOLEAN, Arrays.asList(INT64, INT32)), + new FunctionId("less_than"), + FunctionKind.SCALAR, + true); + } else if (operatorType == OperatorType.ADD) { + return new ResolvedFunction( + new BoundSignature("add", INT64, Arrays.asList(INT64, INT32)), + new FunctionId("add"), + FunctionKind.SCALAR, + true); + } else if (operatorType == OperatorType.EQUAL) { + return new ResolvedFunction( + new BoundSignature( + "equals", BooleanType.BOOLEAN, Arrays.asList(BinaryType.TEXT, BinaryType.TEXT)), + new FunctionId("equals"), + FunctionKind.SCALAR, + true); + } else { + throw new OperatorNotFoundException(operatorType, argumentTypes, new RuntimeException()); + } } + + @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); + } }
