>From Michael Blow <[email protected]>:

Michael Blow has submitted this change. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19317 )

Change subject: Merge branch 'gerrit/trinity' into 'gerrit/goldfish'
......................................................................

Merge branch 'gerrit/trinity' into 'gerrit/goldfish'

Ext-ref: MB-64561
Change-Id: If535113f5438a9d32420ffd1d35d44a24a217b1e
---
M 
asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/ExternalDatasetTestUtils.java
A 
asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
M 
asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
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_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
D 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/ExpectedSchemaBuilder.java
8 files changed, 179 insertions(+), 324 deletions(-)

Approvals:
  Michael Blow: Looks good to me, approved; Verified




diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/ExpectedSchemaBuilder.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/ExpectedSchemaBuilder.java
deleted file mode 100644
index b87cada..0000000
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/pushdown/ExpectedSchemaBuilder.java
+++ /dev/null
@@ -1,288 +0,0 @@
-<<<<<<< HEAD   (474bef Merge branch 'gerrit/trinity' into 'gerrit/goldfish')
-=======
-/*
- * 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.pushdown;
-
-import static 
org.apache.asterix.optimizer.rules.pushdown.ExpressionValueAccessPushdownVisitor.ARRAY_FUNCTIONS;
-import static 
org.apache.asterix.optimizer.rules.pushdown.ExpressionValueAccessPushdownVisitor.SUPPORTED_FUNCTIONS;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.om.utils.ConstantExpressionUtil;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.AbstractComplexExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.AnyExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.ArrayExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.ExpectedSchemaNodeType;
-import org.apache.asterix.optimizer.rules.pushdown.schema.IExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.ObjectExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.RootExpectedSchemaNode;
-import 
org.apache.asterix.optimizer.rules.pushdown.schema.UnionExpectedSchemaNode;
-import org.apache.asterix.runtime.projection.DataProjectionInfo;
-import org.apache.asterix.runtime.projection.FunctionCallInformation;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import 
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
-
-/**
- * This class takes a value access expression and produces an expected schema 
(given the expression).
- * Example:
- * - $$t.getField("hashtags").getItem(0)
- * We expect:
- * 1- $$t is OBJECT
- * 2- the output type of getField("hashtags") is ARRAY
- * 3- the output type of getItem(0) is ANY node
- */
-class ExpectedSchemaBuilder {
-    //Registered Variables
-    private final Map<LogicalVariable, IExpectedSchemaNode> varToNode;
-    private final ExpectedSchemaNodeToIATypeTranslatorVisitor typeBuilder;
-
-    public ExpectedSchemaBuilder() {
-        varToNode = new HashMap<>();
-        typeBuilder = new ExpectedSchemaNodeToIATypeTranslatorVisitor();
-    }
-
-    public DataProjectionInfo createProjectionInfo(LogicalVariable 
recordVariable) {
-        IExpectedSchemaNode rootNode = varToNode.get(recordVariable);
-        Map<String, FunctionCallInformation> sourceInformation = new 
HashMap<>();
-        typeBuilder.reset(sourceInformation);
-        ARecordType recordType = (ARecordType) rootNode.accept(typeBuilder, 
null);
-        return new DataProjectionInfo(recordType, sourceInformation);
-    }
-
-    public boolean setSchemaFromExpression(AbstractFunctionCallExpression 
expr, LogicalVariable producedVar) {
-        return buildExpectedSchemaNodes(expr, producedVar);
-    }
-
-    public boolean 
setSchemaFromCalculatedExpression(AbstractFunctionCallExpression expr, 
LogicalVariable producedVar) {
-        //Parent always nested
-        AbstractComplexExpectedSchemaNode parent = 
(AbstractComplexExpectedSchemaNode) buildNestedNode(expr);
-        if (parent != null) {
-            IExpectedSchemaNode leaf =
-                    new AnyExpectedSchemaNode(parent, 
expr.getSourceLocation(), expr.getFunctionIdentifier().getName());
-            addChild(expr, parent, leaf);
-            if (producedVar != null) {
-                //Register the node if a variable is produced
-                varToNode.put(producedVar, leaf);
-            }
-        }
-        return parent != null;
-    }
-
-    public void registerDataset(LogicalVariable recordVar, 
RootExpectedSchemaNode rootNode) {
-        varToNode.put(recordVar, rootNode);
-    }
-
-    public void unregisterVariable(LogicalVariable variable) {
-        //Remove the node so no other expression will pushdown any expression 
in the future
-        IExpectedSchemaNode node = varToNode.remove(variable);
-        AbstractComplexExpectedSchemaNode parent = node.getParent();
-        if (parent == null) {
-            //It is a root node. Request the entire record
-            varToNode.put(variable, 
RootExpectedSchemaNode.ALL_FIELDS_ROOT_NODE);
-        } else {
-            //It is a nested node. Replace the node to a LEAF node
-            node.replaceIfNeeded(ExpectedSchemaNodeType.ANY, 
parent.getSourceLocation(), parent.getFunctionName());
-        }
-    }
-
-    public boolean isVariableRegistered(LogicalVariable recordVar) {
-        return varToNode.containsKey(recordVar);
-    }
-
-    public boolean containsRegisteredDatasets() {
-        return !varToNode.isEmpty();
-    }
-
-    private boolean buildExpectedSchemaNodes(ILogicalExpression expr, 
LogicalVariable producedVar) {
-        return buildNestedNodes(expr, producedVar);
-    }
-
-    private boolean buildNestedNodes(ILogicalExpression expr, LogicalVariable 
producedVar) {
-        //The current node expression
-        boolean changed = false;
-        if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
-            return false;
-        }
-        AbstractFunctionCallExpression myExpr = 
(AbstractFunctionCallExpression) expr;
-        if (!SUPPORTED_FUNCTIONS.contains(myExpr.getFunctionIdentifier()) || 
noArgsOrFirstArgIsConstant(myExpr)) {
-            // Check if the function consists of the Supported Functions
-            for (Mutable<ILogicalExpression> arg : myExpr.getArguments()) {
-                changed |= buildNestedNodes(arg.getValue(), producedVar);
-            }
-            return changed;
-        }
-        // if the child is not a function expression, then just one node.
-        if (BuiltinFunctions.ARRAY_STAR.equals(myExpr.getFunctionIdentifier())
-                || 
BuiltinFunctions.SCAN_COLLECTION.equals(myExpr.getFunctionIdentifier())) {
-            // these supported function won't have second child
-            IExpectedSchemaNode expectedSchemaNode = buildNestedNode(expr);
-            if (expectedSchemaNode != null) {
-                changed |= 
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) expr, 
producedVar);
-            }
-        } else {
-            ILogicalExpression childExpr = 
myExpr.getArguments().get(1).getValue();
-            if (childExpr.getExpressionTag() != 
LogicalExpressionTag.FUNCTION_CALL) {
-                // must be a variable or constant
-                IExpectedSchemaNode expectedSchemaNode = buildNestedNode(expr);
-                if (expectedSchemaNode != null) {
-                    changed |= 
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) expr, 
producedVar);
-                }
-            } else {
-                // as the childExpr is a function.
-                // if the function had been evaluated at compile time, it 
would have been
-                // evaluated at this stage of compilation.
-                // eg: field-access(t.r.p, substring("name",2,4))
-                // this will be evaluated to field-access(t.r.p, "me") at 
compile time itself.
-                // since the execution reached this branch, this means the 
childExpr
-                // need to be evaluated at runtime, hence the childExpr should 
also be checked
-                // for possible pushdown.
-                // eg: field-access(t.r.p, substring(x.y.age_field, 0, 4))
-                ILogicalExpression parentExpr = 
myExpr.getArguments().get(0).getValue();
-                IExpectedSchemaNode parentExpectedNode = 
buildNestedNode(parentExpr);
-                if (parentExpectedNode != null) {
-                    changed |=
-                            
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) parentExpr, 
producedVar);
-                }
-                changed |= buildNestedNodes(childExpr, producedVar);
-            }
-        }
-        return changed;
-    }
-
-    private boolean noArgsOrFirstArgIsConstant(AbstractFunctionCallExpression 
myExpr) {
-        List<Mutable<ILogicalExpression>> args = myExpr.getArguments();
-        return args.isEmpty() || args.get(0).getValue().getExpressionTag() == 
LogicalExpressionTag.CONSTANT;
-    }
-
-    private IExpectedSchemaNode buildNestedNode(ILogicalExpression expr) {
-        //The current node expression
-        AbstractFunctionCallExpression myExpr = 
(AbstractFunctionCallExpression) expr;
-        if (!SUPPORTED_FUNCTIONS.contains(myExpr.getFunctionIdentifier())) {
-            //Return null if the function is not supported.
-            return null;
-        }
-
-        //The parent expression
-        ILogicalExpression parentExpr = 
myExpr.getArguments().get(0).getValue();
-        if (isVariable(parentExpr)) {
-            //A variable could be the record's originated from data-scan or an 
expression from assign
-            LogicalVariable sourceVar = 
VariableUtilities.getVariable(parentExpr);
-            return changeNodeForVariable(sourceVar, myExpr);
-        }
-
-        //Recursively create the parent nodes. Parent is always a nested node
-        AbstractComplexExpectedSchemaNode newParent = 
(AbstractComplexExpectedSchemaNode) buildNestedNode(parentExpr);
-        //newParent could be null if the expression is not supported
-        if (newParent != null) {
-            //Parent expression must be a function call (as parent is a nested 
node)
-            AbstractFunctionCallExpression parentFuncExpr = 
(AbstractFunctionCallExpression) parentExpr;
-            //Get 'myType' as we will create the child type of the newParent
-            ExpectedSchemaNodeType myType = getExpectedNestedNodeType(myExpr);
-            /*
-             * Create 'myNode'. It is a nested node because the function is 
either getField() or supported array
-             * function
-             */
-            AbstractComplexExpectedSchemaNode myNode = 
AbstractComplexExpectedSchemaNode.createNestedNode(myType,
-                    newParent, myExpr.getSourceLocation(), 
myExpr.getFunctionIdentifier().getName());
-            //Add myNode to the parent
-            addChild(parentFuncExpr, newParent, myNode);
-            return myNode;
-        }
-        return null;
-    }
-
-    private IExpectedSchemaNode changeNodeForVariable(LogicalVariable 
sourceVar,
-            AbstractFunctionCallExpression myExpr) {
-        //Get the associated node with the sourceVar (if any)
-        IExpectedSchemaNode oldNode = varToNode.get(sourceVar);
-        if (oldNode == null) {
-            //Variable is not associated with a node. No pushdown is possible
-            return null;
-        }
-        //What is the expected type of the variable
-        ExpectedSchemaNodeType varExpectedType = 
getExpectedNestedNodeType(myExpr);
-        // Get the node associated with the variable (or change its type if 
needed).
-        IExpectedSchemaNode newNode = oldNode.replaceIfNeeded(varExpectedType, 
myExpr.getSourceLocation(),
-                myExpr.getFunctionIdentifier().getName());
-        //Map the sourceVar to the node
-        varToNode.put(sourceVar, newNode);
-        return newNode;
-    }
-
-    private void addChild(AbstractFunctionCallExpression parentExpr, 
AbstractComplexExpectedSchemaNode parent,
-            IExpectedSchemaNode child) {
-        switch (parent.getType()) {
-            case OBJECT:
-                handleObject(parentExpr, parent, child);
-                break;
-            case ARRAY:
-                handleArray(parent, child);
-                break;
-            case UNION:
-                handleUnion(parentExpr, parent, child);
-                break;
-            default:
-                throw new IllegalStateException("Node " + parent.getType() + " 
is not nested");
-
-        }
-    }
-
-    private void handleObject(AbstractFunctionCallExpression parentExpr, 
AbstractComplexExpectedSchemaNode parent,
-            IExpectedSchemaNode child) {
-        ObjectExpectedSchemaNode objectNode = (ObjectExpectedSchemaNode) 
parent;
-        
objectNode.addChild(ConstantExpressionUtil.getStringArgument(parentExpr, 1), 
child);
-    }
-
-    private void handleArray(AbstractComplexExpectedSchemaNode parent, 
IExpectedSchemaNode child) {
-        ArrayExpectedSchemaNode arrayNode = (ArrayExpectedSchemaNode) parent;
-        arrayNode.addChild(child);
-    }
-
-    private void handleUnion(AbstractFunctionCallExpression parentExpr, 
AbstractComplexExpectedSchemaNode parent,
-            IExpectedSchemaNode child) {
-        UnionExpectedSchemaNode unionNode = (UnionExpectedSchemaNode) parent;
-        ExpectedSchemaNodeType parentType = 
getExpectedNestedNodeType(parentExpr);
-        addChild(parentExpr, unionNode.getChild(parentType), child);
-    }
-
-    private static ExpectedSchemaNodeType 
getExpectedNestedNodeType(AbstractFunctionCallExpression funcExpr) {
-        FunctionIdentifier fid = funcExpr.getFunctionIdentifier();
-        if (BuiltinFunctions.FIELD_ACCESS_BY_NAME.equals(fid)) {
-            return ExpectedSchemaNodeType.OBJECT;
-        } else if (ARRAY_FUNCTIONS.contains(fid)) {
-            return ExpectedSchemaNodeType.ARRAY;
-        }
-        throw new IllegalStateException("Function " + fid + " should not be 
pushed down");
-    }
-
-    private static boolean isVariable(ILogicalExpression expr) {
-        return expr.getExpressionTag() == LogicalExpressionTag.VARIABLE;
-    }
-}
->>>>>>> BRANCH (0ef025 Merge branch 'gerrit/neo' into 'gerrit/trinity')
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 e442d64..23da417 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
@@ -56,6 +56,11 @@

     public boolean setSchemaFromExpression(AbstractFunctionCallExpression 
expr, LogicalVariable producedVar,
             IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+        return buildExpectedSchemaNodes(expr, producedVar, typeEnv);
+    }
+
+    public boolean 
setSchemaFromCalculatedExpression(AbstractFunctionCallExpression expr, 
LogicalVariable producedVar,
+            IVariableTypeEnvironment typeEnv) throws AlgebricksException {
         //Parent always nested
         AbstractComplexExpectedSchemaNode parent = 
(AbstractComplexExpectedSchemaNode) buildNestedNode(expr, typeEnv);
         if (parent != null) {
@@ -104,6 +109,71 @@
         return varToNode.get(variable);
     }

+    private boolean buildExpectedSchemaNodes(ILogicalExpression expr, 
LogicalVariable producedVar,
+            IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+        return buildNestedNodes(expr, producedVar, typeEnv);
+    }
+
+    private boolean buildNestedNodes(ILogicalExpression expr, LogicalVariable 
producedVar,
+            IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+        //The current node expression
+        boolean changed = false;
+        if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+            return false;
+        }
+        AbstractFunctionCallExpression myExpr = 
(AbstractFunctionCallExpression) expr;
+        if (!SUPPORTED_FUNCTIONS.contains(myExpr.getFunctionIdentifier()) || 
noArgsOrFirstArgIsConstant(myExpr)) {
+            // Check if the function consists of the Supported Functions
+            for (Mutable<ILogicalExpression> arg : myExpr.getArguments()) {
+                changed |= buildNestedNodes(arg.getValue(), producedVar, 
typeEnv);
+            }
+            return changed;
+        }
+        // if the child is not a function expression, then just one node.
+        if (BuiltinFunctions.ARRAY_STAR.equals(myExpr.getFunctionIdentifier())
+                || 
BuiltinFunctions.SCAN_COLLECTION.equals(myExpr.getFunctionIdentifier())) {
+            // these supported function won't have second child
+            IExpectedSchemaNode expectedSchemaNode = buildNestedNode(expr, 
typeEnv);
+            if (expectedSchemaNode != null) {
+                changed |=
+                        
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) expr, 
producedVar, typeEnv);
+            }
+        } else {
+            ILogicalExpression childExpr = 
myExpr.getArguments().get(1).getValue();
+            if (childExpr.getExpressionTag() != 
LogicalExpressionTag.FUNCTION_CALL) {
+                // must be a variable or constant
+                IExpectedSchemaNode expectedSchemaNode = buildNestedNode(expr, 
typeEnv);
+                if (expectedSchemaNode != null) {
+                    changed |= 
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) expr, 
producedVar,
+                            typeEnv);
+                }
+            } else {
+                // as the childExpr is a function.
+                // if the function had been evaluated at compile time, it 
would have been
+                // evaluated at this stage of compilation.
+                // eg: field-access(t.r.p, substring("name",2,4))
+                // this will be evaluated to field-access(t.r.p, "me") at 
compile time itself.
+                // since the execution reached this branch, this means the 
childExpr
+                // need to be evaluated at runtime, hence the childExpr should 
also be checked
+                // for possible pushdown.
+                // eg: field-access(t.r.p, substring(x.y.age_field, 0, 4))
+                ILogicalExpression parentExpr = 
myExpr.getArguments().get(0).getValue();
+                IExpectedSchemaNode parentExpectedNode = 
buildNestedNode(parentExpr, typeEnv);
+                if (parentExpectedNode != null) {
+                    changed |= 
setSchemaFromCalculatedExpression((AbstractFunctionCallExpression) parentExpr,
+                            producedVar, typeEnv);
+                }
+                changed |= buildNestedNodes(childExpr, producedVar, typeEnv);
+            }
+        }
+        return changed;
+    }
+
+    private boolean noArgsOrFirstArgIsConstant(AbstractFunctionCallExpression 
myExpr) {
+        List<Mutable<ILogicalExpression>> args = myExpr.getArguments();
+        return args.isEmpty() || args.get(0).getValue().getExpressionTag() == 
LogicalExpressionTag.CONSTANT;
+    }
+
     private IExpectedSchemaNode buildNestedNode(ILogicalExpression expr, 
IVariableTypeEnvironment typeEnv)
             throws AlgebricksException {
         //The current node expression
@@ -142,11 +212,6 @@
         return null;
     }

