Search in sources :

Example 1 with AUnionType

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

the class StaticTypeCastUtil method compatible.

/**
     * Determine if two types are compatible
     *
     * @param reqType
     *            the required type
     * @param inputType
     *            the input type
     * @return true if the two types are compatible; false otherwise
     */
public static boolean compatible(IAType reqType, IAType inputType) {
    if (reqType.getTypeTag() == ATypeTag.ANY || inputType.getTypeTag() == ATypeTag.ANY) {
        return true;
    }
    if (reqType.getTypeTag() != ATypeTag.UNION && inputType.getTypeTag() != ATypeTag.UNION) {
        if (reqType.equals(inputType)) {
            return true;
        } else {
            return false;
        }
    }
    Set<IAType> reqTypePossible = new HashSet<IAType>();
    Set<IAType> inputTypePossible = new HashSet<IAType>();
    if (reqType.getTypeTag() == ATypeTag.UNION) {
        AUnionType unionType = (AUnionType) reqType;
        reqTypePossible.addAll(unionType.getUnionList());
    } else {
        reqTypePossible.add(reqType);
    }
    if (inputType.getTypeTag() == ATypeTag.UNION) {
        AUnionType unionType = (AUnionType) inputType;
        inputTypePossible.addAll(unionType.getUnionList());
    } else {
        inputTypePossible.add(inputType);
    }
    return reqTypePossible.equals(inputTypePossible);
}
Also used : AUnionType(org.apache.asterix.om.types.AUnionType) HashSet(java.util.HashSet) IAType(org.apache.asterix.om.types.IAType)

Example 2 with AUnionType

use of org.apache.asterix.om.types.AUnionType 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 3 with AUnionType

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

the class FieldAccessByIndexEvalFactory method createScalarEvaluator.

@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
    return new IScalarEvaluator() {

        private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();

        private DataOutput out = resultStorage.getDataOutput();

        private IPointable inputArg0 = new VoidPointable();

        private IPointable inputArg1 = new VoidPointable();

        private IScalarEvaluator eval0 = recordEvalFactory.createScalarEvaluator(ctx);

        private IScalarEvaluator eval1 = fieldIndexEvalFactory.createScalarEvaluator(ctx);

        private int fieldIndex;

        private int fieldValueOffset;

        private int fieldValueLength;

        private IAType fieldValueType;

        private ATypeTag fieldValueTypeTag;

        /*
             * inputArg0: the record
             * inputArg1: the index
             *
             * This method outputs into IHyracksTaskContext context [field type tag (1 byte)][the field data]
             */
        @Override
        public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
            try {
                resultStorage.reset();
                eval0.evaluate(tuple, inputArg0);
                byte[] serRecord = inputArg0.getByteArray();
                int offset = inputArg0.getStartOffset();
                if (serRecord[offset] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
                    throw new TypeMismatchException(BuiltinFunctions.FIELD_ACCESS_BY_INDEX, 0, serRecord[offset], ATypeTag.SERIALIZED_RECORD_TYPE_TAG);
                }
                eval1.evaluate(tuple, inputArg1);
                byte[] indexBytes = inputArg1.getByteArray();
                int indexOffset = inputArg1.getStartOffset();
                if (indexBytes[indexOffset] != ATypeTag.SERIALIZED_INT32_TYPE_TAG) {
                    throw new TypeMismatchException(BuiltinFunctions.FIELD_ACCESS_BY_INDEX, 1, indexBytes[offset], ATypeTag.SERIALIZED_INT32_TYPE_TAG);
                }
                fieldIndex = IntegerPointable.getInteger(indexBytes, indexOffset + 1);
                fieldValueType = recordType.getFieldTypes()[fieldIndex];
                fieldValueOffset = ARecordSerializerDeserializer.getFieldOffsetById(serRecord, offset, fieldIndex, nullBitmapSize, recordType.isOpen());
                if (fieldValueOffset == 0) {
                    // the field is null, we checked the null bit map
                    out.writeByte(ATypeTag.SERIALIZED_NULL_TYPE_TAG);
                    result.set(resultStorage);
                    return;
                }
                if (fieldValueOffset < 0) {
                    // the field is missing, we checked the missing bit map
                    out.writeByte(ATypeTag.SERIALIZED_MISSING_TYPE_TAG);
                    result.set(resultStorage);
                    return;
                }
                if (fieldValueType.getTypeTag().equals(ATypeTag.UNION)) {
                    if (((AUnionType) fieldValueType).isUnknownableType()) {
                        fieldValueTypeTag = ((AUnionType) fieldValueType).getActualType().getTypeTag();
                        fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, fieldValueOffset, fieldValueTypeTag, false);
                        out.writeByte(fieldValueTypeTag.serialize());
                    } else {
                        // union .. the general case
                        throw new NotImplementedException();
                    }
                } else {
                    fieldValueTypeTag = fieldValueType.getTypeTag();
                    fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, fieldValueOffset, fieldValueTypeTag, false);
                    out.writeByte(fieldValueTypeTag.serialize());
                }
                out.write(serRecord, fieldValueOffset, fieldValueLength);
                result.set(resultStorage);
            } catch (IOException e) {
                throw new HyracksDataException(e);
            } catch (AsterixException e) {
                throw new HyracksDataException(e);
            }
        }
    };
}
Also used : DataOutput(java.io.DataOutput) AUnionType(org.apache.asterix.om.types.AUnionType) TypeMismatchException(org.apache.asterix.runtime.exceptions.TypeMismatchException) NotImplementedException(org.apache.hyracks.algebricks.common.exceptions.NotImplementedException) IPointable(org.apache.hyracks.data.std.api.IPointable) IOException(java.io.IOException) IScalarEvaluator(org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator) HyracksDataException(org.apache.hyracks.api.exceptions.HyracksDataException) ArrayBackedValueStorage(org.apache.hyracks.data.std.util.ArrayBackedValueStorage) AsterixException(org.apache.asterix.common.exceptions.AsterixException) ATypeTag(org.apache.asterix.om.types.ATypeTag) VoidPointable(org.apache.hyracks.data.std.primitive.VoidPointable) IFrameTupleReference(org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference) IAType(org.apache.asterix.om.types.IAType)

