pavibhai commented on a change in pull request #647:
URL: https://github.com/apache/orc/pull/647#discussion_r586872840



##########
File path: java/core/src/java/org/apache/orc/impl/ParserUtils.java
##########
@@ -249,75 +255,210 @@ public static TypeDescription 
findSubtype(TypeDescription schema,
     return findSubtype(schema, source, true);
   }
 
+
+  public interface TypeVisitor {
+    /**
+     * As we navigate to the column, call this on each level
+     * @param type new level we are moving to
+     * @param posn the position relative to the parent
+     */
+    void visit(TypeDescription type, int posn);
+  }
+
+  public static class TypeFinder implements TypeVisitor {
+    public TypeDescription current;
+
+    public TypeFinder(TypeDescription schema) {
+      current = schema;
+    }
+
+    @Override
+    public void visit(TypeDescription type, int posn) {
+      current = type;
+    }
+  }
+
   public static TypeDescription findSubtype(TypeDescription schema,
                                             ParserUtils.StringPosition source,
                                             boolean 
isSchemaEvolutionCaseAware) {
-    List<String> names = ParserUtils.splitName(source);
+    TypeFinder result = new TypeFinder(removeAcid(schema));
+    findColumn(result.current, source, isSchemaEvolutionCaseAware, result);
+    return result.current;
+  }
+
+  private static TypeDescription removeAcid(TypeDescription schema) {
+    return SchemaEvolution.checkAcidSchema(schema)
+        ? SchemaEvolution.getBaseRow(schema) : schema;
+  }
+
+  private static int findCaseInsensitive(List<String> list, String goal) {
+    for (int i = 0; i < list.size(); i++) {
+      if (list.get(i).equalsIgnoreCase(goal)) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  public static void findSubtype(TypeDescription schema,
+                                 int goal,
+                                 TypeVisitor visitor) {
+    TypeDescription current = schema;
+    int id = schema.getId();
+    if (goal < id || goal > schema.getMaximumId()) {
+      throw new IllegalArgumentException("Unknown type id " + id + " in " +
+          current.toJson());
+    }
+    while (id != goal) {
+      List<TypeDescription> children = current.getChildren();
+      for(int i=0; i < children.size(); ++i) {
+        TypeDescription child = children.get(i);
+        if (goal <= child.getMaximumId()) {
+          current = child;
+          visitor.visit(current, i);
+          break;
+        }
+      }
+      id = current.getId();
+    }
+  }
+
+  /**
+   * Find a column in a schema by walking down the type tree to find the right 
column.
+   * @param schema the schema to look in
+   * @param source the name of the column
+   * @param isSchemaEvolutionCaseAware should the string compare be case 
sensitive
+   * @param visitor The visitor, which is called on each level
+   */
+  public static void findColumn(TypeDescription schema,
+                                ParserUtils.StringPosition source,
+                                boolean isSchemaEvolutionCaseAware,
+                                TypeVisitor visitor) {
+    findColumn(schema, ParserUtils.splitName(source), 
isSchemaEvolutionCaseAware, visitor);
+  }
+
+  /**
+   * Find a column in a schema by walking down the type tree to find the right 
column.
+   * @param schema the schema to look in
+   * @param names the name of the column broken into a list of names per level
+   * @param isSchemaEvolutionCaseAware should the string compare be case 
sensitive
+   * @param visitor The visitor, which is called on each level
+   */
+  public static void findColumn(TypeDescription schema,
+                                List<String> names,
+                                boolean isSchemaEvolutionCaseAware,
+                                TypeVisitor visitor) {
     if (names.size() == 1 && INTEGER_PATTERN.matcher(names.get(0)).matches()) {
-      return schema.findSubtype(Integer.parseInt(names.get(0)));
+      findSubtype(schema, Integer.parseInt(names.get(0)), visitor);
+      return;
     }
-    TypeDescription current = SchemaEvolution.checkAcidSchema(schema)
-        ? SchemaEvolution.getBaseRow(schema) : schema;
+    TypeDescription current = schema;
+    int posn;
     while (names.size() > 0) {
       String first = names.remove(0);
       switch (current.getCategory()) {
         case STRUCT: {
-          int posn = -1;
-          if (isSchemaEvolutionCaseAware) {
-            posn = current.getFieldNames().indexOf(first);
-          } else {
-            // Case-insensitive search like ORC 1.5
-            for (int i = 0; i < current.getFieldNames().size(); i++) {
-              if (current.getFieldNames().get(i).equalsIgnoreCase(first)) {
-                posn = i;
-                break;
-              }
-            }
-          }
-          if (posn == -1) {
-            throw new IllegalArgumentException("Field " + first +
-                " not found in " + current.toString());
-          }
-          current = current.getChildren().get(posn);
+          posn = isSchemaEvolutionCaseAware
+              ? current.getFieldNames().indexOf(first)
+              : findCaseInsensitive(current.getFieldNames(), first);
           break;
         }
         case LIST:
           if (first.equals("_elem")) {
-            current = current.getChildren().get(0);
+            posn = 0;
           } else {
-            throw new IllegalArgumentException("Field " + first +
-                "not found in " + current.toString());
+            posn = -1;
           }
           break;
         case MAP:
           if (first.equals("_key")) {
-            current = current.getChildren().get(0);
+            posn = 0;
           } else if (first.equals("_value")) {
-            current = current.getChildren().get(1);
+            posn = 1;
           } else {
-            throw new IllegalArgumentException("Field " + first +
-                "not found in " + current.toString());
+            posn = -1;
           }
           break;
         case UNION: {
           try {
-            int posn = Integer.parseInt(first);
+            posn = Integer.parseInt(first);
             if (posn < 0 || posn >= current.getChildren().size()) {
               throw new NumberFormatException("off end of union");
             }
-            current = current.getChildren().get(posn);
           } catch (NumberFormatException e) {
             throw new IllegalArgumentException("Field " + first +
                 "not found in " + current.toString(), e);
           }
           break;
         }
         default:
-          throw new IllegalArgumentException("Field " + first +
-              "not found in " + current.toString());
+          posn = -1;
+      }
+      if (posn < 0) {
+        throw new IllegalArgumentException("Field " + first +
+                                           " not found in " + 
current.toString());
+      }
+      current = current.getChildren().get(posn);
+      visitor.visit(current, posn);
+    }
+  }
+
+  static class ColumnFinder implements TypeVisitor {
+    private ColumnVector[] top;
+    private ColumnVector current = null;
+    private final ColumnVector[] result;
+    private int resultIdx = 0;
+
+    ColumnFinder(TypeDescription schema, VectorizedRowBatch batch, 
List<String> levels) {

Review comment:
       done




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to