use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class AccessMethodUtils method createPrimaryIndexUnnestMap.
public static AbstractUnnestMapOperator createPrimaryIndexUnnestMap(AbstractDataSourceOperator dataSourceOp, Dataset dataset, ARecordType recordType, ARecordType metaRecordType, ILogicalOperator inputOp, IOptimizationContext context, boolean sortPrimaryKeys, boolean retainInput, boolean retainNull, boolean requiresBroadcast) throws AlgebricksException {
List<LogicalVariable> primaryKeyVars = AccessMethodUtils.getPrimaryKeyVarsFromSecondaryUnnestMap(dataset, inputOp);
// Optionally add a sort on the primary-index keys before searching the primary index.
OrderOperator order = null;
if (sortPrimaryKeys) {
order = new OrderOperator();
for (LogicalVariable pkVar : primaryKeyVars) {
Mutable<ILogicalExpression> vRef = new MutableObject<>(new VariableReferenceExpression(pkVar));
order.getOrderExpressions().add(new Pair<>(OrderOperator.ASC_ORDER, vRef));
}
// The secondary-index search feeds into the sort.
order.getInputs().add(new MutableObject<>(inputOp));
order.setExecutionMode(ExecutionMode.LOCAL);
context.computeAndSetTypeEnvironmentForOperator(order);
}
// The job gen parameters are transferred to the actual job gen via the UnnestMapOperator's function arguments.
List<Mutable<ILogicalExpression>> primaryIndexFuncArgs = new ArrayList<>();
BTreeJobGenParams jobGenParams = new BTreeJobGenParams(dataset.getDatasetName(), IndexType.BTREE, dataset.getDataverseName(), dataset.getDatasetName(), retainInput, requiresBroadcast);
// Set low/high inclusive to true for a point lookup.
jobGenParams.setLowKeyInclusive(true);
jobGenParams.setHighKeyInclusive(true);
jobGenParams.setLowKeyVarList(primaryKeyVars, 0, primaryKeyVars.size());
jobGenParams.setHighKeyVarList(primaryKeyVars, 0, primaryKeyVars.size());
jobGenParams.setIsEqCondition(true);
jobGenParams.writeToFuncArgs(primaryIndexFuncArgs);
// Variables and types coming out of the primary-index search.
List<LogicalVariable> primaryIndexUnnestVars = new ArrayList<>();
List<Object> primaryIndexOutputTypes = new ArrayList<>();
// Append output variables/types generated by the primary-index search (not forwarded from input).
primaryIndexUnnestVars.addAll(dataSourceOp.getVariables());
appendPrimaryIndexTypes(dataset, recordType, metaRecordType, primaryIndexOutputTypes);
// An index search is expressed as an unnest over an index-search function.
IFunctionInfo primaryIndexSearch = FunctionUtil.getFunctionInfo(BuiltinFunctions.INDEX_SEARCH);
AbstractFunctionCallExpression primaryIndexSearchFunc = new ScalarFunctionCallExpression(primaryIndexSearch, primaryIndexFuncArgs);
// This is the operator that jobgen will be looking for. It contains an unnest function that has all necessary arguments to determine
// which index to use, which variables contain the index-search keys, what is the original dataset, etc.
AbstractUnnestMapOperator primaryIndexUnnestOp = null;
if (retainNull) {
if (retainInput) {
primaryIndexUnnestOp = new LeftOuterUnnestMapOperator(primaryIndexUnnestVars, new MutableObject<ILogicalExpression>(primaryIndexSearchFunc), primaryIndexOutputTypes, retainInput);
} else {
// Left-outer-join without retainNull and retainInput doesn't make sense.
throw new AlgebricksException("Left-outer-join should propagate all inputs from the outer branch.");
}
} else {
primaryIndexUnnestOp = new UnnestMapOperator(primaryIndexUnnestVars, new MutableObject<ILogicalExpression>(primaryIndexSearchFunc), primaryIndexOutputTypes, retainInput);
}
// Fed by the order operator or the secondaryIndexUnnestOp.
if (sortPrimaryKeys) {
primaryIndexUnnestOp.getInputs().add(new MutableObject<ILogicalOperator>(order));
} else {
primaryIndexUnnestOp.getInputs().add(new MutableObject<>(inputOp));
}
context.computeAndSetTypeEnvironmentForOperator(primaryIndexUnnestOp);
primaryIndexUnnestOp.setExecutionMode(ExecutionMode.PARTITIONED);
return primaryIndexUnnestOp;
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class AccessMethodUtils method createSearchKeyExpr.
/**
* Returns the search key expression which feeds a secondary-index search. If we are optimizing a selection query then this method returns
* the a ConstantExpression from the first constant value in the optimizable function expression.
* If we are optimizing a join, then this method returns the VariableReferenceExpression that should feed the secondary index probe.
*
* @throws AlgebricksException
*/
public static Pair<ILogicalExpression, Boolean> createSearchKeyExpr(IOptimizableFuncExpr optFuncExpr, OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree) throws AlgebricksException {
if (probeSubTree == null) {
// We are optimizing a selection query. Search key is a constant.
// Type Checking and type promotion is done here
IAType fieldType = optFuncExpr.getFieldType(0);
if (optFuncExpr.getNumConstantExpr() == 0) {
//TODO: Right now we miss on type promotion for nonpure functions
return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(1)), false);
}
ILogicalExpression constantAtRuntimeExpression = null;
AsterixConstantValue constantValue = null;
ATypeTag constantValueTag = null;
constantAtRuntimeExpression = optFuncExpr.getConstantExpr(0);
if (constantAtRuntimeExpression.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
constantValue = (AsterixConstantValue) ((ConstantExpression) constantAtRuntimeExpression).getValue();
}
constantValueTag = optFuncExpr.getConstantType(0).getTypeTag();
// type casting applied?
boolean typeCastingApplied = false;
// type casting happened from real (FLOAT, DOUBLE) value -> INT value?
boolean realTypeConvertedToIntegerType = false;
AsterixConstantValue replacedConstantValue = null;
// if the constant type and target type does not match, we do a type conversion
if (constantValueTag != fieldType.getTypeTag() && constantValue != null) {
try {
replacedConstantValue = ATypeHierarchy.getAsterixConstantValueFromNumericTypeObject(constantValue.getObject(), fieldType.getTypeTag(), true);
} catch (HyracksDataException e) {
throw new AlgebricksException(e);
}
if (replacedConstantValue != null) {
typeCastingApplied = true;
}
// In this case, we need to change the search parameter. Refer to the caller section for the detail.
switch(constantValueTag) {
case DOUBLE:
case FLOAT:
switch(fieldType.getTypeTag()) {
case TINYINT:
case SMALLINT:
case INTEGER:
case BIGINT:
realTypeConvertedToIntegerType = true;
break;
default:
break;
}
default:
break;
}
}
if (typeCastingApplied) {
return new Pair<>(new ConstantExpression(replacedConstantValue), realTypeConvertedToIntegerType);
} else {
return new Pair<>(optFuncExpr.getConstantExpr(0), false);
}
} else {
// We are optimizing a join query. Determine which variable feeds the secondary index.
if (optFuncExpr.getOperatorSubTree(0) == null || optFuncExpr.getOperatorSubTree(0) == probeSubTree) {
return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(0)), false);
} else {
return new Pair<>(new VariableReferenceExpression(optFuncExpr.getLogicalVar(1)), false);
}
}
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class AccessMethodUtils method analyzeFuncExprArgsForOneConstAndVarAndUpdateAnalysisCtx.
public static boolean analyzeFuncExprArgsForOneConstAndVarAndUpdateAnalysisCtx(AbstractFunctionCallExpression funcExpr, AccessMethodAnalysisContext analysisCtx, IOptimizationContext context, IVariableTypeEnvironment typeEnvironment) throws AlgebricksException {
ILogicalExpression constExpression = null;
IAType constantExpressionType = null;
LogicalVariable fieldVar = null;
ILogicalExpression arg1 = funcExpr.getArguments().get(0).getValue();
ILogicalExpression arg2 = funcExpr.getArguments().get(1).getValue();
// One of the args must be a runtime constant, and the other arg must be a variable.
if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE && arg2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
return false;
}
if (arg2.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
// The arguments of contains() function are asymmetrical, we can only use index if it is on the first argument
if (funcExpr.getFunctionIdentifier() == BuiltinFunctions.STRING_CONTAINS || funcExpr.getFunctionIdentifier() == BuiltinFunctions.FULLTEXT_CONTAINS || funcExpr.getFunctionIdentifier() == BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION) {
return false;
}
IAType expressionType = constantRuntimeResultType(arg1, context, typeEnvironment);
if (expressionType == null) {
//Not constant at runtime
return false;
}
constantExpressionType = expressionType;
constExpression = arg1;
VariableReferenceExpression varExpr = (VariableReferenceExpression) arg2;
fieldVar = varExpr.getVariableReference();
} else if (arg1.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
IAType expressionType = constantRuntimeResultType(arg2, context, typeEnvironment);
if (expressionType == null) {
//Not constant at runtime
return false;
}
constantExpressionType = expressionType;
constExpression = arg2;
// yet in the full-text search.
if (funcExpr.getFunctionIdentifier() == BuiltinFunctions.FULLTEXT_CONTAINS && arg2.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
checkFTSearchConstantExpression(constExpression);
}
VariableReferenceExpression varExpr = (VariableReferenceExpression) arg1;
fieldVar = varExpr.getVariableReference();
} else {
return false;
}
// Updates the given Analysis Context by adding a new optimizable function expression.
constructNewOptFuncExprAndAddToAnalysisCtx(funcExpr, fieldVar, constExpression, constantExpressionType, analysisCtx);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class AccessMethodUtils method writeVarList.
private static void writeVarList(List<LogicalVariable> varList, List<Mutable<ILogicalExpression>> funcArgs) {
Mutable<ILogicalExpression> numKeysRef = new MutableObject<>(new ConstantExpression(new AsterixConstantValue(new AInt32(varList.size()))));
funcArgs.add(numKeysRef);
for (LogicalVariable keyVar : varList) {
Mutable<ILogicalExpression> keyVarRef = new MutableObject<>(new VariableReferenceExpression(keyVar));
funcArgs.add(keyVarRef);
}
}
use of org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression in project asterixdb by apache.
the class SetupCommitExtensionOpRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.DELEGATE_OPERATOR) {
return false;
}
DelegateOperator eOp = (DelegateOperator) op;
if (!(eOp.getDelegate() instanceof CommitOperator)) {
return false;
}
boolean isSink = ((CommitOperator) eOp.getDelegate()).isSink();
List<Mutable<ILogicalExpression>> primaryKeyExprs = null;
Dataset dataset = null;
AbstractLogicalOperator descendantOp = (AbstractLogicalOperator) eOp.getInputs().get(0).getValue();
while (descendantOp != null) {
if (descendantOp.getOperatorTag() == LogicalOperatorTag.INDEX_INSERT_DELETE_UPSERT) {
IndexInsertDeleteUpsertOperator operator = (IndexInsertDeleteUpsertOperator) descendantOp;
if (!operator.isBulkload() && operator.getPrevSecondaryKeyExprs() == null) {
primaryKeyExprs = operator.getPrimaryKeyExpressions();
dataset = ((DatasetDataSource) operator.getDataSourceIndex().getDataSource()).getDataset();
break;
}
} else if (descendantOp.getOperatorTag() == LogicalOperatorTag.INSERT_DELETE_UPSERT) {
InsertDeleteUpsertOperator insertDeleteUpsertOperator = (InsertDeleteUpsertOperator) descendantOp;
if (!insertDeleteUpsertOperator.isBulkload()) {
primaryKeyExprs = insertDeleteUpsertOperator.getPrimaryKeyExpressions();
dataset = ((DatasetDataSource) insertDeleteUpsertOperator.getDataSource()).getDataset();
break;
}
}
if (descendantOp.getInputs().isEmpty()) {
break;
}
descendantOp = (AbstractLogicalOperator) descendantOp.getInputs().get(0).getValue();
}
if (primaryKeyExprs == null) {
return false;
}
//copy primaryKeyExprs
List<LogicalVariable> primaryKeyLogicalVars = new ArrayList<>();
for (Mutable<ILogicalExpression> expr : primaryKeyExprs) {
VariableReferenceExpression varRefExpr = (VariableReferenceExpression) expr.getValue();
primaryKeyLogicalVars.add(new LogicalVariable(varRefExpr.getVariableReference().getId()));
}
//get JobId(TransactorId)
MetadataProvider mp = (MetadataProvider) context.getMetadataProvider();
JobId jobId = mp.getJobId();
//create the logical and physical operator
CommitOperator commitOperator = new CommitOperator(primaryKeyLogicalVars, isSink);
CommitPOperator commitPOperator = new CommitPOperator(jobId, dataset, primaryKeyLogicalVars, isSink);
commitOperator.setPhysicalOperator(commitPOperator);
//create ExtensionOperator and put the commitOperator in it.
DelegateOperator extensionOperator = new DelegateOperator(commitOperator);
extensionOperator.setPhysicalOperator(commitPOperator);
//update plan link
extensionOperator.getInputs().add(eOp.getInputs().get(0));
context.computeAndSetTypeEnvironmentForOperator(extensionOperator);
opRef.setValue(extensionOperator);
return true;
}
Aggregations