Search in sources :

Example 66 with IAType

use of org.apache.asterix.om.types.IAType 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;
    }
}
Also used : Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) AbstractFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression) AbstractCollectionType(org.apache.asterix.om.types.AbstractCollectionType) AlgebricksException(org.apache.hyracks.algebricks.common.exceptions.AlgebricksException) IAType(org.apache.asterix.om.types.IAType)

Example 67 with IAType

use of org.apache.asterix.om.types.IAType in project asterixdb by apache.

the class StaticTypeCastUtil method staticRecordTypeCast.

/**
     * This method statically cast the type of records from their current type to the required type.
     *
     * @param func
     *            The record constructor expression.
     * @param reqType
     *            The required type.
     * @param inputType
     *            The current type.
     * @param env
     *            The type environment.
     * @throws AlgebricksException
     */
private static boolean staticRecordTypeCast(AbstractFunctionCallExpression func, ARecordType reqType, ARecordType inputType, IVariableTypeEnvironment env) throws AlgebricksException {
    if (!(func.getFunctionIdentifier() == BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR || func.getFunctionIdentifier() == BuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR)) {
        return false;
    }
    IAType[] reqFieldTypes = reqType.getFieldTypes();
    String[] reqFieldNames = reqType.getFieldNames();
    IAType[] inputFieldTypes = inputType.getFieldTypes();
    String[] inputFieldNames = inputType.getFieldNames();
    int[] fieldPermutation = new int[reqFieldTypes.length];
    boolean[] nullFields = new boolean[reqFieldTypes.length];
    boolean[] openFields = new boolean[inputFieldTypes.length];
    Arrays.fill(nullFields, false);
    Arrays.fill(openFields, true);
    Arrays.fill(fieldPermutation, -1);
    // forward match: match from actual to required
    boolean matched = false;
    for (int i = 0; i < inputFieldNames.length; i++) {
        String fieldName = inputFieldNames[i];
        IAType fieldType = inputFieldTypes[i];
        if (2 * i + 1 > func.getArguments().size()) {
            // it is not a record constructor function
            return false;
        }
        // 2*i+1 is the index of field value expression
        ILogicalExpression arg = func.getArguments().get(2 * i + 1).getValue();
        matched = false;
        for (int j = 0; j < reqFieldNames.length; j++) {
            String reqFieldName = reqFieldNames[j];
            IAType reqFieldType = reqFieldTypes[j];
            if (fieldName.equals(reqFieldName)) {
                //type matched
                if (fieldType.equals(reqFieldType)) {
                    fieldPermutation[j] = i;
                    openFields[i] = false;
                    matched = true;
                    if (arg.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
                        ScalarFunctionCallExpression scalarFunc = (ScalarFunctionCallExpression) arg;
                        rewriteFuncExpr(scalarFunc, reqFieldType, fieldType, env);
                    }
                    break;
                }
                // match the optional field
                if (NonTaggedFormatUtil.isOptional(reqFieldType)) {
                    IAType itemType = ((AUnionType) reqFieldType).getActualType();
                    reqFieldType = itemType;
                    if (fieldType.equals(BuiltinType.AMISSING) || fieldType.equals(itemType)) {
                        fieldPermutation[j] = i;
                        openFields[i] = false;
                        matched = true;
                        // rewrite record expr
                        if (arg.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
                            ScalarFunctionCallExpression scalarFunc = (ScalarFunctionCallExpression) arg;
                            rewriteFuncExpr(scalarFunc, reqFieldType, fieldType, env);
                        }
                        break;
                    }
                }
                // delay that to runtime by calling the not-null function
                if (NonTaggedFormatUtil.isOptional(fieldType)) {
                    IAType itemType = ((AUnionType) fieldType).getActualType();
                    if (reqFieldType.equals(itemType)) {
                        fieldPermutation[j] = i;
                        openFields[i] = false;
                        matched = true;
                        ScalarFunctionCallExpression notNullFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CHECK_UNKNOWN));
                        notNullFunc.getArguments().add(new MutableObject<ILogicalExpression>(arg));
                        //wrap the not null function to the original function
                        func.getArguments().get(2 * i + 1).setValue(notNullFunc);
                        break;
                    }
                }
                // match the record field: need cast
                if (arg.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
                    ScalarFunctionCallExpression scalarFunc = (ScalarFunctionCallExpression) arg;
                    rewriteFuncExpr(scalarFunc, reqFieldType, fieldType, env);
                    fieldPermutation[j] = i;
                    openFields[i] = false;
                    matched = true;
                    break;
                }
            }
        }
        // the input has extra fields
        if (!matched && !reqType.isOpen()) {
            throw new AlgebricksException("static type mismatch: the input record includes an extra closed field " + fieldName + ":" + fieldType + "! Please check the field name and type.");
        }
    }
    // backward match: match from required to actual
    for (int i = 0; i < reqFieldNames.length; i++) {
        String reqFieldName = reqFieldNames[i];
        IAType reqFieldType = reqFieldTypes[i];
        matched = false;
        for (int j = 0; j < inputFieldNames.length; j++) {
            String fieldName = inputFieldNames[j];
            IAType fieldType = inputFieldTypes[j];
            if (!fieldName.equals(reqFieldName)) {
                continue;
            }
            // the entry index of fieldPermuatons is req field index
            if (!openFields[j]) {
                matched = true;
                break;
            }
            // match the optional field
            if (!NonTaggedFormatUtil.isOptional(reqFieldType)) {
                continue;
            }
            IAType itemType = ((AUnionType) reqFieldType).getActualType();
            if (fieldType.equals(BuiltinType.AMISSING) || fieldType.equals(itemType)) {
                matched = true;
                break;
            }
        }
        if (matched) {
            continue;
        }
        if (NonTaggedFormatUtil.isOptional(reqFieldType)) {
            // add a null field
            nullFields[i] = true;
        } else {
            // no matched field in the input for a required closed field
            if (inputType.isOpen()) {
                //if the input type is open, return false, give that to dynamic type cast to defer the error to the runtime
                return false;
            } else {
                throw new AlgebricksException("static type mismatch: the input record misses a required closed field " + reqFieldName + ":" + reqFieldType + "! Please check the field name and type.");
            }
        }
    }
    List<Mutable<ILogicalExpression>> arguments = func.getArguments();
    List<Mutable<ILogicalExpression>> originalArguments = new ArrayList<Mutable<ILogicalExpression>>();
    originalArguments.addAll(arguments);
    arguments.clear();
    // re-order the closed part and fill in null fields
    for (int i = 0; i < fieldPermutation.length; i++) {
        int pos = fieldPermutation[i];
        if (pos >= 0) {
            arguments.add(originalArguments.get(2 * pos));
            arguments.add(originalArguments.get(2 * pos + 1));
        }
        if (nullFields[i]) {
            // add a null field
            arguments.add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(new AString(reqFieldNames[i])))));
            arguments.add(new MutableObject<ILogicalExpression>(new ConstantExpression(new AsterixConstantValue(ANull.NULL))));
        }
    }
    // add the open part
    for (int i = 0; i < openFields.length; i++) {
        if (openFields[i]) {
            arguments.add(originalArguments.get(2 * i));
            Mutable<ILogicalExpression> expRef = originalArguments.get(2 * i + 1);
            injectCastToRelaxType(expRef, inputFieldTypes[i], env);
            arguments.add(expRef);
        }
    }
    return true;
}
Also used : AUnionType(org.apache.asterix.om.types.AUnionType) ConstantExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression) AlgebricksException(org.apache.hyracks.algebricks.common.exceptions.AlgebricksException) ArrayList(java.util.ArrayList) AString(org.apache.asterix.om.base.AString) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) AsterixConstantValue(org.apache.asterix.om.constants.AsterixConstantValue) AString(org.apache.asterix.om.base.AString) IAType(org.apache.asterix.om.types.IAType) ScalarFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)