Example 4 with AUnionType

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

the class MetadataNode method getNestedComplexDatatypeNamesForThisDatatype.

private List<String> getNestedComplexDatatypeNamesForThisDatatype(JobId jobId, String dataverseName, String datatypeName) throws MetadataException, RemoteException {
    //Return all field types that aren't builtin types
    Datatype parentType = getDatatype(jobId, dataverseName, datatypeName);
    List<IAType> subTypes = null;
    if (parentType.getDatatype().getTypeTag() == ATypeTag.OBJECT) {
        ARecordType recType = (ARecordType) parentType.getDatatype();
        subTypes = Arrays.asList(recType.getFieldTypes());
    } else if (parentType.getDatatype().getTypeTag() == ATypeTag.UNION) {
        AUnionType recType = (AUnionType) parentType.getDatatype();
        subTypes = recType.getUnionList();
    }
    List<String> nestedTypes = new ArrayList<>();
    if (subTypes != null) {
        for (IAType subType : subTypes) {
            if (!(subType instanceof BuiltinType)) {
                nestedTypes.add(subType.getTypeName());
            }
        }
    }
    return nestedTypes;
}
Also used : BuiltinType(org.apache.asterix.om.types.BuiltinType) AUnionType(org.apache.asterix.om.types.AUnionType) ArrayList(java.util.ArrayList) AString(org.apache.asterix.om.base.AString) AMutableString(org.apache.asterix.om.base.AMutableString) ARecordType(org.apache.asterix.om.types.ARecordType) Datatype(org.apache.asterix.metadata.entities.Datatype) IAType(org.apache.asterix.om.types.IAType)

Example 5 with AUnionType

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

the class JSONDeserializerForTypesTest method test.

