You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by im...@apache.org on 2016/04/07 17:00:12 UTC
[37/50] [abbrv] incubator-asterixdb git commit: Move merged files
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
new file mode 100644
index 0000000..cbf05b5
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/FunctionMapUtil.java
@@ -0,0 +1,150 @@
+/*
+ * 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.common.functions.FunctionConstants;
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
+
+public class FunctionMapUtil {
+
+ private final static String CORE_AGGREGATE_PREFIX = "coll_";
+
+ // Maps from a SQL function name to an AQL function name (i.e., AsterixDB internal name).
+ private static final Map<String, String> FUNCTION_NAME_MAP = new HashMap<>();
+
+ static {
+ FUNCTION_NAME_MAP.put("ceil", "ceiling"); //SQL: ceil, AQL: ceiling
+ FUNCTION_NAME_MAP.put("length", "string-length"); // SQL: length, AQL: string-length
+ FUNCTION_NAME_MAP.put("lower", "lowercase"); // SQL: lower, AQL: lowercase
+ FUNCTION_NAME_MAP.put("substr", "substring"); // SQL: substr, AQL: substring
+ FUNCTION_NAME_MAP.put("upper", "uppercase"); //SQL: upper, AQL: uppercase
+ }
+
+ /**
+ * Whether a function signature is a SQL-92 core aggregate function.
+ *
+ * @param fs,
+ * the function signature.
+ * @return true if the function signature is a SQL-92 core aggregate,
+ * false otherwise.
+ */
+ public static boolean isSql92AggregateFunction(FunctionSignature signature) throws AsterixException {
+ IFunctionInfo finfo = FunctionUtil.getFunctionInfo(new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+ signature.getName().toLowerCase(), signature.getArity()));
+ if (finfo == null) {
+ return false;
+ }
+ return AsterixBuiltinFunctions.getAggregateFunction(finfo.getFunctionIdentifier()) != null;
+ }
+
+ /**
+ * Whether a function signature is a SQL++ core aggregate function.
+ *
+ * @param fs,
+ * the function signature.
+ * @return true if the function signature is a SQL++ core aggregate,
+ * false otherwise.
+ */
+ public static boolean isCoreAggregateFunction(FunctionSignature fs) {
+ String name = fs.getName().toLowerCase();
+ if (!name.startsWith(CORE_AGGREGATE_PREFIX)) {
+ return false;
+ }
+ IFunctionInfo finfo = FunctionUtil.getFunctionInfo(new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+ name.substring(CORE_AGGREGATE_PREFIX.length()), fs.getArity()));
+ if (finfo == null) {
+ return false;
+ }
+ return AsterixBuiltinFunctions.getAggregateFunction(finfo.getFunctionIdentifier()) != null;
+ }
+
+ /**
+ * Get the corresponding SQL++ core aggregate function from the SQL-92 aggregate function.
+ *
+ * @param fs,
+ * the SQL-92 aggregate function signature.
+ * @return the SQL++ aggregate function signature.
+ * @throws AsterixException
+ */
+ public static FunctionSignature sql92ToCoreAggregateFunction(FunctionSignature fs) throws AsterixException {
+ if (!isSql92AggregateFunction(fs)) {
+ return fs;
+ }
+ return new FunctionSignature(fs.getNamespace(), CORE_AGGREGATE_PREFIX + fs.getName(), fs.getArity());
+ }
+
+ /**
+ * Maps a user invoked function signature to a system internal function signature.
+ *
+ * @param fs,
+ * the user typed function.
+ * @return the system internal function.
+ */
+ public static FunctionSignature normalizeBuiltinFunctionSignature(FunctionSignature fs, boolean checkSql92Aggregate)
+ throws AsterixException {
+ String mappedName = internalizeBuiltinScalarFunctionName(fs.getName());
+ if (isCoreAggregateFunction(fs)) {
+ mappedName = internalizeCoreAggregateFunctionName(mappedName);
+ } else if (checkSql92Aggregate && isSql92AggregateFunction(fs)) {
+ throw new AsterixException(fs.getName()
+ + " is a SQL-92 aggregate function. The SQL++ core aggregate function " + CORE_AGGREGATE_PREFIX
+ + fs.getName().toLowerCase() + " could potentially express the intent.");
+ }
+ return new FunctionSignature(fs.getNamespace(), mappedName, fs.getArity());
+ }
+
+ /**
+ * Removes the "coll_" prefix for user-facing SQL++ core aggregate function names.
+ *
+ * @param name,
+ * the name of a user-facing SQL++ core aggregate function name.
+ * @return the AsterixDB internal function name for the aggregate function.
+ * @throws AsterixException
+ */
+ private static String internalizeCoreAggregateFunctionName(String name) throws AsterixException {
+ String lowerCaseName = name.toLowerCase();
+ return lowerCaseName.substring(CORE_AGGREGATE_PREFIX.length());
+ }
+
+ /**
+ * Note: function name normalization can ONLY be called
+ * after all user-defined functions (by either "DECLARE FUNCTION" or "CREATE FUNCTION")
+ * are inlined, because user-defined function names are case-sensitive.
+ *
+ * @param name
+ * the user-input function name in the query.
+ * @return the mapped internal name.
+ */
+ private static String internalizeBuiltinScalarFunctionName(String name) {
+ String lowerCaseName = name.toLowerCase();
+ String mappedName = FUNCTION_NAME_MAP.get(lowerCaseName);
+ if (mappedName != null) {
+ return mappedName;
+ }
+ return lowerCaseName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
new file mode 100644
index 0000000..1bca7ac
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
@@ -0,0 +1,265 @@
+/*
+ * 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 java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.common.functions.FunctionSignature;
+import org.apache.asterix.lang.common.base.Expression;
+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.IfExpr;
+import org.apache.asterix.lang.common.expression.IndexAccessor;
+import org.apache.asterix.lang.common.expression.ListConstructor;
+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.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+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.SelectExpression;
+import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+
+/**
+ * This visitor checks if a language construct contains SQL-92 aggregates.
+ */
+public class CheckSql92AggregateVisitor extends AbstractSqlppQueryExpressionVisitor<Boolean, ILangExpression> {
+
+ @Override
+ public Boolean visit(Query q, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(FunctionDecl fd, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(LiteralExpr l, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(VariableExpr v, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(ListConstructor lc, ILangExpression parentSelectBlock) throws AsterixException {
+ return visitExprList(lc.getExprList(), parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(RecordConstructor rc, ILangExpression parentSelectBlock) throws AsterixException {
+ for (FieldBinding fieldBinding : rc.getFbList()) {
+ ILangExpression leftExpr = fieldBinding.getLeftExpr();
+ ILangExpression rightExpr = fieldBinding.getRightExpr();
+ if (leftExpr.accept(this, parentSelectBlock)) {
+ return true;
+ }
+ if (rightExpr.accept(this, parentSelectBlock)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean visit(OperatorExpr ifbo, ILangExpression parentSelectBlock) throws AsterixException {
+ return visitExprList(ifbo.getExprList(), parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(FieldAccessor fa, ILangExpression parentSelectBlock) throws AsterixException {
+ return fa.getExpr().accept(this, parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(IndexAccessor ia, ILangExpression parentSelectBlock) throws AsterixException {
+ return ia.getExpr().accept(this, parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(IfExpr ifexpr, ILangExpression parentSelectBlock) throws AsterixException {
+ if (ifexpr.getCondExpr().accept(this, parentSelectBlock)) {
+ return true;
+ } else {
+ return ifexpr.getThenExpr().accept(this, parentSelectBlock)
+ || ifexpr.getElseExpr().accept(this, parentSelectBlock);
+ }
+ }
+
+ @Override
+ public Boolean visit(QuantifiedExpression qe, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(UnaryExpr u, ILangExpression parentSelectBlock) throws AsterixException {
+ return u.getExpr().accept(this, parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(CallExpr pf, ILangExpression parentSelectBlock) throws AsterixException {
+ FunctionSignature fs = pf.getFunctionSignature();
+ if (FunctionMapUtil.isSql92AggregateFunction(fs)) {
+ return true;
+ }
+ for (Expression parameter : pf.getExprList()) {
+ if (parameter.accept(this, parentSelectBlock)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean visit(LetClause lc, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(WhereClause wc, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(OrderbyClause oc, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(GroupbyClause gc, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(LimitClause lc, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(FromClause fromClause, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(FromTerm fromTerm, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(JoinClause joinClause, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(NestClause nestClause, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(Projection projection, ILangExpression parentSelectBlock) throws AsterixException {
+ return projection.getExpression().accept(this, parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(SelectBlock selectBlock, ILangExpression parentSelectBlock) throws AsterixException {
+ return selectBlock.getSelectClause().accept(this, selectBlock);
+ }
+
+ @Override
+ public Boolean visit(SelectClause selectClause, ILangExpression parentSelectBlock) throws AsterixException {
+ if (selectClause.selectElement()) {
+ return selectClause.getSelectElement().accept(this, parentSelectBlock);
+ } else {
+ return selectClause.getSelectRegular().accept(this, parentSelectBlock);
+ }
+ }
+
+ @Override
+ public Boolean visit(SelectElement selectElement, ILangExpression parentSelectBlock) throws AsterixException {
+ return selectElement.getExpression().accept(this, parentSelectBlock);
+ }
+
+ @Override
+ public Boolean visit(SelectRegular selectRegular, ILangExpression parentSelectBlock) throws AsterixException {
+ for (Projection projection : selectRegular.getProjections()) {
+ if (projection.accept(this, parentSelectBlock)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean visit(SelectSetOperation selectSetOperation, ILangExpression parentSelectBlock)
+ throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(SelectExpression selectStatement, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(UnnestClause unnestClause, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ @Override
+ public Boolean visit(HavingClause havingClause, ILangExpression parentSelectBlock) throws AsterixException {
+ return false;
+ }
+
+ private Boolean visitExprList(List<Expression> exprs, ILangExpression parentSelectBlock) throws AsterixException {
+ for (Expression item : exprs) {
+ if (item.accept(this, parentSelectBlock)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
new file mode 100644
index 0000000..2d891e0
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -0,0 +1,415 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+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.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.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+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.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangExpression, Void> {
+
+ @Override
+ public FromClause visit(FromClause fromClause, Void arg) throws AsterixException {
+ List<FromTerm> fromTerms = new ArrayList<>();
+ for (FromTerm fromTerm : fromClause.getFromTerms()) {
+ fromTerms.add((FromTerm) fromTerm.accept(this, arg));
+ }
+ return new FromClause(fromTerms);
+ }
+
+ @Override
+ public FromTerm visit(FromTerm fromTerm, Void arg) throws AsterixException {
+ // Visit the left expression of a from term.
+ Expression fromExpr = (Expression) fromTerm.getLeftExpression().accept(this, arg);
+ VariableExpr fromVar = (VariableExpr) fromTerm.getLeftVariable().accept(this, arg);
+ VariableExpr positionVar = fromTerm.getPositionalVariable() == null ? null
+ : (VariableExpr) fromTerm.getPositionalVariable().accept(this, arg);
+
+ // Visits join/unnest/nest clauses.
+ List<AbstractBinaryCorrelateClause> correlateClauses = new ArrayList<>();
+ for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+ correlateClauses.add((AbstractBinaryCorrelateClause) correlateClause.accept(this, arg));
+ }
+ return new FromTerm(fromExpr, fromVar, positionVar, correlateClauses);
+ }
+
+ @Override
+ public JoinClause visit(JoinClause joinClause, Void arg) throws AsterixException {
+ Expression rightExpression = (Expression) joinClause.getRightExpression().accept(this, arg);
+ VariableExpr rightVar = (VariableExpr) joinClause.getRightVariable().accept(this, arg);
+ VariableExpr rightPositionVar = joinClause.getPositionalVariable() == null ? null
+ : (VariableExpr) joinClause.getPositionalVariable().accept(this, arg);
+ Expression conditionExpresion = (Expression) joinClause.getConditionExpression().accept(this, arg);
+ return new JoinClause(joinClause.getJoinType(), rightExpression, rightVar, rightPositionVar,
+ conditionExpresion);
+ }
+
+ @Override
+ public NestClause visit(NestClause nestClause, Void arg) throws AsterixException {
+ Expression rightExpression = (Expression) nestClause.getRightExpression().accept(this, arg);
+ VariableExpr rightVar = (VariableExpr) nestClause.getRightVariable().accept(this, arg);
+ VariableExpr rightPositionVar = nestClause.getPositionalVariable() == null ? null
+ : (VariableExpr) nestClause.getPositionalVariable().accept(this, arg);
+ Expression conditionExpresion = (Expression) nestClause.getConditionExpression().accept(this, arg);
+ return new NestClause(nestClause.getJoinType(), rightExpression, rightVar, rightPositionVar,
+ conditionExpresion);
+ }
+
+ @Override
+ public UnnestClause visit(UnnestClause unnestClause, Void arg) throws AsterixException {
+ Expression rightExpression = (Expression) unnestClause.getRightExpression().accept(this, arg);
+ VariableExpr rightVar = (VariableExpr) unnestClause.getRightVariable().accept(this, arg);
+ VariableExpr rightPositionVar = unnestClause.getPositionalVariable() == null ? null
+ : (VariableExpr) unnestClause.getPositionalVariable().accept(this, arg);
+ return new UnnestClause(unnestClause.getJoinType(), rightExpression, rightVar, rightPositionVar);
+ }
+
+ @Override
+ public Projection visit(Projection projection, Void arg) throws AsterixException {
+ return new Projection((Expression) projection.getExpression().accept(this, arg), projection.getName(),
+ projection.star(), projection.exprStar());
+ }
+
+ @Override
+ public SelectBlock visit(SelectBlock selectBlock, Void arg) throws AsterixException {
+ FromClause fromClause = null;
+ List<LetClause> letClauses = new ArrayList<>();
+ WhereClause whereClause = null;
+ GroupbyClause gbyClause = null;
+ List<LetClause> gbyLetClauses = new ArrayList<>();
+ HavingClause havingClause = null;
+ SelectClause selectCluase = null;
+ // Traverses the select block in the order of "from", "let"s, "where",
+ // "group by", "let"s, "having" and "select".
+ if (selectBlock.hasFromClause()) {
+ fromClause = (FromClause) selectBlock.getFromClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetClauses()) {
+ List<LetClause> letList = selectBlock.getLetList();
+ for (LetClause letClause : letList) {
+ letClauses.add((LetClause) letClause.accept(this, arg));
+ }
+ }
+ if (selectBlock.hasWhereClause()) {
+ whereClause = (WhereClause) selectBlock.getWhereClause().accept(this, arg);
+ }
+ if (selectBlock.hasGroupbyClause()) {
+ gbyClause = (GroupbyClause) selectBlock.getGroupbyClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetClausesAfterGroupby()) {
+ List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
+ for (LetClause letClauseAfterGby : letListAfterGby) {
+ gbyLetClauses.add((LetClause) letClauseAfterGby.accept(this, arg));
+ }
+ }
+ if (selectBlock.hasHavingClause()) {
+ havingClause = (HavingClause) selectBlock.getHavingClause().accept(this, arg);
+ }
+ selectCluase = (SelectClause) selectBlock.getSelectClause().accept(this, arg);
+ return new SelectBlock(selectCluase, fromClause, letClauses, whereClause, gbyClause, gbyLetClauses,
+ havingClause);
+ }
+
+ @Override
+ public SelectClause visit(SelectClause selectClause, Void arg) throws AsterixException {
+ SelectElement selectElement = null;
+ SelectRegular selectRegular = null;
+ if (selectClause.selectElement()) {
+ selectElement = (SelectElement) selectClause.getSelectElement().accept(this, arg);
+ }
+ if (selectClause.selectRegular()) {
+ selectRegular = (SelectRegular) selectClause.getSelectRegular().accept(this, arg);
+ }
+ return new SelectClause(selectElement, selectRegular, selectClause.distinct());
+ }
+
+ @Override
+ public SelectElement visit(SelectElement selectElement, Void arg) throws AsterixException {
+ return new SelectElement((Expression) selectElement.getExpression().accept(this, arg));
+ }
+
+ @Override
+ public SelectRegular visit(SelectRegular selectRegular, Void arg) throws AsterixException {
+ List<Projection> projections = new ArrayList<>();
+ for (Projection projection : selectRegular.getProjections()) {
+ projections.add((Projection) projection.accept(this, arg));
+ }
+ return new SelectRegular(projections);
+ }
+
+ @Override
+ public SelectSetOperation visit(SelectSetOperation selectSetOperation, Void arg) throws AsterixException {
+ SetOperationInput leftInput = selectSetOperation.getLeftInput();
+ SetOperationInput newLeftInput = null;
+ if (leftInput.selectBlock()) {
+ newLeftInput = new SetOperationInput((SelectBlock) leftInput.accept(this, arg), null);
+ } else {
+ newLeftInput = new SetOperationInput(null, (SelectExpression) leftInput.accept(this, arg));
+ }
+ List<SetOperationRight> rightInputs = new ArrayList<>();
+ for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+ SetOperationInput newRightInput = null;
+ SetOperationInput setOpRightInput = right.getSetOperationRightInput();
+ if (setOpRightInput.selectBlock()) {
+ newRightInput = new SetOperationInput((SelectBlock) leftInput.accept(this, arg), null);
+ } else {
+ newRightInput = new SetOperationInput(null, (SelectExpression) leftInput.accept(this, arg));
+ }
+ rightInputs.add(new SetOperationRight(right.getSetOpType(), right.isSetSemantics(), newRightInput));
+ }
+ return new SelectSetOperation(newLeftInput, rightInputs);
+ }
+
+ @Override
+ public HavingClause visit(HavingClause havingClause, Void arg) throws AsterixException {
+ return new HavingClause((Expression) havingClause.getFilterExpression().accept(this, arg));
+ }
+
+ @Override
+ public Query visit(Query q, Void arg) throws AsterixException {
+ return new Query(q.isTopLevel(), (Expression) q.getBody().accept(this, arg), q.getVarCounter(),
+ q.getDataverses(), q.getDatasets());
+ }
+
+ @Override
+ public FunctionDecl visit(FunctionDecl fd, Void arg) throws AsterixException {
+ return new FunctionDecl(fd.getSignature(), fd.getParamList(), (Expression) fd.getFuncBody().accept(this, arg));
+ }
+
+ @Override
+ public WhereClause visit(WhereClause whereClause, Void arg) throws AsterixException {
+ return new WhereClause((Expression) whereClause.getWhereExpr().accept(this, arg));
+ }
+
+ @Override
+ public OrderbyClause visit(OrderbyClause oc, Void arg) throws AsterixException {
+ List<Expression> newOrderbyList = new ArrayList<Expression>();
+ for (Expression orderExpr : oc.getOrderbyList()) {
+ newOrderbyList.add((Expression) orderExpr.accept(this, arg));
+ }
+ return new OrderbyClause(newOrderbyList, oc.getModifierList());
+ }
+
+ @Override
+ public GroupbyClause visit(GroupbyClause gc, Void arg) throws AsterixException {
+ List<GbyVariableExpressionPair> gbyPairList = new ArrayList<>();
+ List<GbyVariableExpressionPair> decorPairList = new ArrayList<>();
+ List<VariableExpr> withVarList = new ArrayList<>();
+ VariableExpr groupVarExpr = null;
+ List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
+ for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
+ gbyPairList.add(new GbyVariableExpressionPair((VariableExpr) gbyVarExpr.getVar().accept(this, arg),
+ (Expression) gbyVarExpr.getExpr().accept(this, arg)));
+ }
+ for (GbyVariableExpressionPair gbyVarExpr : gc.getDecorPairList()) {
+ decorPairList.add(new GbyVariableExpressionPair((VariableExpr) gbyVarExpr.getVar().accept(this, arg),
+ (Expression) gbyVarExpr.getExpr().accept(this, arg)));
+ }
+ for (VariableExpr withVar : gc.getWithVarList()) {
+ withVarList.add((VariableExpr) withVar.accept(this, arg));
+ }
+ if (gc.hasGroupVar()) {
+ groupVarExpr = (VariableExpr) gc.getGroupVar().accept(this, arg);
+ }
+ for (Pair<Expression, Identifier> field : gc.getGroupFieldList()) {
+ groupFieldList.add(new Pair<>((Expression) field.first.accept(this, arg), field.second));
+ }
+ return new GroupbyClause(gbyPairList, decorPairList, withVarList, groupVarExpr, groupFieldList,
+ gc.hasHashGroupByHint(), gc.isGroupAll());
+ }
+
+ @Override
+ public LimitClause visit(LimitClause limitClause, Void arg) throws AsterixException {
+ Expression limitExpr = (Expression) limitClause.getLimitExpr().accept(this, arg);
+ Expression offsetExpr = limitClause.hasOffset() ? (Expression) limitClause.getOffset().accept(this, arg) : null;
+ return new LimitClause(limitExpr, offsetExpr);
+ }
+
+ @Override
+ public LetClause visit(LetClause letClause, Void arg) throws AsterixException {
+ return new LetClause((VariableExpr) letClause.getVarExpr().accept(this, arg),
+ (Expression) letClause.getBindingExpr().accept(this, arg));
+ }
+
+ @Override
+ public SelectExpression visit(SelectExpression selectExpression, Void arg) throws AsterixException {
+ List<LetClause> lets = new ArrayList<>();
+ SelectSetOperation select = null;
+ OrderbyClause orderby = null;
+ LimitClause limit = null;
+
+ // visit let list
+ if (selectExpression.hasLetClauses()) {
+ for (LetClause letClause : selectExpression.getLetList()) {
+ lets.add((LetClause) letClause.accept(this, arg));
+ }
+ }
+
+ // visit the main select.
+ select = (SelectSetOperation) selectExpression.getSelectSetOperation().accept(this, arg);
+
+ // visit order by
+ if (selectExpression.hasOrderby()) {
+ List<Expression> orderExprs = new ArrayList<>();
+ for (Expression orderExpr : selectExpression.getOrderbyClause().getOrderbyList()) {
+ orderExprs.add((Expression) orderExpr.accept(this, arg));
+ }
+ orderby = new OrderbyClause(orderExprs, selectExpression.getOrderbyClause().getModifierList());
+ }
+
+ // visit limit
+ if (selectExpression.hasLimit()) {
+ limit = (LimitClause) selectExpression.getLimitClause().accept(this, arg);
+ }
+ return new SelectExpression(lets, select, orderby, limit, selectExpression.isSubquery());
+ }
+
+ @Override
+ public LiteralExpr visit(LiteralExpr l, Void arg) throws AsterixException {
+ return l;
+ }
+
+ @Override
+ public ListConstructor visit(ListConstructor lc, Void arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : lc.getExprList()) {
+ newExprList.add((Expression) expr.accept(this, arg));
+ }
+ return new ListConstructor(lc.getType(), newExprList);
+ }
+
+ @Override
+ public RecordConstructor visit(RecordConstructor rc, Void arg) throws AsterixException {
+ List<FieldBinding> bindings = new ArrayList<>();
+ for (FieldBinding binding : rc.getFbList()) {
+ FieldBinding fb = new FieldBinding((Expression) binding.getLeftExpr().accept(this, arg),
+ (Expression) binding.getRightExpr().accept(this, arg));
+ bindings.add(fb);
+ }
+ return new RecordConstructor(bindings);
+ }
+
+ @Override
+ public OperatorExpr visit(OperatorExpr operatorExpr, Void arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : operatorExpr.getExprList()) {
+ newExprList.add((Expression) expr.accept(this, arg));
+ }
+ return new OperatorExpr(newExprList, operatorExpr.getExprBroadcastIdx(), operatorExpr.getOpList(),
+ operatorExpr.isCurrentop());
+ }
+
+ @Override
+ public IfExpr visit(IfExpr ifExpr, Void arg) throws AsterixException {
+ Expression conditionExpr = (Expression) ifExpr.getCondExpr().accept(this, arg);
+ Expression thenExpr = (Expression) ifExpr.getThenExpr().accept(this, arg);
+ Expression elseExpr = (Expression) ifExpr.getElseExpr().accept(this, arg);
+ return new IfExpr(conditionExpr, thenExpr, elseExpr);
+ }
+
+ @Override
+ public QuantifiedExpression visit(QuantifiedExpression qe, Void arg) throws AsterixException {
+ List<QuantifiedPair> quantifiedPairs = new ArrayList<>();
+ for (QuantifiedPair pair : qe.getQuantifiedList()) {
+ Expression expr = (Expression) pair.getExpr().accept(this, arg);
+ VariableExpr var = (VariableExpr) pair.getVarExpr().accept(this, arg);
+ quantifiedPairs.add(new QuantifiedPair(var, expr));
+ }
+ Expression condition = (Expression) qe.getSatisfiesExpr().accept(this, arg);
+ return new QuantifiedExpression(qe.getQuantifier(), quantifiedPairs, condition);
+ }
+
+ @Override
+ public CallExpr visit(CallExpr callExpr, Void arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : callExpr.getExprList()) {
+ newExprList.add((Expression) expr.accept(this, arg));
+ }
+ return new CallExpr(callExpr.getFunctionSignature(), newExprList);
+ }
+
+ @Override
+ public VariableExpr visit(VariableExpr varExpr, Void arg) throws AsterixException {
+ return new VariableExpr(varExpr.getVar());
+ }
+
+ @Override
+ public UnaryExpr visit(UnaryExpr u, Void arg) throws AsterixException {
+ return new UnaryExpr(u.getSign(), (Expression) u.getExpr().accept(this, arg));
+ }
+
+ @Override
+ public FieldAccessor visit(FieldAccessor fa, Void arg) throws AsterixException {
+ return new FieldAccessor((Expression) fa.getExpr().accept(this, arg), fa.getIdent());
+ }
+
+ @Override
+ public Expression visit(IndexAccessor ia, Void arg) throws AsterixException {
+ Expression expr = (Expression) ia.getExpr().accept(this, arg);
+ Expression indexExpr = null;
+ if (ia.getIndexExpr() != null) {
+ indexExpr = ia.getIndexExpr();
+ }
+ return new IndexAccessor(expr, indexExpr);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
new file mode 100644
index 0000000..6e70455
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/FreeVariableVisitor.java
@@ -0,0 +1,471 @@
+/*
+ * 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 java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Clause.ClauseType;
+import org.apache.asterix.lang.common.base.Expression;
+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.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.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+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.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppQueryExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+
+public class FreeVariableVisitor extends AbstractSqlppQueryExpressionVisitor<Void, Collection<VariableExpr>> {
+
+ @Override
+ public Void visit(FromClause fromClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ Collection<VariableExpr> bindingVars = new HashSet<>();
+ for (FromTerm fromTerm : fromClause.getFromTerms()) {
+ Collection<VariableExpr> fromTermFreeVars = new HashSet<>();
+ fromTerm.accept(this, fromTermFreeVars);
+
+ // Since a right from term can refer to variables defined in a left from term,
+ // we remove binding variables from the free variables.
+ fromTermFreeVars.removeAll(bindingVars);
+
+ // Adds binding variables.
+ bindingVars.addAll(SqlppVariableUtil.getBindingVariables(fromTerm));
+
+ // Adds into freeVars.
+ freeVars.addAll(fromTermFreeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(FromTerm fromTerm, Collection<VariableExpr> freeVars) throws AsterixException {
+ // The encountered binding variables so far in the fromterm.
+ Collection<VariableExpr> bindingVariables = new HashSet<>();
+
+ // Visit the left expression of a from term.
+ fromTerm.getLeftExpression().accept(this, freeVars);
+
+ // Adds binding variables.
+ bindingVariables.add(fromTerm.getLeftVariable());
+ if (fromTerm.hasPositionalVariable()) {
+ bindingVariables.add(fromTerm.getPositionalVariable());
+ }
+
+ // Visits join/unnest/nest clauses.
+ for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+ Collection<VariableExpr> correlateFreeVars = new HashSet<>();
+ correlateClause.accept(this, correlateFreeVars);
+ if (correlateClause.getClauseType() != ClauseType.JOIN_CLAUSE) {
+ // Correlation is allowed if the clause is not a join clause,
+ // therefore we remove left-side binding variables for these cases.
+ correlateFreeVars.removeAll(bindingVariables);
+
+ // Adds binding variables.
+ bindingVariables.add(correlateClause.getRightVariable());
+ if (correlateClause.hasPositionalVariable()) {
+ bindingVariables.add(correlateClause.getPositionalVariable());
+ }
+ }
+ freeVars.addAll(correlateFreeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(JoinClause joinClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ visitJoinAndNest(joinClause, joinClause.getConditionExpression(), freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(NestClause nestClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ visitJoinAndNest(nestClause, nestClause.getConditionExpression(), freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(UnnestClause unnestClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ unnestClause.getRightExpression().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(Projection projection, Collection<VariableExpr> freeVars) throws AsterixException {
+ projection.getExpression().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectBlock selectBlock, Collection<VariableExpr> freeVars) throws AsterixException {
+ Collection<VariableExpr> selectFreeVars = new HashSet<>();
+ Collection<VariableExpr> fromFreeVars = new HashSet<>();
+ Collection<VariableExpr> letsFreeVars = new HashSet<>();
+ Collection<VariableExpr> whereFreeVars = new HashSet<>();
+ Collection<VariableExpr> gbyFreeVars = new HashSet<>();
+ Collection<VariableExpr> gbyLetsFreeVars = new HashSet<>();
+
+ Collection<VariableExpr> fromBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getFromClause());
+ Collection<VariableExpr> letsBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getLetList());
+ Collection<VariableExpr> gbyBindingVars = SqlppVariableUtil.getBindingVariables(selectBlock.getGroupbyClause());
+ Collection<VariableExpr> gbyLetsBindingVars = SqlppVariableUtil
+ .getBindingVariables(selectBlock.getLetListAfterGroupby());
+
+ selectBlock.getSelectClause().accept(this, selectFreeVars);
+ // Removes group-by, from, let, and gby-let binding vars.
+ removeAllBindingVarsInSelectBlock(selectFreeVars, fromBindingVars, letsBindingVars, gbyLetsBindingVars);
+
+ if (selectBlock.hasFromClause()) {
+ selectBlock.getFromClause().accept(this, fromFreeVars);
+ }
+ if (selectBlock.hasLetClauses()) {
+ visitLetClauses(selectBlock.getLetList(), letsFreeVars);
+ letsFreeVars.removeAll(fromBindingVars);
+ }
+ if (selectBlock.hasWhereClause()) {
+ selectBlock.getWhereClause().accept(this, whereFreeVars);
+ whereFreeVars.removeAll(fromBindingVars);
+ whereFreeVars.removeAll(letsBindingVars);
+ }
+ if (selectBlock.hasGroupbyClause()) {
+ selectBlock.getGroupbyClause().accept(this, gbyFreeVars);
+ // Remove group-by and let binding vars.
+ gbyFreeVars.removeAll(fromBindingVars);
+ gbyFreeVars.removeAll(letsBindingVars);
+ if (selectBlock.hasLetClausesAfterGroupby()) {
+ visitLetClauses(selectBlock.getLetListAfterGroupby(), gbyLetsFreeVars);
+ gbyLetsFreeVars.removeAll(fromBindingVars);
+ gbyLetsFreeVars.removeAll(letsBindingVars);
+ gbyLetsFreeVars.removeAll(gbyBindingVars);
+ }
+ if (selectBlock.hasHavingClause()) {
+ selectBlock.getHavingClause().accept(this, selectFreeVars);
+ removeAllBindingVarsInSelectBlock(selectFreeVars, fromBindingVars, letsBindingVars, gbyLetsBindingVars);
+ }
+ }
+
+ // Removes all binding vars from <code>freeVars</code>, which contains the free
+ // vars in the order-by and limit.
+ removeAllBindingVarsInSelectBlock(freeVars, fromBindingVars, letsBindingVars, gbyLetsBindingVars);
+
+ // Adds all free vars.
+ freeVars.addAll(selectFreeVars);
+ freeVars.addAll(fromFreeVars);
+ freeVars.addAll(letsFreeVars);
+ freeVars.addAll(whereFreeVars);
+ freeVars.addAll(gbyFreeVars);
+ freeVars.addAll(gbyLetsFreeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectClause selectClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ if (selectClause.selectElement()) {
+ selectClause.getSelectElement().accept(this, freeVars);
+ }
+ if (selectClause.selectRegular()) {
+ selectClause.getSelectRegular().accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectElement selectElement, Collection<VariableExpr> freeVars) throws AsterixException {
+ selectElement.getExpression().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectRegular selectRegular, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (Projection projection : selectRegular.getProjections()) {
+ projection.accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectSetOperation selectSetOperation, Collection<VariableExpr> freeVars)
+ throws AsterixException {
+ selectSetOperation.getLeftInput().accept(this, freeVars);
+ for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+ right.getSetOperationRightInput().accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(HavingClause havingClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ havingClause.getFilterExpression().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(Query q, Collection<VariableExpr> freeVars) throws AsterixException {
+ q.getBody().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(FunctionDecl fd, Collection<VariableExpr> freeVars) throws AsterixException {
+ fd.getFuncBody().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(WhereClause whereClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ whereClause.getWhereExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(OrderbyClause oc, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (Expression orderExpr : oc.getOrderbyList()) {
+ orderExpr.accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(GroupbyClause gc, Collection<VariableExpr> freeVars) throws AsterixException {
+ // Puts all group-by variables into the symbol set of the new scope.
+ for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
+ gbyVarExpr.getExpr().accept(this, freeVars);
+ }
+ for (GbyVariableExpressionPair decorVarExpr : gc.getDecorPairList()) {
+ decorVarExpr.getExpr().accept(this, freeVars);
+ }
+ if (gc.hasGroupFieldList()) {
+ for (Pair<Expression, Identifier> groupField : gc.getGroupFieldList()) {
+ groupField.first.accept(this, freeVars);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(LimitClause limitClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ limitClause.getLimitExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(LetClause letClause, Collection<VariableExpr> freeVars) throws AsterixException {
+ letClause.getBindingExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(SelectExpression selectExpression, Collection<VariableExpr> freeVars) throws AsterixException {
+ Collection<VariableExpr> letsFreeVars = new HashSet<>();
+ Collection<VariableExpr> selectFreeVars = new HashSet<>();
+ visitLetClauses(selectExpression.getLetList(), letsFreeVars);
+
+ // visit order by
+ if (selectExpression.hasOrderby()) {
+ for (Expression orderExpr : selectExpression.getOrderbyClause().getOrderbyList()) {
+ orderExpr.accept(this, selectFreeVars);
+ }
+ }
+
+ // visit limit
+ if (selectExpression.hasLimit()) {
+ selectExpression.getLimitClause().accept(this, selectFreeVars);
+ }
+
+ // visit the main select
+ selectExpression.getSelectSetOperation().accept(this, selectFreeVars);
+
+ // Removed let binding variables.
+ selectFreeVars.removeAll(SqlppVariableUtil.getBindingVariables(selectExpression.getLetList()));
+ freeVars.addAll(letsFreeVars);
+ freeVars.addAll(selectFreeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(LiteralExpr l, Collection<VariableExpr> freeVars) throws AsterixException {
+ return null;
+ }
+
+ @Override
+ public Void visit(ListConstructor lc, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (Expression expr : lc.getExprList()) {
+ expr.accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(RecordConstructor rc, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (FieldBinding binding : rc.getFbList()) {
+ binding.getLeftExpr().accept(this, freeVars);
+ binding.getRightExpr().accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(OperatorExpr operatorExpr, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (Expression expr : operatorExpr.getExprList()) {
+ expr.accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(IfExpr ifExpr, Collection<VariableExpr> freeVars) throws AsterixException {
+ ifExpr.getCondExpr().accept(this, freeVars);
+ ifExpr.getThenExpr().accept(this, freeVars);
+ ifExpr.getElseExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(QuantifiedExpression qe, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (QuantifiedPair pair : qe.getQuantifiedList()) {
+ pair.getExpr().accept(this, freeVars);
+ }
+ qe.getSatisfiesExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(CallExpr callExpr, Collection<VariableExpr> freeVars) throws AsterixException {
+ for (Expression expr : callExpr.getExprList()) {
+ expr.accept(this, freeVars);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visit(VariableExpr varExpr, Collection<VariableExpr> freeVars) throws AsterixException {
+ freeVars.add(varExpr);
+ return null;
+ }
+
+ @Override
+ public Void visit(UnaryExpr u, Collection<VariableExpr> freeVars) throws AsterixException {
+ u.getExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(FieldAccessor fa, Collection<VariableExpr> freeVars) throws AsterixException {
+ fa.getExpr().accept(this, freeVars);
+ return null;
+ }
+
+ @Override
+ public Void visit(IndexAccessor ia, Collection<VariableExpr> freeVars) throws AsterixException {
+ ia.getExpr().accept(this, freeVars);
+ if (ia.getIndexExpr() != null) {
+ ia.getIndexExpr();
+ }
+ return null;
+ }
+
+ private void visitLetClauses(List<LetClause> letClauses, Collection<VariableExpr> freeVars)
+ throws AsterixException {
+ if (letClauses == null || letClauses.isEmpty()) {
+ return;
+ }
+ Collection<VariableExpr> bindingVars = new HashSet<>();
+ for (LetClause letClause : letClauses) {
+ Collection<VariableExpr> letFreeVars = new HashSet<>();
+ letClause.accept(this, letFreeVars);
+
+ // Removes previous binding variables.
+ letFreeVars.removeAll(bindingVars);
+ freeVars.addAll(letFreeVars);
+
+ // Adds let binding variables into the binding variable collection.
+ bindingVars.add(letClause.getVarExpr());
+ }
+ }
+
+ private void visitJoinAndNest(AbstractBinaryCorrelateClause clause, Expression condition,
+ Collection<VariableExpr> freeVars) throws AsterixException {
+ clause.getRightExpression().accept(this, freeVars);
+ Collection<VariableExpr> conditionFreeVars = new HashSet<>();
+ condition.accept(this, freeVars);
+
+ // The condition expression can free binding variables defined in the join clause.
+ conditionFreeVars.remove(clause.getRightVariable());
+ if (clause.hasPositionalVariable()) {
+ conditionFreeVars.remove(clause.getPositionalVariable());
+ }
+ freeVars.addAll(conditionFreeVars);
+ }
+
+ /**
+ * Removes all binding variables defined in the select block for a free variable collection.
+ *
+ * @param freeVars,
+ * free variables.
+ * @param fromBindingVars,
+ * binding variables defined in the from clause of a select block.
+ * @param letsBindingVars,
+ * binding variables defined in the let clauses of the select block.
+ * @param gbyLetsBindingVars,
+ * binding variables defined in the let clauses after a group-by in the select block.
+ */
+ private void removeAllBindingVarsInSelectBlock(Collection<VariableExpr> selectFreeVars,
+ Collection<VariableExpr> fromBindingVars, Collection<VariableExpr> letsBindingVars,
+ Collection<VariableExpr> gbyLetsBindingVars) {
+ selectFreeVars.removeAll(fromBindingVars);
+ selectFreeVars.removeAll(letsBindingVars);
+ selectFreeVars.removeAll(gbyLetsBindingVars);
+ selectFreeVars.removeAll(gbyLetsBindingVars);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
new file mode 100644
index 0000000..14e80d9
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -0,0 +1,284 @@
+/*
+ * 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 org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+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.context.Scope;
+import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
+import org.apache.asterix.lang.common.expression.QuantifiedExpression;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.parser.ScopeChecker;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.struct.QuantifiedPair;
+import org.apache.asterix.lang.common.struct.VarIdentifier;
+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.JoinClause;
+import org.apache.asterix.lang.sqlpp.clause.NestClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+import org.apache.hyracks.algebricks.core.algebra.base.Counter;
+
+public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleExpressionVisitor {
+
+ protected final ScopeChecker scopeChecker = new ScopeChecker();
+ protected final LangRewritingContext context;
+
+ /**
+ * @param context,
+ * manages ids of variables and guarantees uniqueness of variables.
+ */
+ public AbstractSqlppExpressionScopingVisitor(LangRewritingContext context) {
+ this.context = context;
+ this.scopeChecker.setVarCounter(new Counter(context.getVarCounter()));
+ }
+
+ @Override
+ public Expression visit(FromClause fromClause, Expression arg) throws AsterixException {
+ scopeChecker.extendCurrentScope();
+ for (FromTerm fromTerm : fromClause.getFromTerms()) {
+ fromTerm.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(FromTerm fromTerm, Expression arg) throws AsterixException {
+ scopeChecker.createNewScope();
+ // Visit the left expression of a from term.
+ fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, arg));
+
+ // Registers the data item variable.
+ VariableExpr leftVar = fromTerm.getLeftVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(leftVar.getVar());
+
+ // Registers the positional variable
+ if (fromTerm.hasPositionalVariable()) {
+ VariableExpr posVar = fromTerm.getPositionalVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(posVar.getVar());
+ }
+ // Visits join/unnest/nest clauses.
+ for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+ correlateClause.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(JoinClause joinClause, Expression arg) throws AsterixException {
+ Scope backupScope = scopeChecker.removeCurrentScope();
+ Scope parentScope = scopeChecker.getCurrentScope();
+ scopeChecker.createNewScope();
+ // NOTE: the two join branches cannot be correlated, instead of checking
+ // the correlation here,
+ // we defer the check to the query optimizer.
+ joinClause.setRightExpression(joinClause.getRightExpression().accept(this, arg));
+
+ // Registers the data item variable.
+ VariableExpr rightVar = joinClause.getRightVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(rightVar.getVar());
+
+ if (joinClause.hasPositionalVariable()) {
+ // Registers the positional variable.
+ VariableExpr posVar = joinClause.getPositionalVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(posVar.getVar());
+ }
+
+ Scope rightScope = scopeChecker.removeCurrentScope();
+ Scope mergedScope = new Scope(scopeChecker, parentScope);
+ mergedScope.merge(backupScope);
+ mergedScope.merge(rightScope);
+ scopeChecker.pushExistingScope(mergedScope);
+ // The condition expression can refer to the just registered variables
+ // for the right branch.
+ joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(NestClause nestClause, Expression arg) throws AsterixException {
+ // NOTE: the two branches of a NEST cannot be correlated, instead of
+ // checking the correlation here, we defer the check to the query
+ // optimizer.
+ nestClause.setRightExpression(nestClause.getRightExpression().accept(this, arg));
+
+ // Registers the data item variable.
+ VariableExpr rightVar = nestClause.getRightVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(rightVar.getVar());
+
+ if (nestClause.hasPositionalVariable()) {
+ // Registers the positional variable.
+ VariableExpr posVar = nestClause.getPositionalVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(posVar.getVar());
+ }
+
+ // The condition expression can refer to the just registered variables
+ // for the right branch.
+ nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(UnnestClause unnestClause, Expression arg) throws AsterixException {
+ unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, arg));
+
+ // register the data item variable
+ VariableExpr rightVar = unnestClause.getRightVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(rightVar.getVar());
+
+ if (unnestClause.hasPositionalVariable()) {
+ // register the positional variable
+ VariableExpr posVar = unnestClause.getPositionalVariable();
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(posVar.getVar());
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectSetOperation selectSetOperation, Expression arg) throws AsterixException {
+ selectSetOperation.getLeftInput().accept(this, arg);
+ for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+ scopeChecker.createNewScope();
+ right.getSetOperationRightInput().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(Query q, Expression arg) throws AsterixException {
+ q.setBody(q.getBody().accept(this, arg));
+ q.setVarCounter(scopeChecker.getVarCounter());
+ context.setVarCounter(scopeChecker.getVarCounter());
+ return null;
+ }
+
+ @Override
+ public Expression visit(FunctionDecl fd, Expression arg) throws AsterixException {
+ scopeChecker.createNewScope();
+ fd.setFuncBody(fd.getFuncBody().accept(this, arg));
+ scopeChecker.removeCurrentScope();
+ return null;
+ }
+
+ @Override
+ public Expression visit(GroupbyClause gc, Expression arg) throws AsterixException {
+ Scope newScope = scopeChecker.extendCurrentScopeNoPush(true);
+ // Puts all group-by variables into the symbol set of the new scope.
+ for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
+ gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, arg));
+ VariableExpr gbyVar = gbyVarExpr.getVar();
+ if (gbyVar != null) {
+ newScope.addNewVarSymbolToScope(gbyVarExpr.getVar().getVar());
+ }
+ }
+ for (VariableExpr withVar : gc.getWithVarList()) {
+ newScope.addNewVarSymbolToScope(withVar.getVar());
+ }
+ scopeChecker.replaceCurrentScope(newScope);
+ return null;
+ }
+
+ @Override
+ public Expression visit(LimitClause limitClause, Expression arg) throws AsterixException {
+ scopeChecker.pushForbiddenScope(scopeChecker.getCurrentScope());
+ limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, arg));
+ scopeChecker.popForbiddenScope();
+ return null;
+ }
+
+ @Override
+ public Expression visit(LetClause letClause, Expression arg) throws AsterixException {
+ scopeChecker.extendCurrentScope();
+ letClause.setBindingExpr(letClause.getBindingExpr().accept(this, arg));
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(letClause.getVarExpr().getVar());
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectExpression selectExpression, Expression arg) throws AsterixException {
+ Scope scopeBeforeSelectExpression = scopeChecker.getCurrentScope();
+ scopeChecker.createNewScope();
+
+ // visit let list
+ if (selectExpression.hasLetClauses()) {
+ for (LetClause letClause : selectExpression.getLetList()) {
+ letClause.accept(this, arg);
+ }
+ }
+
+ // visit the main select.
+ selectExpression.getSelectSetOperation().accept(this, selectExpression);
+
+ // visit order by
+ if (selectExpression.hasOrderby()) {
+ selectExpression.getOrderbyClause().accept(this, arg);
+ }
+
+ // visit limit
+ if (selectExpression.hasLimit()) {
+ selectExpression.getLimitClause().accept(this, arg);
+ }
+
+ // Exit scopes that were entered within this select expression
+ while (scopeChecker.getCurrentScope() != scopeBeforeSelectExpression) {
+ scopeChecker.removeCurrentScope();
+ }
+ return selectExpression;
+ }
+
+ @Override
+ public Expression visit(QuantifiedExpression qe, Expression arg) throws AsterixException {
+ scopeChecker.createNewScope();
+ for (QuantifiedPair pair : qe.getQuantifiedList()) {
+ scopeChecker.getCurrentScope().addNewVarSymbolToScope(pair.getVarExpr().getVar());
+ pair.setExpr(pair.getExpr().accept(this, arg));
+ }
+ qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, arg));
+ scopeChecker.removeCurrentScope();
+ return qe;
+ }
+
+ @Override
+ public Expression visit(VariableExpr varExpr, Expression arg) throws AsterixException {
+ String varName = varExpr.getVar().getValue();
+ if (scopeChecker.isInForbiddenScopes(varName)) {
+ throw new AsterixException(
+ "Inside limit clauses, it is disallowed to reference a variable having the same name as any variable bound in the same scope as the limit clause.");
+ }
+ Identifier ident = scopeChecker.lookupSymbol(varName);
+ if (ident != null) {
+ // Exists such an identifier, then this is a variable reference instead of a variable
+ // definition.
+ varExpr.setIsNewVar(false);
+ varExpr.setVar((VarIdentifier) ident);
+ }
+ return varExpr;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-asterixdb/blob/d630d1a2/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
new file mode 100644
index 0000000..18c2789
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppSimpleExpressionVisitor.java
@@ -0,0 +1,347 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+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.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.statement.FunctionDecl;
+import org.apache.asterix.lang.common.statement.Query;
+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.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
+
+public class AbstractSqlppSimpleExpressionVisitor extends AbstractSqlppQueryExpressionVisitor<Expression, Expression> {
+
+ @Override
+ public Expression visit(FromClause fromClause, Expression arg) throws AsterixException {
+ for (FromTerm fromTerm : fromClause.getFromTerms()) {
+ fromTerm.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(FromTerm fromTerm, Expression arg) throws AsterixException {
+ // Visit the left expression of a from term.
+ fromTerm.setLeftExpression(fromTerm.getLeftExpression().accept(this, arg));
+
+ // Visits join/unnest/nest clauses.
+ for (AbstractBinaryCorrelateClause correlateClause : fromTerm.getCorrelateClauses()) {
+ correlateClause.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(JoinClause joinClause, Expression arg) throws AsterixException {
+ joinClause.setRightExpression(joinClause.getRightExpression().accept(this, arg));
+ joinClause.setConditionExpression(joinClause.getConditionExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(NestClause nestClause, Expression arg) throws AsterixException {
+ nestClause.setRightExpression(nestClause.getRightExpression().accept(this, arg));
+ nestClause.setConditionExpression(nestClause.getConditionExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(UnnestClause unnestClause, Expression arg) throws AsterixException {
+ unnestClause.setRightExpression(unnestClause.getRightExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(Projection projection, Expression arg) throws AsterixException {
+ projection.setExpression(projection.getExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectBlock selectBlock, Expression arg) throws AsterixException {
+ // Traverses the select block in the order of "from", "let"s, "where",
+ // "group by", "let"s, "having" and "select".
+ if (selectBlock.hasFromClause()) {
+ selectBlock.getFromClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetClauses()) {
+ List<LetClause> letList = selectBlock.getLetList();
+ for (LetClause letClause : letList) {
+ letClause.accept(this, arg);
+ }
+ }
+ if (selectBlock.hasWhereClause()) {
+ selectBlock.getWhereClause().accept(this, arg);
+ }
+ if (selectBlock.hasGroupbyClause()) {
+ selectBlock.getGroupbyClause().accept(this, arg);
+ }
+ if (selectBlock.hasLetClausesAfterGroupby()) {
+ List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
+ for (LetClause letClauseAfterGby : letListAfterGby) {
+ letClauseAfterGby.accept(this, arg);
+ }
+ }
+ if (selectBlock.hasHavingClause()) {
+ selectBlock.getHavingClause().accept(this, arg);
+ }
+ selectBlock.getSelectClause().accept(this, arg);
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectClause selectClause, Expression arg) throws AsterixException {
+ if (selectClause.selectElement()) {
+ selectClause.getSelectElement().accept(this, arg);
+ }
+ if (selectClause.selectRegular()) {
+ selectClause.getSelectRegular().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectElement selectElement, Expression arg) throws AsterixException {
+ selectElement.setExpression(selectElement.getExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectRegular selectRegular, Expression arg) throws AsterixException {
+ for (Projection projection : selectRegular.getProjections()) {
+ projection.accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectSetOperation selectSetOperation, Expression arg) throws AsterixException {
+ selectSetOperation.getLeftInput().accept(this, arg);
+ for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+ right.getSetOperationRightInput().accept(this, arg);
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(HavingClause havingClause, Expression arg) throws AsterixException {
+ havingClause.setFilterExpression(havingClause.getFilterExpression().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(Query q, Expression arg) throws AsterixException {
+ q.setBody(q.getBody().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(FunctionDecl fd, Expression arg) throws AsterixException {
+ fd.setFuncBody(fd.getFuncBody().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(WhereClause whereClause, Expression arg) throws AsterixException {
+ whereClause.setWhereExpr(whereClause.getWhereExpr().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(OrderbyClause oc, Expression arg) throws AsterixException {
+ List<Expression> newOrderbyList = new ArrayList<Expression>();
+ for (Expression orderExpr : oc.getOrderbyList()) {
+ newOrderbyList.add(orderExpr.accept(this, arg));
+ }
+ oc.setOrderbyList(newOrderbyList);
+ return null;
+ }
+
+ @Override
+ public Expression visit(GroupbyClause gc, Expression arg) throws AsterixException {
+ for (GbyVariableExpressionPair gbyVarExpr : gc.getGbyPairList()) {
+ gbyVarExpr.setExpr(gbyVarExpr.getExpr().accept(this, arg));
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(LimitClause limitClause, Expression arg) throws AsterixException {
+ limitClause.setLimitExpr(limitClause.getLimitExpr().accept(this, arg));
+ if (limitClause.hasOffset()) {
+ limitClause.setOffset(limitClause.getOffset().accept(this, arg));
+ }
+ return null;
+ }
+
+ @Override
+ public Expression visit(LetClause letClause, Expression arg) throws AsterixException {
+ letClause.setBindingExpr(letClause.getBindingExpr().accept(this, arg));
+ return null;
+ }
+
+ @Override
+ public Expression visit(SelectExpression selectExpression, Expression arg) throws AsterixException {
+ // visit let list
+ if (selectExpression.hasLetClauses()) {
+ for (LetClause letClause : selectExpression.getLetList()) {
+ letClause.accept(this, arg);
+ }
+ }
+
+ // visit the main select.
+ selectExpression.getSelectSetOperation().accept(this, arg);
+
+ // visit order by
+ if (selectExpression.hasOrderby()) {
+ for (Expression orderExpr : selectExpression.getOrderbyClause().getOrderbyList()) {
+ orderExpr.accept(this, arg);
+ }
+ }
+
+ // visit limit
+ if (selectExpression.hasLimit()) {
+ selectExpression.getLimitClause().accept(this, arg);
+ }
+ return selectExpression;
+ }
+
+ @Override
+ public Expression visit(LiteralExpr l, Expression arg) throws AsterixException {
+ return l;
+ }
+
+ @Override
+ public Expression visit(ListConstructor lc, Expression arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : lc.getExprList()) {
+ newExprList.add(expr.accept(this, arg));
+ }
+ lc.setExprList(newExprList);
+ return lc;
+ }
+
+ @Override
+ public Expression visit(RecordConstructor rc, Expression arg) throws AsterixException {
+ for (FieldBinding binding : rc.getFbList()) {
+ binding.setLeftExpr(binding.getLeftExpr().accept(this, arg));
+ binding.setRightExpr(binding.getRightExpr().accept(this, arg));
+ }
+ return rc;
+ }
+
+ @Override
+ public Expression visit(OperatorExpr operatorExpr, Expression arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : operatorExpr.getExprList()) {
+ newExprList.add(expr.accept(this, arg));
+ }
+ operatorExpr.setExprList(newExprList);
+ return operatorExpr;
+ }
+
+ @Override
+ public Expression visit(IfExpr ifExpr, Expression arg) throws AsterixException {
+ ifExpr.setCondExpr(ifExpr.getCondExpr().accept(this, arg));
+ ifExpr.setThenExpr(ifExpr.getThenExpr().accept(this, arg));
+ ifExpr.setElseExpr(ifExpr.getElseExpr().accept(this, arg));
+ return ifExpr;
+ }
+
+ @Override
+ public Expression visit(QuantifiedExpression qe, Expression arg) throws AsterixException {
+ for (QuantifiedPair pair : qe.getQuantifiedList()) {
+ pair.setExpr(pair.getExpr().accept(this, arg));
+ }
+ qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, arg));
+ return qe;
+ }
+
+ @Override
+ public Expression visit(CallExpr callExpr, Expression arg) throws AsterixException {
+ List<Expression> newExprList = new ArrayList<Expression>();
+ for (Expression expr : callExpr.getExprList()) {
+ newExprList.add(expr.accept(this, arg));
+ }
+ callExpr.setExprList(newExprList);
+ return callExpr;
+ }
+
+ @Override
+ public Expression visit(VariableExpr varExpr, Expression arg) throws AsterixException {
+ return varExpr;
+ }
+
+ @Override
+ public Expression visit(UnaryExpr u, Expression arg) throws AsterixException {
+ u.setExpr(u.getExpr().accept(this, arg));
+ return u;
+ }
+
+ @Override
+ public Expression visit(FieldAccessor fa, Expression arg) throws AsterixException {
+ fa.setExpr(fa.getExpr().accept(this, arg));
+ return fa;
+ }
+
+ @Override
+ public Expression visit(IndexAccessor ia, Expression arg) throws AsterixException {
+ ia.setExpr(ia.getExpr().accept(this, arg));
+ if (ia.getIndexExpr() != null) {
+ ia.setIndexExpr(ia.getIndexExpr());
+ }
+ return ia;
+ }
+
+}