Example 68 with IAType

use of org.apache.asterix.om.types.IAType in project asterixdb by apache.

the class KeyFieldTypeUtil method getRTreeIndexKeyTypes.

/**
     * Get the types of RTree index key fields
     *
     * @param index,
     *            the index to consider.
     * @param recordType,
     *            the main record type.
     * @param metaRecordType
     *            the auxiliary meta record type.
     * @return a list of IATypes, one for each corresponding index key field.
     * @throws AlgebricksException
     */
public static List<IAType> getRTreeIndexKeyTypes(Index index, ARecordType recordType, ARecordType metaRecordType) throws AlgebricksException {
    List<Integer> keySourceIndicators = index.getKeyFieldSourceIndicators();
    List<IAType> indexKeyTypes = new ArrayList<>();
    ARecordType targetRecType = chooseSource(keySourceIndicators, 0, recordType, metaRecordType);
    Pair<IAType, Boolean> keyPairType = Index.getNonNullableOpenFieldType(index.getKeyFieldTypes().get(0), index.getKeyFieldNames().get(0), targetRecType);
    IAType keyType = keyPairType.first;
    IAType nestedKeyType = NonTaggedFormatUtil.getNestedSpatialType(keyType.getTypeTag());
    int numKeys = KeyFieldTypeUtil.getNumSecondaryKeys(index, targetRecType, metaRecordType);
    for (int i = 0; i < numKeys; i++) {
        indexKeyTypes.add(nestedKeyType);
    }
    return indexKeyTypes;
}
Also used : ArrayList(java.util.ArrayList) ARecordType(org.apache.asterix.om.types.ARecordType) IAType(org.apache.asterix.om.types.IAType)

