use of org.apache.asterix.om.types.IAType in project asterixdb by apache.
the class TypeResolverUtilTest method testIsmophicRecordType.
@Test
public void testIsmophicRecordType() {
// Constructs input types.
ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" }, new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null);
ARecordType rightRecordType = new ARecordType(null, new String[] { "b", "a" }, new IAType[] { BuiltinType.AINT32, BuiltinType.ASTRING }, false, null);
// Resolves input types to a generalized type.
List<IAType> inputTypes = new ArrayList<>();
inputTypes.add(leftRecordType);
inputTypes.add(rightRecordType);
ARecordType resolvedType = (ARecordType) TypeResolverUtil.resolve(inputTypes);
// Compares the resolved type with the expected type.
Assert.assertEquals(resolvedType, leftRecordType);
}
use of org.apache.asterix.om.types.IAType in project asterixdb by apache.
the class InjectTypeCastForSwitchCaseRule method rewriteSwitchCase.
// Injects casts that cast types for different "THEN" and "ELSE" branches.
private boolean rewriteSwitchCase(ILogicalOperator op, AbstractFunctionCallExpression func, IOptimizationContext context) throws AlgebricksException {
IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
IAType producedType = (IAType) env.getType(func);
List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
int argSize = argRefs.size();
boolean rewritten = false;
for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
if (TypeResolverUtil.needsCast(producedType, type)) {
ILogicalExpression argExpr = argRef.getValue();
// Injects a cast call to cast the data type to the produced type of the switch-case function call.
ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
TypeCastUtils.setRequiredAndInputTypes(castFunc, producedType, type);
argRef.setValue(castFunc);
rewritten = true;
}
}
return rewritten;
}
use of org.apache.asterix.om.types.IAType in project asterixdb by apache.
the class InjectTypeCastForUnionRule method injectCast.
// Injects a type cast function on one input (indicated by childIndex) of the union all operator if necessary.
private boolean injectCast(UnionAllOperator op, int childIndex, IOptimizationContext context) throws AlgebricksException {
// Gets the type environments for the union all operator and its child operator with the right child index.
IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op);
Mutable<ILogicalOperator> branchOpRef = op.getInputs().get(childIndex);
IVariableTypeEnvironment childEnv = context.getOutputTypeEnvironment(branchOpRef.getValue());
// The two lists are used for the assign operator that calls cast functions.
List<LogicalVariable> varsToCast = new ArrayList<>();
List<Mutable<ILogicalExpression>> castFunctionsForLeft = new ArrayList<>();
// Iterate through all triples.
List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> triples = op.getVariableMappings();
for (Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple : triples) {
LogicalVariable producedVar = triple.third;
IAType producedType = (IAType) env.getVarType(producedVar);
LogicalVariable varToCast = childIndex == 0 ? triple.first : triple.second;
IAType inputType = (IAType) childEnv.getVarType(varToCast);
if (!TypeResolverUtil.needsCast(producedType, inputType)) {
// Continues to the next triple if no cast is neeeded.
continue;
}
LogicalVariable castedVar = context.newVar();
// Resets triple variables to new variables that bind to the results of type casting.
triple.first = childIndex == 0 ? castedVar : triple.first;
triple.second = childIndex > 0 ? castedVar : triple.second;
ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), new ArrayList<>(Collections.singletonList(new MutableObject<>(new VariableReferenceExpression(varToCast)))));
TypeCastUtils.setRequiredAndInputTypes(castFunc, producedType, inputType);
// Adds the variable and function expression into lists, for the assign operator.
varsToCast.add(castedVar);
castFunctionsForLeft.add(new MutableObject<>(castFunc));
}
if (castFunctionsForLeft.isEmpty()) {
return false;
}
// Injects an assign operator to perform type casts.
AssignOperator assignOp = new AssignOperator(varsToCast, castFunctionsForLeft);
assignOp.getInputs().add(new MutableObject<>(branchOpRef.getValue()));
branchOpRef.setValue(assignOp);
context.computeAndSetTypeEnvironmentForOperator(assignOp);
// Returns true to indicate that rewriting happens.
return true;
}
use of org.apache.asterix.om.types.IAType in project asterixdb by apache.
the class IntroduceDynamicTypeCastForExternalFunctionRule method rewriteFunctionArgs.
private boolean rewriteFunctionArgs(ILogicalOperator op, Mutable<ILogicalExpression> expRef, IOptimizationContext context) throws AlgebricksException {
ILogicalExpression expr = expRef.getValue();
if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL || !(expr instanceof ScalarFunctionCallExpression)) {
return false;
}
ScalarFunctionCallExpression funcCallExpr = (ScalarFunctionCallExpression) expr;
boolean changed = false;
IAType inputRecordType;
ARecordType requiredRecordType;
for (int iter1 = 0; iter1 < funcCallExpr.getArguments().size(); iter1++) {
inputRecordType = (IAType) op.computeOutputTypeEnvironment(context).getType(funcCallExpr.getArguments().get(iter1).getValue());
if (!(((ExternalScalarFunctionInfo) funcCallExpr.getFunctionInfo()).getArgumenTypes().get(iter1) instanceof ARecordType)) {
continue;
}
requiredRecordType = (ARecordType) ((ExternalScalarFunctionInfo) funcCallExpr.getFunctionInfo()).getArgumenTypes().get(iter1);
/**
* the input record type can be an union type
* for the case when it comes from a subplan or left-outer join
*/
boolean checkUnknown = false;
while (NonTaggedFormatUtil.isOptional(inputRecordType)) {
/** while-loop for the case there is a nested multi-level union */
inputRecordType = ((AUnionType) inputRecordType).getActualType();
checkUnknown = true;
}
boolean castFlag = !IntroduceDynamicTypeCastRule.compatible(requiredRecordType, inputRecordType);
if (castFlag || checkUnknown) {
AbstractFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE));
castFunc.getArguments().add(funcCallExpr.getArguments().get(iter1));
TypeCastUtils.setRequiredAndInputTypes(castFunc, requiredRecordType, inputRecordType);
funcCallExpr.getArguments().set(iter1, new MutableObject<>(castFunc));
changed = changed || true;
}
}
return changed;
}
use of org.apache.asterix.om.types.IAType in project asterixdb by apache.
the class IntroduceDynamicTypeCastRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
// Depending on the operator type, we need to extract the following pieces of information.
AbstractLogicalOperator op;
ARecordType requiredRecordType;
LogicalVariable recordVar;
// We identify INSERT and DISTRIBUTE_RESULT operators.
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
switch(op1.getOperatorTag()) {
case SINK:
case DELEGATE_OPERATOR:
{
/**
* pattern match: commit insert assign
* resulting plan: commit-insert-project-assign
*/
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) {
InsertDeleteUpsertOperator insertDeleteOp = (InsertDeleteUpsertOperator) op2;
if (insertDeleteOp.getOperation() == InsertDeleteUpsertOperator.Kind.DELETE) {
return false;
}
// Remember this is the operator we need to modify
op = insertDeleteOp;
// Derive the required ARecordType based on the schema of the DataSource
InsertDeleteUpsertOperator insertDeleteOperator = (InsertDeleteUpsertOperator) op2;
DataSource dataSource = (DataSource) insertDeleteOperator.getDataSource();
requiredRecordType = (ARecordType) dataSource.getItemType();
// Derive the Variable which we will potentially wrap with cast/null functions
ILogicalExpression expr = insertDeleteOperator.getPayloadExpression().getValue();
List<LogicalVariable> payloadVars = new ArrayList<>();
expr.getUsedVariables(payloadVars);
recordVar = payloadVars.get(0);
} else {
return false;
}
break;
}
case DISTRIBUTE_RESULT:
{
// First, see if there was an output-record-type specified
requiredRecordType = (ARecordType) op1.getAnnotations().get("output-record-type");
if (requiredRecordType == null) {
return false;
}
// Remember this is the operator we need to modify
op = op1;
recordVar = ((VariableReferenceExpression) ((DistributeResultOperator) op).getExpressions().get(0).getValue()).getVariableReference();
break;
}
default:
{
return false;
}
}
// Derive the statically-computed type of the record
IVariableTypeEnvironment env = op.computeOutputTypeEnvironment(context);
IAType inputRecordType = (IAType) env.getVarType(recordVar);
/** the input record type can be an union type -- for the case when it comes from a subplan or left-outer join */
boolean checkUnknown = false;
while (NonTaggedFormatUtil.isOptional(inputRecordType)) {
/** while-loop for the case there is a nested multi-level union */
inputRecordType = ((AUnionType) inputRecordType).getActualType();
checkUnknown = true;
}
/** see whether the input record type needs to be casted */
boolean cast = !compatible(requiredRecordType, inputRecordType);
if (checkUnknown) {
recordVar = addWrapperFunction(requiredRecordType, recordVar, op, context, BuiltinFunctions.CHECK_UNKNOWN);
}
if (cast) {
addWrapperFunction(requiredRecordType, recordVar, op, context, BuiltinFunctions.CAST_TYPE);
}
return cast || checkUnknown;
}
Aggregations