use of org.apache.asterix.om.types.ARecordType in project asterixdb by apache.
the class RecordRemoveFieldsTypeComputer method computeType.
@Override
public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expression;
String funcName = funcExpr.getFunctionIdentifier().getName();
IAType type0 = (IAType) env.getType(funcExpr.getArguments().get(0).getValue());
List<List<String>> pathList = new ArrayList<>();
Set<String> fieldNameSet = new HashSet<>();
Deque<String> fieldPathStack = new ArrayDeque<>();
ARecordType inputRecordType = getRecordTypeFromType(funcName, type0);
if (inputRecordType == null) {
return BuiltinType.ANY;
}
AbstractLogicalExpression arg1 = (AbstractLogicalExpression) funcExpr.getArguments().get(1).getValue();
IAType inputListType = (IAType) env.getType(arg1);
AOrderedListType inputOrderedListType = TypeComputeUtils.extractOrderedListType(inputListType);
if (inputOrderedListType == null) {
throw new TypeMismatchException(funcName, 1, inputListType.getTypeTag(), ATypeTag.ARRAY);
}
ATypeTag tt = inputOrderedListType.getItemType().getTypeTag();
if (tt == ATypeTag.STRING) {
// If top-fieldlist
if (setFieldNameSet(arg1, fieldNameSet)) {
return buildOutputType(fieldPathStack, inputRecordType, fieldNameSet, pathList);
} else {
return DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
}
} else {
// tt == ATypeTag.ANY, meaning the list is nested
computeTypeFromNonConstantExpression(funcName, arg1, fieldNameSet, pathList);
IAType resultType = buildOutputType(fieldPathStack, inputRecordType, fieldNameSet, pathList);
return resultType;
}
}
use of org.apache.asterix.om.types.ARecordType in project asterixdb by apache.
the class RecordRemoveFieldsTypeComputer method buildOutputType.
private IAType buildOutputType(Deque<String> fieldPathStack, ARecordType inputRecordType, Set<String> fieldNameSet, List<List<String>> pathList) throws AlgebricksException {
List<String> resultFieldNames = new ArrayList<>();
List<IAType> resultFieldTypes = new ArrayList<>();
String[] fieldNames = inputRecordType.getFieldNames();
IAType[] fieldTypes = inputRecordType.getFieldTypes();
for (int i = 0; i < fieldNames.length; i++) {
if (!fieldNameSet.contains(fieldNames[i])) {
// The main field is to be kept
addField(inputRecordType, fieldNames[i], resultFieldNames, resultFieldTypes);
} else if (!pathList.isEmpty() && fieldTypes[i].getTypeTag() == ATypeTag.OBJECT) {
ARecordType subRecord = (ARecordType) fieldTypes[i];
fieldPathStack.push(fieldNames[i]);
subRecord = deepCheckAndCopy(fieldPathStack, subRecord, pathList, inputRecordType.isOpen());
fieldPathStack.pop();
if (subRecord != null) {
resultFieldNames.add(fieldNames[i]);
resultFieldTypes.add(subRecord);
}
}
}
int n = resultFieldNames.size();
String resultTypeName = "result-record(" + inputRecordType.getTypeName() + ")";
return new ARecordType(resultTypeName, resultFieldNames.toArray(new String[n]), resultFieldTypes.toArray(new IAType[n]), // Make the output type open always
true);
}
use of org.apache.asterix.om.types.ARecordType in project asterixdb by apache.
the class RecordRemoveFieldsTypeComputer method deepCheckAndCopy.
/*
A method to deep copy a record the path validation
i.e., keep only fields that are valid
*/
private ARecordType deepCheckAndCopy(Deque<String> fieldPath, ARecordType srcRecType, List<List<String>> pathList, boolean isOpen) throws AlgebricksException {
// Make sure the current path is valid before going further
if (isRemovePath(fieldPath, pathList)) {
return null;
}
String[] srcFieldNames = srcRecType.getFieldNames();
IAType[] srcFieldTypes = srcRecType.getFieldTypes();
List<IAType> destFieldTypes = new ArrayList<>();
List<String> destFieldNames = new ArrayList<>();
for (int i = 0; i < srcFieldNames.length; i++) {
fieldPath.push(srcFieldNames[i]);
if (!isRemovePath(fieldPath, pathList)) {
if (srcFieldTypes[i].getTypeTag() == ATypeTag.OBJECT) {
ARecordType subRecord = (ARecordType) srcFieldTypes[i];
subRecord = deepCheckAndCopy(fieldPath, subRecord, pathList, isOpen);
if (subRecord != null) {
destFieldNames.add(srcFieldNames[i]);
destFieldTypes.add(subRecord);
}
} else {
destFieldNames.add(srcFieldNames[i]);
destFieldTypes.add(srcFieldTypes[i]);
}
}
fieldPath.pop();
}
int n = destFieldNames.size();
if (n == 0) {
return null;
}
return new ARecordType(srcRecType.getTypeName(), destFieldNames.toArray(new String[n]), destFieldTypes.toArray(new IAType[n]), isOpen);
}
use of org.apache.asterix.om.types.ARecordType in project asterixdb by apache.
the class OpenRecordConstructorResultType method computeType.
@Override
public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
/**
* if type has been top-down propagated, use the enforced type
*/
ARecordType type = (ARecordType) TypeCastUtils.getRequiredType(f);
if (type != null) {
return type;
}
Iterator<Mutable<ILogicalExpression>> argIter = f.getArguments().iterator();
List<String> namesList = new ArrayList<>();
List<IAType> typesList = new ArrayList<>();
// The following set of names do not belong to the closed part,
// but are additional possible field names. For example, a field "foo" with type
// ANY cannot be in the closed part, but "foo" is a possible field name.
Set<String> allPossibleAdditionalFieldNames = new HashSet<>();
boolean canProvideAdditionFieldInfo = true;
boolean isOpen = false;
while (argIter.hasNext()) {
ILogicalExpression e1 = argIter.next().getValue();
ILogicalExpression e2 = argIter.next().getValue();
IAType t2 = (IAType) env.getType(e2);
String fieldName = ConstantExpressionUtil.getStringConstant(e1);
if (fieldName != null && t2 != null && TypeHelper.isClosed(t2)) {
namesList.add(fieldName);
if (t2.getTypeTag() == ATypeTag.UNION) {
AUnionType unionType = (AUnionType) t2;
t2 = AUnionType.createUnknownableType(unionType.getActualType());
}
typesList.add(t2);
} else {
if (canProvideAdditionFieldInfo && fieldName != null) {
allPossibleAdditionalFieldNames.add(fieldName);
} else {
canProvideAdditionFieldInfo = false;
}
isOpen = true;
}
}
String[] fieldNames = namesList.toArray(new String[0]);
IAType[] fieldTypes = typesList.toArray(new IAType[0]);
return canProvideAdditionFieldInfo ? new ARecordType(null, fieldNames, fieldTypes, isOpen, allPossibleAdditionalFieldNames) : new ARecordType(null, fieldNames, fieldTypes, isOpen);
}
use of org.apache.asterix.om.types.ARecordType in project asterixdb by apache.
the class RecordMergeTypeComputer method mergedNestedType.
private IAType mergedNestedType(String fieldName, IAType fieldType1, IAType fieldType0) throws AlgebricksException {
if (fieldType1.getTypeTag() != ATypeTag.OBJECT || fieldType0.getTypeTag() != ATypeTag.OBJECT) {
throw new CompilationException(ErrorCode.COMPILATION_DUPLICATE_FIELD_NAME, fieldName);
}
ARecordType resultType = (ARecordType) fieldType0;
ARecordType fieldType1Copy = (ARecordType) fieldType1;
for (int i = 0; i < fieldType1Copy.getFieldTypes().length; i++) {
String fname = fieldType1Copy.getFieldNames()[i];
int pos = resultType.getFieldIndex(fname);
if (pos >= 0) {
// If a sub-record do merge, else ignore and let the values decide what to do
if (fieldType1Copy.getFieldTypes()[i].getTypeTag() == ATypeTag.OBJECT) {
IAType[] oldTypes = resultType.getFieldTypes();
oldTypes[pos] = mergedNestedType(fname, fieldType1Copy.getFieldTypes()[i], resultType.getFieldTypes()[pos]);
resultType = new ARecordType(resultType.getTypeName(), resultType.getFieldNames(), oldTypes, resultType.isOpen());
}
} else {
IAType[] combinedFieldTypes = ArrayUtils.addAll(resultType.getFieldTypes().clone(), fieldType1Copy.getFieldTypes()[i]);
resultType = new ARecordType(resultType.getTypeName(), ArrayUtils.addAll(resultType.getFieldNames(), fieldType1Copy.getFieldNames()[i]), combinedFieldTypes, resultType.isOpen());
}
}
return resultType;
}
Aggregations