You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2024/08/14 10:46:35 UTC
(iotdb) 01/01: Support constant value in select clause
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 <ja...@gmail.com>
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;
}
}