Skip to content

Commit 9a508d5

Browse files
committed
fix according review
Signed-off-by: Weihao Li <18110526956@163.com>
1 parent 3fcd98f commit 9a508d5

6 files changed

Lines changed: 59 additions & 1 deletion

File tree

integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/extract/IoTDBExtractTableIT.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,28 @@ public void extractTimeFilterPushDownTest() {
285285
DATABASE_NAME);
286286
}
287287

288+
@Test
289+
public void testExtractFromComplexExpression() {
290+
String[] expectedHeader = new String[] {"_col0"};
291+
String[] retArray = new String[] {"0,"};
292+
tableResultSetEqualTest(
293+
"SELECT extract(hour from cast(s1 AS TIMESTAMP))" + " FROM table1 order by time limit 1",
294+
expectedHeader,
295+
retArray,
296+
DATABASE_NAME);
297+
}
298+
299+
@Test
300+
public void testExtractFromConstant() {
301+
String[] expectedHeader = new String[] {"_col0"};
302+
String[] retArray = new String[] {"1,"};
303+
tableResultSetEqualTest(
304+
"SELECT extract(hour from 2025/07/08 01:18:51)" + " FROM table1 order by time limit 1",
305+
expectedHeader,
306+
retArray,
307+
DATABASE_NAME);
308+
}
309+
288310
protected String getTimeStrUTC(String time) {
289311
return time + "." + decimal + 'Z';
290312
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrExpressionInterpreter.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CoalesceExpression;
3838
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
3939
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
40+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Extract;
4041
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
4142
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression;
4243
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
@@ -80,6 +81,7 @@
8081
import static org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticUnaryExpression.Sign.MINUS;
8182
import static org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ArithmeticUnaryExpression.Sign.PLUS;
8283
import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature;
84+
import static org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.ExtractTransformer.constructEvaluateFunction;
8385

8486
public class IrExpressionInterpreter {
8587

@@ -916,6 +918,23 @@ public Object visitCast(Cast node, Object context) {
916918
}
917919
}
918920

921+
@Override
922+
protected Object visitExtract(Extract node, Object context) {
923+
Object value = processWithExceptionHandling(node.getExpression(), context);
924+
if (value == null) {
925+
return null;
926+
}
927+
928+
// if is Extract from constant, the constant must be INT64 type, so it will be Long after the
929+
// process
930+
if (value instanceof Long) {
931+
return constructEvaluateFunction(node.getField(), session.getZoneId()).apply((Long) value);
932+
}
933+
934+
checkState(value instanceof Expression, "Value reach here must be Expression");
935+
return new Extract((Expression) value, node.getField());
936+
}
937+
919938
@Override
920939
protected Object visitExpression(Expression node, Object context) {
921940
throw new SemanticException("not yet implemented: " + node.getClass().getName());

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/IrTypeAnalyzer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ protected Type visitArithmeticUnary(ArithmeticUnaryExpression node, Context cont
309309

310310
@Override
311311
protected Type visitExtract(Extract node, Context context) {
312+
process(node.getExpression(), context);
312313
return setExpressionType(node, INT64);
313314
}
314315

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/GlobalTimePredicateExtractVisitor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ public static boolean isTimeColumn(Expression e, String timeColumnName) {
273273

274274
public static boolean isExtractTimeColumn(Expression e, String timeColumnName) {
275275
return e instanceof Extract
276+
&& ((Extract) e).getExpression() instanceof SymbolReference
276277
&& ((SymbolReference) ((Extract) e).getExpression())
277278
.getName()
278279
.equalsIgnoreCase(timeColumnName);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ExtractTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public ExtractTransformer(
4545
this.evaluateFunction = constructEvaluateFunction(field, zoneId);
4646
}
4747

48-
private Function<Long, Long> constructEvaluateFunction(Extract.Field field, ZoneId zoneId) {
48+
public static Function<Long, Long> constructEvaluateFunction(Extract.Field field, ZoneId zoneId) {
4949
switch (field) {
5050
case YEAR:
5151
return timestamp -> (long) convertToZonedDateTime(timestamp, zoneId).getYear();

iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExtractExpressionTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,16 @@
2020
package org.apache.iotdb.db.queryengine.plan.relational.analyzer;
2121

2222
import org.apache.iotdb.db.queryengine.plan.relational.planner.PlanTester;
23+
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
2324

25+
import com.google.common.collect.ImmutableMap;
2426
import org.junit.Test;
2527

2628
import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.TestUtils.assertAnalyzeSemanticException;
2729
import static org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanAssert.assertPlan;
30+
import static org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.expression;
2831
import static org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.output;
32+
import static org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.project;
2933
import static org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.tableScan;
3034

3135
public class ExtractExpressionTest {
@@ -38,6 +42,17 @@ public void pushDownTest() {
3842
output(tableScan("testdb.table1")));
3943
}
4044

45+
@Test
46+
public void constantFoldTest() {
47+
PlanTester planTester = new PlanTester();
48+
assertPlan(
49+
planTester.createPlan("select extract(hour from 2025/07/08 01:18:51) from table1"),
50+
output(
51+
project(
52+
ImmutableMap.of("expr", expression(new LongLiteral("1"))),
53+
tableScan("testdb.table1"))));
54+
}
55+
4156
@Test
4257
public void exceptionTest() {
4358
String errMsg = "Invalid EXTRACT field: s";

0 commit comments

Comments
 (0)