use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class IntroduceMaterializationForInsertWithSelfScanRule method checkIfInsertAndScanDatasetsSame.
private boolean checkIfInsertAndScanDatasetsSame(AbstractLogicalOperator op, String insertDatasetName) {
boolean sameDataset = false;
for (int i = 0; i < op.getInputs().size(); ++i) {
AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) op.getInputs().get(i).getValue();
if (descendantOp.getOperatorTag() == LogicalOperatorTag.UNNEST_MAP) {
UnnestMapOperator unnestMapOp = (UnnestMapOperator) descendantOp;
ILogicalExpression unnestExpr = unnestMapOp.getExpressionRef().getValue();
if (unnestExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) unnestExpr;
FunctionIdentifier fid = f.getFunctionIdentifier();
if (!fid.equals(BuiltinFunctions.INDEX_SEARCH)) {
throw new IllegalStateException();
}
AccessMethodJobGenParams jobGenParams = new AccessMethodJobGenParams();
jobGenParams.readFromFuncArgs(f.getArguments());
boolean isPrimaryIndex = jobGenParams.isPrimaryIndex();
String indexName = jobGenParams.getIndexName();
if (isPrimaryIndex && indexName.compareTo(insertDatasetName) == 0) {
return true;
}
}
} else if (descendantOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
DataSourceScanOperator dataSourceScanOp = (DataSourceScanOperator) descendantOp;
DataSource ds = (DataSource) dataSourceScanOp.getDataSource();
if ((ds.getDatasourceType() == Type.INTERNAL_DATASET || ds.getDatasourceType() == Type.EXTERNAL_DATASET) && ((DatasetDataSource) ds).getDataset().getDatasetName().compareTo(insertDatasetName) == 0) {
return true;
}
}
sameDataset = checkIfInsertAndScanDatasetsSame(descendantOp, insertDatasetName);
if (sameDataset) {
break;
}
}
return sameDataset;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class NestGroupByRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
return false;
}
SubplanOperator subplan = (SubplanOperator) op1;
if (subplan.getNestedPlans().size() != 1) {
return false;
}
ILogicalPlan p = subplan.getNestedPlans().get(0);
if (p.getRoots().size() != 1) {
return false;
}
Set<LogicalVariable> free = new HashSet<LogicalVariable>();
OperatorPropertiesUtil.getFreeVariablesInSubplans(subplan, free);
if (free.size() != 1) {
return false;
}
LogicalVariable fVar = null;
for (LogicalVariable v : free) {
fVar = v;
break;
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
if (op2.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
GroupByOperator gby = (GroupByOperator) op2;
if (gby.getNestedPlans().size() != 1) {
return false;
}
ILogicalPlan p2 = gby.getNestedPlans().get(0);
if (p2.getRoots().size() != 1) {
return false;
}
Mutable<ILogicalOperator> r2 = p2.getRoots().get(0);
AbstractLogicalOperator opr2 = (AbstractLogicalOperator) r2.getValue();
if (opr2.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggOuter = (AggregateOperator) opr2;
int posInAggList = aggOuter.getVariables().indexOf(fVar);
if (posInAggList < 0) {
return false;
}
AbstractLogicalOperator outerAggSon = (AbstractLogicalOperator) aggOuter.getInputs().get(0).getValue();
if (outerAggSon.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
ILogicalExpression eAgg = aggOuter.getExpressions().get(posInAggList).getValue();
if (eAgg.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression listifyCall = (AbstractFunctionCallExpression) eAgg;
if (listifyCall.getFunctionIdentifier() != BuiltinFunctions.LISTIFY) {
return false;
}
ILogicalExpression argListify = listifyCall.getArguments().get(0).getValue();
if (argListify.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
Mutable<ILogicalOperator> r = p.getRoots().get(0);
AbstractLogicalOperator opInS = (AbstractLogicalOperator) r.getValue();
if (opInS.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggInner = (AggregateOperator) opInS;
do {
opInS = (AbstractLogicalOperator) opInS.getInputs().get(0).getValue();
} while (opInS.getOperatorTag() == LogicalOperatorTag.ASSIGN);
if (opInS.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
AbstractLogicalOperator unnestParent = opInS;
AbstractLogicalOperator opUnder = (AbstractLogicalOperator) opInS.getInputs().get(0).getValue();
// skip Assigns
while (opUnder.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
unnestParent = opUnder;
opUnder = (AbstractLogicalOperator) opUnder.getInputs().get(0).getValue();
}
if (opUnder.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest = (UnnestOperator) opUnder;
AbstractLogicalOperator unnestSon = (AbstractLogicalOperator) unnest.getInputs().get(0).getValue();
if (unnestSon.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
NestedTupleSourceOperator innerNts = (NestedTupleSourceOperator) unnestSon;
ILogicalExpression eUnnest = unnest.getExpressionRef().getValue();
if (eUnnest.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression uf = (AbstractFunctionCallExpression) eUnnest;
if (uf.getFunctionIdentifier() != BuiltinFunctions.SCAN_COLLECTION) {
return false;
}
ILogicalExpression scanArg = uf.getArguments().get(0).getValue();
if (scanArg.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
if (((VariableReferenceExpression) scanArg).getVariableReference() != fVar) {
return false;
}
LogicalVariable uVar = unnest.getVariable();
GroupByOperator innerGby = (GroupByOperator) opInS;
Set<LogicalVariable> freeInInnerGby = new HashSet<LogicalVariable>();
OperatorPropertiesUtil.getFreeVariablesInSubplans(innerGby, freeInInnerGby);
for (LogicalVariable v : freeInInnerGby) {
if (v != uVar) {
return false;
}
}
unnestParent.getInputs().get(0).setValue(innerNts);
LogicalVariable listifiedVar = ((VariableReferenceExpression) argListify).getVariableReference();
substInSubplan(aggInner, uVar, listifiedVar, context);
gby.getNestedPlans().add(p);
innerNts.getDataSourceReference().setValue(gby);
opRef.setValue(gby);
OperatorPropertiesUtil.typePlan(p, context);
OperatorPropertiesUtil.typePlan(p2, context);
context.computeAndSetTypeEnvironmentForOperator(gby);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ExceptionTest method testTypeComputer.
private void testTypeComputer(Class<? extends IResultTypeComputer> c) throws Exception {
// Mocks the type environment.
IVariableTypeEnvironment mockTypeEnv = mock(IVariableTypeEnvironment.class);
// Mocks the metadata provider.
IMetadataProvider<?, ?> mockMetadataProvider = mock(IMetadataProvider.class);
// Mocks function expression.
AbstractFunctionCallExpression mockExpr = mock(AbstractFunctionCallExpression.class);
FunctionIdentifier fid = mock(FunctionIdentifier.class);
when(mockExpr.getFunctionIdentifier()).thenReturn(fid);
when(fid.getName()).thenReturn("testFunction");
int numCombination = (int) Math.pow(ATypeTag.values().length, 2);
// Sets two arguments for the mocked function expression.
for (int index = 0; index < numCombination; ++index) {
try {
List<Mutable<ILogicalExpression>> argRefs = new ArrayList<>();
for (int argIndex = 0; argIndex < 2; ++argIndex) {
int base = (int) Math.pow(ATypeTag.values().length, argIndex);
ILogicalExpression mockArg = mock(ILogicalExpression.class);
argRefs.add(new MutableObject<>(mockArg));
IAType mockType = mock(IAType.class);
when(mockTypeEnv.getType(mockArg)).thenReturn(mockType);
int serializedTypeTag = (index / base) % ATypeTag.values().length + 1;
ATypeTag typeTag = ATypeTag.VALUE_TYPE_MAPPING[serializedTypeTag];
if (typeTag == null) {
// For some reason, type tag 39 does not exist.
typeTag = ATypeTag.ANY;
}
when(mockType.getTypeTag()).thenReturn(typeTag);
}
// Sets up arguments for the mocked expression.
when(mockExpr.getArguments()).thenReturn(argRefs);
// Sets up required/actual types of the mocked expression.
Object[] opaqueParameters = new Object[2];
opaqueParameters[0] = BuiltinType.ANY;
opaqueParameters[1] = BuiltinType.ANY;
when(mockExpr.getOpaqueParameters()).thenReturn(opaqueParameters);
// Invokes a type computer.
IResultTypeComputer instance = (IResultTypeComputer) c.getField("INSTANCE").get(null);
instance.computeType(mockExpr, mockTypeEnv, mockMetadataProvider);
} catch (AlgebricksException ae) {
String msg = ae.getMessage();
if (msg.startsWith("ASX")) {
// Verifies the error code.
int errorCode = Integer.parseInt(msg.substring(3, 7));
Assert.assertTrue(errorCode >= 1000 && errorCode < 2000);
continue;
} else {
// Any root-level compilation exceptions thrown from type computers should have an error code.
Assert.assertTrue(!(ae instanceof AlgebricksException) || (ae.getCause() != null));
}
} catch (ClassCastException e) {
continue;
}
}
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class RTreeAccessMethod method createSecondaryToPrimaryPlan.
private ILogicalOperator createSecondaryToPrimaryPlan(OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, boolean retainInput, boolean retainNull, boolean requiresBroadcast, IOptimizationContext context) throws AlgebricksException {
IOptimizableFuncExpr optFuncExpr = AccessMethodUtils.chooseFirstOptFuncExpr(chosenIndex, analysisCtx);
Dataset dataset = indexSubTree.getDataset();
ARecordType recordType = indexSubTree.getRecordType();
ARecordType metaRecordType = indexSubTree.getMetaRecordType();
int optFieldIdx = AccessMethodUtils.chooseFirstOptFuncVar(chosenIndex, analysisCtx);
Pair<IAType, Boolean> keyPairType = Index.getNonNullableOpenFieldType(optFuncExpr.getFieldType(optFieldIdx), optFuncExpr.getFieldName(optFieldIdx), recordType);
if (keyPairType == null) {
return null;
}
// Get the number of dimensions corresponding to the field indexed by chosenIndex.
IAType spatialType = keyPairType.first;
int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
int numSecondaryKeys = numDimensions * 2;
// we made sure indexSubTree has datasource scan
AbstractDataSourceOperator dataSourceOp = (AbstractDataSourceOperator) indexSubTree.getDataSourceRef().getValue();
RTreeJobGenParams jobGenParams = new RTreeJobGenParams(chosenIndex.getIndexName(), IndexType.RTREE, dataset.getDataverseName(), dataset.getDatasetName(), retainInput, requiresBroadcast);
// A spatial object is serialized in the constant of the func expr we are optimizing.
// The R-Tree expects as input an MBR represented with 1 field per dimension.
// Here we generate vars and funcs for extracting MBR fields from the constant into fields of a tuple (as the
// R-Tree expects them).
// List of variables for the assign.
ArrayList<LogicalVariable> keyVarList = new ArrayList<>();
// List of expressions for the assign.
ArrayList<Mutable<ILogicalExpression>> keyExprList = new ArrayList<>();
Pair<ILogicalExpression, Boolean> returnedSearchKeyExpr = AccessMethodUtils.createSearchKeyExpr(optFuncExpr, indexSubTree, probeSubTree);
ILogicalExpression searchKeyExpr = returnedSearchKeyExpr.first;
for (int i = 0; i < numSecondaryKeys; i++) {
// The create MBR function "extracts" one field of an MBR around the given spatial object.
AbstractFunctionCallExpression createMBR = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CREATE_MBR));
// Spatial object is the constant from the func expr we are optimizing.
createMBR.getArguments().add(new MutableObject<>(searchKeyExpr));
// The number of dimensions.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(numDimensions)))));
// Which part of the MBR to extract.
createMBR.getArguments().add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AInt32(i)))));
// Add a variable and its expr to the lists which will be passed into an assign op.
LogicalVariable keyVar = context.newVar();
keyVarList.add(keyVar);
keyExprList.add(new MutableObject<ILogicalExpression>(createMBR));
}
jobGenParams.setKeyVarList(keyVarList);
// Assign operator that "extracts" the MBR fields from the func-expr constant into a tuple.
AssignOperator assignSearchKeys = new AssignOperator(keyVarList, keyExprList);
if (probeSubTree == null) {
// We are optimizing a selection query.
// Input to this assign is the EmptyTupleSource (which the dataSourceScan also must have had as input).
assignSearchKeys.getInputs().add(new MutableObject<>(OperatorManipulationUtil.deepCopy(dataSourceOp.getInputs().get(0).getValue())));
assignSearchKeys.setExecutionMode(dataSourceOp.getExecutionMode());
} else {
// We are optimizing a join, place the assign op top of the probe subtree.
assignSearchKeys.getInputs().add(probeSubTree.getRootRef());
}
ILogicalOperator secondaryIndexUnnestOp = AccessMethodUtils.createSecondaryIndexUnnestMap(dataset, recordType, metaRecordType, chosenIndex, assignSearchKeys, jobGenParams, context, false, retainInput, retainNull);
// Generate the rest of the upstream plan which feeds the search results into the primary index.
return dataset.getDatasetType() == DatasetType.EXTERNAL ? AccessMethodUtils.createExternalDataLookupUnnestMap(dataSourceOp, dataset, recordType, secondaryIndexUnnestOp, context, retainInput, retainNull) : AccessMethodUtils.createPrimaryIndexUnnestMap(dataSourceOp, dataset, recordType, metaRecordType, secondaryIndexUnnestOp, context, true, retainInput, false, false);
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ResolveVariableRule method rewriteExpressionReference.
// Recursively rewrites for an expression within an operator.
private boolean rewriteExpressionReference(ILogicalOperator op, Mutable<ILogicalExpression> exprRef, Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidateFromParent, Mutable<ILogicalExpression> parentFuncRef, IOptimizationContext context) throws AlgebricksException {
ILogicalExpression expr = exprRef.getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
boolean changed = false;
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
Triple<Boolean, String, String> fullyQualifiedDatasetPathCandidate = resolveFullyQualifiedPath(funcExpr, context);
for (Mutable<ILogicalExpression> funcArgRef : funcExpr.getArguments()) {
if (rewriteExpressionReference(op, funcArgRef, fullyQualifiedDatasetPathCandidate, exprRef, context)) {
changed = true;
}
}
// Cleans up extra scan-collections if there is.
if (changed) {
cleanupScanCollectionForDataset(funcExpr);
}
// Does the actual resolution.
return changed || resolve(op, context, exprRef, fullyQualifiedDatasetPathCandidateFromParent, parentFuncRef);
}
Aggregations