>From Ali Alsuliman <[email protected]>:
Ali Alsuliman has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18385 )
Change subject: WIP: auto generated key
......................................................................
WIP: auto generated key
Change-Id: I54cc2fe65d7a5d2534a2c5b9a2fb6de5448ddc98
---
M
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java
A
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyEvaluator.java
M asterixdb/asterix-app/src/test/resources/runtimets/only_sqlpp.xml
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceAutogenerateIDRule.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java
A
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AddAutoKeyTypeComputer.java
M
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
A
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyDescriptor.java
8 files changed, 483 insertions(+), 1 deletion(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/85/18385/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceAutogenerateIDRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceAutogenerateIDRule.java
index 1fb035f..e2b0b94 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceAutogenerateIDRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceAutogenerateIDRule.java
@@ -160,7 +160,8 @@
VariableReferenceExpression rec0 = new
VariableReferenceExpression(inputRecord);
rec0.setSourceLocation(inputRecordSourceLoc);
ILogicalExpression rec1 =
createPrimaryKeyRecordExpression(pkFieldName, insertOpSourceLoc);
- ILogicalExpression mergedRec = createRecordMergeFunction(rec0, rec1,
insertOpSourceLoc);
+ // ILogicalExpression mergedRec =
createRecordMergeFunction(rec0, pkFieldNameExpression, insertOpSourceLoc);
+ ILogicalExpression mergedRec = createAddAutoKeyFunction(rec0,
pkFieldName, insertOpSourceLoc);
ILogicalExpression nonNullMergedRec = createNotNullFunction(mergedRec);
LogicalVariable v = context.newVar();
@@ -237,4 +238,20 @@
recordMergeFn.setSourceLocation(sourceLoc);
return recordMergeFn;
}
+
+ private AbstractFunctionCallExpression
createAddAutoKeyFunction(ILogicalExpression rec0, List<String> keyName,
+ SourceLocation sourceLoc) {
+ List<Mutable<ILogicalExpression>> addAutoKeyFnArgs = new ArrayList<>();
+ addAutoKeyFnArgs.add(new MutableObject<>(rec0));
+ for (String s : keyName) {
+ ConstantExpression pkFieldNameExpression = new
ConstantExpression(new AsterixConstantValue(new AString(s)));
+ pkFieldNameExpression.setSourceLocation(sourceLoc);
+ addAutoKeyFnArgs.add(new MutableObject<>(pkFieldNameExpression));
+ }
+
+ AbstractFunctionCallExpression addAutoKeyFn = new
ScalarFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(BuiltinFunctions.ADD_AUTO_KEY),
addAutoKeyFnArgs);
+ addAutoKeyFn.setSourceLocation(sourceLoc);
+ return addAutoKeyFn;
+ }
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/only_sqlpp.xml
b/asterixdb/asterix-app/src/test/resources/runtimets/only_sqlpp.xml
index 334dd52..08f98f3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/only_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/only_sqlpp.xml
@@ -19,5 +19,10 @@
!-->
<test-suite xmlns="urn:xml.testframework.asterix.apache.org"
ResultOffsetPath="results" QueryOffsetPath="queries_sqlpp"
QueryFileExtension=".sqlpp">
<test-group name="failed">
+ <test-case FilePath="nested-index-dml">
+ <compilation-unit name="nested-uuid-insert">
+ <output-dir compare="Text">nested-uuid-insert</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
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 c65cf38..a8d3b3ba 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
@@ -65,6 +65,7 @@
import org.apache.asterix.om.typecomputer.impl.ATimeTypeComputer;
import org.apache.asterix.om.typecomputer.impl.AUUIDTypeComputer;
import org.apache.asterix.om.typecomputer.impl.AYearMonthDurationTypeComputer;
+import org.apache.asterix.om.typecomputer.impl.AddAutoKeyTypeComputer;
import org.apache.asterix.om.typecomputer.impl.AnyTypeComputer;
import org.apache.asterix.om.typecomputer.impl.ArrayExceptTypeComputer;
import org.apache.asterix.om.typecomputer.impl.ArrayIfNullTypeComputer;
@@ -245,6 +246,8 @@
public static final FunctionIdentifier RECORD_MERGE =
FunctionConstants.newAsterix("object-merge", 2);
public static final FunctionIdentifier RECORD_MERGE_IGNORE_DUPLICATES =
FunctionConstants.newAsterix("object-merge-ignore-duplicates", 2);
+ public static final FunctionIdentifier ADD_AUTO_KEY =
+ FunctionConstants.newAsterix("add-autogenerated-key",
FunctionIdentifier.VARARGS);
public static final FunctionIdentifier RECORD_CONCAT =
FunctionConstants.newAsterix("object-concat",
FunctionIdentifier.VARARGS);
public static final FunctionIdentifier RECORD_CONCAT_STRICT =
@@ -2002,6 +2005,7 @@
// objects
addFunction(RECORD_MERGE, RecordMergeTypeComputer.INSTANCE, true);
addPrivateFunction(RECORD_MERGE_IGNORE_DUPLICATES,
RecordMergeTypeComputer.INSTANCE_IGNORE_DUPLICATES, true);
+ addPrivateFunction(ADD_AUTO_KEY, AddAutoKeyTypeComputer.INSTANCE,
true);
addFunction(RECORD_CONCAT, OpenARecordTypeComputer.INSTANCE, true);
addPrivateFunction(RECORD_CONCAT_STRICT,
OpenARecordTypeComputer.INSTANCE, true);
addFunction(ADD_FIELDS, RecordAddFieldsTypeComputer.INSTANCE, true);
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AddAutoKeyTypeComputer.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AddAutoKeyTypeComputer.java
new file mode 100644
index 0000000..57a482b
--- /dev/null
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/AddAutoKeyTypeComputer.java
@@ -0,0 +1,132 @@
+/*
+ * 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.om.typecomputer.impl;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.asterix.om.exceptions.TypeMismatchException;
+import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.TypeHelper;
+import org.apache.asterix.om.utils.ConstantExpressionUtil;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+
+public class AddAutoKeyTypeComputer implements IResultTypeComputer {
+
+ public static final AddAutoKeyTypeComputer INSTANCE = new
AddAutoKeyTypeComputer();
+
+ private AddAutoKeyTypeComputer() {
+ }
+
+ @Override
+ public IAType computeType(ILogicalExpression expression,
IVariableTypeEnvironment env,
+ IMetadataProvider<?, ?> metadataProvider) throws
AlgebricksException {
+ AbstractFunctionCallExpression f = (AbstractFunctionCallExpression)
expression;
+ FunctionIdentifier funcId = f.getFunctionIdentifier();
+ List<Mutable<ILogicalExpression>> funArgs = f.getArguments();
+ IAType arg0Type = (IAType) env.getType(funArgs.get(0).getValue());
+ boolean unknownable = TypeHelper.canBeUnknown(arg0Type);
+ ARecordType inRecType = TypeComputeUtils.extractRecordType(arg0Type);
+ if (inRecType == null) {
+ throw new TypeMismatchException(f.getSourceLocation(), funcId, 0,
arg0Type.getTypeTag(), ATypeTag.OBJECT);
+ }
+
+ String[] keyName = validateGetKeyName(funArgs);
+ return computeType(inRecType, keyName, unknownable,
f.getSourceLocation());
+ }
+
+ private static String[]
validateGetKeyName(List<Mutable<ILogicalExpression>> funArgs) {
+ String[] keyName = new String[funArgs.size() - 1];
+ for (int i = 1, k = 0; i < funArgs.size(); i++, k++) {
+ keyName[k] =
ConstantExpressionUtil.getStringConstant(funArgs.get(i).getValue());
+ }
+ return keyName;
+ }
+
+ private static IAType computeType(ARecordType inRecType, String[] keyName,
boolean unknownable,
+ SourceLocation sourceLocation) throws AlgebricksException {
+
+ String[] inFieldNames = inRecType.getFieldNames();
+ String[] resultFieldNames = Arrays.copyOf(inFieldNames,
inFieldNames.length);
+
+ IAType[] resultFieldTypes = new IAType[resultFieldNames.length];
+ for (int i = 0; i < resultFieldNames.length; i++) {
+ IAType fieldType = inRecType.getFieldType(resultFieldNames[i]);
+ if (fieldType.getTypeTag() == ATypeTag.OBJECT) {
+ ARecordType nestedType = (ARecordType) fieldType;
+ // deep copy prevents altering of input types
+ resultFieldTypes[i] = nestedType.deepCopy(nestedType);
+ } else {
+ resultFieldTypes[i] = fieldType;
+ }
+ }
+
+ ARecordType recType = inRecType;
+ IAType fieldType = recType.getFieldType(keyName[0]);
+ int i = 1;
+ for (; i < keyName.length; i++) {
+ ARecordType subRec = null;
+ if (fieldType == null || (subRec = getSubRec(fieldType)) == null) {
+ break;
+ }
+ recType = subRec;
+ fieldType = subRec.getFieldType(keyName[i]);
+ }
+ boolean pkFieldMissing;
+ if (fieldType == null || i != keyName.length) {
+ // make sure the recType is "open" to allow adding the pk field
+ pkFieldMissing = true;
+ // if the recType is not open, then indicate that the record
should be cast to open
+ } else {
+ // make sure the fieldType is UUID?
+ pkFieldMissing = false;
+ }
+
+ boolean isOpen = inRecType.isOpen() || pkFieldMissing;
+ IAType resultType = new ARecordType("", resultFieldNames,
resultFieldTypes, isOpen);
+
+ if (unknownable) {
+ resultType = AUnionType.createUnknownableType(resultType);
+ }
+ return resultType;
+ }
+
+ private static ARecordType getSubRec(IAType fieldType) {
+ IAType t = fieldType;
+ if (fieldType.getTypeTag() == ATypeTag.UNION) {
+ t = ((AUnionType) fieldType).getActualType();
+ }
+ if (t.getTypeTag() == ATypeTag.OBJECT) {
+ return (ARecordType) t;
+ }
+ return null;
+ }
+}
diff --git
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyDescriptor.java
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyDescriptor.java
new file mode 100644
index 0000000..f97d1df
--- /dev/null
+++
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyDescriptor.java
@@ -0,0 +1,76 @@
+/*
+ * 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.records;
+
+import org.apache.asterix.common.annotations.MissingNullInOutFunction;
+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.typecomputer.impl.TypeComputeUtils;
+import org.apache.asterix.om.types.IAType;
+import
org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import org.apache.asterix.runtime.functions.FunctionTypeInferers;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+@MissingNullInOutFunction
+public class AddAutoKeyDescriptor extends
AbstractScalarFunctionDynamicDescriptor {
+
+ public static final IFunctionDescriptorFactory FACTORY = new
IFunctionDescriptorFactory() {
+ @Override
+ public IFunctionDescriptor createFunctionDescriptor() {
+ return new AddAutoKeyDescriptor();
+ }
+
+ @Override
+ public IFunctionTypeInferer createFunctionTypeInferer() {
+ return new FunctionTypeInferers.AddAutoKeyTypeInferer();
+ }
+ };
+
+ private static final long serialVersionUID = 1L;
+ private final IAType[] argTypes = new IAType[2];
+
+ @Override
+ public void setImmutableStates(Object... states) {
+ argTypes[0] = TypeComputeUtils.extractRecordType((IAType) states[0]);
+ argTypes[1] = TypeComputeUtils.extractRecordType((IAType) states[1]);
+ }
+
+ @Override
+ public IScalarEvaluatorFactory createEvaluatorFactory(final
IScalarEvaluatorFactory[] args) {
+ return new IScalarEvaluatorFactory() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public IScalarEvaluator createScalarEvaluator(final
IEvaluatorContext ctx) throws HyracksDataException {
+ return new AddAutoKeyEvaluator(ctx, args, argTypes, sourceLoc,
getIdentifier());
+ }
+ };
+ }
+
+ @Override
+ public FunctionIdentifier getIdentifier() {
+ return BuiltinFunctions.ADD_AUTO_KEY;
+ }
+}
diff --git
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyEvaluator.java
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyEvaluator.java
new file mode 100644
index 0000000..24b465d
--- /dev/null
+++
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/records/AddAutoKeyEvaluator.java
@@ -0,0 +1,225 @@
+/*
+ * 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.records;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.builders.RecordBuilder;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.AGeneratedUUID;
+import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.om.pointables.ARecordVisitablePointable;
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.runtime.RuntimeRecordTypeInfo;
+import org.apache.asterix.runtime.evaluators.comparisons.DeepEqualAssessor;
+import org.apache.asterix.runtime.evaluators.functions.AbstractScalarEval;
+import org.apache.asterix.runtime.evaluators.functions.PointableHelper;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
+import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
+import org.apache.hyracks.api.dataflow.value.IBinaryComparator;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.accessors.UTF8StringBinaryComparatorFactory;
+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;
+
+public class AddAutoKeyEvaluator extends AbstractScalarEval {
+
+ private final ARecordType outRecType;
+
+ private final IVisitablePointable vp0;
+
+ private final IPointable argPtr0 = new VoidPointable();
+ private final IPointable argPtr1 = new VoidPointable();
+ private final IPointable str = new VoidPointable();
+
+ private final IScalarEvaluator eval0;
+ private final IScalarEvaluator evals[];
+
+ private final List<RecordBuilder> rbStack = new ArrayList<>();
+
+ private final ArrayBackedValueStorage tabvs = new
ArrayBackedValueStorage();
+ private final IBinaryComparator stringBinaryComparator =
+
UTF8StringBinaryComparatorFactory.INSTANCE.createBinaryComparator();
+
+ private final RuntimeRecordTypeInfo runtimeRecordTypeInfo = new
RuntimeRecordTypeInfo();
+ private final DeepEqualAssessor deepEqualAssessor = new
DeepEqualAssessor();
+ private final ArrayBackedValueStorage resultStorage = new
ArrayBackedValueStorage();
+ private final DataOutput out = resultStorage.getDataOutput();
+
+ private final ArrayBackedValueStorage uuidStorage = new
ArrayBackedValueStorage();
+ private final DataOutput uuidOut = uuidStorage.getDataOutput();
+ private final AGeneratedUUID uuid = new AGeneratedUUID();
+ private final ISerializerDeserializer<AUUID> uuidSerDe =
+
SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AUUID);
+ private final ARecordType inRecType0;
+ private final PointableAllocator pa;
+ private final ARecordVisitablePointable dummy;
+
+ AddAutoKeyEvaluator(IEvaluatorContext ctx, IScalarEvaluatorFactory[] args,
IAType[] argTypes,
+ SourceLocation sourceLocation, FunctionIdentifier identifier)
throws HyracksDataException {
+ super(sourceLocation, identifier);
+ eval0 = args[0].createScalarEvaluator(ctx);
+ evals = new IScalarEvaluator[args.length - 1];
+ for (int i = 1, e = 0; i < args.length; i++, e++) {
+ evals[e] = args[i].createScalarEvaluator(ctx);
+ }
+
+ outRecType = (ARecordType) argTypes[0];
+ inRecType0 = (ARecordType) argTypes[1];
+ pa = new PointableAllocator();
+ vp0 = pa.allocateRecordValue(inRecType0);
+ dummy =
pa.allocateRecordValue(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
+ }
+
+ @Override
+ public void evaluate(IFrameTupleReference tuple, IPointable result) throws
HyracksDataException {
+ resultStorage.reset();
+ eval0.evaluate(tuple, argPtr0);
+
+ if (PointableHelper.checkAndSetMissingOrNull(result, argPtr0)) {
+ return;
+ }
+
+ vp0.set(argPtr0);
+
+ ARecordVisitablePointable rp0 = (ARecordVisitablePointable) vp0;
+
+ try {
+ mergeFields(outRecType, rp0, null, 0, tuple);
+ rbStack.get(0).write(out, true);
+ } catch (IOException e) {
+ throw HyracksDataException.create(e);
+ }
+ result.set(resultStorage);
+ }
+
+ private void mergeFields(ARecordType combinedType,
ARecordVisitablePointable leftRecord,
+ ARecordVisitablePointable rightRecord, int nestedLevel,
IFrameTupleReference tuple) throws IOException {
+ if (rbStack.size() < (nestedLevel + 1)) {
+ rbStack.add(new RecordBuilder());
+ }
+
+ rbStack.get(nestedLevel).reset(combinedType);
+ rbStack.get(nestedLevel).init();
+
+ evals[nestedLevel].evaluate(tuple, str);
+ // Add all fields from left record
+ boolean foundMatch = false;
+ 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);
+
+ if (PointableHelper.isEqual(leftName, str,
stringBinaryComparator)) {
+ foundMatch = true;
+ if (nestedLevel == evals.length - 1) {
+ if (PointableHelper.sameType(ATypeTag.OBJECT, leftType)) {
+ // throw
+ throw new IOException("last field is not supposed to
be a record");
+ }
+ if (!PointableHelper.sameType(ATypeTag.UUID, leftType)) {
+ // throw
+ throw new IOException("last field is not UUID");
+ }
+ addFieldToSubRecord(combinedType, leftName, leftValue,
null, nestedLevel, tuple);
+ } else {
+ if (!PointableHelper.sameType(ATypeTag.OBJECT, leftType)) {
+ // throw
+ throw new IOException("intermediate field is not a
record");
+ }
+ // we are merging two sub records
+ addFieldToSubRecord(combinedType, leftName, leftValue,
dummy, nestedLevel, tuple);
+ }
+ } else {
+ addFieldToSubRecord(combinedType, leftName, leftValue, null,
nestedLevel, tuple);
+ }
+ }
+ if (!foundMatch) {
+ IVisitablePointable strVisitable =
pa.allocateFieldValue(BuiltinType.ASTRING);
+ strVisitable.set(str);
+ if (nestedLevel == evals.length - 1) {
+ IVisitablePointable uuidVis =
pa.allocateFieldValue(BuiltinType.AUUID);
+ uuidStorage.reset();
+ uuid.nextUUID();
+ uuidSerDe.serialize(uuid, uuidOut);
+ uuidVis.set(uuidStorage);
+ addFieldToSubRecord(combinedType, strVisitable, uuidVis, null,
nestedLevel, tuple);
+ } else {
+ addFieldToSubRecord(combinedType, strVisitable,
+
pa.allocateRecordValue(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE), dummy,
nestedLevel,
+ tuple);
+ }
+ }
+ }
+
+ /*
+ * 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, int
nestedLevel, IFrameTupleReference tuple)
+ throws IOException {
+
+ 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, nestedLevel +
1, tuple);
+
+ 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, nestedLevel +
1, tuple);
+ tabvs.reset();
+ rbStack.get(nestedLevel + 1).write(tabvs.getDataOutput(),
true);
+ rbStack.get(nestedLevel).addField(fieldNamePointable, tabvs);
+ }
+ }
+ }
+}
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 7001c25..9ea99a6 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
@@ -535,6 +535,7 @@
import
org.apache.asterix.runtime.evaluators.functions.bitwise.BitXorDescriptor;
import
org.apache.asterix.runtime.evaluators.functions.bitwise.IsBitSetWithAllFlagDescriptor;
import
org.apache.asterix.runtime.evaluators.functions.bitwise.IsBitSetWithoutAllFlagDescriptor;
+import
org.apache.asterix.runtime.evaluators.functions.records.AddAutoKeyDescriptor;
import
org.apache.asterix.runtime.evaluators.functions.records.FieldAccessByIndexDescriptor;
import
org.apache.asterix.runtime.evaluators.functions.records.FieldAccessByNameDescriptor;
import
org.apache.asterix.runtime.evaluators.functions.records.FieldAccessNestedDescriptor;
@@ -1200,6 +1201,7 @@
fc.add(DeepEqualityDescriptor.FACTORY);
fc.add(RecordMergeDescriptor.FACTORY);
fc.add(RecordMergeIgnoreDuplicatesDescriptor.FACTORY);
+ fc.add(AddAutoKeyDescriptor.FACTORY);
fc.add(RecordAddFieldsDescriptor.FACTORY);
fc.add(RecordRemoveFieldsDescriptor.FACTORY);
fc.add(RecordLengthDescriptor.FACTORY);
diff --git
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
index 9c25f6e..067ef1a 100644
---
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
+++
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionTypeInferers.java
@@ -302,6 +302,18 @@
}
}
+ public static final class AddAutoKeyTypeInferer implements
IFunctionTypeInferer {
+ @Override
+ public void infer(ILogicalExpression expr, IFunctionDescriptor fd,
IVariableTypeEnvironment context,
+ CompilerProperties compilerProps) throws AlgebricksException {
+ AbstractFunctionCallExpression f =
(AbstractFunctionCallExpression) expr;
+ IAType outType = (IAType) context.getType(expr);
+ IAType type0 = (IAType)
context.getType(f.getArguments().get(0).getValue());
+ // check the key name
+ fd.setImmutableStates(outType, type0);
+ }
+ }
+
public static final class RecordRemoveFieldsTypeInferer implements
IFunctionTypeInferer {
@Override
public void infer(ILogicalExpression expr, IFunctionDescriptor fd,
IVariableTypeEnvironment context,
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18385
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: I54cc2fe65d7a5d2534a2c5b9a2fb6de5448ddc98
Gerrit-Change-Number: 18385
Gerrit-PatchSet: 1
Gerrit-Owner: Ali Alsuliman <[email protected]>
Gerrit-MessageType: newchange