You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@asterixdb.apache.org by AsterixDB Code Review <do...@asterix-gerrit.ics.uci.edu> on 2025/03/19 15:45:14 UTC
Change in asterixdb[ionic]: [ASTERIXDB-3582][COMP] Fix expected schema tree generation
From Ritik Raj <ri...@couchbase.com>:
Ritik Raj has uploaded this change for review. ( https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19532 )
Change subject: [ASTERIXDB-3582][COMP] Fix expected schema tree generation
......................................................................
[ASTERIXDB-3582][COMP] Fix expected schema tree generation
- user model changes: no
- storage format changes: no
- interface changes: no
Ext-ref: MB-65792
Change-Id: Ic04a618c7aa182af4b1f4b7ade64d687147ef705
---
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ArrayExpectedSchemaNode.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ObjectExpectedSchemaNode.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/UnionExpectedSchemaNode.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/RootExpectedSchemaNode.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/AbstractComplexExpectedSchemaNode.java
A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582-2.006.query.sqlpp
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ExpectedSchemaBuilder.java
A asterixdb/asterix-app/src/test/resources/runtimets/results/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582.006.adm
8 files changed, 116 insertions(+), 0 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/32/19532/1
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/AbstractComplexExpectedSchemaNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/AbstractComplexExpectedSchemaNode.java
index 34ff582..192e590 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/AbstractComplexExpectedSchemaNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/AbstractComplexExpectedSchemaNode.java
@@ -18,8 +18,10 @@
*/
package org.apache.asterix.optimizer.rules.pushdown.schema;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
public abstract class AbstractComplexExpectedSchemaNode extends AbstractExpectedSchemaNode {
@@ -86,6 +88,9 @@
protected abstract IExpectedSchemaNode replaceChild(IExpectedSchemaNode oldNode, IExpectedSchemaNode newNode);
+ protected abstract IExpectedSchemaNode getChildNode(AbstractFunctionCallExpression parentExpr,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException;
+
/**
* A child is replaceable if
* - child is allowed to be replaced
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ArrayExpectedSchemaNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ArrayExpectedSchemaNode.java
index b8135b7..6efb3b4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ArrayExpectedSchemaNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ArrayExpectedSchemaNode.java
@@ -18,8 +18,10 @@
*/
package org.apache.asterix.optimizer.rules.pushdown.schema;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
public class ArrayExpectedSchemaNode extends AbstractComplexExpectedSchemaNode {
private IExpectedSchemaNode child;
@@ -60,4 +62,10 @@
// This should never happen, but safeguard against unexpected behavior
throw new IllegalStateException("Cannot replace " + child.getType() + " with " + newNode.getType());
}
+
+ @Override
+ protected IExpectedSchemaNode getChildNode(AbstractFunctionCallExpression parentExpr,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+ return child;
+ }
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ExpectedSchemaBuilder.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ExpectedSchemaBuilder.java
index f4b6cb0..7c80818 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ExpectedSchemaBuilder.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ExpectedSchemaBuilder.java
@@ -65,10 +65,12 @@
AbstractComplexExpectedSchemaNode parent = (AbstractComplexExpectedSchemaNode) buildNestedNode(expr, typeEnv);
if (parent != null) {
IExpectedSchemaNode leaf = new AnyExpectedSchemaNode(parent, expr);
+ IExpectedSchemaNode oldChildNode = parent.getChildNode(expr, typeEnv);
IExpectedSchemaNode actualNode = addOrReplaceChild(expr, typeEnv, parent, leaf);
if (producedVar != null) {
//Register the node if a variable is produced
varToNode.put(producedVar, actualNode);
+ updateVarToNodeRef(oldChildNode, actualNode);
}
}
@@ -93,10 +95,45 @@
(AnyExpectedSchemaNode) node.replaceIfNeeded(ExpectedSchemaNodeType.ANY, null, null);
// make the leaf node irreplaceable
leafNode.preventReplacing();
+ // if the node has been replaced by the leafNode,
+ // check for the variable that is associated with the node to be replaced.
varToNode.put(variable, leafNode);
+ updateVarToNodeRef(node, leafNode);
}
}
+ /**
+ * Updates variable references when schema paths point to the same field access.
+ *
+ * Example Query:
+ * SELECT i
+ * ... FROM orders AS o, o.items AS i
+ * ... WHERE (SOME li IN o.items SATISFIES li.qty < 3)
+ * ... AND i.qty >= 100;
+ *
+ * In this query, both 'i' and 'li' reference the same field access (o.items).
+ * The schema paths evolve as follows:
+ * 1. i.qty creates path: {"items": [{qty: any}]}
+ * 2. li.qty references the same qty node
+ * 3. When processing 'i', we replace i.qty with a broader path: {"items": [any]}
+ *
+ * Since both variables reference the same field, we need to update all references
+ * to the old node (qty-specific) with the new node (array-level) in varToNode cache.
+ *
+ * @param oldNode The original node being replaced (e.g., qty-specific node)
+ * @param newNode The new node replacing it (e.g., array-level node)
+ */
+ private void updateVarToNodeRef(IExpectedSchemaNode oldNode, IExpectedSchemaNode newNode) {
+ // Skip if nodes are null, identical, or oldNode is a root node
+ if (oldNode == null || oldNode == newNode
+ || RootExpectedSchemaNode.ROOT_EXPECTED_SCHEMA_NODES.contains(oldNode)) {
+ return;
+ }
+
+ // Update all variable references from oldNode to newNode
+ varToNode.replaceAll((var, node) -> node == oldNode ? newNode : node);
+ }
+
public boolean isVariableRegistered(LogicalVariable variable) {
return varToNode.containsKey(variable);
}
@@ -231,6 +268,7 @@
IExpectedSchemaNode newNode = oldNode.replaceIfNeeded(varExpectedType, parentExpression, expression);
//Map the sourceVar to the node
varToNode.put(sourceVar, newNode);
+ updateVarToNodeRef(oldNode, newNode);
return newNode;
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ObjectExpectedSchemaNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ObjectExpectedSchemaNode.java
index e220437..668a516 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ObjectExpectedSchemaNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/ObjectExpectedSchemaNode.java
@@ -22,8 +22,10 @@
import java.util.Map;
import org.apache.asterix.metadata.utils.PushdownUtil;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -96,4 +98,11 @@
return PushdownUtil.getFieldName(expr);
}
+
+ @Override
+ public IExpectedSchemaNode getChildNode(AbstractFunctionCallExpression parentExpr, IVariableTypeEnvironment typeEnv)
+ throws AlgebricksException {
+ String fieldName = PushdownUtil.getFieldName(parentExpr, typeEnv);
+ return children.get(fieldName);
+ }
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/RootExpectedSchemaNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/RootExpectedSchemaNode.java
index e72e997..1074fb3f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/RootExpectedSchemaNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/RootExpectedSchemaNode.java
@@ -18,6 +18,8 @@
*/
package org.apache.asterix.optimizer.rules.pushdown.schema;
+import java.util.List;
+
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
@@ -33,6 +35,8 @@
public static final RootExpectedSchemaNode ALL_FIELDS_ROOT_IRREPLACEABLE_NODE =
new RootExpectedSchemaNode(ALL_FIELDS_ROOT_IRREPLACEABLE);
public static final RootExpectedSchemaNode EMPTY_ROOT_NODE = new RootExpectedSchemaNode(EMPTY_ROOT);
+ public static final List<RootExpectedSchemaNode> ROOT_EXPECTED_SCHEMA_NODES =
+ List.of(ALL_FIELDS_ROOT_NODE, ALL_FIELDS_ROOT_IRREPLACEABLE_NODE, EMPTY_ROOT_NODE);
private final int rootType;
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/UnionExpectedSchemaNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/UnionExpectedSchemaNode.java
index a15e359..7cc88e4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/UnionExpectedSchemaNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/schema/UnionExpectedSchemaNode.java
@@ -18,12 +18,16 @@
*/
package org.apache.asterix.optimizer.rules.pushdown.schema;
+import static org.apache.asterix.optimizer.rules.pushdown.schema.ExpectedSchemaBuilder.getExpectedNestedNodeType;
+
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
public class UnionExpectedSchemaNode extends AbstractComplexExpectedSchemaNode {
private final Map<ExpectedSchemaNodeType, AbstractComplexExpectedSchemaNode> children;
@@ -91,4 +95,12 @@
}
return this;
}
+
+ @Override
+ protected IExpectedSchemaNode getChildNode(AbstractFunctionCallExpression parentExpr,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+ ExpectedSchemaNodeType parentType = getExpectedNestedNodeType(parentExpr);
+ AbstractComplexExpectedSchemaNode actualParent = getChild(parentType);
+ return actualParent.getChildNode(parentExpr, typeEnv);
+ }
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582-2.006.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582-2.006.query.sqlpp
new file mode 100644
index 0000000..cd30f96
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582-2.006.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+-- there was issue in expected schema tree generation for i and li.qty
+SELECT *
+FROM websales.orders AS o, o.items AS i
+WHERE
+(SOME li IN o.items SATISFIES li.qty < 3)
+ AND i.qty >= 100;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582.006.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582.006.adm
new file mode 100644
index 0000000..27100ee
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/column/filter/ASTERIXDB-3582-2/ASTERIXDB-3582.006.adm
@@ -0,0 +1 @@
+{ "o": { "orderno": 1005, "custid": "C37", "order_date": "2020-08-30", "items": [ { "itemno": 460, "qty": 2, "price": 29.99 }, { "itemno": 347, "qty": 120, "price": 22.0 }, { "itemno": 780, "qty": 1, "price": 1500.0 }, { "itemno": 375, "qty": 2, "price": 149.98 } ] }, "i": { "itemno": 347, "qty": 120, "price": 22.0 } }
\ No newline at end of file
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19532
To unsubscribe, or for help writing mail filters, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: ionic
Gerrit-Change-Id: Ic04a618c7aa182af4b1f4b7ade64d687147ef705
Gerrit-Change-Number: 19532
Gerrit-PatchSet: 1
Gerrit-Owner: Ritik Raj <ri...@couchbase.com>
Gerrit-MessageType: newchange