>From Preetham Poluparthi <[email protected]>:
Preetham Poluparthi has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20828?usp=email )
Change subject: [ASTERIXDB-3677][COMP] Optimize only for {}
......................................................................
[ASTERIXDB-3677][COMP] Optimize only for {}
- user model changes: no
- storage format changes: no
- interface changes: no
Ext-ref: MB-70076
Change-Id: Ida835829ef744424d385f38899a9788469253f2c
---
M asterixdb/NOTICE
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
A
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InlineIfMissingFunctionRule.java
M hyracks-fullstack/NOTICE
M
hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonExpressionsRule.java
6 files changed, 160 insertions(+), 2 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/28/20828/1
diff --git a/asterixdb/NOTICE b/asterixdb/NOTICE
index 5118782..a44569b 100644
--- a/asterixdb/NOTICE
+++ b/asterixdb/NOTICE
@@ -1,5 +1,5 @@
Apache AsterixDB
-Copyright 2015-2025 The Apache Software Foundation
+Copyright 2015-2026 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index 3cea23f..68cdf30 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -177,6 +177,7 @@
List<IAlgebraicRewriteRule> typeInfer = new LinkedList<>();
typeInfer.add(new InlineUnnestFunctionRule());
typeInfer.add(new InferTypesRule());
+ // maybe here
typeInfer.add(new CheckFilterExpressionTypeRule());
return typeInfer;
}
@@ -347,6 +348,7 @@
planCleanupRules.add(new
IntroduceDynamicTypeCastForExternalFunctionRule());
planCleanupRules.add(new RemoveUnusedAssignAndAggregateRule());
planCleanupRules.add(new RemoveCartesianProductWithEmptyBranchRule());
+ // planCleanupRules.add(new InlineIfMissingFunctionRule());
planCleanupRules.add(new InjectTypeCastForFunctionArgumentsRule());
planCleanupRules.add(new InjectTypeCastForUnionRule());
// (1) RemoveOrReplaceDefaultNullCastRule and (2)
RemoveUnknownCheckForKnownTypesRule has to run in this order
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
index 98c54e6..eb494ae 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java
@@ -30,6 +30,8 @@
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
import org.apache.asterix.om.types.IAType;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
@@ -115,6 +117,18 @@
BiIntPredicate argChecker, IOptimizationContext context) throws
AlgebricksException {
IVariableTypeEnvironment env = op.computeInputTypeEnvironment(context);
IAType producedType = (IAType) env.getType(func);
+
+ for (Mutable<ILogicalExpression> argRef : func.getArguments()) {
+ ILogicalExpression argExpr = argRef.get();
+ IAType type = (IAType) env.getType(argExpr);
+ if (type.getTypeTag() == ATypeTag.OBJECT) {
+ ARecordType recordType = (ARecordType) type;
+ if (!recordType.isOpen() && recordType.getFieldNames().length
== 0) {
+ producedType = new ARecordType(null, new String[0], new
IAType[0], true);
+ }
+ }
+ }
+
List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
int argSize = argRefs.size();
boolean rewritten = false;
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InlineIfMissingFunctionRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InlineIfMissingFunctionRule.java
new file mode 100644
index 0000000..24b71e7
--- /dev/null
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InlineIfMissingFunctionRule.java
@@ -0,0 +1,130 @@
+/*
+ * 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.asterix.optimizer.rules;
+
+import java.util.List;
+
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+public class InlineIfMissingFunctionRule implements IAlgebraicRewriteRule {
+
+ @Override
+ public boolean rewritePost(Mutable<ILogicalOperator> opRef,
IOptimizationContext context)
+ throws AlgebricksException {
+
+ ILogicalOperator op = opRef.getValue();
+ if (op.getInputs().isEmpty()) {
+ return false;
+ }
+ // Populates the latest type information.
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ if (op.acceptExpressionTransform(exprRef -> inlineIfMissing(op,
exprRef, context))) {
+ // Generates the up-to-date type information.
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ // 1. keep {} inlined. MUST
+ // 2a. optimize only for {} using a rule
+ // 2b. optimize only for {} in
InjectTypeCastForFunctionArgumentsRule = know when a cast can't be done and use
generalized.
+ // e.g. if-missing-or-null(to-object(a), cast({})); cast to
open-rec instead of cast to {"id": int}
+
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean inlineIfMissing(ILogicalOperator op,
Mutable<ILogicalExpression> exprRef,
+ IOptimizationContext context) throws AlgebricksException {
+
+ ILogicalExpression expr = exprRef.getValue();
+ if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+ return false;
+ }
+ boolean rewritten = false;
+ AbstractFunctionCallExpression func = (AbstractFunctionCallExpression)
expr;
+
+ for (Mutable<ILogicalExpression> argRef : func.getArguments()) {
+ if (inlineIfMissing(op, argRef, context)) {
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ rewritten = true;
+ }
+ }
+ rewritten |= rewriteFunction(op, exprRef, context);
+ return rewritten;
+ }
+
+ private static boolean rewriteFunction(ILogicalOperator op,
Mutable<ILogicalExpression> exprRef,
+ IOptimizationContext context) throws AlgebricksException {
+
+ ILogicalExpression expr = exprRef.getValue();
+ AbstractFunctionCallExpression func = (AbstractFunctionCallExpression)
expr;
+
+ if (func.getFunctionIdentifier() !=
BuiltinFunctions.IF_MISSING_OR_NULL) {
+ return false;
+ }
+
+ List<Mutable<ILogicalExpression>> argRefList = func.getArguments();
+ if (argRefList.isEmpty()) {
+ exprRef.setValue(ConstantExpression.NULL);
+ return true;
+ }
+
+ IVariableTypeEnvironment env = op.computeInputTypeEnvironment(context);
+
+ IAType type = (IAType) env.getType(argRefList.get(0).get());
+
+ if (type.getTypeTag() != ATypeTag.MISSING && type.getTypeTag() !=
ATypeTag.NULL
+ && type.getTypeTag() != ATypeTag.ANY) {
+ exprRef.setValue(argRefList.get(0).get());
+ return true;
+ }
+
+ List<Mutable<ILogicalExpression>> newArgsList = func.getArguments();
+
+ for (Mutable<ILogicalExpression> argRef : argRefList) {
+ ILogicalExpression argExpr = argRef.getValue();
+ IAType argType = (IAType) env.getType(argExpr);
+
+ if (argType.getTypeTag() == ATypeTag.ANY) {
+ newArgsList.add(argRef);
+ } else if (argType.getTypeTag() != ATypeTag.MISSING &&
argType.getTypeTag() != ATypeTag.NULL) {
+ newArgsList.add(argRef);
+ break;
+ }
+
+ }
+
+ argRefList.clear();
+ argRefList.addAll(newArgsList);
+ return true;
+
+ }
+
+}
diff --git a/hyracks-fullstack/NOTICE b/hyracks-fullstack/NOTICE
index 722db88..9050c82 100644
--- a/hyracks-fullstack/NOTICE
+++ b/hyracks-fullstack/NOTICE
@@ -1,5 +1,5 @@
Apache Hyracks and Algebricks
-Copyright 2015-2025 The Apache Software Foundation
+Copyright 2015-2026 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonExpressionsRule.java
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonExpressionsRule.java
index e2ba557..eca1802 100644
---
a/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonExpressionsRule.java
+++
b/hyracks-fullstack/algebricks/algebricks-rewriter/src/main/java/org/apache/hyracks/algebricks/rewriter/rules/ExtractCommonExpressionsRule.java
@@ -89,6 +89,8 @@
// Set of operators for which common subexpression elimination should not
be performed.
private static final Set<LogicalOperatorTag> ignoreOps = new HashSet<>(6);
+ private static final Set<String> NON_EXTRACTABLE_FUNCTION_NAMES = new
HashSet<>();
+
static {
ignoreOps.add(LogicalOperatorTag.UNNEST);
ignoreOps.add(LogicalOperatorTag.UNNEST_MAP);
@@ -97,6 +99,8 @@
ignoreOps.add(LogicalOperatorTag.AGGREGATE);
ignoreOps.add(LogicalOperatorTag.RUNNINGAGGREGATE);
ignoreOps.add(LogicalOperatorTag.WINDOW); //TODO: can extract from
partition/order/frame expressions
+
+ NON_EXTRACTABLE_FUNCTION_NAMES.add("cast");
}
@Override
@@ -260,6 +264,14 @@
return modified;
}
+ private static boolean isExprExtractable(ILogicalExpression expr) {
+ if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+ return false;
+ }
+ AbstractFunctionCallExpression funcExpr =
(AbstractFunctionCallExpression) expr;
+ return
!NON_EXTRACTABLE_FUNCTION_NAMES.contains(funcExpr.getFunctionIdentifier().getName());
+ }
+
private class CommonExpressionSubstitutionVisitor implements
ILogicalExpressionReferenceTransform {
private IOptimizationContext context;
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20828?usp=email
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: trinity
Gerrit-Change-Id: Ida835829ef744424d385f38899a9788469253f2c
Gerrit-Change-Number: 20828
Gerrit-PatchSet: 1
Gerrit-Owner: Preetham Poluparthi <[email protected]>