This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ty/SupportConstant in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 0c128298bc99343ed5e843d96b090289f1b55233 Author: JackieTien97 <[email protected]> AuthorDate: Wed Aug 14 18:46:16 2024 +0800 Support constant value in select clause --- .../query/recent/IoTDBConstantInSelectTableIT.java | 96 ++++++++++++++++++++++ .../relational/ColumnTransformerBuilder.java | 20 ++++- .../plan/planner/TableOperatorGenerator.java | 3 + .../relational/planner/ir/ExpressionRewriter.java | 9 +- .../planner/ir/ExpressionTreeRewriter.java | 8 ++ 5 files changed, 129 insertions(+), 7 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java new file mode 100644 index 00000000000..1dae45a92d0 --- /dev/null +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java @@ -0,0 +1,96 @@ +/* + * 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.relational.it.query.recent; + +import org.apache.iotdb.it.env.EnvFactory; +import org.apache.iotdb.it.framework.IoTDBTestRunner; +import org.apache.iotdb.itbase.category.ClusterIT; +import org.apache.iotdb.itbase.category.LocalStandaloneIT; +import org.apache.iotdb.itbase.env.BaseEnv; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; + +import static org.apache.iotdb.db.it.utils.TestUtils.defaultFormatDataTime; +import static org.apache.iotdb.db.it.utils.TestUtils.prepareTableData; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(IoTDBTestRunner.class) +@Category({LocalStandaloneIT.class, ClusterIT.class}) +public class IoTDBConstantInSelectTableIT { + private static final String DATABASE_NAME = "test"; + private static final String[] createSqls = + new String[] { + "CREATE DATABASE " + DATABASE_NAME, + "USE " + DATABASE_NAME, + "CREATE TABLE table1(id1 STRING ID, id2 STRING ID, s1 INT32 MEASUREMENT, s2 BOOLEAN MEASUREMENT, s3 DOUBLE MEASUREMENT)", + "INSERT INTO table1(time,id1,id2,s1,s2,s3) " + "values(1, null, null, 0, false, 11.1)", + }; + + @BeforeClass + public static void setUp() throws Exception { + EnvFactory.getEnv().initClusterEnvironment(); + prepareTableData(createSqls); + } + + @AfterClass + public static void tearDown() throws Exception { + EnvFactory.getEnv().cleanClusterEnvironment(); + } + + @Test + public void constantInSelectTest() throws Exception { + final String result = defaultFormatDataTime(1) + ",null,null,0,false,11.1,1"; + try (final Connection connectionIsNull = + EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); + final Statement statement = connectionIsNull.createStatement()) { + statement.execute("USE " + DATABASE_NAME); + + ResultSet resultSet = statement.executeQuery("select *, 1 from table1"); + assertTrue(resultSet.next()); + String ans = + resultSet.getString("time") + + "," + + resultSet.getString("id1") + + "," + + resultSet.getString("id2") + + "," + + resultSet.getString("s1") + + "," + + resultSet.getString("s2") + + "," + + resultSet.getString("s3") + + "," + + resultSet.getString("_col6"); + + assertEquals(result, ans); + assertFalse(resultSet.next()); + } + } +} 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 a16994cf35a..e9133b118cc 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 @@ -102,6 +102,7 @@ import org.apache.tsfile.enums.TSDataType; import org.apache.tsfile.read.common.block.column.BinaryColumn; 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.Type; import org.apache.tsfile.utils.Binary; @@ -119,6 +120,7 @@ import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature import static org.apache.tsfile.read.common.type.BlobType.BLOB; 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.StringType.STRING; import static org.apache.tsfile.utils.RegexUtils.compileRegex; @@ -330,10 +332,20 @@ public class ColumnTransformerBuilder context.cache.computeIfAbsent( node, e -> { - ConstantColumnTransformer columnTransformer = - new ConstantColumnTransformer( - INT64, - new LongColumn(1, Optional.empty(), new long[] {node.getParsedValue()})); + ConstantColumnTransformer columnTransformer; + if (node.getParsedValue() >= Integer.MIN_VALUE + && node.getParsedValue() <= Integer.MAX_VALUE) { + columnTransformer = + new ConstantColumnTransformer( + INT32, + new IntColumn( + 1, Optional.empty(), new int[] {(int) node.getParsedValue()})); + } else { + columnTransformer = + new ConstantColumnTransformer( + INT64, + new LongColumn(1, Optional.empty(), new long[] {node.getParsedValue()})); + } context.leafList.add(columnTransformer); return columnTransformer; }); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java index 29086a7f6b7..a2519314266 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java @@ -356,6 +356,7 @@ public class TableOperatorGenerator extends PlanVisitor<Operator, LocalExecution predicate, inputOperator, node.getOutputSymbols().stream().map(Symbol::toSymbolReference).toArray(Expression[]::new), + node.getOutputSymbols(), inputDataTypes, inputLocations, node.getPlanNodeId(), @@ -366,6 +367,7 @@ public class TableOperatorGenerator extends PlanVisitor<Operator, LocalExecution Optional<Expression> predicate, Operator inputOperator, Expression[] projectExpressions, + List<Symbol> projectSymbols, List<TSDataType> inputDataTypes, Map<Symbol, List<InputLocation>> inputLocations, PlanNodeId planNodeId, @@ -476,6 +478,7 @@ public class TableOperatorGenerator extends PlanVisitor<Operator, LocalExecution predicate, inputOperator, node.getAssignments().getMap().values().toArray(new Expression[0]), + new ArrayList<>(node.getAssignments().getMap().keySet()), inputDataTypes, inputLocations, node.getPlanNodeId(), diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java index 13110f43470..23709916eb8 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java @@ -35,6 +35,7 @@ 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.LikePredicate; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullIfExpression; @@ -48,9 +49,6 @@ public class ExpressionRewriter<C> { protected Expression rewriteExpression( Expression node, C context, ExpressionTreeRewriter<C> treeRewriter) { return null; - // throw new IllegalStateException( - // String.format("%s is not supported in ExpressionRewriter yet", - // node.getClass().getName())); } public Expression rewriteFieldReference( @@ -151,6 +149,11 @@ public class ExpressionRewriter<C> { return rewriteExpression(node, context, treeRewriter); } + public Expression rewriteLiteral( + Literal node, C context, ExpressionTreeRewriter<C> treeRewriter) { + return rewriteExpression(node, context, treeRewriter); + } + public Expression rewriteInPredicate( InPredicate node, C context, ExpressionTreeRewriter<C> treeRewriter) { return rewriteExpression(node, context, treeRewriter); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java index 7841d65de1b..fa52d38fd47 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java @@ -575,6 +575,14 @@ public final class ExpressionTreeRewriter<C> { @Override protected Expression visitLiteral(Literal node, Context<C> context) { + if (!context.isDefaultRewrite()) { + Expression result = + rewriter.rewriteLiteral(node, context.get(), ExpressionTreeRewriter.this); + if (result != null) { + return result; + } + } + return node; } }
