use of org.apache.asterix.lang.common.base.ILangExpression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method translateUnionAllFromInputExprs.
// Generates the plan for "UNION ALL" or union expression from its input expressions.
protected Pair<ILogicalOperator, LogicalVariable> translateUnionAllFromInputExprs(List<ILangExpression> inputExprs, Mutable<ILogicalOperator> tupSource) throws CompilationException {
List<Mutable<ILogicalOperator>> inputOpRefsToUnion = new ArrayList<>();
List<LogicalVariable> vars = new ArrayList<>();
for (ILangExpression expr : inputExprs) {
// Visits the expression of one branch.
Pair<ILogicalOperator, LogicalVariable> opAndVar = expr.accept(this, tupSource);
// Creates an unnest operator.
LogicalVariable unnestVar = context.newVar();
List<Mutable<ILogicalExpression>> args = new ArrayList<>();
args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(opAndVar.second)));
UnnestOperator unnestOp = new UnnestOperator(unnestVar, new MutableObject<ILogicalExpression>(new UnnestingFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION), args)));
unnestOp.getInputs().add(new MutableObject<>(opAndVar.first));
inputOpRefsToUnion.add(new MutableObject<ILogicalOperator>(unnestOp));
vars.add(unnestVar);
}
// Creates a tree of binary union-all operators.
UnionAllOperator topUnionAllOp = null;
LogicalVariable topUnionVar = null;
Iterator<Mutable<ILogicalOperator>> inputOpRefIterator = inputOpRefsToUnion.iterator();
Mutable<ILogicalOperator> leftInputBranch = inputOpRefIterator.next();
Iterator<LogicalVariable> inputVarIterator = vars.iterator();
LogicalVariable leftInputVar = inputVarIterator.next();
while (inputOpRefIterator.hasNext()) {
// Generates the variable triple <leftVar, rightVar, outputVar> .
topUnionVar = context.newVar();
Triple<LogicalVariable, LogicalVariable, LogicalVariable> varTriple = new Triple<>(leftInputVar, inputVarIterator.next(), topUnionVar);
List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varTriples = new ArrayList<>();
varTriples.add(varTriple);
// Creates a binary union-all operator.
topUnionAllOp = new UnionAllOperator(varTriples);
topUnionAllOp.getInputs().add(leftInputBranch);
topUnionAllOp.getInputs().add(inputOpRefIterator.next());
// Re-assigns leftInputBranch and leftInputVar.
leftInputBranch = new MutableObject<>(topUnionAllOp);
leftInputVar = topUnionVar;
}
return new Pair<>(topUnionAllOp, topUnionVar);
}
use of org.apache.asterix.lang.common.base.ILangExpression in project asterixdb by apache.
the class SqlppGroupByVisitor method visit.
@Override
public Expression visit(GroupbyClause gc, ILangExpression arg) throws CompilationException {
// Puts all FROM binding variables into withVarList.
FromClause fromClause = (FromClause) arg;
Collection<VariableExpr> fromBindingVars = fromClause == null ? new ArrayList<>() : SqlppVariableUtil.getBindingVariables(fromClause);
Map<Expression, VariableExpr> withVarMap = new HashMap<>();
for (VariableExpr fromBindingVar : fromBindingVars) {
VariableExpr varExpr = new VariableExpr();
varExpr.setIsNewVar(false);
varExpr.setVar(fromBindingVar.getVar());
VariableExpr newVarExpr = (VariableExpr) SqlppRewriteUtil.deepCopy(varExpr);
withVarMap.put(varExpr, newVarExpr);
}
// Sets the field list for the group variable.
List<Pair<Expression, Identifier>> groupFieldList = new ArrayList<>();
if (!gc.hasGroupFieldList()) {
for (VariableExpr varExpr : fromBindingVars) {
Pair<Expression, Identifier> varIdPair = new Pair<>(new VariableExpr(varExpr.getVar()), SqlppVariableUtil.toUserDefinedVariableName(varExpr.getVar()));
groupFieldList.add(varIdPair);
}
gc.setGroupFieldList(groupFieldList);
} else {
for (Pair<Expression, Identifier> groupField : gc.getGroupFieldList()) {
Expression newFieldExpr = groupField.first.accept(this, arg);
groupFieldList.add(new Pair<>(newFieldExpr, groupField.second));
// Adds a field binding variable into withVarList.
VariableExpr bindingVar = new VariableExpr(new VarIdentifier(SqlppVariableUtil.toInternalVariableName(groupField.second.getValue())));
withVarMap.put(newFieldExpr, bindingVar);
}
}
gc.setGroupFieldList(groupFieldList);
// Sets the group variable.
if (!gc.hasGroupVar()) {
VariableExpr groupVar = new VariableExpr(context.newVariable());
gc.setGroupVar(groupVar);
}
// Adds the group variable into the "with" (i.e., re-binding) variable list.
VariableExpr gbyVarRef = new VariableExpr(gc.getGroupVar().getVar());
gbyVarRef.setIsNewVar(false);
withVarMap.put(gbyVarRef, (VariableExpr) SqlppRewriteUtil.deepCopy(gbyVarRef));
gc.setWithVarMap(withVarMap);
// Call super.visit(...) to scope variables.
return super.visit(gc, arg);
}
use of org.apache.asterix.lang.common.base.ILangExpression in project asterixdb by apache.
the class SqlppGroupByVisitor method visit.
@Override
public Expression visit(SelectBlock selectBlock, ILangExpression arg) throws CompilationException {
// Traverses the select block in the order of "from", "let"s, "where",
// "group by", "let"s, "having" and "select".
FromClause fromClause = selectBlock.getFromClause();
if (selectBlock.hasFromClause()) {
fromClause.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()) {
GroupbyClause groupbyClause = selectBlock.getGroupbyClause();
groupbyClause.accept(this, fromClause);
Collection<VariableExpr> visibleVarsInCurrentScope = SqlppVariableUtil.getBindingVariables(groupbyClause);
VariableExpr groupVar = groupbyClause.getGroupVar();
Set<VariableExpr> groupFieldVars = getGroupFieldVariables(groupbyClause);
Collection<VariableExpr> freeVariablesInGbyLets = new HashSet<>();
if (selectBlock.hasLetClausesAfterGroupby()) {
List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
for (LetClause letClauseAfterGby : letListAfterGby) {
letClauseAfterGby.accept(this, arg);
// Rewrites each let clause after the group-by.
SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, letClauseAfterGby, context);
Collection<VariableExpr> freeVariablesInLet = SqlppVariableUtil.getFreeVariables(letClauseAfterGby.getBindingExpr());
freeVariablesInLet.removeAll(visibleVarsInCurrentScope);
freeVariablesInGbyLets.addAll(freeVariablesInLet);
visibleVarsInCurrentScope.add(letClauseAfterGby.getVarExpr());
}
}
Collection<VariableExpr> freeVariables = new HashSet<>();
if (selectBlock.hasHavingClause()) {
// Rewrites the having clause.
HavingClause havingClause = selectBlock.getHavingClause();
havingClause.accept(this, arg);
SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, havingClause, context);
freeVariables.addAll(SqlppVariableUtil.getFreeVariables(havingClause));
}
SelectExpression parentSelectExpression = (SelectExpression) arg;
// We cannot rewrite ORDER BY and LIMIT if it's a SET operation query.
if (!parentSelectExpression.getSelectSetOperation().hasRightInputs()) {
if (parentSelectExpression.hasOrderby()) {
// Rewrites the ORDER BY clause.
OrderbyClause orderbyClause = parentSelectExpression.getOrderbyClause();
orderbyClause.accept(this, arg);
SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, orderbyClause, context);
freeVariables.addAll(SqlppVariableUtil.getFreeVariables(orderbyClause));
}
if (parentSelectExpression.hasLimit()) {
// Rewrites the LIMIT clause.
LimitClause limitClause = parentSelectExpression.getLimitClause();
limitClause.accept(this, arg);
SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, limitClause, context);
freeVariables.addAll(SqlppVariableUtil.getFreeVariables(limitClause));
}
}
// Visits the select clause.
SelectClause selectClause = selectBlock.getSelectClause();
selectClause.accept(this, arg);
// Rewrites the select clause.
SqlppRewriteUtil.rewriteExpressionUsingGroupVariable(groupVar, groupFieldVars, selectClause, context);
freeVariables.addAll(SqlppVariableUtil.getFreeVariables(selectClause));
freeVariables.removeAll(visibleVarsInCurrentScope);
// Gets the final free variables.
freeVariables.addAll(freeVariablesInGbyLets);
// Gets outer scope variables.
Collection<VariableExpr> decorVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope(), true);
decorVars.removeAll(visibleVarsInCurrentScope);
// Need path resolution or not?
boolean needResolution = !decorVars.containsAll(freeVariables);
// Otherwise, we only need to retain used free variables.
if (needResolution) {
// Tracks used variables, including WITH variables.
decorVars.retainAll(freeVariables);
// Adds all non-WITH outer scope variables, for path resolution.
Collection<VariableExpr> visibleOuterScopeNonWithVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope(), false);
visibleOuterScopeNonWithVars.removeAll(visibleVarsInCurrentScope);
decorVars.addAll(visibleOuterScopeNonWithVars);
} else {
// Only retains used free variables.
decorVars.retainAll(freeVariables);
}
if (!decorVars.isEmpty()) {
// Adds used WITH variables.
Collection<VariableExpr> visibleOuterScopeNonWithVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope(), false);
visibleOuterScopeNonWithVars.retainAll(freeVariables);
decorVars.addAll(visibleOuterScopeNonWithVars);
// Adds necessary decoration variables for the GROUP BY.
// NOTE: we need to include WITH binding variables so as they can be evaluated before
// the GROUP BY instead of being inlined as part of nested pipepline. The current optimzier
// is not able to optimize the latter case. The following query is such an example:
// asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/dapd/q2-11
List<GbyVariableExpressionPair> decorList = new ArrayList<>();
for (VariableExpr var : decorVars) {
decorList.add(new GbyVariableExpressionPair((VariableExpr) SqlppRewriteUtil.deepCopy(var), (Expression) SqlppRewriteUtil.deepCopy(var)));
}
groupbyClause.getDecorPairList().addAll(decorList);
}
} else {
selectBlock.getSelectClause().accept(this, arg);
}
return null;
}
use of org.apache.asterix.lang.common.base.ILangExpression in project asterixdb by apache.
the class OperatorExpressionVisitor method visit.
@Override
public Expression visit(OperatorExpr operatorExpr, ILangExpression arg) throws CompilationException {
List<Expression> newExprList = new ArrayList<>();
for (Expression expr : operatorExpr.getExprList()) {
newExprList.add(expr.accept(this, operatorExpr));
}
operatorExpr.setExprList(newExprList);
OperatorType opType = operatorExpr.getOpList().get(0);
switch(opType) {
// There can only be one LIKE/NOT_LIKE/IN/NOT_IN in an operator expression (according to the grammar).
case LIKE:
case NOT_LIKE:
return processLikeOperator(operatorExpr, opType);
case IN:
case NOT_IN:
return processInOperator(operatorExpr, opType);
case CONCAT:
// There can be multiple "||"s in one operator expression (according to the grammar).
return processConcatOperator(operatorExpr);
case BETWEEN:
case NOT_BETWEEN:
return processBetweenOperator(operatorExpr, opType);
default:
break;
}
return operatorExpr;
}
use of org.apache.asterix.lang.common.base.ILangExpression in project asterixdb by apache.
the class SqlppListInputFunctionRewriteVisitor method visit.
@Override
public Expression visit(CallExpr callExpr, ILangExpression arg) throws CompilationException {
List<Expression> newExprList = new ArrayList<>();
for (Expression expr : callExpr.getExprList()) {
newExprList.add(expr.accept(this, arg));
}
callExpr.setExprList(newExprList);
return FunctionMapUtil.normalizedListInputFunctions(callExpr);
}
Aggregations