blob: 62df9239708f3ea2733782b6130c72eebaace9e1 [file] [log] [blame]
/*
* 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.db.mpp.plan.analyze;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.db.mpp.plan.expression.Expression;
import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
import org.apache.iotdb.db.mpp.plan.expression.binary.AdditionExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.DivisionExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.EqualToExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterThanExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LessEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LogicOrExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.ModuloExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.MultiplicationExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.NonEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.SubtractionExpression;
import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand;
import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
import org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand;
import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
import org.apache.iotdb.db.mpp.plan.expression.ternary.BetweenExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.InExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.IsNullExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.LikeExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.LogicNotExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.NegationExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.RegularExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.filter.TimeFilter;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.utils.Pair;
import java.util.ArrayList;
import java.util.List;
public class ExpressionUtils {
public static List<Expression> reconstructTimeSeriesOperands(
List<? extends PartialPath> actualPaths) {
List<Expression> resultExpressions = new ArrayList<>();
for (PartialPath actualPath : actualPaths) {
resultExpressions.add(new TimeSeriesOperand(actualPath));
}
return resultExpressions;
}
public static Expression reconstructTimeSeriesOperand(PartialPath actualPath) {
return new TimeSeriesOperand(actualPath);
}
public static List<Expression> reconstructFunctionExpressions(
FunctionExpression expression, List<List<Expression>> childExpressionsList) {
List<Expression> resultExpressions = new ArrayList<>();
for (List<Expression> functionExpressions : childExpressionsList) {
resultExpressions.add(
new FunctionExpression(
expression.getFunctionName(),
expression.getFunctionAttributes(),
functionExpressions));
}
return resultExpressions;
}
public static Expression reconstructFunctionExpression(
FunctionExpression expression, List<Expression> childExpressions) {
return new FunctionExpression(
expression.getFunctionName(), expression.getFunctionAttributes(), childExpressions);
}
public static List<Expression> reconstructUnaryExpressions(
UnaryExpression expression, List<Expression> childExpressions) {
List<Expression> resultExpressions = new ArrayList<>();
for (Expression childExpression : childExpressions) {
switch (expression.getExpressionType()) {
case IS_NULL:
resultExpressions.add(
new IsNullExpression(childExpression, ((IsNullExpression) expression).isNot()));
break;
case IN:
resultExpressions.add(
new InExpression(
childExpression,
((InExpression) expression).isNotIn(),
((InExpression) expression).getValues()));
break;
case LIKE:
resultExpressions.add(
new LikeExpression(
childExpression,
((LikeExpression) expression).getPatternString(),
((LikeExpression) expression).getPattern()));
break;
case LOGIC_NOT:
resultExpressions.add(new LogicNotExpression(childExpression));
break;
case NEGATION:
resultExpressions.add(new NegationExpression(childExpression));
break;
case REGEXP:
resultExpressions.add(
new RegularExpression(
childExpression,
((RegularExpression) expression).getPatternString(),
((RegularExpression) expression).getPattern()));
break;
default:
throw new IllegalArgumentException(
"unsupported expression type: " + expression.getExpressionType());
}
}
return resultExpressions;
}
public static Expression reconstructUnaryExpression(
UnaryExpression expression, Expression childExpression) {
switch (expression.getExpressionType()) {
case IS_NULL:
return new IsNullExpression(childExpression, ((IsNullExpression) expression).isNot());
case IN:
return new InExpression(
childExpression,
((InExpression) expression).isNotIn(),
((InExpression) expression).getValues());
case LIKE:
return new LikeExpression(
childExpression,
((LikeExpression) expression).getPatternString(),
((LikeExpression) expression).getPattern());
case LOGIC_NOT:
return new LogicNotExpression(childExpression);
case NEGATION:
return new NegationExpression(childExpression);
case REGEXP:
return new RegularExpression(
childExpression,
((RegularExpression) expression).getPatternString(),
((RegularExpression) expression).getPattern());
default:
throw new IllegalArgumentException(
"unsupported expression type: " + expression.getExpressionType());
}
}
public static List<Expression> reconstructBinaryExpressions(
ExpressionType expressionType,
List<Expression> leftExpressions,
List<Expression> rightExpressions) {
List<Expression> resultExpressions = new ArrayList<>();
for (Expression le : leftExpressions) {
for (Expression re : rightExpressions) {
switch (expressionType) {
case ADDITION:
resultExpressions.add(new AdditionExpression(le, re));
break;
case SUBTRACTION:
resultExpressions.add(new SubtractionExpression(le, re));
break;
case MULTIPLICATION:
resultExpressions.add(new MultiplicationExpression(le, re));
break;
case DIVISION:
resultExpressions.add(new DivisionExpression(le, re));
break;
case MODULO:
resultExpressions.add(new ModuloExpression(le, re));
break;
case LESS_THAN:
resultExpressions.add(new LessThanExpression(le, re));
break;
case LESS_EQUAL:
resultExpressions.add(new LessEqualExpression(le, re));
break;
case GREATER_THAN:
resultExpressions.add(new GreaterThanExpression(le, re));
break;
case GREATER_EQUAL:
resultExpressions.add(new GreaterEqualExpression(le, re));
break;
case EQUAL_TO:
resultExpressions.add(new EqualToExpression(le, re));
break;
case NON_EQUAL:
resultExpressions.add(new NonEqualExpression(le, re));
break;
case LOGIC_AND:
resultExpressions.add(new LogicAndExpression(le, re));
break;
case LOGIC_OR:
resultExpressions.add(new LogicOrExpression(le, re));
break;
default:
throw new IllegalArgumentException("unsupported expression type: " + expressionType);
}
}
}
return resultExpressions;
}
public static Expression reconstructBinaryExpression(
ExpressionType expressionType, Expression leftExpression, Expression rightExpression) {
switch (expressionType) {
case ADDITION:
return new AdditionExpression(leftExpression, rightExpression);
case SUBTRACTION:
return new SubtractionExpression(leftExpression, rightExpression);
case MULTIPLICATION:
return new MultiplicationExpression(leftExpression, rightExpression);
case DIVISION:
return new DivisionExpression(leftExpression, rightExpression);
case MODULO:
return new ModuloExpression(leftExpression, rightExpression);
case LESS_THAN:
return new LessThanExpression(leftExpression, rightExpression);
case LESS_EQUAL:
return new LessEqualExpression(leftExpression, rightExpression);
case GREATER_THAN:
return new GreaterThanExpression(leftExpression, rightExpression);
case GREATER_EQUAL:
return new GreaterEqualExpression(leftExpression, rightExpression);
case EQUAL_TO:
return new EqualToExpression(leftExpression, rightExpression);
case NON_EQUAL:
return new NonEqualExpression(leftExpression, rightExpression);
case LOGIC_AND:
return new LogicAndExpression(leftExpression, rightExpression);
case LOGIC_OR:
return new LogicOrExpression(leftExpression, rightExpression);
default:
throw new IllegalArgumentException("unsupported expression type: " + expressionType);
}
}
public static List<Expression> reconstructTernaryExpressions(
Expression expression,
List<Expression> firstExpressions,
List<Expression> secondExpressions,
List<Expression> thirdExpressions) {
List<Expression> resultExpressions = new ArrayList<>();
for (Expression fe : firstExpressions) {
for (Expression se : secondExpressions)
for (Expression te : thirdExpressions) {
switch (expression.getExpressionType()) {
case BETWEEN:
resultExpressions.add(
new BetweenExpression(
fe, se, te, ((BetweenExpression) expression).isNotBetween()));
break;
default:
throw new IllegalArgumentException(
"unsupported expression type: " + expression.getExpressionType());
}
}
}
return resultExpressions;
}
public static Expression reconstructTernaryExpression(
Expression expression,
Expression firstExpression,
Expression secondExpression,
Expression thirdExpression) {
switch (expression.getExpressionType()) {
case BETWEEN:
return new BetweenExpression(
firstExpression,
secondExpression,
thirdExpression,
((BetweenExpression) expression).isNotBetween());
default:
throw new IllegalArgumentException(
"unsupported expression type: " + expression.getExpressionType());
}
}
public static <T> void cartesianProduct(
List<List<T>> dimensionValue, List<List<T>> resultList, int layer, List<T> currentList) {
if (layer < dimensionValue.size() - 1) {
if (dimensionValue.get(layer).isEmpty()) {
cartesianProduct(dimensionValue, resultList, layer + 1, currentList);
} else {
for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
List<T> list = new ArrayList<>(currentList);
list.add(dimensionValue.get(layer).get(i));
cartesianProduct(dimensionValue, resultList, layer + 1, list);
}
}
} else if (layer == dimensionValue.size() - 1) {
if (dimensionValue.get(layer).isEmpty()) {
resultList.add(currentList);
} else {
for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
List<T> list = new ArrayList<>(currentList);
list.add(dimensionValue.get(layer).get(i));
resultList.add(list);
}
}
}
}
public static Filter constructTimeFilter(
ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
if (timeExpression instanceof TimestampOperand
&& valueExpression instanceof ConstantOperand
&& ((ConstantOperand) valueExpression).getDataType() == TSDataType.INT64) {
long value = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
switch (expressionType) {
case LESS_THAN:
return TimeFilter.lt(value);
case LESS_EQUAL:
return TimeFilter.ltEq(value);
case GREATER_THAN:
return TimeFilter.gt(value);
case GREATER_EQUAL:
return TimeFilter.gtEq(value);
case EQUAL_TO:
return TimeFilter.eq(value);
case NON_EQUAL:
return TimeFilter.notEq(value);
default:
throw new IllegalArgumentException("unsupported expression type: " + expressionType);
}
}
return null;
}
public static Pair<Filter, Boolean> getPairFromBetweenTimeFirst(
Expression firstExpression, Expression secondExpression, boolean not) {
if (firstExpression instanceof ConstantOperand
&& secondExpression instanceof ConstantOperand
&& ((ConstantOperand) firstExpression).getDataType() == TSDataType.INT64
&& ((ConstantOperand) secondExpression).getDataType() == TSDataType.INT64) {
long value1 = Long.parseLong(((ConstantOperand) firstExpression).getValueString());
long value2 = Long.parseLong(((ConstantOperand) secondExpression).getValueString());
return new Pair<>(TimeFilter.between(value1, value2, not), false);
} else {
return new Pair<>(null, true);
}
}
public static Pair<Filter, Boolean> getPairFromBetweenTimeSecond(
BetweenExpression predicate, Expression expression) {
if (predicate.isNotBetween()) {
return new Pair<>(
TimeFilter.gt(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
} else {
return new Pair<>(
TimeFilter.ltEq(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
}
}
public static Pair<Filter, Boolean> getPairFromBetweenTimeThird(
BetweenExpression predicate, Expression expression) {
if (predicate.isNotBetween()) {
return new Pair<>(
TimeFilter.lt(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
} else {
return new Pair<>(
TimeFilter.gtEq(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
}
}
public static boolean checkConstantSatisfy(
Expression firstExpression, Expression secondExpression) {
return firstExpression.isConstantOperand()
&& secondExpression.isConstantOperand()
&& ((ConstantOperand) firstExpression).getDataType() == TSDataType.INT64
&& ((ConstantOperand) secondExpression).getDataType() == TSDataType.INT64
&& (Long.parseLong(((ConstantOperand) firstExpression).getValueString())
<= Long.parseLong(((ConstantOperand) secondExpression).getValueString()));
}
public static Expression constructQueryFilter(List<Expression> expressions) {
if (expressions.size() == 1) {
return expressions.get(0);
}
return ExpressionUtils.constructBinaryFilterTreeWithAnd(expressions);
}
private static Expression constructBinaryFilterTreeWithAnd(List<Expression> expressions) {
// TODO: consider AVL tree
if (expressions.size() == 2) {
return new LogicAndExpression(expressions.get(0), expressions.get(1));
} else {
return new LogicAndExpression(
expressions.get(0),
constructBinaryFilterTreeWithAnd(expressions.subList(1, expressions.size())));
}
}
}