use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.
the class ExternalDataLookupPOperator method contributeRuntimeOperator.
@Override
public void contributeRuntimeOperator(IHyracksJobBuilder builder, JobGenContext context, ILogicalOperator op, IOperatorSchema opSchema, IOperatorSchema[] inputSchemas, IOperatorSchema outerPlanSchema) throws AlgebricksException {
UnnestMapOperator unnestMap = (UnnestMapOperator) op;
ILogicalExpression expr = unnestMap.getExpressionRef().getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
throw new IllegalStateException();
}
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
FunctionIdentifier funcIdent = funcExpr.getFunctionIdentifier();
if (!funcIdent.equals(BuiltinFunctions.EXTERNAL_LOOKUP)) {
return;
}
int[] ridIndexes = getKeyIndexes(ridVarList, inputSchemas);
IVariableTypeEnvironment typeEnv = context.getTypeEnvironment(op);
MetadataProvider metadataProvider = (MetadataProvider) context.getMetadataProvider();
Pair<IOperatorDescriptor, AlgebricksPartitionConstraint> externalLoopup = metadataProvider.buildExternalDataLookupRuntime(builder.getJobSpec(), dataset, ridIndexes, retainInput, typeEnv, opSchema, context, metadataProvider, retainMissing);
builder.contributeHyracksOperator(unnestMap, externalLoopup.first);
builder.contributeAlgebricksPartitionConstraint(externalLoopup.first, externalLoopup.second);
ILogicalOperator srcExchange = unnestMap.getInputs().get(0).getValue();
builder.contributeGraphEdge(srcExchange, 0, unnestMap, 0);
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.
the class ByNameToByIndexFieldAccessRule method rewriteExpressionReference.
// Recursively rewrites expression reference.
private boolean rewriteExpressionReference(ILogicalOperator op, Mutable<ILogicalExpression> exprRef, IOptimizationContext context) throws AlgebricksException {
ILogicalExpression expr = exprRef.getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
boolean changed = false;
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
for (Mutable<ILogicalExpression> funcArgRef : funcExpr.getArguments()) {
if (rewriteExpressionReference(op, funcArgRef, context)) {
changed = true;
}
}
AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
if (fce.getFunctionIdentifier() != BuiltinFunctions.FIELD_ACCESS_BY_NAME) {
return changed;
}
changed |= extractFirstArg(fce, op, context);
IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
IAType t = (IAType) env.getType(fce.getArguments().get(0).getValue());
changed |= rewriteFieldAccess(exprRef, fce, getActualType(t));
return changed;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment in project asterixdb by apache.
the class IntroduceUnnestForCollectionToSequenceRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
}
AssignOperator assign = (AssignOperator) op;
List<Mutable<ILogicalExpression>> exprs = assign.getExpressions();
if (exprs.size() != 1) {
return false;
}
ILogicalExpression expr = exprs.get(0).getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression func = (AbstractFunctionCallExpression) expr;
if (func.getFunctionIdentifier() != BuiltinFunctions.COLLECTION_TO_SEQUENCE) {
return false;
}
IVariableTypeEnvironment env = assign.computeInputTypeEnvironment(context);
ILogicalExpression argExpr = func.getArguments().get(0).getValue();
IAType outerExprType = (IAType) env.getType(expr);
IAType innerExprType = (IAType) env.getType(argExpr);
if (outerExprType.equals(innerExprType)) {
/** nothing is changed with the collection-to-sequence function, remove the collection-sequence function call */
assign.getExpressions().set(0, new MutableObject<ILogicalExpression>(argExpr));
return true;
}
/** change the assign operator to an unnest operator */
LogicalVariable var = assign.getVariables().get(0);
@SuppressWarnings("unchecked") UnnestOperator unnest = new UnnestOperator(var, new MutableObject<ILogicalExpression>(new UnnestingFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION), new MutableObject<ILogicalExpression>(argExpr))));
unnest.getInputs().addAll(assign.getInputs());
opRef.setValue(unnest);
context.computeAndSetTypeEnvironmentForOperator(unnest);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment 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.expressions.IVariableTypeEnvironment in project asterixdb by apache.
the class IntroduceDynamicTypeCastRule method addWrapperFunction.
/**
* Inject a function to wrap a variable when necessary
*
* @param requiredRecordType
* the required record type
* @param recordVar
* the record variable
* @param parent
* the current parent operator to be rewritten
* @param context
* the optimization context
* @param fd
* the function to be injected
* @return true if cast is injected; false otherwise.
* @throws AlgebricksException
*/
public static LogicalVariable addWrapperFunction(ARecordType requiredRecordType, LogicalVariable recordVar, ILogicalOperator parent, IOptimizationContext context, FunctionIdentifier fd) throws AlgebricksException {
List<Mutable<ILogicalOperator>> opRefs = parent.getInputs();
for (int index = 0; index < opRefs.size(); index++) {
Mutable<ILogicalOperator> opRef = opRefs.get(index);
ILogicalOperator op = opRef.getValue();
/** get produced vars */
List<LogicalVariable> producedVars = new ArrayList<LogicalVariable>();
VariableUtilities.getProducedVariables(op, producedVars);
IVariableTypeEnvironment env = op.computeOutputTypeEnvironment(context);
for (int i = 0; i < producedVars.size(); i++) {
LogicalVariable var = producedVars.get(i);
if (var.equals(recordVar)) {
/** insert an assign operator to call the function on-top-of the variable */
IAType actualType = (IAType) env.getVarType(var);
AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fd));
cast.getArguments().add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
/** enforce the required record type */
TypeCastUtils.setRequiredAndInputTypes(cast, requiredRecordType, actualType);
LogicalVariable newAssignVar = context.newVar();
AssignOperator newAssignOperator = new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(cast));
newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op));
opRef.setValue(newAssignOperator);
context.computeAndSetTypeEnvironmentForOperator(newAssignOperator);
newAssignOperator.computeOutputTypeEnvironment(context);
VariableUtilities.substituteVariables(parent, recordVar, newAssignVar, context);
return newAssignVar;
}
}
/** recursive descend to the operator who produced the recordVar */
LogicalVariable replacedVar = addWrapperFunction(requiredRecordType, recordVar, op, context, fd);
if (replacedVar != null) {
/** substitute the recordVar by the replacedVar for operators who uses recordVar */
VariableUtilities.substituteVariables(parent, recordVar, replacedVar, context);
return replacedVar;
}
}
return null;
}
Aggregations