use of org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo in project asterixdb by apache.
the class GetRecordFieldValueEvalFactory method createScalarEvaluator.
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
return new IScalarEvaluator() {
private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private final DataOutput out = resultStorage.getDataOutput();
private final IPointable inputArg0 = new VoidPointable();
private final IPointable inputArg1 = new VoidPointable();
private final IScalarEvaluator recordEval = recordEvalFactory.createScalarEvaluator(ctx);
private final IScalarEvaluator fieldNameEval = fldNameEvalFactory.createScalarEvaluator(ctx);
private final RuntimeRecordTypeInfo recTypeInfo = new RuntimeRecordTypeInfo();
{
recTypeInfo.reset(recordType);
}
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
try {
resultStorage.reset();
fieldNameEval.evaluate(tuple, inputArg1);
byte[] serFldName = inputArg1.getByteArray();
int serFldNameOffset = inputArg1.getStartOffset();
int serFldNameLen = inputArg1.getLength();
recordEval.evaluate(tuple, inputArg0);
byte[] serRecord = inputArg0.getByteArray();
int serRecordOffset = inputArg0.getStartOffset();
int serRecordLen = inputArg0.getLength();
if (serRecord[serRecordOffset] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new TypeMismatchException(BuiltinFunctions.GET_RECORD_FIELD_VALUE, 0, serRecord[serRecordOffset], ATypeTag.SERIALIZED_RECORD_TYPE_TAG);
}
int subFieldOffset = -1;
int subFieldLength = -1;
// Look at closed fields first.
int subFieldIndex = recTypeInfo.getFieldIndex(serFldName, serFldNameOffset + 1, serFldNameLen - 1);
if (subFieldIndex >= 0) {
int nullBitmapSize = RecordUtil.computeNullBitmapSize(recordType);
subFieldOffset = ARecordSerializerDeserializer.getFieldOffsetById(serRecord, serRecordOffset, subFieldIndex, nullBitmapSize, recordType.isOpen());
if (subFieldOffset == 0) {
// the field is null, we checked the null bit map
out.writeByte(ATypeTag.SERIALIZED_NULL_TYPE_TAG);
result.set(resultStorage);
return;
}
ATypeTag fieldTypeTag = recordType.getFieldTypes()[subFieldIndex].getTypeTag();
subFieldLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, fieldTypeTag, false);
// write result.
out.writeByte(fieldTypeTag.serialize());
out.write(serRecord, subFieldOffset, subFieldLength);
result.set(resultStorage);
return;
}
// Look at open fields.
subFieldOffset = ARecordSerializerDeserializer.getFieldOffsetByName(serRecord, serRecordOffset, serRecordLen, serFldName, serFldNameOffset);
if (subFieldOffset < 0) {
out.writeByte(ATypeTag.SERIALIZED_MISSING_TYPE_TAG);
result.set(resultStorage);
return;
}
// Get the field length.
ATypeTag fieldValueTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serRecord[subFieldOffset]);
subFieldLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, fieldValueTypeTag, true) + 1;
// write result.
result.set(serRecord, subFieldOffset, subFieldLength);
} catch (IOException e) {
throw new HyracksDataException(e);
} catch (AsterixException e) {
throw new HyracksDataException(e);
}
}
};
}
use of org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo in project asterixdb by apache.
the class RecordAddFieldsDescriptor method createEvaluatorFactory.
@Override
public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
return new IScalarEvaluatorFactory() {
private static final long serialVersionUID = 1L;
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
final PointableAllocator allocator = new PointableAllocator();
final IVisitablePointable vp0 = allocator.allocateRecordValue(inRecType);
final IVisitablePointable vp1 = allocator.allocateListValue(inListType);
final IPointable argPtr0 = new VoidPointable();
final IPointable argPtr1 = new VoidPointable();
final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
final IScalarEvaluator eval1 = args[1].createScalarEvaluator(ctx);
final ArrayBackedValueStorage fieldNamePointable = new ArrayBackedValueStorage();
final ArrayBackedValueStorage fieldValuePointer = new ArrayBackedValueStorage();
final PointableHelper pointableHelper = new PointableHelper();
try {
pointableHelper.serializeString("field-name", fieldNamePointable, true);
pointableHelper.serializeString("field-value", fieldValuePointer, true);
} catch (AsterixException e) {
throw new HyracksDataException(e);
}
return new IScalarEvaluator() {
// the default 32k frame size
public static final int TABLE_FRAME_SIZE = 32768;
// the default 32k frame size
public static final int TABLE_SIZE = 100;
private final RecordBuilder recordBuilder = new RecordBuilder();
private final RuntimeRecordTypeInfo requiredRecordTypeInfo = new RuntimeRecordTypeInfo();
private final IBinaryHashFunction putHashFunc = ListItemBinaryHashFunctionFactory.INSTANCE.createBinaryHashFunction();
private final IBinaryHashFunction getHashFunc = ListItemBinaryHashFunctionFactory.INSTANCE.createBinaryHashFunction();
private final BinaryEntry keyEntry = new BinaryEntry();
private final BinaryEntry valEntry = new BinaryEntry();
private final IVisitablePointable tempValReference = allocator.allocateEmpty();
private final IBinaryComparator cmp = ListItemBinaryComparatorFactory.INSTANCE.createBinaryComparator();
private BinaryHashMap hashMap = new BinaryHashMap(TABLE_SIZE, TABLE_FRAME_SIZE, putHashFunc, getHashFunc, cmp);
private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private DataOutput out = resultStorage.getDataOutput();
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
resultStorage.reset();
recordBuilder.reset(outRecType);
requiredRecordTypeInfo.reset(outRecType);
eval0.evaluate(tuple, argPtr0);
eval1.evaluate(tuple, argPtr1);
// Make sure we get a valid record
byte typeTag0 = argPtr0.getByteArray()[argPtr0.getStartOffset()];
if (typeTag0 != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new TypeMismatchException(getIdentifier(), 0, typeTag0, ATypeTag.SERIALIZED_RECORD_TYPE_TAG);
}
// Make sure we get a valid list
byte typeTag1 = argPtr1.getByteArray()[argPtr1.getStartOffset()];
if (typeTag1 != ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
throw new TypeMismatchException(getIdentifier(), 1, typeTag1, ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG);
}
vp0.set(argPtr0);
vp1.set(argPtr1);
ARecordVisitablePointable recordPointable = (ARecordVisitablePointable) vp0;
AListVisitablePointable listPointable = (AListVisitablePointable) vp1;
// Initialize our hashmap
int tableSize = recordPointable.getFieldNames().size() + listPointable.getItems().size();
// Thus avoiding unnecessary object construction
if (hashMap == null || tableSize > TABLE_SIZE) {
hashMap = new BinaryHashMap(tableSize, TABLE_FRAME_SIZE, putHashFunc, getHashFunc, cmp);
} else {
hashMap.clear();
}
addFields(recordPointable, listPointable);
recordBuilder.write(out, true);
result.set(resultStorage);
}
private void addFields(ARecordVisitablePointable inputRecordPointer, AListVisitablePointable listPointable) throws HyracksDataException {
List<IVisitablePointable> inputRecordFieldNames = inputRecordPointer.getFieldNames();
List<IVisitablePointable> inputRecordFieldValues = inputRecordPointer.getFieldValues();
List<IVisitablePointable> inputFields = listPointable.getItems();
IVisitablePointable namePointable = null;
IVisitablePointable valuePointable = null;
int numInputRecordFields = inputRecordFieldNames.size();
try {
// Add original record without duplicate checking
for (int i = 0; i < numInputRecordFields; ++i) {
IVisitablePointable fnp = inputRecordFieldNames.get(i);
IVisitablePointable fvp = inputRecordFieldValues.get(i);
int pos = requiredRecordTypeInfo.getFieldIndex(fnp.getByteArray(), fnp.getStartOffset() + 1, fnp.getLength() - 1);
if (pos >= 0) {
recordBuilder.addField(pos, fvp);
} else {
recordBuilder.addField(fnp, fvp);
}
keyEntry.set(fnp.getByteArray(), fnp.getStartOffset(), fnp.getLength());
valEntry.set(fvp.getByteArray(), fvp.getStartOffset(), fvp.getLength());
hashMap.put(keyEntry, valEntry);
}
// Get the fields from a list of records
for (int i = 0; i < inputFields.size(); i++) {
if (!PointableHelper.sameType(ATypeTag.OBJECT, inputFields.get(i))) {
throw new AsterixException("Expected list of record, got " + PointableHelper.getTypeTag(inputFields.get(i)));
}
List<IVisitablePointable> names = ((ARecordVisitablePointable) inputFields.get(i)).getFieldNames();
List<IVisitablePointable> values = ((ARecordVisitablePointable) inputFields.get(i)).getFieldValues();
// Get name and value of the field to be added
// Use loop to account for the cases where users switches the order of the fields
IVisitablePointable fieldName;
for (int j = 0; j < names.size(); j++) {
fieldName = names.get(j);
// if fieldName is "field-name" then read the name
if (PointableHelper.byteArrayEqual(fieldNamePointable, fieldName)) {
namePointable = values.get(j);
} else {
// otherwise the fieldName is "field-value". Thus, read the value
valuePointable = values.get(j);
}
}
if (namePointable == null || valuePointable == null) {
throw new InvalidDataFormatException(getIdentifier(), "fields to be added");
}
// Check that the field being added is a valid field
int pos = requiredRecordTypeInfo.getFieldIndex(namePointable.getByteArray(), namePointable.getStartOffset() + 1, namePointable.getLength() - 1);
keyEntry.set(namePointable.getByteArray(), namePointable.getStartOffset(), namePointable.getLength());
// Check if already in our built record
BinaryEntry entry = hashMap.get(keyEntry);
if (entry != null) {
tempValReference.set(entry.getBuf(), entry.getOffset(), entry.getLength());
// If value is not equal throw conflicting duplicate field, otherwise ignore
if (!PointableHelper.byteArrayEqual(valuePointable, tempValReference)) {
throw new RuntimeDataException(ErrorCode.DUPLICATE_FIELD_NAME, getIdentifier());
}
} else {
if (pos > -1) {
recordBuilder.addField(pos, valuePointable);
} else {
recordBuilder.addField(namePointable, valuePointable);
}
valEntry.set(valuePointable.getByteArray(), valuePointable.getStartOffset(), valuePointable.getLength());
hashMap.put(keyEntry, valEntry);
}
}
} catch (AsterixException e) {
throw new HyracksDataException(e);
}
}
};
}
};
}
use of org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo in project asterixdb by apache.
the class RecordMergeDescriptor method createEvaluatorFactory.
@Override
public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) {
return new IScalarEvaluatorFactory() {
private static final long serialVersionUID = 1L;
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
final PointableAllocator pa = new PointableAllocator();
final IVisitablePointable vp0 = pa.allocateRecordValue(inRecType0);
final IVisitablePointable vp1 = pa.allocateRecordValue(inRecType1);
final IPointable argPtr0 = new VoidPointable();
final IPointable argPtr1 = new VoidPointable();
final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx);
final IScalarEvaluator eval1 = args[1].createScalarEvaluator(ctx);
final List<RecordBuilder> rbStack = new ArrayList<>();
final ArrayBackedValueStorage tabvs = new ArrayBackedValueStorage();
return new IScalarEvaluator() {
private final RuntimeRecordTypeInfo runtimeRecordTypeInfo = new RuntimeRecordTypeInfo();
private final DeepEqualAssessor deepEqualAssesor = new DeepEqualAssessor();
private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private DataOutput out = resultStorage.getDataOutput();
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
resultStorage.reset();
eval0.evaluate(tuple, argPtr0);
eval1.evaluate(tuple, argPtr1);
vp0.set(argPtr0);
vp1.set(argPtr1);
ARecordVisitablePointable rp0 = (ARecordVisitablePointable) vp0;
ARecordVisitablePointable rp1 = (ARecordVisitablePointable) vp1;
try {
mergeFields(outRecType, rp0, rp1, true, 0);
rbStack.get(0).write(out, true);
} catch (IOException | AsterixException e) {
throw new HyracksDataException(e);
}
result.set(resultStorage);
}
private void mergeFields(ARecordType combinedType, ARecordVisitablePointable leftRecord, ARecordVisitablePointable rightRecord, boolean openFromParent, int nestedLevel) throws IOException, AsterixException, HyracksDataException {
if (rbStack.size() < (nestedLevel + 1)) {
rbStack.add(new RecordBuilder());
}
rbStack.get(nestedLevel).reset(combinedType);
rbStack.get(nestedLevel).init();
//Add all fields from left record
for (int i = 0; i < leftRecord.getFieldNames().size(); i++) {
IVisitablePointable leftName = leftRecord.getFieldNames().get(i);
IVisitablePointable leftValue = leftRecord.getFieldValues().get(i);
IVisitablePointable leftType = leftRecord.getFieldTypeTags().get(i);
boolean foundMatch = false;
for (int j = 0; j < rightRecord.getFieldNames().size(); j++) {
IVisitablePointable rightName = rightRecord.getFieldNames().get(j);
IVisitablePointable rightValue = rightRecord.getFieldValues().get(j);
IVisitablePointable rightType = rightRecord.getFieldTypeTags().get(j);
// Check if same fieldname
if (PointableHelper.isEqual(leftName, rightName) && !deepEqualAssesor.isEqual(leftValue, rightValue)) {
//Field was found on the right and are subrecords, merge them
if (PointableHelper.sameType(ATypeTag.OBJECT, rightType) && PointableHelper.sameType(ATypeTag.OBJECT, leftType)) {
//We are merging two sub records
addFieldToSubRecord(combinedType, leftName, leftValue, rightValue, openFromParent, nestedLevel);
foundMatch = true;
} else {
throw new RuntimeDataException(ErrorCode.DUPLICATE_FIELD_NAME, getIdentifier());
}
}
}
if (!foundMatch) {
addFieldToSubRecord(combinedType, leftName, leftValue, null, openFromParent, nestedLevel);
}
}
//Repeat for right side (ignoring duplicates this time)
for (int j = 0; j < rightRecord.getFieldNames().size(); j++) {
IVisitablePointable rightName = rightRecord.getFieldNames().get(j);
IVisitablePointable rightValue = rightRecord.getFieldValues().get(j);
boolean foundMatch = false;
for (int i = 0; i < leftRecord.getFieldNames().size(); i++) {
IVisitablePointable leftName = leftRecord.getFieldNames().get(i);
if (rightName.equals(leftName)) {
foundMatch = true;
}
}
if (!foundMatch) {
addFieldToSubRecord(combinedType, rightName, rightValue, null, openFromParent, nestedLevel);
}
}
}
/*
* Takes in a record type, field name, and the field values (which are record) from two records
* Merges them into one record of combinedType
* And adds that record as a field to the Record in subrb
* the second value can be null, indicated that you just add the value of left as a field to subrb
*
*/
private void addFieldToSubRecord(ARecordType combinedType, IVisitablePointable fieldNamePointable, IVisitablePointable leftValue, IVisitablePointable rightValue, boolean openFromParent, int nestedLevel) throws IOException, AsterixException, HyracksDataException {
runtimeRecordTypeInfo.reset(combinedType);
int pos = runtimeRecordTypeInfo.getFieldIndex(fieldNamePointable.getByteArray(), fieldNamePointable.getStartOffset() + 1, fieldNamePointable.getLength() - 1);
//Add the merged field
if (combinedType != null && pos >= 0) {
if (rightValue == null) {
rbStack.get(nestedLevel).addField(pos, leftValue);
} else {
mergeFields((ARecordType) combinedType.getFieldTypes()[pos], (ARecordVisitablePointable) leftValue, (ARecordVisitablePointable) rightValue, false, nestedLevel + 1);
tabvs.reset();
rbStack.get(nestedLevel + 1).write(tabvs.getDataOutput(), true);
rbStack.get(nestedLevel).addField(pos, tabvs);
}
} else {
if (rightValue == null) {
rbStack.get(nestedLevel).addField(fieldNamePointable, leftValue);
} else {
mergeFields(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE, (ARecordVisitablePointable) leftValue, (ARecordVisitablePointable) rightValue, false, nestedLevel + 1);
tabvs.reset();
rbStack.get(nestedLevel + 1).write(tabvs.getDataOutput(), true);
rbStack.get(nestedLevel).addField(fieldNamePointable, tabvs);
}
}
}
};
}
};
}
use of org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo in project asterixdb by apache.
the class RecordRemoveFieldsEvalFactory method createScalarEvaluator.
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
final PointableAllocator pa = new PointableAllocator();
final IVisitablePointable vp0 = pa.allocateRecordValue(inputRecType);
final IVisitablePointable vp1 = pa.allocateListValue(inputListType);
final IPointable inputArg0 = new VoidPointable();
final IPointable inputArg1 = new VoidPointable();
final IScalarEvaluator eval0 = inputRecordEvalFactory.createScalarEvaluator(ctx);
final IScalarEvaluator eval1 = removeFieldPathsFactory.createScalarEvaluator(ctx);
return new IScalarEvaluator() {
private final RuntimeRecordTypeInfo runtimeRecordTypeInfo = new RuntimeRecordTypeInfo();
private final List<RecordBuilder> rbStack = new ArrayList<>();
private final ArrayBackedValueStorage tabvs = new ArrayBackedValueStorage();
private final Deque<IVisitablePointable> recordPath = new ArrayDeque<>();
private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private DataOutput out = resultStorage.getDataOutput();
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
resultStorage.reset();
eval0.evaluate(tuple, inputArg0);
eval1.evaluate(tuple, inputArg1);
byte inputTypeTag0 = inputArg0.getByteArray()[inputArg0.getStartOffset()];
if (inputTypeTag0 != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new TypeMismatchException(BuiltinFunctions.REMOVE_FIELDS, 0, inputTypeTag0, ATypeTag.SERIALIZED_INT32_TYPE_TAG);
}
byte inputTypeTag1 = inputArg1.getByteArray()[inputArg1.getStartOffset()];
if (inputTypeTag1 != ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG) {
throw new TypeMismatchException(BuiltinFunctions.REMOVE_FIELDS, 1, inputTypeTag1, ATypeTag.SERIALIZED_ORDEREDLIST_TYPE_TAG);
}
vp0.set(inputArg0);
vp1.set(inputArg1);
ARecordVisitablePointable recordPointable = (ARecordVisitablePointable) vp0;
AListVisitablePointable listPointable = (AListVisitablePointable) vp1;
try {
recordPath.clear();
rbStack.clear();
processRecord(requiredRecType, recordPointable, listPointable, 0);
rbStack.get(0).write(out, true);
} catch (IOException | AsterixException e) {
throw new HyracksDataException(e);
}
result.set(resultStorage);
}
private void processRecord(ARecordType requiredType, ARecordVisitablePointable srp, AListVisitablePointable inputList, int nestedLevel) throws IOException, AsterixException, HyracksDataException {
if (rbStack.size() < (nestedLevel + 1)) {
rbStack.add(new RecordBuilder());
}
rbStack.get(nestedLevel).reset(requiredType);
rbStack.get(nestedLevel).init();
List<IVisitablePointable> fieldNames = srp.getFieldNames();
List<IVisitablePointable> fieldValues = srp.getFieldValues();
List<IVisitablePointable> fieldTypes = srp.getFieldTypeTags();
for (int i = 0; i < fieldNames.size(); i++) {
IVisitablePointable subRecFieldName = fieldNames.get(i);
recordPath.push(subRecFieldName);
if (isValidPath(inputList)) {
if (requiredType != null && requiredType.getTypeTag() != ATypeTag.ANY) {
addKeptFieldToSubRecord(requiredType, subRecFieldName, fieldValues.get(i), fieldTypes.get(i), inputList, nestedLevel);
} else {
addKeptFieldToSubRecord(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE, subRecFieldName, fieldValues.get(i), fieldTypes.get(i), inputList, nestedLevel);
}
}
recordPath.pop();
}
}
private void addKeptFieldToSubRecord(ARecordType requiredType, IVisitablePointable fieldNamePointable, IVisitablePointable fieldValuePointable, IVisitablePointable fieldTypePointable, AListVisitablePointable inputList, int nestedLevel) throws IOException, AsterixException, HyracksDataException {
runtimeRecordTypeInfo.reset(requiredType);
int pos = runtimeRecordTypeInfo.getFieldIndex(fieldNamePointable.getByteArray(), fieldNamePointable.getStartOffset() + 1, fieldNamePointable.getLength() - 1);
if (pos >= 0) {
// Closed field
if (PointableHelper.sameType(ATypeTag.OBJECT, fieldTypePointable)) {
processRecord((ARecordType) requiredType.getFieldTypes()[pos], (ARecordVisitablePointable) fieldValuePointable, inputList, nestedLevel + 1);
tabvs.reset();
rbStack.get(nestedLevel + 1).write(tabvs.getDataOutput(), true);
rbStack.get(nestedLevel).addField(pos, tabvs);
} else {
rbStack.get(nestedLevel).addField(pos, fieldValuePointable);
}
} else {
// Open field
if (PointableHelper.sameType(ATypeTag.OBJECT, fieldTypePointable)) {
processRecord(null, (ARecordVisitablePointable) fieldValuePointable, inputList, nestedLevel + 1);
tabvs.reset();
rbStack.get(nestedLevel + 1).write(tabvs.getDataOutput(), true);
rbStack.get(nestedLevel).addField(fieldNamePointable, tabvs);
} else {
rbStack.get(nestedLevel).addField(fieldNamePointable, fieldValuePointable);
}
}
}
private boolean isValidPath(AListVisitablePointable inputList) throws HyracksDataException {
List<IVisitablePointable> items = inputList.getItems();
List<IVisitablePointable> typeTags = inputList.getItemTags();
int pathLen = recordPath.size();
for (int i = 0; i < items.size(); i++) {
IVisitablePointable item = items.get(i);
if (PointableHelper.sameType(ATypeTag.ARRAY, typeTags.get(i))) {
List<IVisitablePointable> inputPathItems = ((AListVisitablePointable) item).getItems();
if (pathLen == inputPathItems.size()) {
boolean match = true;
Iterator<IVisitablePointable> fpi = recordPath.iterator();
for (int j = inputPathItems.size() - 1; j >= 0; j--) {
match &= PointableHelper.isEqual(inputPathItems.get(j), fpi.next());
if (!match) {
break;
}
}
if (match) {
// Not a valid path for the output record
return false;
}
}
} else {
if (PointableHelper.isEqual(recordPath.getFirst(), item)) {
return false;
}
}
}
return true;
}
};
}
use of org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo in project asterixdb by apache.
the class FieldAccessNestedEvalFactory method createScalarEvaluator.
@Override
public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException {
return new IScalarEvaluator() {
private ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage();
private final DataOutput out = resultStorage.getDataOutput();
private final ByteArrayAccessibleOutputStream subRecordTmpStream = new ByteArrayAccessibleOutputStream();
private final IPointable inputArg0 = new VoidPointable();
private final IScalarEvaluator eval0 = recordEvalFactory.createScalarEvaluator(ctx);
private final IPointable[] fieldPointables = new VoidPointable[fieldPath.size()];
private final RuntimeRecordTypeInfo[] recTypeInfos = new RuntimeRecordTypeInfo[fieldPath.size()];
@SuppressWarnings("unchecked")
private final ISerializerDeserializer<ANull> nullSerde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
@SuppressWarnings("unchecked")
private final ISerializerDeserializer<AMissing> missingSerde = SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AMISSING);
{
generateFieldsPointables();
for (int index = 0; index < fieldPath.size(); ++index) {
recTypeInfos[index] = new RuntimeRecordTypeInfo();
}
}
@SuppressWarnings("unchecked")
private void generateFieldsPointables() throws HyracksDataException {
for (int i = 0; i < fieldPath.size(); i++) {
ArrayBackedValueStorage storage = new ArrayBackedValueStorage();
DataOutput out = storage.getDataOutput();
AString as = new AString(fieldPath.get(i));
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(as.getType()).serialize(as, out);
fieldPointables[i] = new VoidPointable();
fieldPointables[i].set(storage);
}
}
@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();
int start = offset;
int len = inputArg0.getLength();
if (serRecord[start] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new TypeMismatchException(BuiltinFunctions.FIELD_ACCESS_NESTED, 0, serRecord[start], ATypeTag.SERIALIZED_RECORD_TYPE_TAG);
}
int subFieldIndex = -1;
int subFieldOffset = -1;
int subFieldLength = -1;
int nullBitmapSize = -1;
IAType subType = recordType;
recTypeInfos[0].reset(recordType);
ATypeTag subTypeTag = ATypeTag.MISSING;
boolean openField = false;
int pathIndex = 0;
// Moving through closed fields first.
for (; pathIndex < fieldPointables.length; pathIndex++) {
if (subType.getTypeTag().equals(ATypeTag.UNION)) {
//enforced SubType
subType = ((AUnionType) subType).getActualType();
byte serializedTypeTag = subType.getTypeTag().serialize();
if (serializedTypeTag != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new UnsupportedTypeException(BuiltinFunctions.FIELD_ACCESS_NESTED.getName(), serializedTypeTag);
}
if (subType.getTypeTag() == ATypeTag.OBJECT) {
recTypeInfos[pathIndex].reset((ARecordType) subType);
}
}
subFieldIndex = recTypeInfos[pathIndex].getFieldIndex(fieldPointables[pathIndex].getByteArray(), fieldPointables[pathIndex].getStartOffset() + 1, fieldPointables[pathIndex].getLength() - 1);
if (subFieldIndex == -1) {
break;
}
nullBitmapSize = RecordUtil.computeNullBitmapSize((ARecordType) subType);
subFieldOffset = ARecordSerializerDeserializer.getFieldOffsetById(serRecord, start, subFieldIndex, nullBitmapSize, ((ARecordType) subType).isOpen());
if (subFieldOffset == 0) {
// the field is null, we checked the null bit map
// any path after null will return null.
nullSerde.serialize(ANull.NULL, out);
result.set(resultStorage);
return;
}
if (subFieldOffset < 0) {
// the field is missing, we checked the missing bit map
// any path after missing will return null.
missingSerde.serialize(AMissing.MISSING, out);
result.set(resultStorage);
return;
}
subType = ((ARecordType) subType).getFieldTypes()[subFieldIndex];
if (subType.getTypeTag() == ATypeTag.OBJECT && pathIndex + 1 < fieldPointables.length) {
// Move to the next Depth
recTypeInfos[pathIndex + 1].reset((ARecordType) subType);
}
if (subType.getTypeTag().equals(ATypeTag.UNION)) {
subTypeTag = ((AUnionType) subType).getActualType().getTypeTag();
subFieldLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, subTypeTag, false);
} else {
subTypeTag = subType.getTypeTag();
subFieldLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, subTypeTag, false);
}
if (pathIndex < fieldPointables.length - 1) {
//setup next iteration
subRecordTmpStream.reset();
subRecordTmpStream.write(subTypeTag.serialize());
subRecordTmpStream.write(serRecord, subFieldOffset, subFieldLength);
serRecord = subRecordTmpStream.getByteArray();
start = 0;
}
// type check
if (pathIndex < fieldPointables.length - 1 && serRecord[start] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new UnsupportedTypeException(BuiltinFunctions.FIELD_ACCESS_NESTED, serRecord[start]);
}
}
// Moving through open fields after we hit the first open field.
for (; pathIndex < fieldPointables.length; pathIndex++) {
openField = true;
subFieldOffset = ARecordSerializerDeserializer.getFieldOffsetByName(serRecord, start, len, fieldPointables[pathIndex].getByteArray(), fieldPointables[pathIndex].getStartOffset());
if (subFieldOffset < 0) {
out.writeByte(ATypeTag.SERIALIZED_MISSING_TYPE_TAG);
result.set(resultStorage);
return;
}
subTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serRecord[subFieldOffset]);
subFieldLength = NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, subTypeTag, true) + 1;
if (pathIndex >= fieldPointables.length - 1) {
continue;
}
//setup next iteration
start = subFieldOffset;
len = subFieldLength;
// type check
if (serRecord[start] == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) {
missingSerde.serialize(AMissing.MISSING, out);
result.set(resultStorage);
return;
}
if (serRecord[start] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) {
throw new UnsupportedTypeException(BuiltinFunctions.FIELD_ACCESS_NESTED.getName(), serRecord[start]);
}
}
// emit the final result.
if (openField) {
result.set(serRecord, subFieldOffset, subFieldLength);
} else {
out.writeByte(subTypeTag.serialize());
out.write(serRecord, subFieldOffset, subFieldLength);
result.set(resultStorage);
}
} catch (IOException | AsterixException e) {
throw new HyracksDataException(e);
}
}
};
}
Aggregations