You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by GitBox <gi...@apache.org> on 2019/01/14 09:02:07 UTC

[drill] Diff for: [GitHub] arina-ielchiieva merged pull request #1599: DRILL-6903: SchemaBuilder code improvements

diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnBuilder.java
index aa5d19ab599..33a8eeb8cfa 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnBuilder.java
@@ -36,7 +36,6 @@
 import org.apache.drill.exec.physical.rowSet.impl.UnionState.UnionVectorState;
 import org.apache.drill.exec.physical.rowSet.project.ImpliedTupleRequest;
 import org.apache.drill.exec.record.MaterializedField;
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.PrimitiveColumnMetadata;
 import org.apache.drill.exec.record.metadata.ProjectionType;
@@ -76,7 +75,6 @@
  * the list metadata must contain that one type so the code knows how to build
  * the nullable array writer for that column.
  */
-
 public class ColumnBuilder {
 
   private ColumnBuilder() { }
@@ -85,16 +83,15 @@ private ColumnBuilder() { }
    * Implementation of the work to add a new column to this tuple given a
    * schema description of the column.
    *
+   * @param parent container
    * @param columnSchema schema of the column
    * @return writer for the new column
    */
-
   public static ColumnState buildColumn(ContainerState parent, ColumnMetadata columnSchema) {
 
     // Indicate projection in the metadata.
 
-    ((AbstractColumnMetadata) columnSchema).setProjected(
-        parent.projectionType(columnSchema.name()) != ProjectionType.UNPROJECTED);
+    columnSchema.setProjected(parent.projectionType(columnSchema.name()) != ProjectionType.UNPROJECTED);
 
     // Build the column
 
@@ -218,8 +215,7 @@ private static ColumnState buildSingleMap(ContainerState parent, ColumnMetadata
       vector = null;
       vectorState = new NullVectorState();
     }
-    final TupleObjectWriter mapWriter = MapWriter.buildMap(columnSchema,
-        vector, new ArrayList<AbstractObjectWriter>());
+    final TupleObjectWriter mapWriter = MapWriter.buildMap(columnSchema, vector, new ArrayList<>());
     final SingleMapState mapState = new SingleMapState(parent.loader(),
         parent.vectorCache().childCache(columnSchema.name()),
         parent.projectionSet().mapProjection(columnSchema.name()));
@@ -256,8 +252,7 @@ private static ColumnState buildMapArray(ContainerState parent, ColumnMetadata c
     // Create the writer using the offset vector
 
     final AbstractObjectWriter writer = MapWriter.buildMapArray(
-        columnSchema, mapVector,
-        new ArrayList<AbstractObjectWriter>());
+        columnSchema, mapVector, new ArrayList<>());
 
     // Wrap the offset vector in a vector state
 
@@ -293,11 +288,10 @@ private static ColumnState buildMapArray(ContainerState parent, ColumnMetadata c
    * in a join column, say.) Still, Drill supports unions, so the code here
    * does so. Unions are fully tested in the row set writer mechanism.
    *
-   * @param parent
-   * @param columnSchema
-   * @return
+   * @param parent container
+   * @param columnSchema column schema
+   * @return column
    */
-
   private static ColumnState buildUnion(ContainerState parent, ColumnMetadata columnSchema) {
     assert columnSchema.isVariant() && ! columnSchema.isArray();
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnState.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnState.java
index 24e270a4f7d..95f011a23ea 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnState.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/impl/ColumnState.java
@@ -25,7 +25,6 @@
 import org.apache.drill.exec.vector.accessor.ScalarWriter.ColumnWriterListener;
 import org.apache.drill.exec.vector.accessor.impl.HierarchicalFormatter;
 import org.apache.drill.exec.vector.accessor.writer.AbstractObjectWriter;
-import org.apache.drill.exec.vector.accessor.writer.AbstractScalarWriter;
 
 /**
  * Represents the write-time state for a column including the writer and the (optional)
@@ -39,7 +38,6 @@
  * vector, or even a non-existent vector. The {@link VectorState} class abstracts out
  * these differences.
  */
-
 public abstract class ColumnState {
 
   private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ColumnState.class);
@@ -61,7 +59,7 @@ public PrimitiveColumnState(LoaderInternals loader,
       } else {
         scalarWriter = writer.scalar();
       }
-      ((AbstractScalarWriter) scalarWriter).bindListener(this);
+      scalarWriter.bindListener(this);
     }
 
     @Override
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/BaseTupleModel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/BaseTupleModel.java
index a8e57f9ef80..9320d11a474 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/BaseTupleModel.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/BaseTupleModel.java
@@ -20,7 +20,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
 import org.apache.drill.exec.record.metadata.TupleSchema;
@@ -30,7 +29,6 @@
  * and "hyper" cases. Deals primarily with the structure of the model,
  * which is common between the two physical implementations.
  */
-
 public abstract class BaseTupleModel implements TupleModel {
 
   public static abstract class BaseColumnModel implements ColumnModel {
@@ -61,10 +59,9 @@ public BaseColumnModel(ColumnMetadata schema) {
 
   /**
    * Descriptive schema associated with the columns above. Unlike a
-   * {@link VectorContainer}, this abstraction keeps the schema in sync
+   * {@link org.apache.drill.exec.record.VectorContainer}, this abstraction keeps the schema in sync
    * with vectors as columns are added.
    */
-
   protected final TupleSchema schema;
 
   public BaseTupleModel() {
@@ -107,9 +104,8 @@ public ColumnModel column(String name) {
    *
    * @param column column implementation to add
    */
-
   protected void addBaseColumn(BaseColumnModel column) {
-    schema.add((AbstractColumnMetadata) column.schema());
+    schema.add(column.schema());
     columns.add(column);
     assert columns.size() == schema.size();
   }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/MetadataProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/MetadataProvider.java
index 5212afb0814..fea7ecd46dc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/MetadataProvider.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/MetadataProvider.java
@@ -18,7 +18,6 @@
 package org.apache.drill.exec.physical.rowSet.model;
 
 import org.apache.drill.exec.record.MaterializedField;
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.MetadataUtils;
 import org.apache.drill.exec.record.metadata.RepeatedListColumnMetadata;
@@ -38,17 +37,16 @@
   TupleMetadata tuple();
   VariantMetadata variant();
 
-  public static class VectorDescrip {
+  class VectorDescrip {
     public final MetadataProvider parent;
     public final ColumnMetadata metadata;
 
     public VectorDescrip(MetadataProvider provider, ColumnMetadata metadata) {
-      parent = provider;
+      this.parent = provider;
       this.metadata = metadata;
     }
 
-    public VectorDescrip(MetadataProvider provider, int index,
-        MaterializedField field) {
+    public VectorDescrip(MetadataProvider provider, int index, MaterializedField field) {
       this(provider, provider.metadata(index, field));
     }
 
@@ -57,7 +55,7 @@ public MetadataProvider childProvider() {
     }
   }
 
-  public static class MetadataCreator implements MetadataProvider {
+  class MetadataCreator implements MetadataProvider {
 
     private final TupleSchema tuple;
 
@@ -101,7 +99,7 @@ public VariantMetadata variant() {
     }
   }
 
-  public static class VariantSchemaCreator implements MetadataProvider {
+  class VariantSchemaCreator implements MetadataProvider {
 
     private final VariantSchema variantSchema;
 
@@ -130,7 +128,7 @@ public VariantMetadata variant() {
     }
   }
 
-  public static class ArraySchemaCreator implements MetadataProvider {
+  class ArraySchemaCreator implements MetadataProvider {
 
     private final RepeatedListColumnMetadata arraySchema;
 
@@ -142,7 +140,7 @@ public ArraySchemaCreator(RepeatedListColumnMetadata arraySchema) {
     public ColumnMetadata metadata(int index, MaterializedField field) {
       assert index == 0;
       assert arraySchema.childSchema() == null;
-      AbstractColumnMetadata childSchema = MetadataUtils.fromField(field.cloneEmpty());
+      ColumnMetadata childSchema = MetadataUtils.fromField(field.cloneEmpty());
       arraySchema.childSchema(childSchema);
       return childSchema;
     }
@@ -163,7 +161,7 @@ public VariantMetadata variant() {
     }
   }
 
-  public static class MetadataRetrieval implements MetadataProvider {
+  class MetadataRetrieval implements MetadataProvider {
 
     private final TupleMetadata tuple;
 
@@ -203,7 +201,7 @@ public VariantMetadata variant() {
     }
   }
 
-  public static class VariantSchemaRetrieval implements MetadataProvider {
+  class VariantSchemaRetrieval implements MetadataProvider {
 
     private final VariantSchema variantSchema;
 
@@ -232,7 +230,7 @@ public VariantMetadata variant() {
     }
   }
 
-  public static class ArraySchemaRetrieval implements MetadataProvider {
+  class ArraySchemaRetrieval implements MetadataProvider {
 
     private final ColumnMetadata arraySchema;
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/single/SingleSchemaInference.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/single/SingleSchemaInference.java
index ad0c8c0454b..e6467d6163d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/single/SingleSchemaInference.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/rowSet/model/single/SingleSchemaInference.java
@@ -24,7 +24,6 @@
 import org.apache.drill.common.types.TypeProtos.MinorType;
 import org.apache.drill.exec.record.MaterializedField;
 import org.apache.drill.exec.record.VectorContainer;
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.MetadataUtils;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
@@ -55,7 +54,6 @@
  * (repeated), variant (LIST, UNION) and tuple (MAP) columns, the tree grows
  * quite complex.
  */
-
 public class SingleSchemaInference {
 
   public TupleMetadata infer(VectorContainer container) {
@@ -66,7 +64,7 @@ public TupleMetadata infer(VectorContainer container) {
     return MetadataUtils.fromColumns(columns);
   }
 
-  private AbstractColumnMetadata inferVector(ValueVector vector) {
+  private ColumnMetadata inferVector(ValueVector vector) {
     final MaterializedField field = vector.getField();
     switch (field.getType().getMinorType()) {
     case MAP:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/AbstractColumnMetadata.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/AbstractColumnMetadata.java
index ab82d650ce4..595c5c49d3b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/AbstractColumnMetadata.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/AbstractColumnMetadata.java
@@ -34,7 +34,6 @@
  * since maps (and the row itself) will, by definition, differ between
  * the two views.
  */
-
 public abstract class AbstractColumnMetadata implements ColumnMetadata {
 
   // Capture the key schema information. We cannot use the MaterializedField
@@ -87,7 +86,8 @@ public AbstractColumnMetadata(AbstractColumnMetadata from) {
     expectedElementCount = from.expectedElementCount;
   }
 
-  protected void bind(TupleSchema parentTuple) { }
+  @Override
+  public void bind(TupleMetadata parentTuple) { }
 
   @Override
   public String name() { return name; }
@@ -204,6 +204,4 @@ public String toString() {
         .append("]")
         .toString();
   }
-
-  public abstract AbstractColumnMetadata copy();
 }
\ No newline at end of file
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/ColumnBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/ColumnBuilder.java
index e60ff93642c..d23eeb4c77b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/ColumnBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/ColumnBuilder.java
@@ -28,16 +28,16 @@
  * some may need a mode other than required, may need a width, may
  * need scale and precision, and so on.
  */
-
 public class ColumnBuilder {
+
   private final String name;
   private final MajorType.Builder typeBuilder;
 
   public ColumnBuilder(String name, MinorType type) {
     this.name = name;
-    typeBuilder = MajorType.newBuilder()
-        .setMinorType(type)
-        .setMode(DataMode.REQUIRED);
+    this.typeBuilder = MajorType.newBuilder()
+      .setMinorType(type)
+      .setMode(DataMode.REQUIRED);
   }
 
   public ColumnBuilder setMode(DataMode mode) {
@@ -54,9 +54,9 @@ public ColumnBuilder setPrecision(int precision) {
     return this;
   }
 
-  public ColumnBuilder setScale(int scale, int precision) {
-    typeBuilder.setScale(scale);
+  public ColumnBuilder setPrecisionAndScale(int precision, int scale) {
     typeBuilder.setPrecision(precision);
+    typeBuilder.setScale(scale);
     return this;
   }
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapBuilder.java
index 5ed455737f4..408dcc4aa10 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapBuilder.java
@@ -25,14 +25,24 @@
 /**
  * Internal structure for building a map. A map is just a schema,
  * but one that is part of a parent column.
+ * <p/>
+ * Class can be created with and without parent container.
+ * In the first case, column is added to the parent container during creation
+ * and all <tt>resumeXXX</tt> methods return qualified parent container.
+ * In the second case column is created without parent container as standalone entity.
+ * All <tt>resumeXXX</tt> methods do not produce any action and return null.
+ * To access built column {@link #buildColumn()} should be used.
  */
-
 public class MapBuilder implements SchemaContainer {
   private final SchemaContainer parent;
   private final TupleBuilder tupleBuilder = new TupleBuilder();
   private final String memberName;
   private final DataMode mode;
 
+  public MapBuilder(String memberName, DataMode mode) {
+    this(null, memberName, mode);
+  }
+
   public MapBuilder(SchemaContainer parent, String memberName, DataMode mode) {
     this.parent = parent;
     this.memberName = memberName;
@@ -40,7 +50,7 @@ public MapBuilder(SchemaContainer parent, String memberName, DataMode mode) {
   }
 
   @Override
-  public void addColumn(AbstractColumnMetadata column) {
+  public void addColumn(ColumnMetadata column) {
     tupleBuilder.addColumn(column);
   }
 
@@ -99,10 +109,9 @@ public MapBuilder addDecimal(String name, MinorType type,
    * map. Building that map, using {@link MapBuilder#resumeSchema()},
    * will return the original schema builder.
    *
-   * @param pathName the name of the map column
+   * @param name the name of the map column
    * @return a builder for the map
    */
-
   public MapBuilder addMap(String name) {
     return tupleBuilder.addMap(this, name);
   }
@@ -123,22 +132,28 @@ public RepeatedListBuilder addRepeatedList(String name) {
     return tupleBuilder.addRepeatedList(this, name);
   }
 
-  private MapColumnMetadata buildCol() {
+  public MapColumnMetadata buildColumn() {
     return new MapColumnMetadata(memberName, mode, tupleBuilder.schema());
   }
 
+  public void build() {
+    if (parent != null) {
+      parent.addColumn(buildColumn());
+    }
+  }
+
   public SchemaBuilder resumeSchema() {
-    parent.addColumn(buildCol());
+    build();
     return (SchemaBuilder) parent;
   }
 
   public MapBuilder resumeMap() {
-    parent.addColumn(buildCol());
+    build();
     return (MapBuilder) parent;
   }
 
   public RepeatedListBuilder resumeList() {
-    parent.addColumn(buildCol());
+    build();
     return (RepeatedListBuilder) parent;
   }
 
@@ -146,7 +161,7 @@ public UnionBuilder resumeUnion() {
     // TODO: Use the map schema directly rather than
     // rebuilding it as is done here.
 
-    parent.addColumn(buildCol());
+    build();
     return (UnionBuilder) parent;
   }
 }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapColumnMetadata.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapColumnMetadata.java
index 795fd7f6732..9db2e3e7eaf 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapColumnMetadata.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MapColumnMetadata.java
@@ -26,8 +26,8 @@
  * Describes a map and repeated map. Both are tuples that have a tuple
  * schema as part of the column definition.
  */
-
 public class MapColumnMetadata extends AbstractColumnMetadata {
+
   private TupleMetadata parentTuple;
   private final TupleSchema mapSchema;
 
@@ -36,20 +36,17 @@
    *
    * @param schema materialized field description of the map
    */
-
   public MapColumnMetadata(MaterializedField schema) {
     this(schema, null);
   }
 
   /**
    * Build a map column metadata by cloning the type information (but not
-   * the children) of the materialized field provided. Use the hints
-   * provided.
+   * the children) of the materialized field provided.
    *
    * @param schema the schema to use
-   * @param hints metadata hints for this column
+   * @param mapSchema parent schema
    */
-
   MapColumnMetadata(MaterializedField schema, TupleSchema mapSchema) {
     super(schema);
     if (mapSchema == null) {
@@ -76,12 +73,12 @@ public MapColumnMetadata(String name, DataMode mode,
   }
 
   @Override
-  public AbstractColumnMetadata copy() {
+  public ColumnMetadata copy() {
     return new MapColumnMetadata(this);
   }
 
   @Override
-  protected void bind(TupleSchema parentTuple) {
+  public void bind(TupleMetadata parentTuple) {
     this.parentTuple = parentTuple;
   }
 
@@ -99,8 +96,6 @@ protected void bind(TupleSchema parentTuple) {
 
   public TupleMetadata parentTuple() { return parentTuple; }
 
-  public TupleSchema mapSchemaImpl() { return mapSchema; }
-
   @Override
   public ColumnMetadata cloneEmpty() {
     return new MapColumnMetadata(name, mode, new TupleSchema());
@@ -123,4 +118,4 @@ public MaterializedField emptySchema() {
           .setMode(mode)
           .build());
   }
-}
\ No newline at end of file
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MetadataUtils.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MetadataUtils.java
index 8c8dea7b770..469c433d6ac 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MetadataUtils.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/MetadataUtils.java
@@ -44,7 +44,7 @@ public static TupleSchema fromFields(Iterable<MaterializedField> fields) {
    * @return the column metadata that wraps the field
    */
 
-  public static AbstractColumnMetadata fromField(MaterializedField field) {
+  public static ColumnMetadata fromField(MaterializedField field) {
     MinorType type = field.getType().getMinorType();
     switch (type) {
     case MAP:
@@ -79,7 +79,7 @@ public static AbstractColumnMetadata fromField(MaterializedField field) {
     }
   }
 
-  public static AbstractColumnMetadata fromView(MaterializedField field) {
+  public static ColumnMetadata fromView(MaterializedField field) {
     if (field.getType().getMinorType() == MinorType.MAP) {
       return new MapColumnMetadata(field, null);
     } else {
@@ -98,7 +98,7 @@ public static AbstractColumnMetadata fromView(MaterializedField field) {
   public static TupleSchema fromColumns(List<ColumnMetadata> columns) {
     TupleSchema tuple = new TupleSchema();
     for (ColumnMetadata column : columns) {
-      tuple.add((AbstractColumnMetadata) column);
+      tuple.add(column);
     }
     return tuple;
   }
@@ -149,11 +149,11 @@ public static VariantColumnMetadata newVariant(String name, DataMode cardinality
     }
   }
 
-  public static RepeatedListColumnMetadata newRepeatedList(String name, AbstractColumnMetadata child) {
+  public static RepeatedListColumnMetadata newRepeatedList(String name, ColumnMetadata child) {
     return new RepeatedListColumnMetadata(name, child);
   }
 
-  public static AbstractColumnMetadata newMapArray(String name, TupleMetadata schema) {
+  public static ColumnMetadata newMapArray(String name, TupleMetadata schema) {
     return new MapColumnMetadata(name, DataMode.REPEATED, (TupleSchema) schema);
   }
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/PrimitiveColumnMetadata.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/PrimitiveColumnMetadata.java
index f0c25eb2ff4..dfbd4a9ee1f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/PrimitiveColumnMetadata.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/PrimitiveColumnMetadata.java
@@ -31,7 +31,7 @@
 
 public class PrimitiveColumnMetadata extends AbstractColumnMetadata {
 
-  protected int expectedWidth;
+  private int expectedWidth;
 
   public PrimitiveColumnMetadata(MaterializedField schema) {
     super(schema);
@@ -71,7 +71,7 @@ public PrimitiveColumnMetadata(PrimitiveColumnMetadata from) {
   }
 
   @Override
-  public AbstractColumnMetadata copy() {
+  public ColumnMetadata copy() {
     return new PrimitiveColumnMetadata(this);
   }
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListBuilder.java
index 233b4c20e38..9bb6b8d5a73 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListBuilder.java
@@ -25,13 +25,23 @@
  * list as a chain of materialized fields and that is the pattern used
  * here. It would certainly be cleaner to have a single field, with the
  * number of dimensions as a property, but that is not how Drill evolved.
+ * <p/>
+ * Class can be created with and without parent container.
+ * In the first case, column is added to the parent container during creation
+ * and all <tt>resumeXXX</tt> methods return qualified parent container.
+ * In the second case column is created without parent container as standalone entity.
+ * All <tt>resumeXXX</tt> methods do not produce any action and return null.
+ * To access built column {@link #buildColumn()} should be used.
  */
-
 public class RepeatedListBuilder implements SchemaContainer {
 
   private final SchemaContainer parent;
   private final String name;
-  private AbstractColumnMetadata child;
+  private ColumnMetadata child;
+
+  public RepeatedListBuilder(String name) {
+    this(null, name);
+  }
 
   public RepeatedListBuilder(SchemaContainer parent, String name) {
     this.parent = parent;
@@ -57,12 +67,14 @@ public RepeatedListBuilder addArray(MinorType type) {
     return this;
   }
 
-  private RepeatedListColumnMetadata buildCol() {
+  public RepeatedListColumnMetadata buildColumn() {
     return MetadataUtils.newRepeatedList(name, child);
   }
 
   public void build() {
-    parent.addColumn(buildCol());
+    if (parent != null) {
+      parent.addColumn(buildColumn());
+    }
   }
 
   public RepeatedListBuilder resumeList() {
@@ -86,7 +98,7 @@ public MapBuilder resumeMap() {
   }
 
   @Override
-  public void addColumn(AbstractColumnMetadata column) {
+  public void addColumn(ColumnMetadata column) {
     assert child == null;
     child = column;
   }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListColumnMetadata.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListColumnMetadata.java
index 0f8ae763f0c..e677a0a2361 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListColumnMetadata.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/RepeatedListColumnMetadata.java
@@ -28,10 +28,9 @@
   /**
    * Indicates we don't know the number of dimensions.
    */
-
   public static final int UNKNOWN_DIMENSIONS = -1;
 
-  private AbstractColumnMetadata childSchema;
+  private ColumnMetadata childSchema;
 
   public RepeatedListColumnMetadata(MaterializedField field) {
     super(field);
@@ -44,7 +43,7 @@ public RepeatedListColumnMetadata(MaterializedField field) {
     }
   }
 
-  public RepeatedListColumnMetadata(String name, AbstractColumnMetadata childSchema) {
+  public RepeatedListColumnMetadata(String name, ColumnMetadata childSchema) {
     super(name, MinorType.LIST, DataMode.REPEATED);
     if (childSchema != null) {
       Preconditions.checkArgument(childSchema.isArray());
@@ -55,7 +54,7 @@ public RepeatedListColumnMetadata(String name, AbstractColumnMetadata childSchem
   public void childSchema(ColumnMetadata childMetadata) {
     Preconditions.checkState(childSchema == null);
     Preconditions.checkArgument(childMetadata.mode() == DataMode.REPEATED);
-    childSchema = (AbstractColumnMetadata) childMetadata;
+    childSchema = childMetadata;
   }
 
   @Override
@@ -84,7 +83,7 @@ public ColumnMetadata cloneEmpty() {
   }
 
   @Override
-  public AbstractColumnMetadata copy() {
+  public ColumnMetadata copy() {
     return new RepeatedListColumnMetadata(name, childSchema);
   }
 
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaBuilder.java
index 4d326ea1249..0c7c5243c6f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaBuilder.java
@@ -23,7 +23,6 @@
 import org.apache.drill.exec.record.BatchSchema;
 import org.apache.drill.exec.record.BatchSchema.SelectionVectorMode;
 import org.apache.drill.exec.record.MaterializedField;
-import org.apache.drill.exec.record.metadata.TupleMetadata;
 
 /**
  * Builder of a row set schema expressed as a list of materialized
@@ -106,7 +105,7 @@ public static MaterializedField columnSchema(String name, MinorType type, DataMo
   }
 
   @Override
-  public void addColumn(AbstractColumnMetadata column) {
+  public void addColumn(ColumnMetadata column) {
     tupleBuilder.addColumn(column);
   }
 
@@ -174,10 +173,9 @@ public SchemaBuilder addArray(String name, MinorType type, int dims) {
    * map. Building that map, using {@link MapBuilder#resumeSchema()},
    * will return the original schema builder.
    *
-   * @param pathName the name of the map column
+   * @param name the name of the map column
    * @return a builder for the map
    */
-
   public MapBuilder addMap(String name) {
     return tupleBuilder.addMap(this, name);
   }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaContainer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaContainer.java
index ef93d1528f4..873da4c21eb 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaContainer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/SchemaContainer.java
@@ -21,7 +21,7 @@
  * Magic that allows one schema builder to nest inside another
  * without needing to know the type of the parent.
  */
-
 interface SchemaContainer {
-  void addColumn(AbstractColumnMetadata column);
+
+  void addColumn(ColumnMetadata column);
 }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleBuilder.java
index d4f51c09039..d5ffebb8e0f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleBuilder.java
@@ -30,13 +30,12 @@
  * versions of the "add" methods return themselves to allow fluent
  * construction.
  */
+public class TupleBuilder implements SchemaContainer {
 
-class TupleBuilder implements SchemaContainer {
-
-  protected TupleSchema schema = new TupleSchema();
+  private final TupleSchema schema = new TupleSchema();
 
   @Override
-  public void addColumn(AbstractColumnMetadata column) {
+  public void addColumn(ColumnMetadata column) {
     schema.add(column);
   }
 
@@ -80,11 +79,10 @@ public void addArray(String name, MinorType type) {
     add(name, type, DataMode.REPEATED);
   }
 
-  public void addDecimal(String name, MinorType type, DataMode mode,
-      int precision, int scale) {
+  public void addDecimal(String name, MinorType type, DataMode mode, int precision, int scale) {
     MaterializedField field = new ColumnBuilder(name, type)
         .setMode(mode)
-        .setScale(scale, precision)
+        .setPrecisionAndScale(precision, scale)
         .build();
     add(field);
   }
@@ -96,9 +94,7 @@ public void addDecimal(String name, MinorType type, DataMode mode,
    * @param name column name
    * @param type base data type
    * @param dims number of dimensions, 1 or more
-   * @return this builder
    */
-
   public void addArray(String name, MinorType type, int dims) {
     assert dims >= 1;
     if (dims == 1) {
@@ -126,10 +122,10 @@ private void buildMultiDimArray(RepeatedListBuilder listBuilder,
    * map. Building that map, using {@link MapBuilder#resumeSchema()},
    * will return the original schema builder.
    *
-   * @param pathName the name of the map column
+   * @param parent schema container
+   * @param name the name of the map column
    * @return a builder for the map
    */
-
   public MapBuilder addMap(SchemaContainer parent, String name) {
     return new MapBuilder(parent, name, DataMode.REQUIRED);
   }
@@ -139,21 +135,17 @@ public MapBuilder addMapArray(SchemaContainer parent, String name) {
   }
 
   public UnionBuilder addUnion(SchemaContainer parent, String name) {
-    return new UnionBuilder(parent, name, MinorType.UNION, DataMode.OPTIONAL);
+    return new UnionBuilder(parent, name, MinorType.UNION);
   }
 
   public UnionBuilder addList(SchemaContainer parent, String name) {
-    return new UnionBuilder(parent, name, MinorType.LIST, DataMode.REPEATED);
+    return new UnionBuilder(parent, name, MinorType.LIST);
   }
 
   public RepeatedListBuilder addRepeatedList(SchemaContainer parent, String name) {
     return new RepeatedListBuilder(parent, name);
   }
 
-  void finish(AbstractColumnMetadata col) {
-    schema.add(col);
-  }
-
   public BatchSchema batchSchema(SelectionVectorMode svMode) {
     return schema.toBatchSchema(svMode);
   }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleSchema.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleSchema.java
index 0c69dbc499a..1196143a912 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleSchema.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/TupleSchema.java
@@ -20,6 +20,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.drill.exec.record.BatchSchema;
 import org.apache.drill.exec.record.MaterializedField;
@@ -45,20 +46,20 @@ public void bind(MapColumnMetadata parentMap) {
   public TupleMetadata copy() {
     TupleMetadata tuple = new TupleSchema();
     for (ColumnMetadata md : this) {
-      tuple.addColumn(((AbstractColumnMetadata) md).copy());
+      tuple.addColumn(md.copy());
     }
     return tuple;
   }
 
   @Override
   public ColumnMetadata add(MaterializedField field) {
-    AbstractColumnMetadata md = MetadataUtils.fromField(field);
+    ColumnMetadata md = MetadataUtils.fromField(field);
     add(md);
     return md;
   }
 
   public ColumnMetadata addView(MaterializedField field) {
-    AbstractColumnMetadata md = MetadataUtils.fromView(field);
+    ColumnMetadata md = MetadataUtils.fromView(field);
     add(md);
     return md;
   }
@@ -70,15 +71,14 @@ public ColumnMetadata addView(MaterializedField field) {
    * @param md the custom column metadata which must have the correct
    * index set (from {@link #size()}
    */
-
-  public void add(AbstractColumnMetadata md) {
+  public void add(ColumnMetadata md) {
     md.bind(this);
     nameSpace.add(md.name(), md);
   }
 
   @Override
   public int addColumn(ColumnMetadata column) {
-    add((AbstractColumnMetadata) column);
+    add(column);
     return size() - 1;
   }
 
@@ -145,6 +145,11 @@ public boolean isEquivalent(TupleMetadata other) {
     return cols;
   }
 
+  @Override
+  public List<ColumnMetadata> toMetadataList() {
+    return new ArrayList<>(nameSpace.entries());
+  }
+
   public BatchSchema toBatchSchema(SelectionVectorMode svMode) {
     return new BatchSchema(svMode, toFieldList());
   }
@@ -179,18 +184,16 @@ public String fullName() {
 
   @Override
   public String toString() {
-    StringBuilder buf = new StringBuilder()
+    StringBuilder builder = new StringBuilder()
         .append("[")
         .append(getClass().getSimpleName())
         .append(" ");
-    boolean first = true;
-    for (ColumnMetadata md : nameSpace) {
-      if (! first) {
-        buf.append(", ");
-      }
-      buf.append(md.toString());
-    }
-    buf.append("]");
-    return buf.toString();
+
+    builder.append(nameSpace.entries().stream()
+      .map(ColumnMetadata::toString)
+      .collect(Collectors.joining(", ")));
+
+    builder.append("]");
+    return builder.toString();
   }
 }
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/UnionBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/UnionBuilder.java
index 98e30e152a7..eee9b3ad3fc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/UnionBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/UnionBuilder.java
@@ -24,20 +24,30 @@
 /**
  * Builds unions or (non-repeated) lists (which implicitly contain
  * unions.)
+ * <p/>
+ * Class can be created with and without parent container.
+ * In the first case, column is added to the parent container during creation
+ * and all <tt>resumeXXX</tt> methods return qualified parent container.
+ * In the second case column is created without parent container as standalone entity.
+ * All <tt>resumeXXX</tt> methods do not produce any action and return null.
+ * To access built column {@link #buildColumn()} should be used.
  */
-
 public class UnionBuilder implements SchemaContainer {
+
   private final SchemaContainer parent;
   private final String name;
   private final MinorType type;
   private final VariantSchema union;
 
-  public UnionBuilder(SchemaContainer parent, String name,
-      MinorType type, DataMode mode) {
+  public UnionBuilder(String name, MinorType type) {
+    this(null, name, type);
+  }
+
+  public UnionBuilder(SchemaContainer parent, String name, MinorType type) {
     this.parent = parent;
     this.name = name;
     this.type = type;
-    union = new VariantSchema();
+    this.union = new VariantSchema();
   }
 
   private void checkType(MinorType type) {
@@ -47,7 +57,7 @@ private void checkType(MinorType type) {
   }
 
   @Override
-  public void addColumn(AbstractColumnMetadata column) {
+  public void addColumn(ColumnMetadata column) {
     assert column.name().equals(Types.typeKey(column.type()));
     union.addType(column);
   }
@@ -65,8 +75,7 @@ public MapBuilder addMap() {
 
   public UnionBuilder addList() {
     checkType(MinorType.LIST);
-    return new UnionBuilder(this, Types.typeKey(MinorType.LIST),
-        MinorType.LIST, DataMode.OPTIONAL);
+    return new UnionBuilder(this, Types.typeKey(MinorType.LIST), MinorType.LIST);
   }
 
   public RepeatedListBuilder addRepeatedList() {
@@ -74,27 +83,28 @@ public RepeatedListBuilder addRepeatedList() {
     return new RepeatedListBuilder(this, Types.typeKey(MinorType.LIST));
   }
 
-  private VariantColumnMetadata buildCol() {
+  public VariantColumnMetadata buildColumn() {
     return new VariantColumnMetadata(name, type, union);
   }
 
-  public SchemaBuilder resumeSchema() {
-    parent.addColumn(buildCol());
-    return (SchemaBuilder) parent;
+  public void build() {
+    if (parent != null) {
+      parent.addColumn(buildColumn());
+    }
   }
 
-  public UnionBuilder buildNested() {
-    parent.addColumn(buildCol());
-    return (UnionBuilder) parent;
+  public SchemaBuilder resumeSchema() {
+    build();
+    return (SchemaBuilder) parent;
   }
 
   public MapBuilder resumeMap() {
-    parent.addColumn(buildCol());
+    build();
     return (MapBuilder) parent;
   }
 
   public UnionBuilder resumeUnion() {
-    parent.addColumn(buildCol());
+    build();
     return (UnionBuilder) parent;
   }
 }
\ No newline at end of file
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantColumnMetadata.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantColumnMetadata.java
index b4171079131..c87e25b366f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantColumnMetadata.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantColumnMetadata.java
@@ -32,7 +32,7 @@ public VariantColumnMetadata(MaterializedField schema) {
     super(schema);
     variantSchema = new VariantSchema();
     variantSchema.bind(this);
-    List<MinorType> types = null;
+    List<MinorType> types;
     if (type() == MinorType.UNION) {
       types = schema.getType().getSubTypeList();
     } else {
@@ -104,7 +104,7 @@ public ColumnMetadata cloneEmpty() {
   }
 
   @Override
-  public AbstractColumnMetadata copy() {
+  public ColumnMetadata copy() {
     // TODO Auto-generated method stub
     assert false;
     return null;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantSchema.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantSchema.java
index 5c43bfc863e..179ff12e55b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantSchema.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/metadata/VariantSchema.java
@@ -38,7 +38,7 @@ protected void bind(VariantColumnMetadata parent) {
     this.parent = parent;
   }
 
-  public static AbstractColumnMetadata memberMetadata(MinorType type) {
+  public static ColumnMetadata memberMetadata(MinorType type) {
     String name = Types.typeKey(type);
     switch (type) {
     case LIST:
@@ -64,7 +64,7 @@ public static AbstractColumnMetadata memberMetadata(MinorType type) {
   @Override
   public ColumnMetadata addType(MinorType type) {
     checkType(type);
-    AbstractColumnMetadata dummyCol = memberMetadata(type);
+    ColumnMetadata dummyCol = memberMetadata(type);
     types.put(type, dummyCol);
     return dummyCol;
   }
@@ -140,7 +140,7 @@ public ColumnMetadata addType(MaterializedField field) {
     Preconditions.checkState(! isSimple);
     MinorType type = field.getType().getMinorType();
     checkType(type);
-    AbstractColumnMetadata col;
+    ColumnMetadata col;
     switch (type) {
     case LIST:
       col = new VariantColumnMetadata(field);
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/rowSet/impl/TestResultSetLoaderUnions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/rowSet/impl/TestResultSetLoaderUnions.java
index 175b818906b..09c7eb096f1 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/rowSet/impl/TestResultSetLoaderUnions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/rowSet/impl/TestResultSetLoaderUnions.java
@@ -74,7 +74,6 @@
  * Most operators do not support them. But, JSON uses them, so they must
  * be made to work in the result set loader layer.
  */
-
 public class TestResultSetLoaderUnions extends SubOperatorTest {
 
   @Test
@@ -219,7 +218,7 @@ public void testUnionOverflow() {
     // Make a bit bigger to overflow early.
 
     final int strLength = 600;
-    final byte value[] = new byte[strLength - 6];
+    final byte[] value = new byte[strLength - 6];
     Arrays.fill(value, (byte) 'X');
     final String strValue = new String(value, Charsets.UTF_8);
     int count = 0;
@@ -633,7 +632,7 @@ public void testListofListofScalar() {
         .addList("a")
           .addList()
             .addType(MinorType.INT)
-            .buildNested()
+            .resumeUnion()
           .resumeSchema()
         .buildSchema();
     final RowSet expected = new RowSetBuilder(fixture.allocator(), expectedSchema)
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/record/TestTupleSchema.java b/exec/java-exec/src/test/java/org/apache/drill/exec/record/TestTupleSchema.java
index 5e4bbe879e6..a59a6c1e425 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/record/TestTupleSchema.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/record/TestTupleSchema.java
@@ -51,7 +51,6 @@
 /**
  * Test the tuple and column metadata, including extended attributes.
  */
-
 public class TestTupleSchema extends SubOperatorTest {
 
   /**
@@ -452,7 +451,7 @@ public void testEmptyRootTuple() {
   @Test
   public void testNonEmptyRootTuple() {
 
-    TupleMetadata root = new TupleSchema();
+    TupleSchema root = new TupleSchema();
 
     MaterializedField fieldA = SchemaBuilder.columnSchema("a", MinorType.INT, DataMode.REQUIRED );
     ColumnMetadata colA = root.add(fieldA);
@@ -529,11 +528,11 @@ public void testNonEmptyRootTuple() {
 
     // A tuple is equivalent to its copy.
 
-    assertTrue(root.isEquivalent(((TupleSchema) root).copy()));
+    assertTrue(root.isEquivalent(root.copy()));
 
     // And it is equivalent to the round trip to a batch schema.
 
-    BatchSchema batchSchema = ((TupleSchema) root).toBatchSchema(SelectionVectorMode.NONE);
+    BatchSchema batchSchema = root.toBatchSchema(SelectionVectorMode.NONE);
     assertTrue(root.isEquivalent(MetadataUtils.fromFields(batchSchema)));
   }
 
@@ -549,7 +548,7 @@ public void testNonEmptyRootTuple() {
   @Test
   public void testMapTupleFromMetadata() {
 
-    TupleMetadata root = new TupleSchema();
+    TupleSchema root = new TupleSchema();
 
     MaterializedField fieldA = SchemaBuilder.columnSchema("a", MinorType.MAP, DataMode.REQUIRED);
     ColumnMetadata colA = root.add(fieldA);
@@ -606,7 +605,7 @@ public void testMapTupleFromMetadata() {
 
     // Copying should be deep.
 
-    TupleMetadata root2 = ((TupleSchema) root).copy();
+    TupleMetadata root2 = root.copy();
     assertEquals(2, root2.metadata(0).mapSchema().metadata(0).mapSchema().metadata(0).mapSchema().size());
     assert(root.isEquivalent(root2));
 
@@ -791,7 +790,7 @@ public void testNestedSchema() {
           .addList()
             .addType(MinorType.FLOAT8)
             .addType(MinorType.DECIMAL18)
-            .buildNested()
+            .resumeUnion()
           .resumeSchema()
         .buildSchema();
 
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/DummyWriterTest.java b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/DummyWriterTest.java
index 3b64c3f8165..e353e6d8645 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/DummyWriterTest.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/DummyWriterTest.java
@@ -23,7 +23,6 @@
 import java.util.List;
 
 import org.apache.drill.common.types.TypeProtos.MinorType;
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.SchemaBuilder;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
@@ -133,8 +132,8 @@ public void testDummyMap() {
 
     // Mark schema as non-projected
 
-    ((AbstractColumnMetadata) schema.metadata("m1")).setProjected(false);
-    ((AbstractColumnMetadata) schema.metadata("m2")).setProjected(false);
+    schema.metadata("m1").setProjected(false);
+    schema.metadata("m2").setProjected(false);
 
     // Create the writers
 
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestSchemaBuilder.java b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestSchemaBuilder.java
index a26ef436405..358330d2f9b 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestSchemaBuilder.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestSchemaBuilder.java
@@ -26,12 +26,14 @@
 import org.apache.drill.common.types.TypeProtos.MinorType;
 import org.apache.drill.common.types.Types;
 import org.apache.drill.exec.record.MaterializedField;
-import org.apache.drill.exec.record.metadata.AbstractColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata;
 import org.apache.drill.exec.record.metadata.ColumnMetadata.StructureType;
+import org.apache.drill.exec.record.metadata.MapBuilder;
 import org.apache.drill.exec.record.metadata.MetadataUtils;
+import org.apache.drill.exec.record.metadata.RepeatedListBuilder;
 import org.apache.drill.exec.record.metadata.SchemaBuilder;
 import org.apache.drill.exec.record.metadata.TupleMetadata;
+import org.apache.drill.exec.record.metadata.UnionBuilder;
 import org.apache.drill.exec.record.metadata.VariantMetadata;
 import org.apache.drill.test.DrillTest;
 import org.junit.Test;
@@ -41,7 +43,6 @@
  * lists and repeated lists. This test verifies that it assembles the various
  * pieces correctly for the various nesting combinations.
  */
-
 public class TestSchemaBuilder extends DrillTest {
 
   @Test
@@ -81,7 +82,7 @@ public void testRowPreBuilt() {
 
     MaterializedField aField = MaterializedField.create("a",
         Types.optional(MinorType.VARCHAR));
-    AbstractColumnMetadata bCol = MetadataUtils.newScalar("b",
+    ColumnMetadata bCol = MetadataUtils.newScalar("b",
         MinorType.INT, DataMode.REQUIRED);
 
     SchemaBuilder builder = new SchemaBuilder()
@@ -596,4 +597,82 @@ public void testRepeatedListShortcut() {
     assertEquals(MinorType.VARCHAR, child.type());
     assertEquals(DataMode.REPEATED, child.mode());
   }
+
+  @Test
+  public void testStandaloneMapBuilder() {
+    ColumnMetadata columnMetadata= new MapBuilder("m1", DataMode.OPTIONAL)
+      .addNullable("b", MinorType.BIGINT)
+      .addMap("m2")
+      .addNullable("v", MinorType.VARCHAR)
+      .resumeMap()
+      .buildColumn();
+
+    assertTrue(columnMetadata.isMap());
+    assertTrue(columnMetadata.isNullable());
+    assertEquals("m1", columnMetadata.name());
+
+    TupleMetadata schema = columnMetadata.mapSchema();
+
+    ColumnMetadata col0 = schema.metadata(0);
+    assertEquals("b", col0.name());
+    assertEquals(MinorType.BIGINT, col0.type());
+    assertTrue(col0.isNullable());
+
+    ColumnMetadata col1 = schema.metadata(1);
+    assertEquals("m2", col1.name());
+    assertTrue(col1.isMap());
+    assertFalse(col1.isNullable());
+
+    ColumnMetadata child = col1.mapSchema().metadata(0);
+    assertEquals("v", child.name());
+    assertEquals(MinorType.VARCHAR, child.type());
+    assertTrue(child.isNullable());
+  }
+
+  @Test
+  public void testStandaloneRepeatedListBuilder() {
+    ColumnMetadata columnMetadata = new RepeatedListBuilder("l")
+      .addMapArray()
+      .addNullable("v", MinorType.VARCHAR)
+      .add("i", MinorType.INT)
+      .resumeList()
+      .buildColumn();
+
+    assertTrue(columnMetadata.isArray());
+    assertEquals("l", columnMetadata.name());
+    assertEquals(MinorType.LIST, columnMetadata.type());
+
+    ColumnMetadata child = columnMetadata.childSchema();
+    assertEquals("l", child.name());
+    assertTrue(child.isArray());
+    assertTrue(child.isMap());
+
+    TupleMetadata mapSchema = child.mapSchema();
+
+    ColumnMetadata col0 = mapSchema.metadata(0);
+    assertEquals("v", col0.name());
+    assertEquals(MinorType.VARCHAR, col0.type());
+    assertTrue(col0.isNullable());
+
+    ColumnMetadata col1 = mapSchema.metadata(1);
+    assertEquals("i", col1.name());
+    assertEquals(MinorType.INT, col1.type());
+    assertFalse(col1.isNullable());
+  }
+
+  @Test
+  public void testStandaloneUnionBuilder() {
+    ColumnMetadata columnMetadata = new UnionBuilder("u", MinorType.VARCHAR)
+      .addType(MinorType.INT)
+      .addType(MinorType.VARCHAR)
+      .buildColumn();
+
+    assertEquals("u", columnMetadata.name());
+    assertTrue(columnMetadata.isVariant());
+
+    VariantMetadata variantMetadata = columnMetadata.variantSchema();
+    assertTrue(variantMetadata.hasType(MinorType.INT));
+    assertTrue(variantMetadata.hasType(MinorType.VARCHAR));
+  }
+
 }
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestVariantAccessors.java b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestVariantAccessors.java
index 10c9bd7a59b..3d017c31f34 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestVariantAccessors.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestVariantAccessors.java
@@ -67,7 +67,6 @@
  * result set builder. It does not, however, work in the Project
  * and other operators. Some assembly required for future use.)
  */
-
 public class TestVariantAccessors extends SubOperatorTest {
 
   @Test
@@ -84,7 +83,7 @@ public void testBuildRowSetUnion() {
             .resumeUnion()
           .addList()
             .addType(MinorType.VARCHAR)
-            .buildNested()
+            .resumeUnion()
           .resumeSchema()
         .buildSchema();
 
@@ -216,7 +215,7 @@ public void testScalarVariant() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.INT);
+    assertSame(vr.dataType(), MinorType.INT);
     assertSame(intReader, vr.scalar());
     assertNotNull(vr.member());
     assertSame(vr.scalar(), vr.member().scalar());
@@ -229,7 +228,7 @@ public void testScalarVariant() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.VARCHAR);
+    assertSame(vr.dataType(), MinorType.VARCHAR);
     assertSame(strReader, vr.scalar());
     assertFalse(strReader.isNull());
     assertEquals("fred", strReader.getString());
@@ -250,7 +249,7 @@ public void testScalarVariant() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.FLOAT8);
+    assertSame(vr.dataType(), MinorType.FLOAT8);
     assertSame(floatReader, vr.scalar());
     assertFalse(floatReader.isNull());
     assertEquals(123.45, vr.scalar().getDouble(), 0.001);
@@ -261,7 +260,7 @@ public void testScalarVariant() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.INT);
+    assertSame(vr.dataType(), MinorType.INT);
     assertTrue(intReader.isNull());
 
     // Int 20
@@ -321,7 +320,7 @@ public void testBuildRowSetUnionArray() {
 
           .addList()
             .addType(MinorType.FLOAT8)
-            .buildNested()
+            .resumeUnion()
           .resumeSchema()
         .buildSchema();
 
@@ -1054,7 +1053,7 @@ public void testAddTypes() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.INT);
+    assertSame(vr.dataType(), MinorType.INT);
     assertSame(vr.scalar(MinorType.INT), vr.scalar());
     assertNotNull(vr.member());
     assertSame(vr.scalar(), vr.member().scalar());
@@ -1062,7 +1061,7 @@ public void testAddTypes() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.VARCHAR);
+    assertSame(vr.dataType(), MinorType.VARCHAR);
     assertSame(vr.scalar(MinorType.VARCHAR), vr.scalar());
     assertEquals("fred", vr.scalar().getString());
 
@@ -1073,7 +1072,7 @@ public void testAddTypes() {
 
     assertTrue(reader.next());
     assertFalse(vr.isNull());
-    assertTrue(vr.dataType() == MinorType.FLOAT8);
+    assertSame(vr.dataType(), MinorType.FLOAT8);
     assertSame(vr.scalar(MinorType.FLOAT8), vr.scalar());
     assertEquals(123.45, vr.scalar().getDouble(), 0.001);
 
@@ -1093,7 +1092,7 @@ public void testUnionWithList() {
           .addType(MinorType.INT)
           .addList()
             .addType(MinorType.VARCHAR)
-            .buildNested()
+            .resumeUnion()
           .resumeSchema()
         .buildSchema();
 
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/ColumnMetadata.java b/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/ColumnMetadata.java
index f3aa877b7bf..0e0fb492043 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/ColumnMetadata.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/ColumnMetadata.java
@@ -26,7 +26,6 @@
  * Metadata description of a column including names, types and structure
  * information.
  */
-
 public interface ColumnMetadata {
 
   /**
@@ -203,4 +202,8 @@
 
   int precision();
   int scale();
+
+  void bind(TupleMetadata parentTuple);
+
+  ColumnMetadata copy();
 }
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/TupleMetadata.java b/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/TupleMetadata.java
index a65c9f2e54b..cd21fa78b99 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/TupleMetadata.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/record/metadata/TupleMetadata.java
@@ -43,13 +43,12 @@
  * In the future, this structure will also gather metadata useful
  * for vector processing such as expected widths and so on.
  */
-
 public interface TupleMetadata extends Iterable<ColumnMetadata> {
 
   /**
    * Add a new column to the schema.
    *
-   * @param columnSchema
+   * @param field materialized field
    * @return the index of the new column
    */
   ColumnMetadata add(MaterializedField field);
@@ -73,9 +72,16 @@
    * @return a list of the top-level fields. Maps contain their child
    * fields
    */
-
   List<MaterializedField> toFieldList();
 
+  /**
+   * Returns schema as list of <tt>ColumnMetadata</tt> objects
+   * which can be used to create JSON schema object.
+   *
+   * @return a list of metadata for each column
+   */
+  List<ColumnMetadata> toMetadataList();
+
   /**
    * Full name of the column. Note: this name cannot be used to look up
    * the column because of ambiguity. The name "a.b.c" may mean a single


With regards,
Apache Git Services