Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.ComparisonExpression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Expression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Extract;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.GenericLiteral;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.IfExpression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.InListExpression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.InPredicate;
Expand All @@ -39,6 +40,7 @@
import org.apache.iotdb.db.i18n.DataNodeQueryMessages;

import com.google.common.collect.ImmutableList;
import org.apache.tsfile.read.common.type.TimestampType;
import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.filter.factory.FilterFactory;
import org.apache.tsfile.read.filter.factory.TimeFilterApi;
Expand Down Expand Up @@ -70,14 +72,14 @@ public Filter visitInPredicate(InPredicate node, Void context) {
checkArgument(valueList instanceof InListExpression);
List<Expression> values = ((InListExpression) valueList).getValues();
for (Expression value : values) {
checkArgument(value instanceof LongLiteral);
checkArgument(isTimeLiteral(value));
}
if (values.size() == 1) {
return TimeFilterApi.eq(getLongValue(values.get(0)));
}
Set<Long> longValues = new HashSet<>();
for (Expression value : values) {
longValues.add(((LongLiteral) value).getParsedValue());
longValues.add(getLongValue(value));
}
return TimeFilterApi.in(longValues);
}
Expand Down Expand Up @@ -317,6 +319,23 @@ public Filter visitBetweenPredicate(BetweenPredicate node, Void context) {
}

public static long getLongValue(Expression expression) {
if (isTimestampLiteral(expression)) {
return Long.parseLong(((GenericLiteral) expression).getValue());
}
return ((LongLiteral) expression).getParsedValue();
}

private static boolean isTimeLiteral(Expression expression) {
return expression instanceof LongLiteral || isTimestampLiteral(expression);
}

// A constant TIMESTAMP expression, such as CAST(1000 AS TIMESTAMP), is folded into a
// GenericLiteral whose value is the timestamp as a long in the current precision.
private static boolean isTimestampLiteral(Expression expression) {
return expression instanceof GenericLiteral
&& TimestampType.TIMESTAMP
.getTypeEnum()
.name()
.equals(((GenericLiteral) expression).getType());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,33 @@

import org.apache.iotdb.commons.queryengine.plan.relational.metadata.ColumnSchema;
import org.apache.iotdb.commons.queryengine.plan.relational.planner.Symbol;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.BetweenPredicate;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.ComparisonExpression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.DoubleLiteral;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.Expression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.GenericLiteral;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.InListExpression;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.InPredicate;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.LongLiteral;
import org.apache.iotdb.commons.queryengine.plan.relational.sql.ast.SymbolReference;
import org.apache.iotdb.db.queryengine.plan.analyze.PredicateUtils;

import org.apache.tsfile.read.common.type.IntType;
import org.apache.tsfile.read.common.type.LongType;
import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.filter.factory.TimeFilterApi;
import org.apache.tsfile.read.filter.operator.FalseLiteralFilter;
import org.apache.tsfile.read.filter.operator.LongFilterOperators;
import org.apache.tsfile.read.filter.operator.ValueIsNotNullOperator;
import org.junit.Assert;
import org.junit.Test;

import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.FIELD;

Expand Down Expand Up @@ -503,4 +512,44 @@ public void testInt64LiteralAndInt32Column() {

Assert.assertEquals(new LongFilterOperators.ValueGtEq(0, 123), actualFilter);
}

@Test
public void testTimestampConstantAndTimeColumn() {
// A constant TIMESTAMP expression such as CAST(1000 AS TIMESTAMP) reaches the conversion as a
// folded GenericLiteral, not a LongLiteral.
SymbolReference time = new SymbolReference("time");
GenericLiteral ts1000 = new GenericLiteral("TIMESTAMP", "1000");
GenericLiteral ts2000 = new GenericLiteral("TIMESTAMP", "2000");

// time >= CAST(1000 AS TIMESTAMP)
Assert.assertEquals(
TimeFilterApi.gtEq(1000),
convertTimePredicate(
new ComparisonExpression(
ComparisonExpression.Operator.GREATER_THAN_OR_EQUAL, time, ts1000)));
// CAST(1000 AS TIMESTAMP) < time
Assert.assertEquals(
TimeFilterApi.gt(1000),
convertTimePredicate(
new ComparisonExpression(ComparisonExpression.Operator.LESS_THAN, ts1000, time)));
// time IN (CAST(1000 AS TIMESTAMP), CAST(2000 AS TIMESTAMP))
Assert.assertEquals(
TimeFilterApi.in(new HashSet<>(Arrays.asList(1000L, 2000L))),
convertTimePredicate(
new InPredicate(time, new InListExpression(Arrays.asList(ts1000, ts2000)))));
// time BETWEEN CAST(1000 AS TIMESTAMP) AND CAST(2000 AS TIMESTAMP)
Assert.assertEquals(
TimeFilterApi.between(1000, 2000),
convertTimePredicate(new BetweenPredicate(time, ts1000, ts2000)));
}

private static Filter convertTimePredicate(Expression predicate) {
return PredicateUtils.convertPredicateToFilter(
predicate,
Collections.emptyMap(),
Collections.emptyMap(),
"time",
ZoneId.of("UTC"),
TimeUnit.MILLISECONDS);
}
}