use of org.apache.asterix.lang.sqlpp.expression.CaseExpression in project asterixdb by apache.
the class SqlppExpressionToPlanTranslator method visit.
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(CaseExpression caseExpression, Mutable<ILogicalOperator> tupSource) throws CompilationException {
//Creates a series of subplan operators, one for each branch.
Mutable<ILogicalOperator> currentOpRef = tupSource;
ILogicalOperator currentOperator = null;
List<Expression> whenExprList = caseExpression.getWhenExprs();
List<Expression> thenExprList = caseExpression.getThenExprs();
List<ILogicalExpression> branchCondVarReferences = new ArrayList<>();
List<ILogicalExpression> allVarReferences = new ArrayList<>();
for (int index = 0; index < whenExprList.size(); ++index) {
Pair<ILogicalOperator, LogicalVariable> whenExprResult = whenExprList.get(index).accept(this, currentOpRef);
currentOperator = whenExprResult.first;
// Variable whenConditionVar is corresponds to the current "WHEN" condition.
LogicalVariable whenConditionVar = whenExprResult.second;
Mutable<ILogicalExpression> branchEntraceConditionExprRef = new MutableObject<>(new VariableReferenceExpression(whenConditionVar));
// even though multiple "WHEN" conditions can be satisfied.
if (!branchCondVarReferences.isEmpty()) {
// The additional filter generated here makes sure the the tuple has not
// entered other matched "WHEN...THEN" case.
List<Mutable<ILogicalExpression>> andArgs = new ArrayList<>();
andArgs.add(generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences));
andArgs.add(branchEntraceConditionExprRef);
// A "THEN" branch can be entered only when the tuple has not enter any other preceding
// branches and the current "WHEN" condition is TRUE.
branchEntraceConditionExprRef = new MutableObject<>(new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.AND), andArgs));
}
// Translates the corresponding "THEN" expression.
Pair<ILogicalOperator, LogicalVariable> opAndVarForThen = constructSubplanOperatorForBranch(currentOperator, branchEntraceConditionExprRef, thenExprList.get(index));
branchCondVarReferences.add(new VariableReferenceExpression(whenConditionVar));
allVarReferences.add(new VariableReferenceExpression(whenConditionVar));
allVarReferences.add(new VariableReferenceExpression(opAndVarForThen.second));
currentOperator = opAndVarForThen.first;
currentOpRef = new MutableObject<>(currentOperator);
}
// Creates a subplan for the "ELSE" branch.
Mutable<ILogicalExpression> elseCondExprRef = generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences);
Pair<ILogicalOperator, LogicalVariable> opAndVarForElse = constructSubplanOperatorForBranch(currentOperator, elseCondExprRef, caseExpression.getElseExpr());
// Uses switch-case function to select the results of two branches.
LogicalVariable selectVar = context.newVar();
List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
arguments.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(ABoolean.TRUE))));
for (ILogicalExpression argVar : allVarReferences) {
arguments.add(new MutableObject<>(argVar));
}
arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForElse.second)));
AbstractFunctionCallExpression swithCaseExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.SWITCH_CASE), arguments);
AssignOperator assignOp = new AssignOperator(selectVar, new MutableObject<>(swithCaseExpr));
assignOp.getInputs().add(new MutableObject<>(opAndVarForElse.first));
// Unnests the selected (a "THEN" or "ELSE" branch) result.
LogicalVariable unnestVar = context.newVar();
UnnestOperator unnestOp = new UnnestOperator(unnestVar, new MutableObject<>(new UnnestingFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION), Collections.singletonList(new MutableObject<>(new VariableReferenceExpression(selectVar))))));
unnestOp.getInputs().add(new MutableObject<>(assignOp));
// Produces the final assign operator.
LogicalVariable resultVar = context.newVar();
AssignOperator finalAssignOp = new AssignOperator(resultVar, new MutableObject<>(new VariableReferenceExpression(unnestVar)));
finalAssignOp.getInputs().add(new MutableObject<>(unnestOp));
return new Pair<>(finalAssignOp, resultVar);
}
use of org.apache.asterix.lang.sqlpp.expression.CaseExpression in project asterixdb by apache.
the class DeepCopyVisitor method visit.
@Override
public ILangExpression visit(CaseExpression caseExpr, Void arg) throws CompilationException {
Expression conditionExpr = (Expression) caseExpr.getConditionExpr().accept(this, arg);
List<Expression> whenExprList = copyExprList(caseExpr.getWhenExprs(), arg);
List<Expression> thenExprList = copyExprList(caseExpr.getThenExprs(), arg);
Expression elseExpr = (Expression) caseExpr.getElseExpr().accept(this, arg);
return new CaseExpression(conditionExpr, whenExprList, thenExprList, elseExpr);
}
use of org.apache.asterix.lang.sqlpp.expression.CaseExpression in project asterixdb by apache.
the class SqlppBuiltinFunctionRewriteVisitor method normalizeCaseExpr.
// Normalizes WHEN expressions so that it can have correct NULL/MISSING semantics as well
// as type promotion semantics.
private CaseExpression normalizeCaseExpr(CaseExpression caseExpr) throws CompilationException {
LiteralExpr trueLiteral = new LiteralExpr(TrueLiteral.INSTANCE);
Expression conditionExpr = caseExpr.getConditionExpr();
if (trueLiteral.equals(conditionExpr)) {
return caseExpr;
}
List<Expression> normalizedWhenExprs = new ArrayList<>();
for (Expression expr : caseExpr.getWhenExprs()) {
OperatorExpr operatorExpr = new OperatorExpr();
operatorExpr.addOperand((Expression) SqlppRewriteUtil.deepCopy(expr));
operatorExpr.addOperand(caseExpr.getConditionExpr());
operatorExpr.addOperator("=");
normalizedWhenExprs.add(operatorExpr);
}
return new CaseExpression(trueLiteral, normalizedWhenExprs, caseExpr.getThenExprs(), caseExpr.getElseExpr());
}
use of org.apache.asterix.lang.sqlpp.expression.CaseExpression in project asterixdb by apache.
the class SqlppBuiltinFunctionRewriteVisitor method visit.
@Override
public Expression visit(CaseExpression caseExpr, ILangExpression arg) throws CompilationException {
// Visits it as usual first.
Expression expr = super.visit(caseExpr, arg);
if (expr != caseExpr) {
return expr.accept(this, arg);
}
CaseExpression newCaseExpr = normalizeCaseExpr(caseExpr);
if (SqlppRewriteUtil.constainsSubquery(newCaseExpr)) {
// If the CASE expression contains a subquery, we do not rewrite it to a switch-case function call.
return newCaseExpr;
}
// If the CASE expression does not contain a subquery, we rewrite it to a switch-case function call.
FunctionSignature functionSignature = new FunctionSignature(MetadataConstants.METADATA_DATAVERSE_NAME, "switch-case", FunctionIdentifier.VARARGS);
List<Expression> whenExprList = newCaseExpr.getWhenExprs();
List<Expression> thenExprList = newCaseExpr.getThenExprs();
List<Expression> newExprList = new ArrayList<>();
newExprList.add(newCaseExpr.getConditionExpr());
for (int index = 0; index < whenExprList.size(); ++index) {
newExprList.add(whenExprList.get(index));
newExprList.add(thenExprList.get(index));
}
newExprList.add(newCaseExpr.getElseExpr());
return new CallExpr(functionSignature, newExprList);
}
use of org.apache.asterix.lang.sqlpp.expression.CaseExpression in project asterixdb by apache.
the class SqlppCloneAndSubstituteVariablesVisitor method visit.
@Override
public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(CaseExpression caseExpr, VariableSubstitutionEnvironment env) throws CompilationException {
Expression conditionExpr = (Expression) caseExpr.getConditionExpr().accept(this, env).first;
List<Expression> whenExprList = VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getWhenExprs(), env, this);
List<Expression> thenExprList = VariableCloneAndSubstitutionUtil.visitAndCloneExprList(caseExpr.getThenExprs(), env, this);
Expression elseExpr = (Expression) caseExpr.getElseExpr().accept(this, env).first;
CaseExpression newCaseExpr = new CaseExpression(conditionExpr, whenExprList, thenExprList, elseExpr);
return new Pair<>(newCaseExpr, env);
}
Aggregations