-    private boolean noArgsOrFirstArgIsConstant(AbstractFunctionCallExpression 
myExpr) {
-        List<Mutable<ILogicalExpression>> args = myExpr.getArguments();
-        return args.isEmpty() || args.get(0).getValue().getExpressionTag() == 
LogicalExpressionTag.CONSTANT;
-    }
-
     private IExpectedSchemaNode changeNodeForVariable(LogicalVariable 
sourceVar,
             AbstractFunctionCallExpression parentExpression, 
ILogicalExpression expression) {
         //Get the associated node with the sourceVar (if any)
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/ExternalDatasetTestUtils.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/ExternalDatasetTestUtils.java
index 92f0063..9e63c44 100644
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/ExternalDatasetTestUtils.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/external_dataset/ExternalDatasetTestUtils.java
@@ -395,7 +395,7 @@
         loadData(generatedDataBasePath, "", "heterogeneous_1.parquet", 
definition, definitionSegment, false, false);
         loadData(generatedDataBasePath, "", "heterogeneous_2.parquet", 
definition, definitionSegment, false, false);
         loadData(generatedDataBasePath, "", "parquetTypes.parquet", 
definition, definitionSegment, false, false);
-<<<<<<< HEAD   (474bef Merge branch 'gerrit/trinity' into 'gerrit/goldfish')
+        loadData(generatedDataBasePath, "", "friends.parquet", definition, 
definitionSegment, false, false);

         Collection<File> files =
                 IoUtil.getMatchingFiles(Paths.get(generatedDataBasePath + 
"/external-filter"), PARQUET_FILTER);
@@ -471,9 +471,6 @@
             size++;
         }
         LOGGER.info("Loaded {} files from {}", size, dataBasePath + 
File.separator + rootPath);
-=======
-        loadData(generatedDataBasePath, "", "friends.parquet", definition, 
definitionSegment, false, false);
->>>>>>> BRANCH (0ef025 Merge branch 'gerrit/neo' into 'gerrit/trinity')
     }

     private static void loadData(String fileBasePath, String filePathSegment, 
String filename, String definition,
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
index c5f8436..1f2126c 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
@@ -1,22 +1,22 @@
-distribute result [$$297] [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+distribute result [$$311] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    project ([$$297]) [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+    project ([$$311]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
     -- STREAM_PROJECT  |PARTITIONED|
-      assign [$$297] <- [{"id": $$331}] [cardinality: 2.1, op-cost: 0.0, 
total-cost: 2.1]
+      assign [$$311] <- [{"id": $$345}] [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
       -- ASSIGN  |PARTITIONED|
-        select (not(is-null($$331))) [cardinality: 2.1, op-cost: 0.0, 
total-cost: 2.1]
+        select (not(is-null($$345))) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
         -- STREAM_SELECT  |PARTITIONED|
-          project ([$$331]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 
2.1]
+          project ([$$345]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
           -- STREAM_PROJECT  |PARTITIONED|
-            assign [$$331] <- [string-default-null($$s.getField("id"))] 
[cardinality: 1000000.0, op-cost: 0.0, total-cost: 2.1]
+            assign [$$345] <- [string-default-null($$s.getField("id"))] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
             -- ASSIGN  |PARTITIONED|
-              project ([$$s]) [cardinality: 1000000.0, op-cost: 0.0, 
total-cost: 2.1]
+              project ([$$s]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
               -- STREAM_PROJECT  |PARTITIONED|
-                exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 
2.1]
+                exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  data-scan []<-[$$300, $$s] <- test.dat1 [cardinality: 
1000000.0, op-cost: 2.1, total-cost: 2.1]
+                  data-scan []<-[$$314, $$s] <- test.dat1 [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                   -- DATASOURCE_SCAN  |PARTITIONED|
                     exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
index 3029611..2f074b7 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
@@ -1,39 +1,39 @@
-distribute result [$$303] [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+distribute result [$$317] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+  exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    project ([$$303]) [cardinality: 2.1, op-cost: 0.0, total-cost: 2.1]
+    project ([$$317]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
     -- STREAM_PROJECT  |PARTITIONED|
-      assign [$$303] <- [{"dat3": {"id": $$337, "a": 
string-default-null($$331), "d": int64-default-null($$304)}}] [cardinality: 
2.1, op-cost: 0.0, total-cost: 2.1]
+      assign [$$317] <- [{"dat3": {"id": $$351, "a": 
string-default-null($$345), "d": int64-default-null($$318)}}] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
       -- ASSIGN  |PARTITIONED|
-        project ([$$337, $$331, $$304]) [cardinality: 2.1, op-cost: 0.0, 
total-cost: 2.1]
+        project ([$$351, $$345, $$318]) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
         -- STREAM_PROJECT  |PARTITIONED|
-          select (le($$304, get-item($$281, 0))) [cardinality: 2.1, op-cost: 
0.0, total-cost: 2.1]
+          select (le($$318, get-item($$295, 0))) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
           -- STREAM_SELECT  |PARTITIONED|
-            project ([$$337, $$331, $$304, $$281]) [cardinality: 1000000.0, 
op-cost: 0.0, total-cost: 2.1]
+            project ([$$351, $$345, $$318, $$295]) [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
             -- STREAM_PROJECT  |PARTITIONED|
               subplan {
-                        aggregate [$$281] <- [listify($$316)] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                        aggregate [$$295] <- [listify($$330)] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
                         -- AGGREGATE  |LOCAL|
-                          aggregate [$$316] <- [agg-sql-count(1)] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          aggregate [$$330] <- [agg-sql-count(1)] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- AGGREGATE  |LOCAL|
-                            unnest $$319 <- scan-collection($$329) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            unnest $$333 <- scan-collection($$343) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- UNNEST  |LOCAL|
                               nested tuple source [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
                               -- NESTED_TUPLE_SOURCE  |LOCAL|
-                     } [cardinality: 1000000.0, op-cost: 0.0, total-cost: 2.1]
+                     } [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
               -- SUBPLAN  |PARTITIONED|
-                select (not(is-null($$337))) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                select (not(is-null($$351))) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                 -- STREAM_SELECT  |PARTITIONED|
-                  project ([$$337, $$331, $$304, $$329]) [cardinality: 
1000000.0, op-cost: 0.0, total-cost: 2.1]
+                  project ([$$351, $$345, $$318, $$343]) [cardinality: 0.0, 
op-cost: 0.0, total-cost: 0.0]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    assign [$$337, $$331, $$304, $$329] <- 
[string-default-null($$s.getField("id")), $$s.getField("a"), $$s.getField("d"), 
$$s.getField("e")] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 2.1]
+                    assign [$$351, $$345, $$318, $$343] <- 
[string-default-null($$s.getField("id")), $$s.getField("a"), $$s.getField("d"), 
$$s.getField("e")] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- ASSIGN  |PARTITIONED|
-                      project ([$$s]) [cardinality: 1000000.0, op-cost: 0.0, 
total-cost: 2.1]
+                      project ([$$s]) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 0.0, 
total-cost: 2.1]
+                        exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 
0.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          data-scan []<-[$$305, $$s] <- test.dat1 
[cardinality: 1000000.0, op-cost: 2.1, total-cost: 2.1]
+                          data-scan []<-[$$319, $$s] <- test.dat1 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- DATASOURCE_SCAN  |PARTITIONED|
                             exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
new file mode 100644
index 0000000..dc43c42
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.3.plan
@@ -0,0 +1,24 @@
+distribute result [$$311] [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    project ([$$311]) [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+    -- STREAM_PROJECT  |PARTITIONED|
+      assign [$$311] <- [{"id": $$345}] [cardinality: 8.0, op-cost: 0.0, 
total-cost: 8.0]
+      -- ASSIGN  |PARTITIONED|
+        select (not(is-null($$345))) [cardinality: 8.0, op-cost: 0.0, 
total-cost: 8.0]
+        -- STREAM_SELECT  |PARTITIONED|
+          project ([$$345]) [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+          -- STREAM_PROJECT  |PARTITIONED|
+            assign [$$345] <- [string-default-null($$s.getField("id"))] 
[cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+            -- ASSIGN  |PARTITIONED|
+              project ([$$s]) [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+              -- STREAM_PROJECT  |PARTITIONED|
+                exchange [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$314, $$s] <- test.dat1 [cardinality: 8.0, 
op-cost: 8.0, total-cost: 8.0]
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
new file mode 100644
index 0000000..b9dda19
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/subquery/query-ASTERIXDB-3538/query-ASTERIXDB-3538.5.plan
@@ -0,0 +1,41 @@
+distribute result [$$317] [cardinality: 4.0, op-cost: 0.0, total-cost: 8.0]
+-- DISTRIBUTE_RESULT  |PARTITIONED|
+  exchange [cardinality: 4.0, op-cost: 0.0, total-cost: 8.0]
+  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+    project ([$$317]) [cardinality: 4.0, op-cost: 0.0, total-cost: 8.0]
+    -- STREAM_PROJECT  |PARTITIONED|
+      assign [$$317] <- [{"dat3": {"id": $$351, "a": 
string-default-null($$345), "d": int64-default-null($$318)}}] [cardinality: 
4.0, op-cost: 0.0, total-cost: 8.0]
+      -- ASSIGN  |PARTITIONED|
+        project ([$$351, $$345, $$318]) [cardinality: 4.0, op-cost: 0.0, 
total-cost: 8.0]
+        -- STREAM_PROJECT  |PARTITIONED|
+          select (le($$318, get-item($$295, 0))) [cardinality: 4.0, op-cost: 
0.0, total-cost: 8.0]
+          -- STREAM_SELECT  |PARTITIONED|
+            project ([$$351, $$345, $$318, $$295]) [cardinality: 8.0, op-cost: 
0.0, total-cost: 8.0]
+            -- STREAM_PROJECT  |PARTITIONED|
+              subplan {
+                        aggregate [$$295] <- [listify($$330)] [cardinality: 
0.0, op-cost: 0.0, total-cost: 0.0]
+                        -- AGGREGATE  |LOCAL|
+                          aggregate [$$330] <- [agg-sql-count(1)] 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+                          -- AGGREGATE  |LOCAL|
+                            unnest $$333 <- scan-collection($$343) 
[cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- UNNEST  |LOCAL|
+                              nested tuple source [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                              -- NESTED_TUPLE_SOURCE  |LOCAL|
+                     } [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+              -- SUBPLAN  |PARTITIONED|
+                select (not(is-null($$351))) [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                -- STREAM_SELECT  |PARTITIONED|
+                  project ([$$351, $$345, $$318, $$343]) [cardinality: 8.0, 
op-cost: 0.0, total-cost: 8.0]
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    assign [$$351, $$345, $$318, $$343] <- 
[string-default-null($$s.getField("id")), $$s.getField("a"), $$s.getField("d"), 
$$s.getField("e")] [cardinality: 8.0, op-cost: 0.0, total-cost: 8.0]
+                    -- ASSIGN  |PARTITIONED|
+                      project ([$$s]) [cardinality: 8.0, op-cost: 0.0, 
total-cost: 8.0]
+                      -- STREAM_PROJECT  |PARTITIONED|
+                        exchange [cardinality: 8.0, op-cost: 0.0, total-cost: 
8.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          data-scan []<-[$$319, $$s] <- test.dat1 
[cardinality: 8.0, op-cost: 8.0, total-cost: 8.0]
+                          -- DATASOURCE_SCAN  |PARTITIONED|
+                            exchange [cardinality: 0.0, op-cost: 0.0, 
total-cost: 0.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              empty-tuple-source [cardinality: 0.0, op-cost: 
0.0, total-cost: 0.0]
+                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19317
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings

Gerrit-Project: asterixdb
Gerrit-Branch: goldfish
Gerrit-Change-Id: If535113f5438a9d32420ffd1d35d44a24a217b1e
Gerrit-Change-Number: 19317
Gerrit-PatchSet: 3
Gerrit-Owner: Michael Blow <[email protected]>
Gerrit-Reviewer: Jenkins <[email protected]>
Gerrit-Reviewer: Michael Blow <[email protected]>
Gerrit-CC: Anon. E. Moose #1000171
Gerrit-MessageType: merged

Reply via email to