use of org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator in project asterixdb by apache.
the class IntroduceStaticTypeCastForInsertRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
/**
* pattern match: sink/insert/assign record type is propagated from
* insert data source to the record-constructor expression
*/
if (context.checkIfInDontApplySet(this, opRef.getValue())) {
return false;
}
context.addToDontApplySet(this, opRef.getValue());
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
List<LogicalVariable> producedVariables = new ArrayList<LogicalVariable>();
LogicalVariable oldRecordVariable;
if (op1.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR && op1.getOperatorTag() != LogicalOperatorTag.SINK) {
return false;
}
if (op1.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR) {
DelegateOperator eOp = (DelegateOperator) op1;
if (!(eOp.getDelegate() instanceof CommitOperator)) {
return false;
}
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
if (op2.getOperatorTag() != LogicalOperatorTag.INSERT_DELETE_UPSERT) {
return false;
}
InsertDeleteUpsertOperator insertDeleteOp = (InsertDeleteUpsertOperator) op2;
if (insertDeleteOp.getOperation() == InsertDeleteUpsertOperator.Kind.DELETE) {
return false;
}
/**
* get required record type
*/
InsertDeleteUpsertOperator insertDeleteOperator = (InsertDeleteUpsertOperator) op2;
DataSource dataSource = (DataSource) insertDeleteOperator.getDataSource();
IAType requiredRecordType = dataSource.getItemType();
List<LogicalVariable> usedVariables = new ArrayList<LogicalVariable>();
insertDeleteOperator.getPayloadExpression().getValue().getUsedVariables(usedVariables);
// empty
if (usedVariables.size() == 0) {
return false;
}
oldRecordVariable = usedVariables.get(0);
LogicalVariable inputRecordVar = usedVariables.get(0);
IVariableTypeEnvironment env = insertDeleteOperator.computeOutputTypeEnvironment(context);
IAType inputRecordType = (IAType) env.getVarType(inputRecordVar);
AbstractLogicalOperator currentOperator = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
/**
* find the assign operator for the "input record" to the insert_delete
* operator
*/
do {
context.addToDontApplySet(this, currentOperator);
if (currentOperator.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
AssignOperator assignOp = (AssignOperator) currentOperator;
producedVariables.clear();
VariableUtilities.getProducedVariables(currentOperator, producedVariables);
int position = producedVariables.indexOf(oldRecordVariable);
/**
* set the top-down propagated type
*/
if (position >= 0) {
AssignOperator originalAssign = (AssignOperator) currentOperator;
List<Mutable<ILogicalExpression>> expressionRefs = originalAssign.getExpressions();
ILogicalExpression expr = expressionRefs.get(position).getValue();
if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
// fail but just return false
if (TypeCastUtils.getRequiredType(funcExpr) != null) {
context.computeAndSetTypeEnvironmentForOperator(assignOp);
return false;
}
IVariableTypeEnvironment assignEnv = assignOp.computeOutputTypeEnvironment(context);
StaticTypeCastUtil.rewriteFuncExpr(funcExpr, requiredRecordType, inputRecordType, assignEnv);
}
context.computeAndSetTypeEnvironmentForOperator(originalAssign);
}
}
if (currentOperator.getInputs().size() > 0) {
currentOperator = (AbstractLogicalOperator) currentOperator.getInputs().get(0).getValue();
} else {
break;
}
} while (currentOperator != null);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator in project asterixdb by apache.
the class IntroduceAutogenerateIDRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
// match: commit OR distribute-result OR SINK - ... followed by:
// [insert to internal dataset with autogenerated id] - assign - project
// produce: insert - assign - assign* - project
// **
// OR [insert to internal dataset with autogenerated id] - assign - [datasource scan]
// produce insert - assign - assign* - datasource scan
AbstractLogicalOperator currentOp = (AbstractLogicalOperator) opRef.getValue();
if (currentOp.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR) {
DelegateOperator dOp = (DelegateOperator) currentOp;
if (!(dOp.getDelegate() instanceof CommitOperator)) {
return false;
} else if (!((CommitOperator) dOp.getDelegate()).isSink()) {
return false;
}
} else if (currentOp.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT && currentOp.getOperatorTag() != LogicalOperatorTag.SINK) {
return false;
}
ArrayDeque<AbstractLogicalOperator> opStack = new ArrayDeque<>();
opStack.push(currentOp);
while (currentOp.getInputs().size() == 1) {
currentOp = (AbstractLogicalOperator) currentOp.getInputs().get(0).getValue();
if (currentOp.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE_UPSERT) {
break;
}
opStack.push(currentOp);
}
if (currentOp.getOperatorTag() != LogicalOperatorTag.INSERT_DELETE_UPSERT) {
return false;
}
InsertDeleteUpsertOperator insertOp = (InsertDeleteUpsertOperator) currentOp;
if (insertOp.getOperation() != Kind.INSERT && insertOp.getOperation() != Kind.UPSERT) {
return false;
}
DatasetDataSource dds = (DatasetDataSource) insertOp.getDataSource();
boolean autogenerated = ((InternalDatasetDetails) dds.getDataset().getDatasetDetails()).isAutogenerated();
if (!autogenerated) {
return false;
}
if (((DataSource) insertOp.getDataSource()).getDatasourceType() != Type.INTERNAL_DATASET) {
return false;
}
AbstractLogicalOperator parentOp = (AbstractLogicalOperator) currentOp.getInputs().get(0).getValue();
if (parentOp.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
}
AssignOperator assignOp = (AssignOperator) parentOp;
LogicalVariable inputRecord;
//TODO: bug here. will not work for internal datasets with filters since the pattern becomes
//[project-assign-assign-insert]
AbstractLogicalOperator grandparentOp = (AbstractLogicalOperator) parentOp.getInputs().get(0).getValue();
if (grandparentOp.getOperatorTag() == LogicalOperatorTag.PROJECT) {
ProjectOperator projectOp = (ProjectOperator) grandparentOp;
inputRecord = projectOp.getVariables().get(0);
} else if (grandparentOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
DataSourceScanOperator dssOp = (DataSourceScanOperator) grandparentOp;
inputRecord = dssOp.getVariables().get(0);
} else {
return false;
}
List<String> pkFieldName = ((InternalDatasetDetails) dds.getDataset().getDatasetDetails()).getPrimaryKey().get(0);
ILogicalExpression rec0 = new VariableReferenceExpression(inputRecord);
ILogicalExpression rec1 = createPrimaryKeyRecordExpression(pkFieldName);
ILogicalExpression mergedRec = createRecordMergeFunction(rec0, rec1);
ILogicalExpression nonNullMergedRec = createNotNullFunction(mergedRec);
LogicalVariable v = context.newVar();
AssignOperator newAssign = new AssignOperator(v, new MutableObject<ILogicalExpression>(nonNullMergedRec));
newAssign.getInputs().add(new MutableObject<ILogicalOperator>(grandparentOp));
assignOp.getInputs().set(0, new MutableObject<ILogicalOperator>(newAssign));
VariableUtilities.substituteVariables(assignOp, inputRecord, v, context);
VariableUtilities.substituteVariables(insertOp, inputRecord, v, context);
context.computeAndSetTypeEnvironmentForOperator(newAssign);
context.computeAndSetTypeEnvironmentForOperator(assignOp);
context.computeAndSetTypeEnvironmentForOperator(insertOp);
;
for (AbstractLogicalOperator op : opStack) {
VariableUtilities.substituteVariables(op, inputRecord, v, context);
context.computeAndSetTypeEnvironmentForOperator(op);
}
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator in project asterixdb by apache.
the class IntroduceSelectAccessMethodRule method rewritePre.
/**
* Recursively check the given plan from the root operator to transform a plan
* with SELECT operator into an index-utilized plan.
*/
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
clear();
setMetadataDeclarations(context);
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
// Already checked?
if (context.checkIfInDontApplySet(this, op)) {
return false;
}
// which is DISTRIBUTE_RESULT, SINK, or COMMIT since we start the process from the root operator.
if (op.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT && op.getOperatorTag() != LogicalOperatorTag.SINK && op.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR) {
return false;
}
if (op.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR && !(((DelegateOperator) op).getDelegate() instanceof CommitOperator)) {
return false;
}
afterSelectRefs = new ArrayList<>();
// Recursively check the given plan whether the desired pattern exists in it.
// If so, try to optimize the plan.
boolean planTransformed = checkAndApplyTheSelectTransformation(opRef, context);
if (selectOp != null) {
// We found an optimization here. Don't need to optimize this operator again.
context.addToDontApplySet(this, selectOp);
}
if (!planTransformed) {
return false;
} else {
OperatorPropertiesUtil.typeOpRec(opRef, context);
}
return planTransformed;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator in project asterixdb by apache.
the class IntroduceJoinAccessMethodRule method rewritePre.
/**
* Recursively check the given plan from the root operator to transform a plan
* with JOIN or LEFT-OUTER-JOIN operator into an index-utilized plan.
*/
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
clear();
setMetadataDeclarations(context);
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
// Already checked?
if (context.checkIfInDontApplySet(this, op)) {
return false;
}
// we start the process from the root operator.
if (op.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT && op.getOperatorTag() != LogicalOperatorTag.SINK && op.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR) {
return false;
}
if (op.getOperatorTag() == LogicalOperatorTag.DELEGATE_OPERATOR && !(((DelegateOperator) op).getDelegate() instanceof CommitOperator)) {
return false;
}
// Recursively check the given plan whether the desired pattern exists in it.
// If so, try to optimize the plan.
boolean planTransformed = checkAndApplyJoinTransformation(opRef, context);
if (joinOp != null) {
// We found an optimization here. Don't need to optimize this operator again.
context.addToDontApplySet(this, joinOp);
}
if (!planTransformed) {
return false;
} else {
OperatorPropertiesUtil.typeOpRec(opRef, context);
}
return planTransformed;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.DelegateOperator 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);
}
Aggregations