From 0c128298bc99343ed5e843d96b090289f1b55233 Mon Sep 17 00:00:00 2001 From: JackieTien97 Date: Wed, 14 Aug 2024 18:46:16 +0800 Subject: [PATCH 1/2] Support constant value in select clause --- .../recent/IoTDBConstantInSelectTableIT.java | 96 +++++++++++++++++++ .../relational/ColumnTransformerBuilder.java | 20 +++- .../plan/planner/TableOperatorGenerator.java | 3 + .../planner/ir/ExpressionRewriter.java | 9 +- .../planner/ir/ExpressionTreeRewriter.java | 8 ++ 5 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java 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 0000000000000..1dae45a92d04d --- /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 a16994cf35a33..e9133b118cc86 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.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.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 @@ protected ColumnTransformer visitLongLiteral(LongLiteral node, Context context) 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 29086a7f6b71c..a251931426660 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 Operator visitFilter(FilterNode node, LocalExecutionPlanContext context) predicate, inputOperator, node.getOutputSymbols().stream().map(Symbol::toSymbolReference).toArray(Expression[]::new), + node.getOutputSymbols(), inputDataTypes, inputLocations, node.getPlanNodeId(), @@ -366,6 +367,7 @@ private Operator constructFilterAndProjectOperator( Optional predicate, Operator inputOperator, Expression[] projectExpressions, + List projectSymbols, List inputDataTypes, Map> inputLocations, PlanNodeId planNodeId, @@ -476,6 +478,7 @@ public Operator visitProject(ProjectNode node, LocalExecutionPlanContext context 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 13110f434700f..23709916eb868 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.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 { protected Expression rewriteExpression( Expression node, C context, ExpressionTreeRewriter 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 Expression rewriteLikePredicate( return rewriteExpression(node, context, treeRewriter); } + public Expression rewriteLiteral( + Literal node, C context, ExpressionTreeRewriter treeRewriter) { + return rewriteExpression(node, context, treeRewriter); + } + public Expression rewriteInPredicate( InPredicate node, C context, ExpressionTreeRewriter 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 7841d65de1bdc..fa52d38fd47df 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 @@ protected Expression visitIdentifier(Identifier node, Context context) { @Override protected Expression visitLiteral(Literal node, Context context) { + if (!context.isDefaultRewrite()) { + Expression result = + rewriter.rewriteLiteral(node, context.get(), ExpressionTreeRewriter.this); + if (result != null) { + return result; + } + } + return node; } } From 0343b2696f901208bc0465a0c4f9ccfef3c85fa5 Mon Sep 17 00:00:00 2001 From: JackieTien97 Date: Wed, 14 Aug 2024 18:54:20 +0800 Subject: [PATCH 2/2] remove useless CI --- .../recent/IoTDBConstantInSelectTableIT.java | 96 ------------------- .../it/query/recent/IoTDBNullIdQueryIT.java | 24 ++++- .../plan/planner/TableOperatorGenerator.java | 3 - 3 files changed, 23 insertions(+), 100 deletions(-) delete mode 100644 integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java 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 deleted file mode 100644 index 1dae45a92d04d..0000000000000 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBConstantInSelectTableIT.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBNullIdQueryIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBNullIdQueryIT.java index 0330891775157..19370bb947d89 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBNullIdQueryIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/IoTDBNullIdQueryIT.java @@ -66,7 +66,7 @@ public static void tearDown() throws Exception { @Test public void nullFilterTest() throws Exception { - final String result = defaultFormatDataTime(1) + ",0,false,11.1"; + String result = defaultFormatDataTime(1) + ",0,false,11.1"; try (final Connection connectionIsNull = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT); final Statement statement = connectionIsNull.createStatement()) { @@ -134,6 +134,28 @@ public void nullFilterTest() throws Exception { + resultSet.getString("s3"); assertEquals(result, ans); assertFalse(resultSet.next()); + + // Test constant select item + resultSet = statement.executeQuery("select *, 1 from testNullId"); + result = defaultFormatDataTime(1) + ",null,null,0,false,11.1,1"; + assertTrue(resultSet.next()); + 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/plan/planner/TableOperatorGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java index a251931426660..29086a7f6b71c 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,7 +356,6 @@ public Operator visitFilter(FilterNode node, LocalExecutionPlanContext context) predicate, inputOperator, node.getOutputSymbols().stream().map(Symbol::toSymbolReference).toArray(Expression[]::new), - node.getOutputSymbols(), inputDataTypes, inputLocations, node.getPlanNodeId(), @@ -367,7 +366,6 @@ private Operator constructFilterAndProjectOperator( Optional predicate, Operator inputOperator, Expression[] projectExpressions, - List projectSymbols, List inputDataTypes, Map> inputLocations, PlanNodeId planNodeId, @@ -478,7 +476,6 @@ public Operator visitProject(ProjectNode node, LocalExecutionPlanContext context predicate, inputOperator, node.getAssignments().getMap().values().toArray(new Expression[0]), - new ArrayList<>(node.getAssignments().getMap().keySet()), inputDataTypes, inputLocations, node.getPlanNodeId(),