use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class IntroduceSecondaryIndexInsertDeleteRule method getRecordVar.
private LogicalVariable getRecordVar(IOptimizationContext context, AbstractLogicalOperator inputOp, ILogicalExpression recordExpr, int expectedRecordIndex) throws AlgebricksException {
if (exprIsRecord(context.getOutputTypeEnvironment(inputOp), recordExpr)) {
return ((VariableReferenceExpression) recordExpr).getVariableReference();
} else {
/**
* For the case primary key-assignment expressions are constant
* expressions, find assign op that creates record to be
* inserted/deleted.
*/
FunctionIdentifier fid = null;
AbstractLogicalOperator currentInputOp = inputOp;
while (fid != BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR) {
if (currentInputOp.getInputs().isEmpty()) {
return null;
}
currentInputOp = (AbstractLogicalOperator) currentInputOp.getInputs().get(0).getValue();
if (currentInputOp.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
continue;
}
AssignOperator assignOp = (AssignOperator) currentInputOp;
ILogicalExpression assignExpr = assignOp.getExpressions().get(expectedRecordIndex).getValue();
if (assignExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) assignOp.getExpressions().get(expectedRecordIndex).getValue();
fid = funcExpr.getFunctionIdentifier();
}
}
return ((AssignOperator) currentInputOp).getVariables().get(0);
}
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression 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;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression in project asterixdb by apache.
the class PushFieldAccessRule method isAccessToIndexedField.
@SuppressWarnings("unchecked")
private boolean isAccessToIndexedField(AssignOperator assign, IOptimizationContext context) throws AlgebricksException {
AbstractFunctionCallExpression accessFun = (AbstractFunctionCallExpression) assign.getExpressions().get(0).getValue();
ILogicalExpression e0 = accessFun.getArguments().get(0).getValue();
if (e0.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
LogicalVariable var = ((VariableReferenceExpression) e0).getVariableReference();
if (context.findPrimaryKey(var) == null) {
// not referring to a dataset record
return false;
}
AbstractLogicalOperator op = assign;
while (op.getInputs().size() == 1 && op.getOperatorTag() != LogicalOperatorTag.DATASOURCESCAN) {
op = (AbstractLogicalOperator) op.getInputs().get(0).getValue();
}
if (op.getOperatorTag() != LogicalOperatorTag.DATASOURCESCAN) {
return false;
}
DataSourceScanOperator scan = (DataSourceScanOperator) op;
LogicalVariable recVar = scan.getVariables().get(scan.getVariables().size() - 1);
if (recVar != var) {
return false;
}
MetadataProvider mp = (MetadataProvider) context.getMetadataProvider();
DataSourceId asid = ((IDataSource<DataSourceId>) scan.getDataSource()).getId();
Dataset dataset = mp.findDataset(asid.getDataverseName(), asid.getDatasourceName());
if (dataset == null) {
throw new AlgebricksException("Dataset " + asid.getDatasourceName() + " not found.");
}
if (dataset.getDatasetType() != DatasetType.INTERNAL) {
return false;
}
final Integer pos = ConstantExpressionUtil.getIntConstant(accessFun.getArguments().get(1).getValue());
if (pos != null) {
String tName = dataset.getItemTypeName();
IAType t = mp.findType(dataset.getItemTypeDataverseName(), tName);
if (t.getTypeTag() != ATypeTag.OBJECT) {
return false;
}
ARecordType rt = (ARecordType) t;
if (pos >= rt.getFieldNames().length) {
return false;
}
}
List<Index> datasetIndexes = mp.getDatasetIndexes(dataset.getDataverseName(), dataset.getDatasetName());
boolean hasSecondaryIndex = false;
for (Index index : datasetIndexes) {
if (index.isSecondaryIndex()) {
hasSecondaryIndex = true;
break;
}
}
return hasSecondaryIndex;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression 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.expressions.VariableReferenceExpression in project asterixdb by apache.
the class MetaKeyExpressionReferenceTransform method transform.
@Override
public boolean transform(Mutable<ILogicalExpression> exprRef) throws AlgebricksException {
ILogicalExpression expr = exprRef.getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
if (!funcExpr.getFunctionIdentifier().equals(BuiltinFunctions.META_KEY)) {
return false;
}
// Function is meta key access
for (int i = 0; i < metaKeyAccessExpressions.size(); i++) {
if (metaKeyAccessExpressions.get(i).equals(funcExpr)) {
exprRef.setValue(new VariableReferenceExpression(keyVars.get(i)));
return true;
}
}
return false;
}
Aggregations