[NO ISSUE][COMP] Introduce AbstractCallExpression
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Introduce AbstractCallExpression - base class for
CallExpr and WindowExpression
- Modify implementations of IQueryRewriter.getFunctionCalls()
and IFunctionCollector.getFunctionCalls() to return
WindowExpression in addition to CallExpr
Change-Id: I40599e7f8083d8bb28aa3c8a87eed8afdc59f739
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/10044
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index c000d8b..40a3c10 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -2168,7 +2168,7 @@
apiFramework.reWriteQuery(declaredFunctions, metadataProvider, wrappedQuery, sessionOutput, false,
paramVars, warningCollector);
List<List<Triple<DataverseName, String, String>>> dependencies = FunctionUtil.getFunctionDependencies(
- rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression(), metadataProvider);
+ rewriterFactory.createQueryRewriter(), cfs.getFunctionBodyExpression());
newInlineTypes = Collections.emptyMap();
function = new Function(functionSignature, paramNames, null, null, cfs.getFunctionBody(),
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
index 7500ab9..3e1851c 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/base/IQueryRewriter.java
@@ -23,7 +23,7 @@
import java.util.Set;
import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
import org.apache.asterix.lang.common.statement.FunctionDecl;
@@ -52,11 +52,10 @@
/**
* Find the function calls used by a given expression
*/
- Set<CallExpr> getFunctionCalls(Expression expression) throws CompilationException;
+ Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException;
/**
* Find all external variables (positional and named variables) in given expression
*/
Set<VariableExpr> getExternalVariables(Expression expr) throws CompilationException;
-
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/AbstractCallExpression.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/AbstractCallExpression.java
new file mode 100644
index 0000000..c8de5c5
--- /dev/null
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/AbstractCallExpression.java
@@ -0,0 +1,71 @@
+/*
+ * 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.common.expression;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.common.base.AbstractExpression;
+import org.apache.asterix.lang.common.base.Expression;
+
+public abstract class AbstractCallExpression extends AbstractExpression {
+
+ protected FunctionSignature functionSignature;
+
+ protected List<Expression> exprList;
+
+ protected Expression aggFilterExpr;
+
+ protected AbstractCallExpression(FunctionSignature functionSignature, List<Expression> exprList,
+ Expression aggFilterExpr) {
+ this.functionSignature = Objects.requireNonNull(functionSignature);
+ this.exprList = Objects.requireNonNull(exprList);
+ this.aggFilterExpr = aggFilterExpr;
+ }
+
+ public FunctionSignature getFunctionSignature() {
+ return functionSignature;
+ }
+
+ public void setFunctionSignature(FunctionSignature functionSignature) {
+ this.functionSignature = Objects.requireNonNull(functionSignature);
+ }
+
+ public List<Expression> getExprList() {
+ return exprList;
+ }
+
+ public void setExprList(List<Expression> exprList) {
+ this.exprList = Objects.requireNonNull(exprList);
+ }
+
+ public boolean hasAggregateFilterExpr() {
+ return aggFilterExpr != null;
+ }
+
+ public Expression getAggregateFilterExpr() {
+ return aggFilterExpr;
+ }
+
+ public void setAggregateFilterExpr(Expression aggFilterExpr) {
+ this.aggFilterExpr = aggFilterExpr;
+ }
+}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/CallExpr.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/CallExpr.java
index d0c29d5..6895a65 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/CallExpr.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/CallExpr.java
@@ -23,39 +23,17 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.lang.common.base.AbstractExpression;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
-public class CallExpr extends AbstractExpression {
- private FunctionSignature functionSignature;
- private List<Expression> exprList;
- private Expression aggFilterExpr;
+public class CallExpr extends AbstractCallExpression {
public CallExpr(FunctionSignature functionSignature, List<Expression> exprList) {
- this(functionSignature, exprList, null);
+ super(functionSignature, exprList, null);
}
public CallExpr(FunctionSignature functionSignature, List<Expression> exprList, Expression aggFilterExpr) {
- this.functionSignature = functionSignature;
- this.exprList = exprList;
- this.aggFilterExpr = aggFilterExpr;
- }
-
- public FunctionSignature getFunctionSignature() {
- return functionSignature;
- }
-
- public List<Expression> getExprList() {
- return exprList;
- }
-
- public boolean hasAggregateFilterExpr() {
- return aggFilterExpr != null;
- }
-
- public Expression getAggregateFilterExpr() {
- return aggFilterExpr;
+ super(functionSignature, exprList, aggFilterExpr);
}
@Override
@@ -63,18 +41,6 @@
return Kind.CALL_EXPRESSION;
}
- public void setFunctionSignature(FunctionSignature functionSignature) {
- this.functionSignature = functionSignature;
- }
-
- public void setExprList(List<Expression> exprList) {
- this.exprList = exprList;
- }
-
- public void setAggregateFilterExpr(Expression aggFilterExpr) {
- this.aggFilterExpr = aggFilterExpr;
- }
-
@Override
public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws CompilationException {
return visitor.visit(this, arg);
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 0592d1e..b491e82 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
@@ -35,6 +35,7 @@
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.IQueryRewriter;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.CallExpr;
import org.apache.asterix.lang.common.expression.OrderedListTypeDefinition;
import org.apache.asterix.lang.common.expression.TypeExpression;
@@ -105,7 +106,7 @@
@FunctionalInterface
public interface IFunctionCollector {
- Set<CallExpr> getFunctionCalls(Expression expression) throws CompilationException;
+ Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException;
}
public static FunctionSignature resolveFunctionCall(FunctionSignature fs, SourceLocation sourceLoc,
@@ -220,61 +221,82 @@
}
List<FunctionDecl> functionDecls =
inputFunctionDecls == null ? new ArrayList<>() : new ArrayList<>(inputFunctionDecls);
- Set<CallExpr> functionCalls = functionCollector.getFunctionCalls(expression);
+ Set<AbstractCallExpression> functionCalls = functionCollector.getFunctionCalls(expression);
Set<FunctionSignature> functionSignatures = new HashSet<>();
- for (CallExpr functionCall : functionCalls) {
- FunctionSignature fs = functionCall.getFunctionSignature();
- if (fs.getDataverseName() == null) {
- throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, functionCall.getSourceLocation(),
- fs);
- }
- if (!functionSignatures.add(fs)) {
- // already seen this signature
- continue;
- }
- if (declaredFunctions != null && declaredFunctions.contains(fs)) {
- continue;
- }
- Function function;
- try {
- function = metadataProvider.lookupUserDefinedFunction(fs);
- } catch (AlgebricksException e) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, functionCall.getSourceLocation(),
- e.toString());
- }
- if (function == null || !functionParser.getLanguage().equals(function.getLanguage())) {
- // the function is either unknown, builtin, or in a different language.
- // either way we ignore it here because it will be handled by the function inlining rule later
- continue;
- }
+ for (AbstractCallExpression functionCall : functionCalls) {
+ switch (functionCall.getKind()) {
+ case CALL_EXPRESSION:
+ FunctionSignature fs = functionCall.getFunctionSignature();
+ if (fs.getDataverseName() == null) {
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE,
+ functionCall.getSourceLocation(), fs);
+ }
+ if (!functionSignatures.add(fs)) {
+ // already seen this signature
+ continue;
+ }
+ if (declaredFunctions != null && declaredFunctions.contains(fs)) {
+ continue;
+ }
+ Function function;
+ try {
+ function = metadataProvider.lookupUserDefinedFunction(fs);
+ } catch (AlgebricksException e) {
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, e, functionCall.getSourceLocation(),
+ e.toString());
+ }
+ if (function == null || !functionParser.getLanguage().equals(function.getLanguage())) {
+ // the function is either unknown, builtin, or in a different language.
+ // either way we ignore it here because it will be handled by the function inlining rule later
+ continue;
+ }
- FunctionDecl functionDecl = functionParser.getFunctionDecl(function, warningCollector);
- if (functionDecls.contains(functionDecl)) {
- throw new CompilationException(ErrorCode.COMPILATION_ERROR, functionCall.getSourceLocation(),
- "Recursive invocation " + functionDecls.get(functionDecls.size() - 1).getSignature() + " <==> "
- + functionDecl.getSignature());
+ FunctionDecl functionDecl = functionParser.getFunctionDecl(function, warningCollector);
+ if (functionDecls.contains(functionDecl)) {
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, functionCall.getSourceLocation(),
+ "Recursive invocation " + functionDecls.get(functionDecls.size() - 1).getSignature()
+ + " <==> " + functionDecl.getSignature());
+ }
+ functionDecls.add(functionDecl);
+ functionDecls = retrieveUsedStoredFunctions(metadataProvider, functionDecl.getFuncBody(),
+ declaredFunctions, functionDecls, functionCollector, functionParser, warningCollector);
+ break;
+ case WINDOW_EXPRESSION:
+ // there cannot be used-defined window functions
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expression.getSourceLocation(),
+ functionCall.getFunctionSignature().toString(false));
}
- functionDecls.add(functionDecl);
- functionDecls = retrieveUsedStoredFunctions(metadataProvider, functionDecl.getFuncBody(), declaredFunctions,
- functionDecls, functionCollector, functionParser, warningCollector);
}
return functionDecls;
}
public static List<List<Triple<DataverseName, String, String>>> getFunctionDependencies(IQueryRewriter rewriter,
- Expression expression, MetadataProvider metadataProvider) throws CompilationException {
- Set<CallExpr> functionCalls = rewriter.getFunctionCalls(expression);
+ Expression expression) throws CompilationException {
+ Set<AbstractCallExpression> functionCalls = rewriter.getFunctionCalls(expression);
//Get the List of used functions and used datasets
List<Triple<DataverseName, String, String>> datasourceDependencies = new ArrayList<>();
List<Triple<DataverseName, String, String>> functionDependencies = new ArrayList<>();
- for (CallExpr functionCall : functionCalls) {
- FunctionSignature signature = functionCall.getFunctionSignature();
- if (isBuiltinDatasetFunction(signature)) {
- Pair<DataverseName, String> datasetReference = parseDatasetFunctionArguments(functionCall);
- datasourceDependencies.add(new Triple<>(datasetReference.first, datasetReference.second, null));
- } else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
- functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
- Integer.toString(signature.getArity())));
+ for (AbstractCallExpression functionCall : functionCalls) {
+ switch (functionCall.getKind()) {
+ case CALL_EXPRESSION:
+ FunctionSignature signature = functionCall.getFunctionSignature();
+ if (isBuiltinDatasetFunction(signature)) {
+ Pair<DataverseName, String> datasetReference =
+ parseDatasetFunctionArguments((CallExpr) functionCall);
+ datasourceDependencies.add(new Triple<>(datasetReference.first, datasetReference.second, null));
+ } else if (BuiltinFunctions.getBuiltinFunctionInfo(signature.createFunctionIdentifier()) == null) {
+ functionDependencies.add(new Triple<>(signature.getDataverseName(), signature.getName(),
+ Integer.toString(signature.getArity())));
+ }
+ break;
+ case WINDOW_EXPRESSION:
+ // there cannot be used-defined window functions
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, expression.getSourceLocation(),
+ functionCall.getFunctionSignature().toString(false));
}
}
List<List<Triple<DataverseName, String, String>>> dependencies = new ArrayList<>(3);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 44b2092..3ad0f1b 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -31,6 +31,7 @@
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.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.CallExpr;
import org.apache.asterix.lang.common.expression.FieldAccessor;
import org.apache.asterix.lang.common.expression.FieldBinding;
@@ -57,7 +58,7 @@
public class GatherFunctionCallsVisitor extends AbstractQueryExpressionVisitor<Void, Void> {
- protected final Set<CallExpr> calls = new LinkedHashSet<>();
+ protected final Set<AbstractCallExpression> calls = new LinkedHashSet<>();
@Override
public Void visit(CallExpr callExpr, Void arg) throws CompilationException {
@@ -239,7 +240,7 @@
return null;
}
- public Set<CallExpr> getCalls() {
+ public Set<AbstractCallExpression> getCalls() {
return calls;
}
@@ -247,5 +248,4 @@
public Void visit(FunctionDecl fd, Void arg) throws CompilationException {
return null;
}
-
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
index 9b603cd..417cae6 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
@@ -24,9 +24,9 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.lang.common.base.AbstractExpression;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.struct.Identifier;
import org.apache.asterix.lang.common.util.ExpressionUtils;
@@ -35,11 +35,7 @@
import org.apache.commons.lang3.StringUtils;
import org.apache.hyracks.algebricks.common.utils.Pair;
-public class WindowExpression extends AbstractExpression {
-
- private FunctionSignature functionSignature;
- private List<Expression> exprList;
- private Expression aggFilterExpr;
+public class WindowExpression extends AbstractCallExpression {
private List<Expression> partitionList;
private List<Expression> orderbyList;
@@ -64,12 +60,7 @@
FrameBoundaryKind frameStartKind, Expression frameStartExpr, FrameBoundaryKind frameEndKind,
Expression frameEndExpr, FrameExclusionKind frameExclusionKind, VariableExpr windowVar,
List<Pair<Expression, Identifier>> windowFieldList, Boolean ignoreNulls, Boolean fromLast) {
- if (functionSignature == null || exprList == null) {
- throw new NullPointerException();
- }
- this.functionSignature = functionSignature;
- this.exprList = exprList;
- this.aggFilterExpr = aggFilterExpr;
+ super(functionSignature, exprList, aggFilterExpr);
this.partitionList = partitionList;
this.orderbyList = orderbyList;
this.orderbyModifierList = orderbyModifierList;
@@ -90,40 +81,6 @@
return Kind.WINDOW_EXPRESSION;
}
- public FunctionSignature getFunctionSignature() {
- return functionSignature;
- }
-
- public void setFunctionSignature(FunctionSignature functionSignature) {
- if (functionSignature == null) {
- throw new NullPointerException();
- }
- this.functionSignature = functionSignature;
- }
-
- public List<Expression> getExprList() {
- return exprList;
- }
-
- public void setExprList(List<Expression> exprList) {
- if (exprList == null) {
- throw new NullPointerException();
- }
- this.exprList = exprList;
- }
-
- public boolean hasAggregateFilterExpr() {
- return aggFilterExpr != null;
- }
-
- public Expression getAggregateFilterExpr() {
- return aggFilterExpr;
- }
-
- public void setAggregateFilterExpr(Expression filterExpr) {
- this.aggFilterExpr = filterExpr;
- }
-
public boolean hasPartitionList() {
return partitionList != null && !partitionList.isEmpty();
}
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 755c1df..af1bb41 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
@@ -33,7 +33,7 @@
import org.apache.asterix.lang.common.base.IQueryRewriter;
import org.apache.asterix.lang.common.base.IReturningStatement;
import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.expression.CallExpr;
+import org.apache.asterix.lang.common.expression.AbstractCallExpression;
import org.apache.asterix.lang.common.expression.ListSliceExpression;
import org.apache.asterix.lang.common.expression.VariableExpr;
import org.apache.asterix.lang.common.parser.FunctionParser;
@@ -345,7 +345,7 @@
}
@Override
- public Set<CallExpr> getFunctionCalls(Expression expression) throws CompilationException {
+ public Set<AbstractCallExpression> getFunctionCalls(Expression expression) throws CompilationException {
GatherFunctionCalls gfc = new GatherFunctionCalls();
expression.accept(gfc, null);
return gfc.getCalls();
@@ -507,6 +507,7 @@
@Override
public Void visit(WindowExpression winExpr, Void arg) throws CompilationException {
+ calls.add(winExpr);
if (winExpr.hasPartitionList()) {
for (Expression expr : winExpr.getPartitionList()) {
expr.accept(this, arg);