>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

Reply via email to