Example 69 with IAType

use of org.apache.asterix.om.types.IAType in project asterixdb by apache.

the class RTreeResourceFactoryProvider method getCmpFactories.

private static IBinaryComparatorFactory[] getCmpFactories(MetadataProvider metadataProvider, Index index, ARecordType recordType, ARecordType metaType) throws AlgebricksException {
    IBinaryComparatorFactoryProvider cmpFactoryProvider = metadataProvider.getStorageComponentProvider().getComparatorFactoryProvider();
    List<List<String>> secondaryKeyFields = index.getKeyFieldNames();
    int numSecondaryKeys = secondaryKeyFields.size();
    if (numSecondaryKeys != 1) {
        throw new AsterixException("Cannot use " + numSecondaryKeys + " fields as a key for the R-tree index. " + "There can be only one field as a key for the R-tree index.");
    }
    List<Integer> keySourceIndicators = index.getKeyFieldSourceIndicators();
    ARecordType sourceType;
    if (keySourceIndicators == null || keySourceIndicators.get(0) == 0) {
        sourceType = recordType;
    } else {
        sourceType = metaType;
    }
    Pair<IAType, Boolean> spatialTypePair = Index.getNonNullableOpenFieldType(index.getKeyFieldTypes().get(0), secondaryKeyFields.get(0), sourceType);
    IAType spatialType = spatialTypePair.first;
    if (spatialType == null) {
        throw new AsterixException("Could not find field " + secondaryKeyFields.get(0) + " in the schema.");
    }
    IAType nestedKeyType = NonTaggedFormatUtil.getNestedSpatialType(spatialType.getTypeTag());
    int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
    int numNestedSecondaryKeyFields = numDimensions * 2;
    IBinaryComparatorFactory[] secondaryComparatorFactories = new IBinaryComparatorFactory[numNestedSecondaryKeyFields];
    for (int i = 0; i < numNestedSecondaryKeyFields; i++) {
        secondaryComparatorFactories[i] = cmpFactoryProvider.getBinaryComparatorFactory(nestedKeyType, true);
    }
    return secondaryComparatorFactories;
}
Also used : IBinaryComparatorFactory(org.apache.hyracks.api.dataflow.value.IBinaryComparatorFactory) IBinaryComparatorFactoryProvider(org.apache.hyracks.algebricks.data.IBinaryComparatorFactoryProvider) AsterixException(org.apache.asterix.common.exceptions.AsterixException) List(java.util.List) ARecordType(org.apache.asterix.om.types.ARecordType) IAType(org.apache.asterix.om.types.IAType)

