>From <[email protected]>:
[email protected] has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18401 )
Change subject: [NO ISSUE][COMP] Honor select-list field order
......................................................................
[NO ISSUE][COMP] Honor select-list field order
- user model changes: no
- storage format changes: no
- interface changes: no
Change-Id: Ia6e37080e581b92744ddd9090b291936513c75af
---
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/ARecordVisitablePointable.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
M
asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
5 files changed, 98 insertions(+), 13 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/01/18401/1
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
index 9d52a85..8b2acaf 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
@@ -175,15 +175,16 @@
String[] fieldNamesArray = fieldNames.toArray(new String[0]);
IAType[] fieldTypesArray = fieldTypes.toArray(new IAType[0]);
ARecordType resultType;
+ LinkedHashSet<String> resultFieldOrder =
generalizeRecordFieldOrderHint(leftType, rightType);
if (resultTypeIsOpen && knowsAdditonalFieldNames) {
resultType = new ARecordType("generalized-record-type",
fieldNamesArray, fieldTypesArray, resultTypeIsOpen,
- allPossibleAdditionalFieldNames);
- LinkedHashSet<String> resultFieldOrder =
generalizeRecordFieldOrderHint(leftType, rightType);
+ allPossibleAdditionalFieldNames, resultFieldOrder);
if (resultFieldOrder != null) {
resultType.getAnnotations().add(new
RecordFieldOrderAnnotation(resultFieldOrder));
}
} else {
- resultType = new ARecordType("generalized-record-type",
fieldNamesArray, fieldTypesArray, resultTypeIsOpen);
+ resultType = new ARecordType("generalized-record-type",
fieldNamesArray, fieldTypesArray, resultTypeIsOpen,
+ resultFieldOrder);
}
return resultType;
}
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/ARecordVisitablePointable.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/ARecordVisitablePointable.java
index 193ff7d..dea96f0 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/ARecordVisitablePointable.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/ARecordVisitablePointable.java
@@ -22,7 +22,9 @@
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import
org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
import org.apache.asterix.om.pointables.base.IVisitablePointable;
@@ -37,6 +39,7 @@
import org.apache.asterix.om.utils.RecordUtil;
import org.apache.asterix.om.utils.ResettableByteArrayOutputStream;
import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.string.UTF8StringUtil;
import org.apache.hyracks.util.string.UTF8StringWriter;
/**
@@ -70,6 +73,9 @@
private final int numberOfSchemaFields;
private final int[] fieldOffsets;
+
+ private final Map<String, Integer> openFieldLocator = new HashMap<>();
+ private final Map<String, Integer> closedFieldLocator = new HashMap<>();
private final IVisitablePointable nullReference =
PointableAllocator.allocateUnrestableEmpty();
private final IVisitablePointable missingReference =
PointableAllocator.allocateUnrestableEmpty();
@@ -113,6 +119,7 @@
int nameStart = typeBos.size();
typeDos.writeByte(ATypeTag.SERIALIZED_STRING_TYPE_TAG);
utf8Writer.writeUTF8(fieldNameStrs[i], typeDos);
+ closedFieldLocator.put(fieldNameStrs[i], i);
int nameEnd = typeBos.size();
IVisitablePointable typeNameReference =
AFlatValuePointable.FACTORY.create(null);
typeNameReference.set(typeBos.getByteArray(), nameStart,
nameEnd - nameStart);
@@ -150,6 +157,7 @@
for (int i = fieldTypeTags.size() - 1; i >= numberOfSchemaFields; i--)
{
fieldTypeTags.remove(i);
}
+ openFieldLocator.clear();
fieldValues.clear();
}
@@ -250,6 +258,9 @@
IVisitablePointable fieldName = allocator.allocateEmpty();
fieldName.set(dataBos.getByteArray(), fnstart, fnend -
fnstart);
fieldNames.add(fieldName);
+ String openFieldName = UTF8StringUtil
+ .toString(new StringBuilder(),
dataBos.getByteArray(), fnstart + 1).toString();
+ openFieldLocator.put(openFieldName, numberOfSchemaFields +
openFieldLocator.size());
fieldOffset += fieldValueLength;
// set the field type tag
@@ -273,6 +284,14 @@
}
}
+ public Integer getFieldIndex(String fieldName) {
+ int index = closedFieldLocator.getOrDefault(fieldName, -1);
+ if (index != -1) {
+ return index;
+ }
+ return openFieldLocator.getOrDefault(fieldName, -1);
+ }
+
public List<IVisitablePointable> getFieldNames() {
return fieldNames;
}
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
index 7823637..7c6ab37 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
@@ -20,6 +20,7 @@
package org.apache.asterix.om.pointables.printer;
import java.io.PrintStream;
+import java.util.LinkedHashSet;
import java.util.List;
import org.apache.asterix.om.pointables.ARecordVisitablePointable;
@@ -53,17 +54,21 @@
throws HyracksDataException {
final List<IVisitablePointable> fieldNames =
recordAccessor.getFieldNames();
final List<IVisitablePointable> fieldValues =
recordAccessor.getFieldValues();
+ final LinkedHashSet<String> orderedFields =
recordAccessor.getInputRecordType().getAllOrderedFields();
nameVisitorArg.first = ps;
itemVisitorArg.first = ps;
ps.print(startRecord);
- final int size = fieldNames.size();
boolean first = true;
- for (int i = 0; i < size; ++i) {
- final IVisitablePointable fieldName = fieldNames.get(i);
- final IVisitablePointable fieldValue = fieldValues.get(i);
+ for (String orderedFieldName : orderedFields) {
+ int index = recordAccessor.getFieldIndex(orderedFieldName);
+ if (index == -1) {
+ continue;
+ }
+ final IVisitablePointable fieldName = fieldNames.get(index);
+ final IVisitablePointable fieldValue = fieldValues.get(index);
final ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
.deserialize(fieldValue.getByteArray()[fieldValue.getStartOffset()]);
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
index 838f6f8..9daa01b 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/OpenRecordConstructorResultType.java
@@ -102,10 +102,11 @@
IAType[] fieldTypes = typesList.toArray(new IAType[0]);
ARecordType resultType;
if (isOpen && canProvideAdditionFieldInfo) {
- resultType = new ARecordType(null, fieldNames, fieldTypes, isOpen,
allPossibleAdditionalFieldNames);
+ resultType = new ARecordType(null, fieldNames, fieldTypes, isOpen,
allPossibleAdditionalFieldNames,
+ allPossibleFieldNamesOrdered);
resultType.getAnnotations().add(new
RecordFieldOrderAnnotation(allPossibleFieldNamesOrdered));
} else {
- resultType = new ARecordType(null, fieldNames, fieldTypes, isOpen);
+ resultType = new ARecordType(null, fieldNames, fieldTypes, isOpen,
allPossibleFieldNamesOrdered);
}
return resultType;
}
diff --git
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
index fd51433..eacfd2e 100644
---
a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
+++
b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
@@ -21,8 +21,10 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -54,10 +56,15 @@
private static final long serialVersionUID = 1L;
private static final JavaType SET =
OBJECT_MAPPER.getTypeFactory().constructCollectionType(Set.class, String.class);
+
+ private static final JavaType LIST =
+
OBJECT_MAPPER.getTypeFactory().constructCollectionType(LinkedHashSet.class,
String.class);
private static final String IS_OPEN = "isOpen";
private static final String FIELD_NAMES = "fieldNames";
private static final String FIELD_TYPES = "fieldTypes";
private static final String ADDITIONAL_FIELDS = "additionalFieldNames";
+
+ private static final String ORDERED_FIELDS = "orderedFields";
private final String[] fieldNames;
private final IAType[] fieldTypes;
private final Map<String, Integer> fieldNameToIndexMap = new HashMap<>();
@@ -71,6 +78,8 @@
// the bounded set of all possible additional field names.
private final Set<String> allPossibleAdditionalFieldNames;
+ private final LinkedHashSet<String> allOrderedFields;
+
/**
* @param typeName the name of the type
* @param fieldNames the names of the closed fields
@@ -78,7 +87,31 @@
* @param isOpen whether the record is open
*/
public ARecordType(String typeName, String[] fieldNames, IAType[]
fieldTypes, boolean isOpen) {
- this(typeName, fieldNames, fieldTypes, isOpen, null);
+ this(typeName, fieldNames, fieldTypes, isOpen, null, null);
+ }
+
+ /**
+ * @param typeName the name of the type
+ * @param fieldNames the names of the closed fields
+ * @param fieldTypes the types of the closed fields
+ * @param isOpen whether the record is open
+ * @param allPossibleAdditionalFieldNames, all possible additional field
names.
+ */
+ public ARecordType(String typeName, String[] fieldNames, IAType[]
fieldTypes, boolean isOpen,
+ Set<String> allPossibleAdditionalFieldNames) {
+ this(typeName, fieldNames, fieldTypes, isOpen,
allPossibleAdditionalFieldNames, null);
+ }
+
+ /**
+ * @param typeName the name of the type
+ * @param fieldNames the names of the closed fields
+ * @param fieldTypes the types of the closed fields
+ * @param isOpen whether the record is open
+ * @param allOrderedFields fields in order.
+ */
+ public ARecordType(String typeName, String[] fieldNames, IAType[]
fieldTypes, boolean isOpen,
+ LinkedHashSet<String> allOrderedFields) {
+ this(typeName, fieldNames, fieldTypes, isOpen, null, allOrderedFields);
}
/**
@@ -86,10 +119,11 @@
* @param fieldNames the names of the closed fields
* @param fieldTypes the types of the closed fields
* @param isOpen whether the record is open
- * @param allPossibleAdditionalFieldNames, all possible additional field
names.
+ * @param allPossibleAdditionalFieldNames, all possible additional field
names
+ * @param allOrderedFields fields in order.
*/
public ARecordType(String typeName, String[] fieldNames, IAType[]
fieldTypes, boolean isOpen,
- Set<String> allPossibleAdditionalFieldNames) {
+ Set<String> allPossibleAdditionalFieldNames, LinkedHashSet<String>
allOrderedFields) {
super(typeName);
this.fieldNames = fieldNames;
this.fieldTypes = fieldTypes;
@@ -100,6 +134,12 @@
fieldNameToIndexMap.put(fieldNames[index], index);
}
this.allPossibleAdditionalFieldNames = allPossibleAdditionalFieldNames;
+ if (isOpen && allOrderedFields != null) {
+ this.allOrderedFields = allOrderedFields;
+ } else {
+ this.allOrderedFields = new LinkedHashSet<>();
+ Collections.addAll(this.allOrderedFields, fieldNames);
+ }
}
public boolean canContainField(String fieldName) {
@@ -383,6 +423,7 @@
jsonObject.put(IS_OPEN, isOpen);
jsonObject.putPOJO(FIELD_NAMES, fieldNames);
jsonObject.putPOJO(ADDITIONAL_FIELDS, allPossibleAdditionalFieldNames);
+ jsonObject.putPOJO(ORDERED_FIELDS, allOrderedFields);
ArrayNode fieldTypesArray = OBJECT_MAPPER.createArrayNode();
for (int i = 0; i < fieldTypes.length; i++) {
fieldTypesArray.add(fieldTypes[i].toJson(registry));
@@ -397,12 +438,17 @@
boolean isOpen = json.get(IS_OPEN).asBoolean();
String[] fieldNames =
OBJECT_MAPPER.convertValue(json.get(FIELD_NAMES), String[].class);
Set<String> additionalFields =
OBJECT_MAPPER.convertValue(json.get(ADDITIONAL_FIELDS), SET);
+ LinkedHashSet<String> orderedFields =
OBJECT_MAPPER.convertValue(json.get(ORDERED_FIELDS), LIST);
ArrayNode fieldTypesNode = (ArrayNode) json.get(FIELD_TYPES);
IAType[] fieldTypes = new IAType[fieldTypesNode.size()];
for (int i = 0; i < fieldTypesNode.size(); i++) {
fieldTypes[i] = (IAType)
registry.deserialize(fieldTypesNode.get(i));
}
- return new ARecordType(typeName, fieldNames, fieldTypes, isOpen,
additionalFields);
+ return new ARecordType(typeName, fieldNames, fieldTypes, isOpen,
additionalFields, orderedFields);
+ }
+
+ public LinkedHashSet<String> getAllOrderedFields() {
+ return allOrderedFields;
}
public List<IAType> getFieldTypes(List<List<String>> fields) throws
AlgebricksException {
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18401
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: Ia6e37080e581b92744ddd9090b291936513c75af
Gerrit-Change-Number: 18401
Gerrit-PatchSet: 1
Gerrit-Owner: [email protected]
Gerrit-MessageType: newchange