use of org.apache.asterix.lang.common.base.Expression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method visit.
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(OperatorExpr op, Mutable<ILogicalOperator> tupSource) throws CompilationException {
List<OperatorType> ops = op.getOpList();
int nOps = ops.size();
if (nOps > 0 && (ops.get(0) == OperatorType.AND || ops.get(0) == OperatorType.OR)) {
return visitAndOrOperator(op, tupSource);
}
List<Expression> exprs = op.getExprList();
Mutable<ILogicalOperator> topOp = tupSource;
ILogicalExpression currExpr = null;
for (int i = 0; i <= nOps; i++) {
Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = langExprToAlgExpression(exprs.get(i), topOp);
topOp = p.second;
ILogicalExpression e = p.first;
// now look at the operator
if (i < nOps) {
if (OperatorExpr.opIsComparison(ops.get(i))) {
AbstractFunctionCallExpression c = createComparisonExpression(ops.get(i));
// chain the operators
if (i == 0) {
c.getArguments().add(new MutableObject<>(e));
currExpr = c;
if (op.isBroadcastOperand(i)) {
BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
bcast.setObject(BroadcastSide.LEFT);
c.getAnnotations().put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
}
} else {
((AbstractFunctionCallExpression) currExpr).getArguments().add(new MutableObject<>(e));
c.getArguments().add(new MutableObject<>(currExpr));
currExpr = c;
if (i == 1 && op.isBroadcastOperand(i)) {
BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
bcast.setObject(BroadcastSide.RIGHT);
c.getAnnotations().put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
}
}
} else {
AbstractFunctionCallExpression f = createFunctionCallExpressionForBuiltinOperator(ops.get(i));
if (i == 0) {
f.getArguments().add(new MutableObject<>(e));
currExpr = f;
} else {
((AbstractFunctionCallExpression) currExpr).getArguments().add(new MutableObject<>(e));
f.getArguments().add(new MutableObject<>(currExpr));
currExpr = f;
}
}
} else {
// don't forget the last expression...
((AbstractFunctionCallExpression) currExpr).getArguments().add(new MutableObject<>(e));
if (i == 1 && op.isBroadcastOperand(i)) {
BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
bcast.setObject(BroadcastSide.RIGHT);
((AbstractFunctionCallExpression) currExpr).getAnnotations().put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
}
}
}
// Add hints as annotations.
if (op.hasHints() && (currExpr instanceof AbstractFunctionCallExpression)) {
AbstractFunctionCallExpression currFuncExpr = (AbstractFunctionCallExpression) currExpr;
for (IExpressionAnnotation hint : op.getHints()) {
currFuncExpr.getAnnotations().put(hint, hint);
}
}
LogicalVariable assignedVar = context.newVar();
AssignOperator a = new AssignOperator(assignedVar, new MutableObject<>(currExpr));
a.getInputs().add(topOp);
return new Pair<>(a, assignedVar);
}
use of org.apache.asterix.lang.common.base.Expression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method translateUpsert.
private ILogicalOperator translateUpsert(DatasetDataSource targetDatasource, Mutable<ILogicalExpression> varRef, List<Mutable<ILogicalExpression>> varRefsForLoading, List<Mutable<ILogicalExpression>> additionalFilteringExpressions, ILogicalOperator assign, List<String> additionalFilteringField, LogicalVariable unnestVar, ILogicalOperator topOp, List<Mutable<ILogicalExpression>> exprs, LogicalVariable resVar, AssignOperator additionalFilteringAssign, ICompiledDmlStatement stmt) throws AlgebricksException {
if (!targetDatasource.getDataset().allow(topOp, DatasetUtil.OP_UPSERT)) {
throw new AlgebricksException(targetDatasource.getDataset().getDatasetName() + ": upsert into dataset is not supported on Datasets with Meta records");
}
ProjectOperator project = (ProjectOperator) topOp;
CompiledUpsertStatement compiledUpsert = (CompiledUpsertStatement) stmt;
Expression returnExpression = compiledUpsert.getReturnExpression();
InsertDeleteUpsertOperator upsertOp;
ILogicalOperator rootOperator;
if (targetDatasource.getDataset().hasMetaPart()) {
if (returnExpression != null) {
throw new AlgebricksException("Returning not allowed on datasets with Meta records");
}
AssignOperator metaAndKeysAssign;
List<LogicalVariable> metaAndKeysVars;
List<Mutable<ILogicalExpression>> metaAndKeysExprs;
List<Mutable<ILogicalExpression>> metaExpSingletonList;
metaAndKeysVars = new ArrayList<>();
metaAndKeysExprs = new ArrayList<>();
// add the meta function
IFunctionInfo finfoMeta = FunctionUtil.getFunctionInfo(BuiltinFunctions.META);
ScalarFunctionCallExpression metaFunction = new ScalarFunctionCallExpression(finfoMeta, new MutableObject<>(new VariableReferenceExpression(unnestVar)));
// create assign for the meta part
LogicalVariable metaVar = context.newVar();
metaExpSingletonList = new ArrayList<>(1);
metaExpSingletonList.add(new MutableObject<>(new VariableReferenceExpression(metaVar)));
metaAndKeysVars.add(metaVar);
metaAndKeysExprs.add(new MutableObject<>(metaFunction));
project.getVariables().add(metaVar);
varRefsForLoading.clear();
for (Mutable<ILogicalExpression> assignExpr : exprs) {
if (assignExpr.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
AbstractFunctionCallExpression funcCall = (AbstractFunctionCallExpression) assignExpr.getValue();
funcCall.substituteVar(resVar, unnestVar);
LogicalVariable pkVar = context.newVar();
metaAndKeysVars.add(pkVar);
metaAndKeysExprs.add(new MutableObject<>(assignExpr.getValue()));
project.getVariables().add(pkVar);
varRefsForLoading.add(new MutableObject<>(new VariableReferenceExpression(pkVar)));
}
}
// A change feed, we don't need the assign to access PKs
upsertOp = new InsertDeleteUpsertOperator(targetDatasource, varRef, varRefsForLoading, metaExpSingletonList, InsertDeleteUpsertOperator.Kind.UPSERT, false);
// Create and add a new variable used for representing the original record
upsertOp.setPrevRecordVar(context.newVar());
upsertOp.setPrevRecordType(targetDatasource.getItemType());
if (targetDatasource.getDataset().hasMetaPart()) {
List<LogicalVariable> metaVars = new ArrayList<>();
metaVars.add(context.newVar());
upsertOp.setPrevAdditionalNonFilteringVars(metaVars);
List<Object> metaTypes = new ArrayList<>();
metaTypes.add(targetDatasource.getMetaItemType());
upsertOp.setPrevAdditionalNonFilteringTypes(metaTypes);
}
if (additionalFilteringField != null) {
upsertOp.setPrevFilterVar(context.newVar());
upsertOp.setPrevFilterType(((ARecordType) targetDatasource.getItemType()).getFieldType(additionalFilteringField.get(0)));
additionalFilteringAssign.getInputs().clear();
additionalFilteringAssign.getInputs().add(assign.getInputs().get(0));
upsertOp.getInputs().add(new MutableObject<>(additionalFilteringAssign));
} else {
upsertOp.getInputs().add(assign.getInputs().get(0));
}
metaAndKeysAssign = new AssignOperator(metaAndKeysVars, metaAndKeysExprs);
metaAndKeysAssign.getInputs().add(topOp.getInputs().get(0));
topOp.getInputs().set(0, new MutableObject<>(metaAndKeysAssign));
upsertOp.setAdditionalFilteringExpressions(additionalFilteringExpressions);
} else {
upsertOp = new InsertDeleteUpsertOperator(targetDatasource, varRef, varRefsForLoading, InsertDeleteUpsertOperator.Kind.UPSERT, false);
upsertOp.setAdditionalFilteringExpressions(additionalFilteringExpressions);
upsertOp.getInputs().add(new MutableObject<>(assign));
// Create and add a new variable used for representing the original record
ARecordType recordType = (ARecordType) targetDatasource.getItemType();
upsertOp.setPrevRecordVar(context.newVar());
upsertOp.setPrevRecordType(recordType);
if (additionalFilteringField != null) {
upsertOp.setPrevFilterVar(context.newVar());
upsertOp.setPrevFilterType(recordType.getFieldType(additionalFilteringField.get(0)));
}
}
rootOperator = new DelegateOperator(new CommitOperator(returnExpression == null));
rootOperator.getInputs().add(new MutableObject<>(upsertOp));
// Compiles the return expression.
return processReturningExpression(rootOperator, upsertOp, compiledUpsert);
}
use of org.apache.asterix.lang.common.base.Expression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method visitAndOrOperator.
protected Pair<ILogicalOperator, LogicalVariable> visitAndOrOperator(OperatorExpr op, Mutable<ILogicalOperator> tupSource) throws CompilationException {
List<OperatorType> ops = op.getOpList();
int nOps = ops.size();
List<Expression> exprs = op.getExprList();
Mutable<ILogicalOperator> topOp = tupSource;
OperatorType opLogical = ops.get(0);
AbstractFunctionCallExpression f = createFunctionCallExpressionForBuiltinOperator(opLogical);
for (int i = 0; i <= nOps; i++) {
Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = langExprToAlgExpression(exprs.get(i), topOp);
topOp = p.second;
// now look at the operator
if (i < nOps && ops.get(i) != opLogical) {
throw new TranslationException("Unexpected operator " + ops.get(i) + " in an OperatorExpr starting with " + opLogical);
}
f.getArguments().add(new MutableObject<>(p.first));
}
LogicalVariable assignedVar = context.newVar();
AssignOperator a = new AssignOperator(assignedVar, new MutableObject<>(f));
a.getInputs().add(topOp);
return new Pair<>(a, assignedVar);
}
use of org.apache.asterix.lang.common.base.Expression 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.common.base.Expression in project asterixdb by apache.
the class AqlExpressionToPlanTranslator method visit.
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(FLWOGRExpression flwor, Mutable<ILogicalOperator> tupSource) throws CompilationException {
Mutable<ILogicalOperator> flworPlan = tupSource;
boolean isTop = context.isTopFlwor();
if (!isTop) {
context.enterSubplan();
}
if (isTop) {
context.setTopFlwor(false);
}
for (Clause c : flwor.getClauseList()) {
Pair<ILogicalOperator, LogicalVariable> pC = c.accept(this, flworPlan);
flworPlan = new MutableObject<>(pC.first);
}
Expression r = flwor.getReturnExpr();
boolean noForClause = flwor.noForClause();
Pair<ILogicalOperator, LogicalVariable> result;
if (r.getKind() == Kind.VARIABLE_EXPRESSION) {
VariableExpr v = (VariableExpr) r;
LogicalVariable var = context.getVar(v.getVar().getId());
result = produceFlworPlan(noForClause, isTop, flworPlan, var);
} else {
Mutable<ILogicalOperator> baseOp = new MutableObject<>(flworPlan.getValue());
Pair<ILogicalOperator, LogicalVariable> rRes = r.accept(this, baseOp);
ILogicalOperator rOp = rRes.first;
ILogicalOperator resOp;
if (expressionNeedsNoNesting(r)) {
baseOp.setValue(flworPlan.getValue());
resOp = rOp;
} else {
SubplanOperator s = new SubplanOperator(rOp);
s.getInputs().add(flworPlan);
resOp = s;
baseOp.setValue(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(s)));
}
Mutable<ILogicalOperator> resOpRef = new MutableObject<>(resOp);
result = produceFlworPlan(noForClause, isTop, resOpRef, rRes.second);
}
if (!isTop) {
context.exitSubplan();
}
return result;
}
Aggregations