Example 70 with IAType

use of org.apache.asterix.om.types.IAType in project asterixdb by apache.

the class RTreeResourceFactoryProvider method getTypeTraits.

private static ITypeTraits[] getTypeTraits(MetadataProvider metadataProvider, Dataset dataset, Index index, ARecordType recordType, ARecordType metaType) throws AlgebricksException {
    ITypeTraitProvider ttProvider = metadataProvider.getStorageComponentProvider().getTypeTraitProvider();
    List<List<String>> secondaryKeyFields = index.getKeyFieldNames();
    int numSecondaryKeys = secondaryKeyFields.size();
    int numPrimaryKeys = dataset.getPrimaryKeys().size();
    ITypeTraits[] primaryTypeTraits = dataset.getPrimaryTypeTraits(metadataProvider, recordType, metaType);
    if (numSecondaryKeys != 1) {
        throw new AsterixException("Cannot use " + numSecondaryKeys + " fields as a key for the R-tree index. " + "There can be only one field as a key for the R-tree index.");
    }
    ARecordType sourceType;
    List<Integer> keySourceIndicators = index.getKeyFieldSourceIndicators();
    if (keySourceIndicators == null || keySourceIndicators.get(0) == 0) {
        sourceType = recordType;
    } else {
        sourceType = metaType;
    }
    Pair<IAType, Boolean> spatialTypePair = Index.getNonNullableOpenFieldType(index.getKeyFieldTypes().get(0), secondaryKeyFields.get(0), sourceType);
    IAType spatialType = spatialTypePair.first;
    if (spatialType == null) {
        throw new AsterixException("Could not find field " + secondaryKeyFields.get(0) + " in the schema.");
    }
    int numDimensions = NonTaggedFormatUtil.getNumDimensions(spatialType.getTypeTag());
    int numNestedSecondaryKeyFields = numDimensions * 2;
    ITypeTraits[] secondaryTypeTraits = new ITypeTraits[numNestedSecondaryKeyFields + numPrimaryKeys];
    IAType nestedKeyType = NonTaggedFormatUtil.getNestedSpatialType(spatialType.getTypeTag());
    for (int i = 0; i < numNestedSecondaryKeyFields; i++) {
        secondaryTypeTraits[i] = ttProvider.getTypeTrait(nestedKeyType);
    }
    for (int i = 0; i < numPrimaryKeys; i++) {
        secondaryTypeTraits[numNestedSecondaryKeyFields + i] = primaryTypeTraits[i];
    }
    return secondaryTypeTraits;
}
Also used : ITypeTraits(org.apache.hyracks.api.dataflow.value.ITypeTraits) AsterixException(org.apache.asterix.common.exceptions.AsterixException) ITypeTraitProvider(org.apache.hyracks.algebricks.data.ITypeTraitProvider) List(java.util.List) ARecordType(org.apache.asterix.om.types.ARecordType) IAType(org.apache.asterix.om.types.IAType)

Aggregations

IAType (org.apache.asterix.om.types.IAType)190 ARecordType (org.apache.asterix.om.types.ARecordType)73 ArrayList (java.util.ArrayList)64 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)42 ATypeTag (org.apache.asterix.om.types.ATypeTag)40 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)37 List (java.util.List)32 AlgebricksException (org.apache.hyracks.algebricks.common.exceptions.AlgebricksException)32 AUnionType (org.apache.asterix.om.types.AUnionType)31 AString (org.apache.asterix.om.base.AString)28 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)27 Mutable (org.apache.commons.lang3.mutable.Mutable)25 Pair (org.apache.hyracks.algebricks.common.utils.Pair)24 HyracksDataException (org.apache.hyracks.api.exceptions.HyracksDataException)20 Dataset (org.apache.asterix.metadata.entities.Dataset)18 AsterixException (org.apache.asterix.common.exceptions.AsterixException)17 AOrderedListType (org.apache.asterix.om.types.AOrderedListType)16 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)16 IVisitablePointable (org.apache.asterix.om.pointables.base.IVisitablePointable)15 IVariableTypeEnvironment (org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment)15