This is an automated email from the ASF dual-hosted git repository. hui pushed a commit to branch lmh/PredicatePushDown in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 7b67d2c080fcccc08120c7bba06f50817772df2e Author: Minghui Liu <[email protected]> AuthorDate: Sun Jan 7 22:24:06 2024 +0800 add new expression analyzer --- .../queryengine/plan/analyze/PredicateUtils.java | 50 +++++----------- .../visitor/logical/LogicalAndVisitor.java | 70 ++++++++++++++++++++++ .../visitor/logical/LogicalOrVisitor.java | 70 ++++++++++++++++++++++ .../logical/SourceSymbolUniquenessChecker.java | 48 +++++++++++++++ .../visitor/logical/TimeFilterExistChecker.java | 36 +++++++++++ 5 files changed, 238 insertions(+), 36 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/PredicateUtils.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/PredicateUtils.java index f097beaba95..ff970fe3259 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/PredicateUtils.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/PredicateUtils.java @@ -26,15 +26,12 @@ import org.apache.iotdb.db.queryengine.plan.expression.UnknownExpressionTypeExce import org.apache.iotdb.db.queryengine.plan.expression.binary.BinaryExpression; import org.apache.iotdb.db.queryengine.plan.expression.binary.LogicAndExpression; import org.apache.iotdb.db.queryengine.plan.expression.leaf.ConstantOperand; -import org.apache.iotdb.db.queryengine.plan.expression.leaf.NullOperand; -import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand; -import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand; -import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression; -import org.apache.iotdb.db.queryengine.plan.expression.other.CaseWhenThenExpression; import org.apache.iotdb.db.queryengine.plan.expression.ternary.TernaryExpression; import org.apache.iotdb.db.queryengine.plan.expression.unary.InExpression; import org.apache.iotdb.db.queryengine.plan.expression.unary.LogicNotExpression; import org.apache.iotdb.db.queryengine.plan.expression.unary.UnaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.visitor.logical.SourceSymbolUniquenessChecker; +import org.apache.iotdb.db.queryengine.plan.expression.visitor.logical.TimeFilterExistChecker; import org.apache.iotdb.db.queryengine.plan.expression.visitor.predicate.ConvertPredicateToTimeFilterVisitor; import org.apache.iotdb.db.queryengine.plan.expression.visitor.predicate.ReversePredicateVisitor; import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; @@ -194,37 +191,7 @@ public class PredicateUtils { * @return true if the given expression contains time filter */ public static boolean checkIfTimeFilterExist(Expression predicate) { - if (predicate instanceof TernaryExpression) { - return checkIfTimeFilterExist(((TernaryExpression) predicate).getFirstExpression()) - || checkIfTimeFilterExist(((TernaryExpression) predicate).getSecondExpression()) - || checkIfTimeFilterExist(((TernaryExpression) predicate).getThirdExpression()); - } else if (predicate instanceof BinaryExpression) { - return checkIfTimeFilterExist(((BinaryExpression) predicate).getLeftExpression()) - || checkIfTimeFilterExist(((BinaryExpression) predicate).getRightExpression()); - } else if (predicate instanceof UnaryExpression) { - return checkIfTimeFilterExist(((UnaryExpression) predicate).getExpression()); - } else if (predicate instanceof FunctionExpression) { - boolean timeFilterExist = false; - for (Expression childExpression : predicate.getExpressions()) { - timeFilterExist = timeFilterExist || checkIfTimeFilterExist(childExpression); - } - return timeFilterExist; - } else if (predicate instanceof CaseWhenThenExpression) { - for (Expression childExpression : predicate.getExpressions()) { - if (checkIfTimeFilterExist(childExpression)) { - return true; - } - } - return false; - } else if (predicate instanceof TimeSeriesOperand - || predicate instanceof ConstantOperand - || predicate instanceof NullOperand) { - return false; - } else if (predicate instanceof TimestampOperand) { - return true; - } else { - throw new UnknownExpressionTypeException(predicate.getExpressionType()); - } + return new TimeFilterExistChecker().process(predicate, null); } /** @@ -357,6 +324,12 @@ public class PredicateUtils { return combineConjuncts(new ArrayList<>(conjuncts)); } + public static List<Expression> extractConjuncts(Expression predicate) { + Set<Expression> conjuncts = new HashSet<>(); + extractConjuncts(predicate, conjuncts); + return new ArrayList<>(conjuncts); + } + private static void extractConjuncts(Expression predicate, Set<Expression> conjuncts) { if (predicate.getExpressionType().equals(ExpressionType.LOGIC_AND)) { extractConjuncts(((BinaryExpression) predicate).getLeftExpression(), conjuncts); @@ -365,4 +338,9 @@ public class PredicateUtils { conjuncts.add(predicate); } } + + public static boolean isPredicateOnlyContainSourceSymbol( + Expression predicate, String checkedSourceSymbol) { + return new SourceSymbolUniquenessChecker().process(predicate, checkedSourceSymbol); + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalAndVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalAndVisitor.java new file mode 100644 index 00000000000..d3369e2c9d0 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalAndVisitor.java @@ -0,0 +1,70 @@ +/* + * 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.queryengine.plan.expression.visitor.logical; + +import org.apache.iotdb.db.queryengine.plan.expression.Expression; +import org.apache.iotdb.db.queryengine.plan.expression.binary.BinaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression; +import org.apache.iotdb.db.queryengine.plan.expression.other.CaseWhenThenExpression; +import org.apache.iotdb.db.queryengine.plan.expression.ternary.TernaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.unary.UnaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.visitor.ExpressionAnalyzeVisitor; + +public abstract class LogicalAndVisitor<C> extends ExpressionAnalyzeVisitor<Boolean, C> { + + @Override + public Boolean visitTernaryExpression(TernaryExpression ternaryExpression, C context) { + return process(ternaryExpression.getFirstExpression(), context) + && process(ternaryExpression.getSecondExpression(), context) + && process(ternaryExpression.getThirdExpression(), context); + } + + @Override + public Boolean visitBinaryExpression(BinaryExpression binaryExpression, C context) { + return process(binaryExpression.getLeftExpression(), context) + && process(binaryExpression.getRightExpression(), context); + } + + @Override + public Boolean visitUnaryExpression(UnaryExpression unaryExpression, C context) { + return process(unaryExpression.getExpression(), context); + } + + @Override + public Boolean visitCaseWhenThenExpression( + CaseWhenThenExpression caseWhenThenExpression, C context) { + for (Expression childExpression : caseWhenThenExpression.getExpressions()) { + if (Boolean.FALSE.equals(process(childExpression, context))) { + return Boolean.FALSE; + } + } + return Boolean.TRUE; + } + + @Override + public Boolean visitFunctionExpression(FunctionExpression functionExpression, C context) { + for (Expression childExpression : functionExpression.getExpressions()) { + if (Boolean.FALSE.equals(process(childExpression, context))) { + return Boolean.FALSE; + } + } + return Boolean.TRUE; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalOrVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalOrVisitor.java new file mode 100644 index 00000000000..96c0077460e --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/LogicalOrVisitor.java @@ -0,0 +1,70 @@ +/* + * 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.queryengine.plan.expression.visitor.logical; + +import org.apache.iotdb.db.queryengine.plan.expression.Expression; +import org.apache.iotdb.db.queryengine.plan.expression.binary.BinaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression; +import org.apache.iotdb.db.queryengine.plan.expression.other.CaseWhenThenExpression; +import org.apache.iotdb.db.queryengine.plan.expression.ternary.TernaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.unary.UnaryExpression; +import org.apache.iotdb.db.queryengine.plan.expression.visitor.ExpressionAnalyzeVisitor; + +public abstract class LogicalOrVisitor<C> extends ExpressionAnalyzeVisitor<Boolean, C> { + + @Override + public Boolean visitTernaryExpression(TernaryExpression ternaryExpression, C context) { + return process(ternaryExpression.getFirstExpression(), context) + || process(ternaryExpression.getSecondExpression(), context) + || process(ternaryExpression.getThirdExpression(), context); + } + + @Override + public Boolean visitBinaryExpression(BinaryExpression binaryExpression, C context) { + return process(binaryExpression.getLeftExpression(), context) + || process(binaryExpression.getRightExpression(), context); + } + + @Override + public Boolean visitUnaryExpression(UnaryExpression unaryExpression, C context) { + return process(unaryExpression.getExpression(), context); + } + + @Override + public Boolean visitCaseWhenThenExpression( + CaseWhenThenExpression caseWhenThenExpression, C context) { + for (Expression childExpression : caseWhenThenExpression.getExpressions()) { + if (Boolean.TRUE.equals(process(childExpression, context))) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + + @Override + public Boolean visitFunctionExpression(FunctionExpression functionExpression, C context) { + for (Expression childExpression : functionExpression.getExpressions()) { + if (Boolean.TRUE.equals(process(childExpression, context))) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/SourceSymbolUniquenessChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/SourceSymbolUniquenessChecker.java new file mode 100644 index 00000000000..e312564f2a4 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/SourceSymbolUniquenessChecker.java @@ -0,0 +1,48 @@ +/* + * 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.queryengine.plan.expression.visitor.logical; + +import org.apache.iotdb.commons.path.MeasurementPath; +import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.db.queryengine.plan.expression.leaf.LeafOperand; +import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand; + +import static org.apache.iotdb.tsfile.utils.Preconditions.checkArgument; + +public class SourceSymbolUniquenessChecker extends LogicalAndVisitor<String> { + + @Override + public Boolean visitTimeSeriesOperand( + TimeSeriesOperand timeSeriesOperand, String checkedSourceSymbol) { + PartialPath path = timeSeriesOperand.getPath(); + + checkArgument(path instanceof MeasurementPath); + if (((MeasurementPath) path).isUnderAlignedEntity()) { + return path.getDevice().equals(checkedSourceSymbol); + } else { + return path.getFullPath().equals(checkedSourceSymbol); + } + } + + @Override + public Boolean visitLeafOperand(LeafOperand leafOperand, String checkedSourceSymbol) { + return Boolean.TRUE; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/TimeFilterExistChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/TimeFilterExistChecker.java new file mode 100644 index 00000000000..a1d0992facc --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/logical/TimeFilterExistChecker.java @@ -0,0 +1,36 @@ +/* + * 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.queryengine.plan.expression.visitor.logical; + +import org.apache.iotdb.db.queryengine.plan.expression.leaf.LeafOperand; +import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand; + +public class TimeFilterExistChecker extends LogicalOrVisitor<Void> { + + @Override + public Boolean visitTimeStampOperand(TimestampOperand timestampOperand, Void context) { + return Boolean.TRUE; + } + + @Override + public Boolean visitLeafOperand(LeafOperand leafOperand, Void context) { + return Boolean.FALSE; + } +}
