use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method visit.
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(ListConstructor lc, Mutable<ILogicalOperator> tupSource) throws CompilationException {
FunctionIdentifier fid = (lc.getType() == ListConstructor.Type.ORDERED_LIST_CONSTRUCTOR) ? BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR : BuiltinFunctions.UNORDERED_LIST_CONSTRUCTOR;
AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fid));
LogicalVariable v1 = context.newVar();
AssignOperator a = new AssignOperator(v1, new MutableObject<>(f));
Mutable<ILogicalOperator> topOp = tupSource;
for (Expression expr : lc.getExprList()) {
Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = langExprToAlgExpression(expr, topOp);
f.getArguments().add(new MutableObject<>(eo.first));
topOp = eo.second;
}
a.getInputs().add(topOp);
return new Pair<>(a, v1);
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class LangExpressionToPlanTranslator method visit.
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(RecordConstructor rc, Mutable<ILogicalOperator> tupSource) throws CompilationException {
AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR));
LogicalVariable v1 = context.newVar();
AssignOperator a = new AssignOperator(v1, new MutableObject<>(f));
Mutable<ILogicalOperator> topOp = tupSource;
for (FieldBinding fb : rc.getFbList()) {
Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo1 = langExprToAlgExpression(fb.getLeftExpr(), topOp);
f.getArguments().add(new MutableObject<>(eo1.first));
topOp = eo1.second;
Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo2 = langExprToAlgExpression(fb.getRightExpr(), topOp);
f.getArguments().add(new MutableObject<>(eo2.first));
topOp = eo2.second;
}
a.getInputs().add(topOp);
return new Pair<>(a, v1);
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class StaticTypeCastUtil method injectCastToRelaxType.
private static boolean injectCastToRelaxType(Mutable<ILogicalExpression> expRef, IAType inputFieldType, IVariableTypeEnvironment env) throws AlgebricksException {
ILogicalExpression argExpr = expRef.getValue();
List<LogicalVariable> parameterVars = new ArrayList<LogicalVariable>();
argExpr.getUsedVariables(parameterVars);
// we need to handle open fields recursively by their default
// types
// for list, their item type is any
// for record, their
boolean castInjected = false;
if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL || argExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
IAType reqFieldType = inputFieldType;
// do not enforce nested type in the case of no-used variables
switch(inputFieldType.getTypeTag()) {
case OBJECT:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
break;
case ARRAY:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
break;
case MULTISET:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
break;
default:
break;
}
// do not enforce nested type in the case of no-used variables
if (!inputFieldType.equals(reqFieldType) && !parameterVars.isEmpty()) {
//inject dynamic type casting
injectCastFunction(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), reqFieldType, inputFieldType, expRef, argExpr);
castInjected = true;
}
//recursively rewrite function arguments
if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL && TypeCastUtils.getRequiredType((AbstractFunctionCallExpression) argExpr) == null && reqFieldType != null) {
if (castInjected) {
//rewrite the arg expression inside the dynamic cast
ScalarFunctionCallExpression argFunc = (ScalarFunctionCallExpression) argExpr;
rewriteFuncExpr(argFunc, inputFieldType, inputFieldType, env);
} else {
//rewrite arg
ScalarFunctionCallExpression argFunc = (ScalarFunctionCallExpression) argExpr;
rewriteFuncExpr(argFunc, reqFieldType, inputFieldType, env);
}
}
}
return castInjected;
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class StaticTypeCastUtil method rewriteFuncExpr.
/**
* This method is to recursively enforce required types, for the list type and the record type.
* The List constructor is very special because
* 1. a nested list in a list is of type List<ANY>;
* 2. a nested record in a list is of type Open_Record{}.
* The open record constructor is very special because
* 1. a nested list in the open part is of type List<ANY>;
* 2. a nested record in the open part is of type Open_Record{}.
* However, the bottom-up type inference (InferTypeRule in algebricks) did not infer that so we need this method to enforce the type.
* We do not want to break the generality of algebricks so this method is called in an ASTERIX rule: @ IntroduceStaticTypeCastRule} .
*
* @param funcExpr
* the function expression whose type needs to be top-down enforced
* @param reqType
* the required type inferred from parent operators/expressions
* @param inputType
* the current inferred
* @param env
* the type environment
* @return true if the type is casted; otherwise, false.
* @throws AlgebricksException
*/
public static boolean rewriteFuncExpr(AbstractFunctionCallExpression funcExpr, IAType reqType, IAType inputType, IVariableTypeEnvironment env) throws AlgebricksException {
/**
* sanity check: if there are list(ordered or unordered)/record variable expressions in the funcExpr, we will not do STATIC type casting
* because they are not "statically cast-able".
* instead, the record will be dynamically casted at the runtime
*/
if (funcExpr.getFunctionIdentifier() == BuiltinFunctions.UNORDERED_LIST_CONSTRUCTOR) {
if (reqType.equals(BuiltinType.ANY)) {
reqType = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
}
return rewriteListFuncExpr(funcExpr, (AbstractCollectionType) reqType, (AbstractCollectionType) inputType, env);
} else if (funcExpr.getFunctionIdentifier() == BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR) {
if (reqType.equals(BuiltinType.ANY)) {
reqType = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
}
return rewriteListFuncExpr(funcExpr, (AbstractCollectionType) reqType, (AbstractCollectionType) inputType, env);
} else if (inputType.getTypeTag().equals(ATypeTag.OBJECT)) {
if (reqType.equals(BuiltinType.ANY)) {
reqType = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
}
return rewriteRecordFuncExpr(funcExpr, (ARecordType) reqType, (ARecordType) inputType, env);
} else {
List<Mutable<ILogicalExpression>> args = funcExpr.getArguments();
boolean changed = false;
for (Mutable<ILogicalExpression> arg : args) {
ILogicalExpression argExpr = arg.getValue();
if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
AbstractFunctionCallExpression argFuncExpr = (AbstractFunctionCallExpression) argExpr;
IAType exprType = (IAType) env.getType(argFuncExpr);
changed = changed || rewriteFuncExpr(argFuncExpr, exprType, exprType, env);
}
}
if (!compatible(reqType, inputType)) {
throw new AlgebricksException("type mismatch, required: " + reqType.toString() + " actual: " + inputType.toString());
}
return changed;
}
}
use of org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression in project asterixdb by apache.
the class ConsolidateSelectsRule method rewritePre.
@Override
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.SELECT) {
return false;
}
SelectOperator firstSelect = (SelectOperator) op;
IFunctionInfo andFn = context.getMetadataProvider().lookupFunction(AlgebricksBuiltinFunctions.AND);
// New conjuncts for consolidated select.
AbstractFunctionCallExpression conj = null;
AbstractLogicalOperator topMostOp = null;
AbstractLogicalOperator selectParent = null;
AbstractLogicalOperator nextSelect = firstSelect;
do {
// Skip through assigns.
do {
selectParent = nextSelect;
nextSelect = (AbstractLogicalOperator) selectParent.getInputs().get(0).getValue();
} while (nextSelect.getOperatorTag() == LogicalOperatorTag.ASSIGN && OperatorPropertiesUtil.isMovable(nextSelect));
// Stop if the child op is not a select.
if (nextSelect.getOperatorTag() != LogicalOperatorTag.SELECT) {
break;
}
// Remember the top-most op that we are not removing.
topMostOp = selectParent;
// Initialize the new conjuncts, if necessary.
if (conj == null) {
conj = new ScalarFunctionCallExpression(andFn);
// Add the first select's condition.
conj.getArguments().add(new MutableObject<ILogicalExpression>(firstSelect.getCondition().getValue()));
}
// Consolidate all following selects.
do {
// Add the condition nextSelect to the new list of conjuncts.
conj.getArguments().add(((SelectOperator) nextSelect).getCondition());
selectParent = nextSelect;
nextSelect = (AbstractLogicalOperator) nextSelect.getInputs().get(0).getValue();
} while (nextSelect.getOperatorTag() == LogicalOperatorTag.SELECT);
// Hook up the input of the top-most remaining op if necessary.
if (topMostOp.getOperatorTag() == LogicalOperatorTag.ASSIGN || topMostOp == firstSelect) {
topMostOp.getInputs().set(0, selectParent.getInputs().get(0));
}
// Prepare for next iteration.
nextSelect = selectParent;
} while (true);
// Did we consolidate any selects?
if (conj == null) {
return false;
}
// Set the new conjuncts.
firstSelect.getCondition().setValue(conj);
context.computeAndSetTypeEnvironmentForOperator(firstSelect);
return true;
}
Aggregations