>From Ali Alsuliman <[email protected]>: Ali Alsuliman has submitted this change. ( https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20590?usp=email )
Change subject: [NO ISSUE][FUN] Add array-star-field() ...................................................................... [NO ISSUE][FUN] Add array-star-field() - user model changes: no - storage format changes: no - interface changes: no Details: array-star-field(input_array, field_name) is similar to array-star(input_array) except that it only constructs the array values for the desired field name. Change-Id: I6859e392aa934b4327cd04489f234a6210938d0a Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20590 Tested-by: Murtadha Hubail <[email protected]> Reviewed-by: Murtadha Hubail <[email protected]> Integration-Tests: Murtadha Hubail <[email protected]> Contrib: Murtadha Hubail <[email protected]> --- M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarFieldDescriptor.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java 3 files changed, 246 insertions(+), 0 deletions(-) Approvals: Murtadha Hubail: Looks good to me, approved; Verified; No violations found; Verified diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java index f631b32..13eace7 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java @@ -235,6 +235,7 @@ public static final FunctionIdentifier ARRAY_SYMDIFFN = FunctionConstants.newAsterix("array-symdiffn", FunctionIdentifier.VARARGS); public static final FunctionIdentifier ARRAY_STAR = FunctionConstants.newAsterix("array-star", 1); + public static final FunctionIdentifier ARRAY_STAR_FIELD = FunctionConstants.newAsterix("array-star-field", 2); public static final FunctionIdentifier ARRAY_SLICE_WITHOUT_END_POSITION = FunctionConstants.newAsterix("array-slice", 2); public static final FunctionIdentifier ARRAY_SLICE_WITH_END_POSITION = @@ -2038,6 +2039,7 @@ addFunction(ARRAY_SYMDIFF, AListMultiListArgsTypeComputer.INSTANCE, true); addFunction(ARRAY_SYMDIFFN, AListMultiListArgsTypeComputer.INSTANCE, true); addFunction(ARRAY_STAR, OpenARecordTypeComputer.INSTANCE, true); + addFunction(ARRAY_STAR_FIELD, OrderedListOfAnyTypeComputer.INSTANCE, true); addFunction(ARRAY_SLICE_WITH_END_POSITION, AListTypeComputer.INSTANCE_SLICE, true); addFunction(ARRAY_SLICE_WITHOUT_END_POSITION, AListTypeComputer.INSTANCE_SLICE, true); addFunction(ARRAY_EXCEPT, ArrayExceptTypeComputer.INSTANCE, true); diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarFieldDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarFieldDescriptor.java new file mode 100755 index 0000000..3cabf4f --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarFieldDescriptor.java @@ -0,0 +1,242 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.asterix.runtime.evaluators.functions; + +import static org.apache.asterix.om.types.EnumDeserializer.ATYPETAGDESERIALIZER; + +import java.io.IOException; + +import org.apache.asterix.builders.IAsterixListBuilder; +import org.apache.asterix.builders.OrderedListBuilder; +import org.apache.asterix.common.annotations.MissingNullInOutFunction; +import org.apache.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer; +import org.apache.asterix.formats.nontagged.BinaryComparatorFactoryProvider; +import org.apache.asterix.formats.nontagged.BinaryHashFunctionFactoryProvider; +import org.apache.asterix.om.functions.BuiltinFunctions; +import org.apache.asterix.om.functions.IFunctionDescriptor; +import org.apache.asterix.om.functions.IFunctionDescriptorFactory; +import org.apache.asterix.om.functions.IFunctionTypeInferer; +import org.apache.asterix.om.pointables.base.DefaultOpenFieldType; +import org.apache.asterix.om.types.AOrderedListType; +import org.apache.asterix.om.types.ATypeTag; +import org.apache.asterix.om.types.IAType; +import org.apache.asterix.om.utils.NonTaggedFormatUtil; +import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor; +import org.apache.asterix.runtime.evaluators.common.ListAccessor; +import org.apache.asterix.runtime.functions.FunctionTypeInferers; +import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; +import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.context.IEvaluatorContext; +import org.apache.hyracks.api.dataflow.value.IBinaryComparator; +import org.apache.hyracks.api.dataflow.value.IBinaryHashFunction; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; +import org.apache.hyracks.data.std.primitive.VoidPointable; +import org.apache.hyracks.data.std.util.ArrayBackedValueStorage; +import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference; + +@MissingNullInOutFunction +public class ArrayStarFieldDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new ArrayStarFieldDescriptor(); + } + + @Override + public IFunctionTypeInferer createFunctionTypeInferer() { + return FunctionTypeInferers.SET_ARGUMENT_TYPE; + } + }; + + private IAType inputListType; + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.ARRAY_STAR_FIELD; + } + + @Override + public void setImmutableStates(Object... states) { + inputListType = (IAType) states[0]; + } + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) + throws AlgebricksException { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(final IEvaluatorContext ctx) throws HyracksDataException { + return new ArrayStarEval(args, ctx); + } + }; + } + + public class ArrayStarEval implements IScalarEvaluator { + private final IBinaryHashFunction fieldNameHashFunction = + BinaryHashFunctionFactoryProvider.UTF8STRING_POINTABLE_INSTANCE.createBinaryHashFunction(); + private final IBinaryComparator fieldNameComparator = + BinaryComparatorFactoryProvider.UTF8STRING_POINTABLE_INSTANCE.createBinaryComparator(); + private final ArrayBackedValueStorage storage; + private final IScalarEvaluator listEval; + private final IPointable tempList; + private final IPointable object; + private final IPointable castedObject; + private final ListAccessor listAccessor; + private final IAsterixListBuilder listBuilder; + private final IPointable fieldName; + private final IPointable fieldVal; + private final IScalarEvaluator fieldNameEval; + private final TypeCaster caster; + private final IAType itemType; + private final boolean openList; + private boolean addedValue; + + public ArrayStarEval(IScalarEvaluatorFactory[] args, IEvaluatorContext ctx) throws HyracksDataException { + storage = new ArrayBackedValueStorage(); + castedObject = new VoidPointable(); + object = new VoidPointable(); + tempList = new VoidPointable(); + listEval = args[0].createScalarEvaluator(ctx); + fieldNameEval = args[1].createScalarEvaluator(ctx); + caster = new TypeCaster(sourceLoc); + listAccessor = new ListAccessor(); + listBuilder = new OrderedListBuilder(); + fieldName = new VoidPointable(); + fieldVal = new VoidPointable(); + if (inputListType.getTypeTag() == ATypeTag.ARRAY) { + AOrderedListType listType = (AOrderedListType) inputListType; + if (listType.isTyped()) { + itemType = listType.getItemType(); + openList = itemType.getTypeTag() == ATypeTag.ANY; + } else { + itemType = null; + openList = true; + } + } else { + itemType = null; + openList = true; // should be ANY type; if the arg is found to be ARRAY at runtime, then it must be open + } + } + + @Override + public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException { + listEval.evaluate(tuple, tempList); + fieldNameEval.evaluate(tuple, fieldName); + if (PointableHelper.checkAndSetMissingOrNull(result, tempList, fieldName)) { + return; + } + ATypeTag listTag = ATYPETAGDESERIALIZER.deserialize(tempList.getByteArray()[tempList.getStartOffset()]); + ATypeTag fieldTag = ATYPETAGDESERIALIZER.deserialize(fieldName.getByteArray()[fieldName.getStartOffset()]); + if (listTag != ATypeTag.ARRAY || fieldTag != ATypeTag.STRING) { + PointableHelper.setNull(result); + return; + } + + addedValue = false; + storage.reset(); + listBuilder.reset(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE); + try { + listAccessor.reset(tempList.getByteArray(), tempList.getStartOffset()); + if (openList) { + processOpenList(); + } else { + processTypedList(); + } + if (!addedValue) { + PointableHelper.setMissing(result); + return; + } + + storage.reset(); + listBuilder.write(storage.getDataOutput(), true); + result.set(storage); + } catch (IOException e) { + throw HyracksDataException.create(e); + } + } + + private void processOpenList() throws IOException { + int numObjects = listAccessor.size(); + for (int objectIndex = 0; objectIndex < numObjects; objectIndex++) { + listAccessor.getOrWriteItem(objectIndex, object, storage); + processOpenObject(object); + } + } + + private void processTypedList() throws IOException { + int numObjects = listAccessor.size(); + for (int objectIndex = 0; objectIndex < numObjects; objectIndex++) { + listAccessor.getOrWriteItem(objectIndex, object, storage); + processTypedObject(object); + } + } + + private void processOpenObject(IPointable object) throws HyracksDataException { + int serRecordOffset = object.getStartOffset(); + byte[] serRecord = object.getByteArray(); + int serRecordLen = object.getLength(); + if (serRecord[serRecordOffset] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) { + listBuilder.addItem(PointableHelper.NULL_REF); + return; + } + addValue(serRecord, serRecordOffset, serRecordLen); + } + + private void processTypedObject(IPointable object) throws HyracksDataException { + int serRecordOffset = object.getStartOffset(); + byte[] serRecord = object.getByteArray(); + if (serRecord[serRecordOffset] != ATypeTag.SERIALIZED_RECORD_TYPE_TAG) { + listBuilder.addItem(PointableHelper.NULL_REF); + return; + } + try { + caster.allocateAndCast(object, itemType, castedObject, DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE); + serRecordOffset = castedObject.getStartOffset(); + serRecord = castedObject.getByteArray(); + addValue(serRecord, serRecordOffset, castedObject.getLength()); + } finally { + caster.deallocatePointables(); + } + } + + private void addValue(byte[] serRecord, int serRecordOffset, int serRecordLen) throws HyracksDataException { + byte[] serFldName = fieldName.getByteArray(); + int serFldNameOffset = fieldName.getStartOffset(); + int subFieldOffset = ARecordSerializerDeserializer.getFieldOffsetByName(serRecord, serRecordOffset, + serRecordLen, serFldName, serFldNameOffset, fieldNameHashFunction, fieldNameComparator); + if (subFieldOffset < 0) { + listBuilder.addItem(PointableHelper.NULL_REF); + return; + } + ATypeTag fieldValueTypeTag = ATYPETAGDESERIALIZER.deserialize(serRecord[subFieldOffset]); + int subFieldLength = + NonTaggedFormatUtil.getFieldValueLength(serRecord, subFieldOffset, fieldValueTypeTag, true) + 1; + fieldVal.set(serRecord, subFieldOffset, subFieldLength); + listBuilder.addItem(fieldVal); + addedValue = true; + } + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java index 166352c..0a544a8 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java @@ -364,6 +364,7 @@ import org.apache.asterix.runtime.evaluators.functions.ArraySliceWithoutEndPositionDescriptor; import org.apache.asterix.runtime.evaluators.functions.ArraySortDescriptor; import org.apache.asterix.runtime.evaluators.functions.ArrayStarDescriptor; +import org.apache.asterix.runtime.evaluators.functions.ArrayStarFieldDescriptor; import org.apache.asterix.runtime.evaluators.functions.ArraySwapDescriptor; import org.apache.asterix.runtime.evaluators.functions.ArraySymDiffDescriptor; import org.apache.asterix.runtime.evaluators.functions.ArraySymDiffnDescriptor; @@ -697,6 +698,7 @@ fc.add(ArraySymDiffDescriptor.FACTORY); fc.add(ArraySymDiffnDescriptor.FACTORY); fc.add(ArrayStarDescriptor.FACTORY); + fc.add(ArrayStarFieldDescriptor.FACTORY); fc.add(ArrayExceptDescriptor.FACTORY); fc.add(ArrayMoveDescriptor.FACTORY); fc.add(ArraySwapDescriptor.FACTORY); -- To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/20590?usp=email To unsubscribe, or for help writing mail filters, visit https://asterix-gerrit.ics.uci.edu/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: asterixdb Gerrit-Branch: phoenix Gerrit-Change-Id: I6859e392aa934b4327cd04489f234a6210938d0a Gerrit-Change-Number: 20590 Gerrit-PatchSet: 2 Gerrit-Owner: Ali Alsuliman <[email protected]> Gerrit-Reviewer: Ali Alsuliman <[email protected]> Gerrit-Reviewer: Anon. E. Moose #1000171 Gerrit-Reviewer: Murtadha Hubail <[email protected]>
