Dmitry Lychagin has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/3436


Change subject: [NO ISSUE][COMP] Do not inline non-functional LET clauses
......................................................................

[NO ISSUE][COMP] Do not inline non-functional LET clauses

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- When inlining LET clauses in LET ... SELECT ...
  skip those that contain non-functional expressions

Change-Id: I3740745e2e8c8a0bb11aa7908e68c682dd9a5553
---
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.2.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.2.adm
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
M 
asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
M 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
A 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
A 
asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
M 
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
9 files changed, 430 insertions(+), 7 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/36/3436/1

diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.2.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.2.query.sqlpp
new file mode 100644
index 0000000..c23f43b
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.2.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description    : Test that a LET clause containing random() is not inlined
+ * Success        : Yes
+ */
+
+LET x = random(), y = tostring(x)
+FROM range(1, 1) r
+SELECT VALUE string(x) = y
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.2.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.2.adm
new file mode 100644
index 0000000..f32a580
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.2.adm
@@ -0,0 +1 @@
+true
\ No newline at end of file
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
index 6752f77..24384f2 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/FunctionUtil.java
@@ -58,6 +58,15 @@
         return getFunctionInfo(new FunctionIdentifier(fs.getNamespace(), 
fs.getName(), fs.getArity()));
     }

+    public static IFunctionInfo getBuiltinFunctionInfo(String functionName, 
int arity) {
+        IFunctionInfo fi =
+                getFunctionInfo(new 
FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, functionName, 
arity));
+        if (fi == null) {
+            fi = getFunctionInfo(new 
FunctionIdentifier(FunctionConstants.ASTERIX_NS, functionName, arity));
+        }
+        return fi;
+    }
+
     @FunctionalInterface
     public interface IFunctionCollector {
         Set<CallExpr> getFunctionCalls(Expression expression) throws 
CompilationException;
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
index 117fa77..28533e1 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/base/AbstractQueryExpressionVisitor.java
@@ -39,12 +39,14 @@
 import org.apache.asterix.lang.common.statement.DropDatasetStatement;
 import org.apache.asterix.lang.common.statement.FeedDropStatement;
 import org.apache.asterix.lang.common.statement.FeedPolicyDropStatement;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.FunctionDropStatement;
 import org.apache.asterix.lang.common.statement.IndexDropStatement;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.LoadStatement;
 import org.apache.asterix.lang.common.statement.NodeGroupDropStatement;
 import org.apache.asterix.lang.common.statement.NodegroupDecl;
+import org.apache.asterix.lang.common.statement.Query;
 import org.apache.asterix.lang.common.statement.SetStatement;
 import org.apache.asterix.lang.common.statement.StartFeedStatement;
 import org.apache.asterix.lang.common.statement.StopFeedStatement;
@@ -56,6 +58,16 @@
 public abstract class AbstractQueryExpressionVisitor<R, T> implements 
ILangVisitor<R, T> {

     @Override
+    public R visit(Query q, T arg) throws CompilationException {
+        return null;
+    }
+
+    @Override
+    public R visit(FunctionDecl fd, T arg) throws CompilationException {
+        return null;
+    }
+
+    @Override
     public R visit(CreateIndexStatement cis, T arg) throws 
CompilationException {
         return null;
     }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index 28851fd..8bc319f 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -150,10 +150,6 @@
         // Rewrites like/not-like expressions.
         rewriteOperatorExpression();

-        // Inlines WITH expressions after variableCheckAndRewrite(...) so that 
the variable scoping for WITH
-        // expression is correct.
-        inlineWithExpressions();
-
         // Rewrites several variable-arg functions into their corresponding 
internal list-input functions.
         rewriteListInputFunctions();

@@ -165,6 +161,10 @@
         // names could be case sensitive.
         rewriteFunctionNames();

+        // Inlines WITH expressions after variableCheckAndRewrite(...) so that 
the variable scoping for WITH
+        // expression is correct.
+        inlineWithExpressions();
+
         // Sets the var counter of the query.
         topStatement.setVarCounter(context.getVarCounter().get());
     }
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
index ebb7b10..9865bdf 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineWithExpressionVisitor.java
@@ -32,9 +32,13 @@
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
 import org.apache.asterix.lang.sqlpp.util.SqlppRewriteUtil;
+import 
org.apache.asterix.lang.sqlpp.visitor.CheckNonFunctionalExpressionVisitor;
 import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;

 public class InlineWithExpressionVisitor extends 
AbstractSqlppExpressionScopingVisitor {
+
+    private final CheckNonFunctionalExpressionVisitor 
checkNonFunctionalExpressionVisitor =
+            new CheckNonFunctionalExpressionVisitor();

     public InlineWithExpressionVisitor(LangRewritingContext context) {
         super(context);
@@ -57,11 +61,14 @@
                 // Performs the rewriting recursively in the newBindingExpr 
itself.
                 super.visit(newBindingExpr, arg);

+                Expression bindingExpr = letClause.getBindingExpr();
+                Boolean isNonFunctional = 
bindingExpr.accept(checkNonFunctionalExpressionVisitor, null);
+                if (isNonFunctional != null && isNonFunctional) {
+                    continue;
+                }
+
                 // Removes the WITH entry and adds variable-expr mapping into 
the varExprMap.
                 with.remove();
-                Expression bindingExpr = letClause.getBindingExpr();
-                // Wraps the binding expression with IndependentSubquery, so 
that free identifier references
-                // in the binding expression will not be resolved use 
outer-scope variables.
                 varExprMap.put(letClause.getVarExpr(), bindingExpr);
             }

diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
new file mode 100644
index 0000000..167660a
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckNonFunctionalExpressionVisitor.java
@@ -0,0 +1,44 @@
+/*
+ * 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.lang.sqlpp.visitor;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import 
org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppContainsExpressionVisitor;
+import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
+
+/**
+ * Checks whether given expression is non-functional (i.e. whether it calls a 
non-functional function)
+ */
+public final class CheckNonFunctionalExpressionVisitor extends 
AbstractSqlppContainsExpressionVisitor<Void> {
+    @Override
+    public Boolean visit(CallExpr callExpr, Void arg) throws 
CompilationException {
+        FunctionSignature fs = callExpr.getFunctionSignature();
+        IFunctionInfo fi = FunctionUtil.getBuiltinFunctionInfo(fs.getName(), 
fs.getArity());
+        // TODO: all external functions are considered functional for now.
+        // we'll need to revisit this code once we enable non-functional in 
ExternalFunctionInfo
+        if (fi != null && !fi.isFunctional()) {
+            return true;
+        }
+        return super.visit(callExpr, arg);
+    }
+}
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
new file mode 100644
index 0000000..72d4a92
--- /dev/null
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppContainsExpressionVisitor.java
@@ -0,0 +1,322 @@
+/*
+ * 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.lang.sqlpp.visitor.base;
+
+import java.util.Collection;
+
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.clause.GroupbyClause;
+import org.apache.asterix.lang.common.clause.LetClause;
+import org.apache.asterix.lang.common.clause.LimitClause;
+import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.clause.WhereClause;
+import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.FieldAccessor;
+import org.apache.asterix.lang.common.expression.FieldBinding;
+import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
+import org.apache.asterix.lang.common.expression.IfExpr;
+import org.apache.asterix.lang.common.expression.IndexAccessor;
+import org.apache.asterix.lang.common.expression.ListConstructor;
+import org.apache.asterix.lang.common.expression.ListSliceExpression;
+import org.apache.asterix.lang.common.expression.LiteralExpr;
+import org.apache.asterix.lang.common.expression.OperatorExpr;
+import org.apache.asterix.lang.common.expression.QuantifiedExpression;
+import org.apache.asterix.lang.common.expression.RecordConstructor;
+import org.apache.asterix.lang.common.expression.UnaryExpr;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.struct.QuantifiedPair;
+import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.FromTerm;
+import org.apache.asterix.lang.sqlpp.clause.HavingClause;
+import org.apache.asterix.lang.sqlpp.clause.JoinClause;
+import org.apache.asterix.lang.sqlpp.clause.NestClause;
+import org.apache.asterix.lang.sqlpp.clause.Projection;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectElement;
+import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+/**
+ * Base class for visitors that search for expressions having certain 
properties and return a boolean value
+ * indicating whether such expressions were found or not, or {@code null} if 
search could not be performed.
+ */
+public abstract class AbstractSqlppContainsExpressionVisitor<T>
+        extends AbstractSqlppQueryExpressionVisitor<Boolean, T> {
+
+    @Override
+    public Boolean visit(FromClause fromClause, T arg) throws 
CompilationException {
+        for (FromTerm fromTerm : fromClause.getFromTerms()) {
+            if (fromTerm.accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(FromTerm fromTerm, T arg) throws CompilationException 
{
+        if (visit(fromTerm.getLeftExpression(), arg)) {
+            return true;
+        }
+        for (AbstractBinaryCorrelateClause correlateClause : 
fromTerm.getCorrelateClauses()) {
+            if (correlateClause.accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(JoinClause joinClause, T arg) throws 
CompilationException {
+        return visit(joinClause.getRightExpression(), arg) || 
visit(joinClause.getConditionExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(NestClause nestClause, T arg) throws 
CompilationException {
+        return nestClause.accept(this, arg);
+    }
+
+    @Override
+    public Boolean visit(Projection projection, T arg) throws 
CompilationException {
+        ILangExpression expr = projection.getExpression();
+        return expr != null && expr.accept(this, arg);
+    }
+
+    @Override
+    public Boolean visit(SelectBlock selectBlock, T arg) throws 
CompilationException {
+        return visit(selectBlock.getFromClause(), arg) || 
visit(selectBlock.getGroupbyClause(), arg)
+                || visit(selectBlock.getSelectClause(), arg) || 
visitExprList(selectBlock.getLetWhereList(), arg)
+                || visitExprList(selectBlock.getLetHavingListAfterGroupby(), 
arg);
+    }
+
+    @Override
+    public Boolean visit(SelectClause selectClause, T arg) throws 
CompilationException {
+        return visit(selectClause.getSelectElement(), arg) || 
visit(selectClause.getSelectRegular(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectElement selectElement, T arg) throws 
CompilationException {
+        return visit(selectElement.getExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectRegular selectRegular, T arg) throws 
CompilationException {
+        return visitExprList(selectRegular.getProjections(), arg);
+    }
+
+    @Override
+    public Boolean visit(SelectSetOperation selectSetOperation, T arg) throws 
CompilationException {
+        if (selectSetOperation.getLeftInput().accept(this, arg)) {
+            return true;
+        }
+        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+            if (right.getSetOperationRightInput().accept(this, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(SelectExpression selectStatement, T arg) throws 
CompilationException {
+        return visitExprList(selectStatement.getLetList(), arg) || 
visit(selectStatement.getSelectSetOperation(), arg)
+                || visit(selectStatement.getOrderbyClause(), arg) || 
visit(selectStatement.getLimitClause(), arg);
+    }
+
+    @Override
+    public Boolean visit(UnnestClause unnestClause, T arg) throws 
CompilationException {
+        return visit(unnestClause.getRightExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(HavingClause havingClause, T arg) throws 
CompilationException {
+        return visit(havingClause.getFilterExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(CaseExpression caseExpression, T arg) throws 
CompilationException {
+        return visit(caseExpression.getConditionExpr(), arg) || 
visitExprList(caseExpression.getWhenExprs(), arg)
+                || visitExprList(caseExpression.getThenExprs(), arg) || 
visit(caseExpression.getElseExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(LiteralExpr l, T arg) throws CompilationException {
+        return false;
+    }
+
+    @Override
+    public Boolean visit(VariableExpr v, T arg) throws CompilationException {
+        return false;
+    }
+
+    @Override
+    public Boolean visit(ListConstructor lc, T arg) throws 
CompilationException {
+        return visitExprList(lc.getExprList(), arg);
+    }
+
+    @Override
+    public Boolean visit(RecordConstructor rc, T arg) throws 
CompilationException {
+        for (FieldBinding fb : rc.getFbList()) {
+            if (visit(fb.getLeftExpr(), arg)) {
+                return true;
+            }
+            if (visit(fb.getRightExpr(), arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(OperatorExpr operatorExpr, T arg) throws 
CompilationException {
+        return visitExprList(operatorExpr.getExprList(), arg);
+    }
+
+    @Override
+    public Boolean visit(FieldAccessor fa, T arg) throws CompilationException {
+        return visit(fa.getExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(IndexAccessor ia, T arg) throws CompilationException {
+        return visit(ia.getExpr(), arg) || visit(ia.getIndexExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(ListSliceExpression expression, T arg) throws 
CompilationException {
+        return visit(expression.getExpr(), arg) || 
visit(expression.getStartIndexExpression(), arg)
+                || visit(expression.getEndIndexExpression(), arg);
+    }
+
+    @Override
+    public Boolean visit(IfExpr ifexpr, T arg) throws CompilationException {
+        return visit(ifexpr.getCondExpr(), arg) || visit(ifexpr.getThenExpr(), 
arg) || visit(ifexpr.getElseExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(QuantifiedExpression qe, T arg) throws 
CompilationException {
+        for (QuantifiedPair qf : qe.getQuantifiedList()) {
+            if (visit(qf.getExpr(), arg)) {
+                return true;
+            }
+        }
+        return visit(qe.getSatisfiesExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(LetClause lc, T arg) throws CompilationException {
+        return visit(lc.getBindingExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(WhereClause wc, T arg) throws CompilationException {
+        return visit(wc.getWhereExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(OrderbyClause oc, T arg) throws CompilationException {
+        return visitExprList(oc.getOrderbyList(), arg);
+    }
+
+    @Override
+    public Boolean visit(GroupbyClause gc, T arg) throws CompilationException {
+        for (GbyVariableExpressionPair key : gc.getGbyPairList()) {
+            if (visit(key.getExpr(), arg)) {
+                return true;
+            }
+        }
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair key : gc.getDecorPairList()) {
+                if (visit(key.getExpr(), arg)) {
+                    return true;
+                }
+            }
+        }
+        if (gc.hasGroupFieldList() && visitFieldList(gc.getGroupFieldList(), 
arg)) {
+            return true;
+        }
+        if (gc.hasWithMap() && visitExprList(gc.getWithVarMap().keySet(), 
arg)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean visit(LimitClause lc, T arg) throws CompilationException {
+        return visit(lc.getLimitExpr(), arg) || visit(lc.getOffset(), arg);
+    }
+
+    @Override
+    public Boolean visit(UnaryExpr u, T arg) throws CompilationException {
+        return visit(u.getExpr(), arg);
+    }
+
+    @Override
+    public Boolean visit(WindowExpression winExpr, T arg) throws 
CompilationException {
+        return (winExpr.hasPartitionList() && 
visitExprList(winExpr.getPartitionList(), arg))
+                || (winExpr.hasOrderByList() && 
visitExprList(winExpr.getOrderbyList(), arg))
+                || (winExpr.hasFrameStartExpr() && 
visit(winExpr.getFrameStartExpr(), arg))
+                || (winExpr.hasFrameEndExpr() && 
visit(winExpr.getFrameEndExpr(), arg))
+                || (winExpr.hasWindowFieldList() && 
visitFieldList(winExpr.getWindowFieldList(), arg))
+                || visitExprList(winExpr.getExprList(), arg);
+    }
+
+    @Override
+    public Boolean visit(CallExpr callExpr, T arg) throws CompilationException 
{
+        return visitExprList(callExpr.getExprList(), arg);
+    }
+
+    private boolean visit(ILangExpression expr, T arg) throws 
CompilationException {
+        if (expr == null) {
+            return false;
+        }
+        return expr.accept(this, arg);
+    }
+
+    private <E extends ILangExpression> boolean visitExprList(Collection<E> 
exprList, T arg)
+            throws CompilationException {
+        for (E langExpr : exprList) {
+            if (visit(langExpr, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private <E extends ILangExpression> boolean 
visitFieldList(Collection<Pair<E, Identifier>> fieldList, T arg)
+            throws CompilationException {
+        for (Pair<E, Identifier> p : fieldList) {
+            if (visit(p.first, arg)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
index 2c80470..c1ad794 100644
--- 
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
+++ 
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/ExternalFunctionInfo.java
@@ -37,6 +37,7 @@

     public ExternalFunctionInfo(String namespace, String name, int arity, 
FunctionKind kind, List<IAType> argumentTypes,
             IAType returnType, IResultTypeComputer rtc, String body, String 
language) {
+        // TODO: fix CheckNonFunctionalExpressionVisitor once we have 
non-functional external functions
         super(namespace, name, arity, true);
         this.rtc = rtc;
         this.argumentTypes = argumentTypes;

--
To view, visit https://asterix-gerrit.ics.uci.edu/3436
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I3740745e2e8c8a0bb11aa7908e68c682dd9a5553
Gerrit-Change-Number: 3436
Gerrit-PatchSet: 1
Gerrit-Owner: Dmitry Lychagin <dmitry.lycha...@couchbase.com>

Reply via email to