@Test
public void test() throws Exception {
    // Tests a record type with primitive types.
    String[] fieldNames = { "a1", "a2", "a3" };
    IAType[] fieldTypes = { BuiltinType.ASTRING, BuiltinType.AINT16, BuiltinType.ABITARRAY };
    ARecordType recordType = new ARecordType("ARecord", fieldNames, fieldTypes, true);
    Assert.assertEquals(recordType, JSONDeserializerForTypes.convertFromJSON(recordType.toJSON()));
    // Tests a record type with a nested record type.
    String[] fieldNames2 = { "a1", "a2" };
    IAType[] fieldTypes2 = { BuiltinType.ABOOLEAN, recordType };
    ARecordType recordType2 = new ARecordType("ARecord2", fieldNames2, fieldTypes2, true);
    Assert.assertEquals(recordType2, JSONDeserializerForTypes.convertFromJSON(recordType2.toJSON()));
    // Tests a record type with a union type.
    String[] fieldNames3 = { "a1", "a2" };
    List<IAType> unionTypes = new ArrayList<IAType>();
    unionTypes.add(BuiltinType.ADURATION);
    unionTypes.add(recordType2);
    AUnionType unionType = new AUnionType(unionTypes, "union");
    IAType[] fieldTypes3 = { BuiltinType.ABOOLEAN, unionType };
    ARecordType recordType3 = new ARecordType("ARecord3", fieldNames3, fieldTypes3, true);
    Assert.assertEquals(recordType3, JSONDeserializerForTypes.convertFromJSON(recordType3.toJSON()));
    // Tests a record type with an ordered list.
    String[] fieldNames4 = { "a1", "a2" };
    IAType[] fieldTypes4 = { BuiltinType.ABOOLEAN, new AOrderedListType(BuiltinType.ADATETIME, "list") };
    ARecordType recordType4 = new ARecordType("ARecord4", fieldNames4, fieldTypes4, false);
    Assert.assertEquals(recordType4, JSONDeserializerForTypes.convertFromJSON(recordType4.toJSON()));
    // Tests a record type with an unordered list.
    String[] fieldNames5 = { "a1", "a2" };
    IAType[] fieldTypes5 = { BuiltinType.ABOOLEAN, new AUnorderedListType(recordType2, "list") };
    ARecordType recordType5 = new ARecordType("ARecord5", fieldNames5, fieldTypes5, false);
    Assert.assertEquals(recordType5, JSONDeserializerForTypes.convertFromJSON(recordType5.toJSON()));
}
Also used : AUnionType(org.apache.asterix.om.types.AUnionType) AOrderedListType(org.apache.asterix.om.types.AOrderedListType) ArrayList(java.util.ArrayList) ARecordType(org.apache.asterix.om.types.ARecordType) AUnorderedListType(org.apache.asterix.om.types.AUnorderedListType) IAType(org.apache.asterix.om.types.IAType) Test(org.junit.Test)

Aggregations

AUnionType (org.apache.asterix.om.types.AUnionType)32 IAType (org.apache.asterix.om.types.IAType)31 ATypeTag (org.apache.asterix.om.types.ATypeTag)13 ARecordType (org.apache.asterix.om.types.ARecordType)11 ArrayList (java.util.ArrayList)10 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)7 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)6 AOrderedListType (org.apache.asterix.om.types.AOrderedListType)5 AUnorderedListType (org.apache.asterix.om.types.AUnorderedListType)5 Mutable (org.apache.commons.lang3.mutable.Mutable)5 HyracksDataException (org.apache.hyracks.api.exceptions.HyracksDataException)5 DataOutput (java.io.DataOutput)4 AString (org.apache.asterix.om.base.AString)4 IOException (java.io.IOException)3 List (java.util.List)3 RuntimeDataException (org.apache.asterix.common.exceptions.RuntimeDataException)3 IVisitablePointable (org.apache.asterix.om.pointables.base.IVisitablePointable)3 AlgebricksException (org.apache.hyracks.algebricks.common.exceptions.AlgebricksException)3 HashSet (java.util.HashSet)2 AsterixException (org.apache.asterix.common.exceptions.AsterixException)2