drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jacq...@apache.org
Subject [07/45] drill git commit: DRILL-3987: (MOVE) Extract key vector, field reader, complex/field writer classes.
Date Fri, 13 Nov 2015 02:37:37 GMT
http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/ComplexReaders.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/ComplexReaders.java b/exec/vector/src/main/codegen/templates/ComplexReaders.java
new file mode 100644
index 0000000..607b71d
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/ComplexReaders.java
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.Override;
+import java.util.List;
+
+import org.apache.drill.exec.record.TransferPair;
+import org.apache.drill.exec.vector.complex.IndexHolder;
+import org.apache.drill.exec.vector.complex.writer.IntervalWriter;
+import org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter;
+
+<@pp.dropOutputFile />
+<#list vv.types as type>
+<#list type.minor as minor>
+<#list ["", "Repeated"] as mode>
+<#assign lowerName = minor.class?uncap_first />
+<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+<#assign name = mode + minor.class?cap_first />
+<#assign javaType = (minor.javaType!type.javaType) />
+<#assign friendlyType = (minor.friendlyType!minor.boxedType!type.boxedType) />
+<#assign safeType=friendlyType />
+<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
+
+<#assign hasFriendly = minor.friendlyType!"no" == "no" />
+
+<#list ["", "Nullable"] as nullMode>
+<#if (mode == "Repeated" && nullMode  == "") || mode == "" >
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${nullMode}${name}ReaderImpl.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+
+<#include "/@includes/vv_imports.ftl" />
+
+@SuppressWarnings("unused")
+public class ${nullMode}${name}ReaderImpl extends AbstractFieldReader {
+  
+  private final ${nullMode}${name}Vector vector;
+  
+  public ${nullMode}${name}ReaderImpl(${nullMode}${name}Vector vector){
+    super();
+    this.vector = vector;
+  }
+
+  public MajorType getType(){
+    return vector.getField().getType();
+  }
+
+  public MaterializedField getField(){
+    return vector.getField();
+  }
+  
+  public boolean isSet(){
+    <#if nullMode == "Nullable">
+    return !vector.getAccessor().isNull(idx());
+    <#else>
+    return true;
+    </#if>
+  }
+
+
+  
+  
+  <#if mode == "Repeated">
+
+  public void copyAsValue(${minor.class?cap_first}Writer writer){
+    Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl) writer;
+    impl.vector.copyFromSafe(idx(), impl.idx(), vector);
+  }
+  
+  public void copyAsField(String name, MapWriter writer){
+    Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl)  writer.list(name).${lowerName}();
+    impl.vector.copyFromSafe(idx(), impl.idx(), vector);
+  }
+  
+  public int size(){
+    return vector.getAccessor().getInnerValueCountAt(idx());
+  }
+  
+  public void read(int arrayIndex, ${minor.class?cap_first}Holder h){
+    vector.getAccessor().get(idx(), arrayIndex, h);
+  }
+  public void read(int arrayIndex, Nullable${minor.class?cap_first}Holder h){
+    vector.getAccessor().get(idx(), arrayIndex, h);
+  }
+  
+  public ${friendlyType} read${safeType}(int arrayIndex){
+    return vector.getAccessor().getSingleObject(idx(), arrayIndex);
+  }
+
+  
+  public List<Object> readObject(){
+    return (List<Object>) (Object) vector.getAccessor().getObject(idx());
+  }
+  
+  <#else>
+  
+  public void copyAsValue(${minor.class?cap_first}Writer writer){
+    ${nullMode}${minor.class?cap_first}WriterImpl impl = (${nullMode}${minor.class?cap_first}WriterImpl) writer;
+    impl.vector.copyFromSafe(idx(), impl.idx(), vector);
+  }
+  
+  public void copyAsField(String name, MapWriter writer){
+    ${nullMode}${minor.class?cap_first}WriterImpl impl = (${nullMode}${minor.class?cap_first}WriterImpl) writer.${lowerName}(name);
+    impl.vector.copyFromSafe(idx(), impl.idx(), vector);
+  }
+
+  <#if nullMode != "Nullable">
+  public void read(${minor.class?cap_first}Holder h){
+    vector.getAccessor().get(idx(), h);
+  }
+  </#if>
+
+  public void read(Nullable${minor.class?cap_first}Holder h){
+    vector.getAccessor().get(idx(), h);
+  }
+  
+  public ${friendlyType} read${safeType}(){
+    return vector.getAccessor().getObject(idx());
+  }
+  
+  public void copyValue(FieldWriter w){
+    
+  }
+  
+  public Object readObject(){
+    return vector.getAccessor().getObject(idx());
+  }
+
+  
+  </#if>
+}
+</#if>
+</#list>
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/reader/${name}Reader.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.reader;
+
+<#include "/@includes/vv_imports.ftl" />
+@SuppressWarnings("unused")
+public interface ${name}Reader extends BaseReader{
+  
+  <#if mode == "Repeated">
+  public int size();
+  public void read(int arrayIndex, ${minor.class?cap_first}Holder h);
+  public void read(int arrayIndex, Nullable${minor.class?cap_first}Holder h);
+  public Object readObject(int arrayIndex);
+  public ${friendlyType} read${safeType}(int arrayIndex);
+  <#else>
+  public void read(${minor.class?cap_first}Holder h);
+  public void read(Nullable${minor.class?cap_first}Holder h);
+  public Object readObject();
+  public ${friendlyType} read${safeType}();
+  </#if>  
+  public boolean isSet();
+  public void copyAsValue(${minor.class}Writer writer);
+  public void copyAsField(String name, ${minor.class}Writer writer);
+  
+}
+
+
+
+</#list>
+</#list>
+</#list>
+
+

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/ComplexWriters.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/ComplexWriters.java b/exec/vector/src/main/codegen/templates/ComplexWriters.java
new file mode 100644
index 0000000..71a7f9a
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/ComplexWriters.java
@@ -0,0 +1,159 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.Override;
+import java.util.Vector;
+
+import org.apache.drill.exec.vector.AllocationHelper;
+import org.apache.drill.exec.vector.ValueVector.Mutator;
+import org.apache.drill.exec.vector.complex.IndexHolder;
+import org.apache.drill.exec.vector.complex.reader.FieldReader;
+
+<@pp.dropOutputFile />
+<#list vv.types as type>
+<#list type.minor as minor>
+<#list ["", "Nullable", "Repeated"] as mode>
+<#assign name = mode + minor.class?cap_first />
+<#assign eName = name />
+<#assign javaType = (minor.javaType!type.javaType) />
+<#assign fields = minor.fields!type.fields />
+
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${eName}WriterImpl.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+
+<#include "/@includes/vv_imports.ftl" />
+
+/*
+ * This class is generated using FreeMarker on the ${.template_name} template.
+ */
+@SuppressWarnings("unused")
+public class ${eName}WriterImpl extends AbstractFieldWriter {
+
+  private final ${name}Vector.Mutator mutator;
+  final ${name}Vector vector;
+
+  public ${eName}WriterImpl(${name}Vector vector, AbstractFieldWriter parent) {
+    super(parent);
+    this.mutator = vector.getMutator();
+    this.vector = vector;
+  }
+
+  @Override
+  public MaterializedField getField() {
+    return vector.getField();
+  }
+
+  @Override
+  public int getValueCapacity() {
+    return vector.getValueCapacity();
+  }
+
+  @Override
+  public void allocate() {
+    vector.allocateNew();
+  }
+
+  @Override
+  public void close() {
+    vector.close();
+  }
+
+  @Override
+  public void clear() {
+    vector.clear();
+  }
+
+  @Override
+  protected int idx() {
+    return super.idx();
+  }
+
+  <#if mode == "Repeated">
+
+  public void write(${minor.class?cap_first}Holder h) {
+    mutator.addSafe(idx(), h);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+
+  public void write(Nullable${minor.class?cap_first}Holder h) {
+    mutator.addSafe(idx(), h);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+
+  <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+    mutator.addSafe(idx(), <#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+  </#if>
+
+  public void setPosition(int idx) {
+    super.setPosition(idx);
+    mutator.startNewValue(idx);
+  }
+
+
+  <#else>
+
+  public void write(${minor.class}Holder h) {
+    mutator.setSafe(idx(), h);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+
+  public void write(Nullable${minor.class}Holder h) {
+    mutator.setSafe(idx(), h);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+
+  <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+    mutator.setSafe(idx(), <#if mode == "Nullable">1, </#if><#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
+    vector.getMutator().setValueCount(idx()+1);
+  }
+
+  <#if mode == "Nullable">
+
+  public void writeNull() {
+    mutator.setNull(idx());
+    vector.getMutator().setValueCount(idx()+1);
+  }
+  </#if>
+  </#if>
+  </#if>
+}
+
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/writer/${eName}Writer.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.writer;
+
+<#include "/@includes/vv_imports.ftl" />
+@SuppressWarnings("unused")
+public interface ${eName}Writer extends BaseWriter {
+  public void write(${minor.class}Holder h);
+
+  <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+  public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>);
+  </#if>
+}
+
+</#list>
+</#list>
+</#list>

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/FixedValueVectors.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/FixedValueVectors.java b/exec/vector/src/main/codegen/templates/FixedValueVectors.java
new file mode 100644
index 0000000..d9d5fae
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/FixedValueVectors.java
@@ -0,0 +1,815 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.Override;
+
+<@pp.dropOutputFile />
+<#list vv.types as type>
+<#list type.minor as minor>
+<#assign friendlyType = (minor.friendlyType!minor.boxedType!type.boxedType) />
+
+<#if type.major == "Fixed">
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/${minor.class}Vector.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector;
+
+<#include "/@includes/vv_imports.ftl" />
+
+/**
+ * ${minor.class} implements a vector of fixed width values.  Elements in the vector are accessed
+ * by position, starting from the logical start of the vector.  Values should be pushed onto the
+ * vector sequentially, but may be randomly accessed.
+ *   The width of each element is ${type.width} byte(s)
+ *   The equivalent Java primitive is '${minor.javaType!type.javaType}'
+ *
+ * NB: this class is automatically generated from ${.template_name} and ValueVectorTypes.tdd using FreeMarker.
+ */
+public final class ${minor.class}Vector extends BaseDataValueVector implements FixedWidthVector{
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${minor.class}Vector.class);
+
+  private final FieldReader reader = new ${minor.class}ReaderImpl(${minor.class}Vector.this);
+  private final Accessor accessor = new Accessor();
+  private final Mutator mutator = new Mutator();
+
+  private int allocationSizeInBytes = INITIAL_VALUE_ALLOCATION * ${type.width};
+  private int allocationMonitor = 0;
+
+  public ${minor.class}Vector(MaterializedField field, BufferAllocator allocator) {
+    super(field, allocator);
+  }
+
+  @Override
+  public FieldReader getReader(){
+    return reader;
+  }
+
+  @Override
+  public int getBufferSizeFor(final int valueCount) {
+    if (valueCount == 0) {
+      return 0;
+    }
+    return valueCount * ${type.width};
+  }
+
+  @Override
+  public int getValueCapacity(){
+    return (int) (data.capacity() *1.0 / ${type.width});
+  }
+
+  @Override
+  public Accessor getAccessor(){
+    return accessor;
+  }
+
+  @Override
+  public Mutator getMutator(){
+    return mutator;
+  }
+
+  @Override
+  public void setInitialCapacity(final int valueCount) {
+    final long size = 1L * valueCount * ${type.width};
+    if (size > MAX_ALLOCATION_SIZE) {
+      throw new OversizedAllocationException("Requested amount of memory is more than max allowed allocation size");
+    }
+    allocationSizeInBytes = (int)size;
+  }
+
+  @Override
+  public void allocateNew() {
+    if(!allocateNewSafe()){
+      throw new OutOfMemoryRuntimeException("Failure while allocating buffer.");
+    }
+  }
+
+  @Override
+  public boolean allocateNewSafe() {
+    long curAllocationSize = allocationSizeInBytes;
+    if (allocationMonitor > 10) {
+      curAllocationSize = Math.max(8, curAllocationSize / 2);
+      allocationMonitor = 0;
+    } else if (allocationMonitor < -2) {
+      curAllocationSize = allocationSizeInBytes * 2L;
+      allocationMonitor = 0;
+    }
+
+    try{
+      allocateBytes(curAllocationSize);
+    } catch (DrillRuntimeException ex) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Allocate a new buffer that supports setting at least the provided number of values. May actually be sized bigger
+   * depending on underlying buffer rounding size. Must be called prior to using the ValueVector.
+   *
+   * Note that the maximum number of values a vector can allocate is Integer.MAX_VALUE / value width.
+   *
+   * @param valueCount
+   * @throws org.apache.drill.exec.memory.OutOfMemoryRuntimeException if it can't allocate the new buffer
+   */
+  @Override
+  public void allocateNew(final int valueCount) {
+    allocateBytes(valueCount * ${type.width});
+  }
+
+  @Override
+  public void reset() {
+    allocationSizeInBytes = INITIAL_VALUE_ALLOCATION;
+    allocationMonitor = 0;
+    zeroVector();
+    super.reset();
+    }
+
+  private void allocateBytes(final long size) {
+    if (size > MAX_ALLOCATION_SIZE) {
+      throw new OversizedAllocationException("Requested amount of memory is more than max allowed allocation size");
+    }
+
+    final int curSize = (int)size;
+    clear();
+    data = allocator.buffer(curSize);
+    data.readerIndex(0);
+    allocationSizeInBytes = curSize;
+  }
+
+/**
+ * Allocate new buffer with double capacity, and copy data into the new buffer. Replace vector's buffer with new buffer, and release old one
+ *
+ * @throws org.apache.drill.exec.memory.OutOfMemoryRuntimeException if it can't allocate the new buffer
+ */
+  public void reAlloc() {
+    final long newAllocationSize = allocationSizeInBytes * 2L;
+    if (newAllocationSize > MAX_ALLOCATION_SIZE)  {
+      throw new OversizedAllocationException("Unable to expand the buffer. Max allowed buffer size is reached.");
+    }
+
+    logger.debug("Reallocating vector [{}]. # of bytes: [{}] -> [{}]", field, allocationSizeInBytes, newAllocationSize);
+    final DrillBuf newBuf = allocator.buffer((int)newAllocationSize);
+    newBuf.setBytes(0, data, 0, data.capacity());
+    final int halfNewCapacity = newBuf.capacity() / 2;
+    newBuf.setZero(halfNewCapacity, halfNewCapacity);
+    newBuf.writerIndex(data.writerIndex());
+    data.release(1);
+    data = newBuf;
+    allocationSizeInBytes = (int)newAllocationSize;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void zeroVector() {
+    data.setZero(0, data.capacity());
+  }
+
+  @Override
+  public void load(SerializedField metadata, DrillBuf buffer) {
+    Preconditions.checkArgument(this.field.matches(metadata), "The field %s doesn't match the provided metadata %s.", this.field, metadata);
+    final int actualLength = metadata.getBufferLength();
+    final int valueCount = metadata.getValueCount();
+    final int expectedLength = valueCount * ${type.width};
+    assert actualLength == expectedLength : String.format("Expected to load %d bytes but actually loaded %d bytes", expectedLength, actualLength);
+
+    clear();
+    if (data != null) {
+      data.release(1);
+    }
+    data = buffer.slice(0, actualLength);
+    data.retain(1);
+    data.writerIndex(actualLength);
+    }
+
+  public TransferPair getTransferPair(){
+    return new TransferImpl(getField());
+  }
+
+  @Override
+  public TransferPair getTransferPair(FieldReference ref){
+    return new TransferImpl(getField().withPath(ref));
+  }
+
+  @Override
+  public TransferPair makeTransferPair(ValueVector to) {
+    return new TransferImpl((${minor.class}Vector) to);
+  }
+
+  public void transferTo(${minor.class}Vector target){
+    target.clear();
+    target.data = data;
+    target.data.retain(1);
+    target.data.writerIndex(data.writerIndex());
+    clear();
+  }
+
+  public void splitAndTransferTo(int startIndex, int length, ${minor.class}Vector target) {
+    final int startPoint = startIndex * ${type.width};
+    final int sliceLength = length * ${type.width};
+    target.clear();
+    target.data = data.slice(startPoint, sliceLength);
+    target.data.retain(1);
+    target.data.writerIndex(sliceLength);
+  }
+
+  private class TransferImpl implements TransferPair{
+    private ${minor.class}Vector to;
+
+    public TransferImpl(MaterializedField field){
+      to = new ${minor.class}Vector(field, allocator);
+    }
+
+    public TransferImpl(${minor.class}Vector to) {
+      this.to = to;
+    }
+
+    @Override
+    public ${minor.class}Vector getTo(){
+      return to;
+    }
+
+    @Override
+    public void transfer(){
+      transferTo(to);
+    }
+
+    @Override
+    public void splitAndTransfer(int startIndex, int length) {
+      splitAndTransferTo(startIndex, length, to);
+    }
+
+    @Override
+    public void copyValueSafe(int fromIndex, int toIndex) {
+      to.copyFromSafe(fromIndex, toIndex, ${minor.class}Vector.this);
+    }
+  }
+
+  public void copyFrom(int fromIndex, int thisIndex, ${minor.class}Vector from){
+    <#if (type.width > 8)>
+    from.data.getBytes(fromIndex * ${type.width}, data, thisIndex * ${type.width}, ${type.width});
+    <#else> <#-- type.width <= 8 -->
+    data.set${(minor.javaType!type.javaType)?cap_first}(thisIndex * ${type.width},
+        from.data.get${(minor.javaType!type.javaType)?cap_first}(fromIndex * ${type.width})
+    );
+    </#if> <#-- type.width -->
+  }
+
+  public void copyFromSafe(int fromIndex, int thisIndex, ${minor.class}Vector from){
+    while(thisIndex >= getValueCapacity()) {
+        reAlloc();
+    }
+    copyFrom(fromIndex, thisIndex, from);
+  }
+
+  public void decrementAllocationMonitor() {
+    if (allocationMonitor > 0) {
+      allocationMonitor = 0;
+    }
+    --allocationMonitor;
+  }
+
+  private void incrementAllocationMonitor() {
+    ++allocationMonitor;
+  }
+
+  public final class Accessor extends BaseDataValueVector.BaseAccessor {
+    @Override
+    public int getValueCount() {
+      return data.writerIndex() / ${type.width};
+    }
+
+    @Override
+    public boolean isNull(int index){
+      return false;
+    }
+
+    <#if (type.width > 8)>
+
+    public ${minor.javaType!type.javaType} get(int index) {
+      return data.slice(index * ${type.width}, ${type.width});
+    }
+
+    <#if (minor.class == "Interval")>
+    public void get(int index, ${minor.class}Holder holder){
+
+      final int offsetIndex = index * ${type.width};
+      holder.months = data.getInt(offsetIndex);
+      holder.days = data.getInt(offsetIndex + ${minor.daysOffset});
+      holder.milliseconds = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+    }
+
+    public void get(int index, Nullable${minor.class}Holder holder){
+      final int offsetIndex = index * ${type.width};
+      holder.isSet = 1;
+      holder.months = data.getInt(offsetIndex);
+      holder.days = data.getInt(offsetIndex + ${minor.daysOffset});
+      holder.milliseconds = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+    }
+
+    @Override
+    public ${friendlyType} getObject(int index) {
+      final int offsetIndex = index * ${type.width};
+      final int months  = data.getInt(offsetIndex);
+      final int days    = data.getInt(offsetIndex + ${minor.daysOffset});
+      final int millis = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+      final Period p = new Period();
+      return p.plusMonths(months).plusDays(days).plusMillis(millis);
+    }
+
+    public StringBuilder getAsStringBuilder(int index) {
+
+      final int offsetIndex = index * ${type.width};
+
+      int months  = data.getInt(offsetIndex);
+      final int days    = data.getInt(offsetIndex + ${minor.daysOffset});
+      int millis = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+
+      final int years  = (months / org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+      months = (months % org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+
+      final int hours  = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis);
+      millis     = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis);
+
+      final int minutes = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis);
+      millis      = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis);
+
+      final long seconds = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis);
+      millis      = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis);
+
+      final String yearString = (Math.abs(years) == 1) ? " year " : " years ";
+      final String monthString = (Math.abs(months) == 1) ? " month " : " months ";
+      final String dayString = (Math.abs(days) == 1) ? " day " : " days ";
+
+
+      return(new StringBuilder().
+             append(years).append(yearString).
+             append(months).append(monthString).
+             append(days).append(dayString).
+             append(hours).append(":").
+             append(minutes).append(":").
+             append(seconds).append(".").
+             append(millis));
+    }
+
+    <#elseif (minor.class == "IntervalDay")>
+    public void get(int index, ${minor.class}Holder holder){
+
+      final int offsetIndex = index * ${type.width};
+      holder.days = data.getInt(offsetIndex);
+      holder.milliseconds = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+    }
+
+    public void get(int index, Nullable${minor.class}Holder holder){
+      final int offsetIndex = index * ${type.width};
+      holder.isSet = 1;
+      holder.days = data.getInt(offsetIndex);
+      holder.milliseconds = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+    }
+
+    @Override
+    public ${friendlyType} getObject(int index) {
+      final int offsetIndex = index * ${type.width};
+      final int millis = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+      final int  days   = data.getInt(offsetIndex);
+      final Period p = new Period();
+      return p.plusDays(days).plusMillis(millis);
+    }
+
+
+    public StringBuilder getAsStringBuilder(int index) {
+      final int offsetIndex = index * ${type.width};
+
+      int millis = data.getInt(offsetIndex + ${minor.millisecondsOffset});
+      final int  days   = data.getInt(offsetIndex);
+
+      final int hours  = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis);
+      millis     = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.hoursToMillis);
+
+      final int minutes = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis);
+      millis      = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.minutesToMillis);
+
+      final int seconds = millis / (org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis);
+      millis      = millis % (org.apache.drill.exec.expr.fn.impl.DateUtility.secondsToMillis);
+
+      final String dayString = (Math.abs(days) == 1) ? " day " : " days ";
+
+      return(new StringBuilder().
+              append(days).append(dayString).
+              append(hours).append(":").
+              append(minutes).append(":").
+              append(seconds).append(".").
+              append(millis));
+    }
+
+    <#elseif (minor.class == "Decimal28Sparse") || (minor.class == "Decimal38Sparse") || (minor.class == "Decimal28Dense") || (minor.class == "Decimal38Dense")>
+
+    public void get(int index, ${minor.class}Holder holder) {
+        holder.start = index * ${type.width};
+        holder.buffer = data;
+        holder.scale = getField().getScale();
+        holder.precision = getField().getPrecision();
+    }
+
+    public void get(int index, Nullable${minor.class}Holder holder) {
+        holder.isSet = 1;
+        holder.start = index * ${type.width};
+        holder.buffer = data;
+        holder.scale = getField().getScale();
+        holder.precision = getField().getPrecision();
+    }
+
+      @Override
+      public ${friendlyType} getObject(int index) {
+      <#if (minor.class == "Decimal28Sparse") || (minor.class == "Decimal38Sparse")>
+      // Get the BigDecimal object
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(data, index * ${type.width}, ${minor.nDecimalDigits}, getField().getScale());
+      <#else>
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDense(data, index * ${type.width}, ${minor.nDecimalDigits}, getField().getScale(), ${minor.maxPrecisionDigits}, ${type.width});
+      </#if>
+    }
+
+    <#else>
+    public void get(int index, ${minor.class}Holder holder){
+      holder.buffer = data;
+      holder.start = index * ${type.width};
+    }
+
+    public void get(int index, Nullable${minor.class}Holder holder){
+      holder.isSet = 1;
+      holder.buffer = data;
+      holder.start = index * ${type.width};
+    }
+
+    @Override
+    public ${friendlyType} getObject(int index) {
+      return data.slice(index * ${type.width}, ${type.width})
+    }
+
+    </#if>
+    <#else> <#-- type.width <= 8 -->
+
+    public ${minor.javaType!type.javaType} get(int index) {
+      return data.get${(minor.javaType!type.javaType)?cap_first}(index * ${type.width});
+    }
+
+    <#if type.width == 4>
+    public long getTwoAsLong(int index) {
+      return data.getLong(index * ${type.width});
+    }
+
+    </#if>
+
+    <#if minor.class == "Date">
+    @Override
+    public ${friendlyType} getObject(int index) {
+        org.joda.time.DateTime date = new org.joda.time.DateTime(get(index), org.joda.time.DateTimeZone.UTC);
+        date = date.withZoneRetainFields(org.joda.time.DateTimeZone.getDefault());
+        return date;
+    }
+
+    <#elseif minor.class == "TimeStamp">
+    @Override
+    public ${friendlyType} getObject(int index) {
+        org.joda.time.DateTime date = new org.joda.time.DateTime(get(index), org.joda.time.DateTimeZone.UTC);
+        date = date.withZoneRetainFields(org.joda.time.DateTimeZone.getDefault());
+        return date;
+    }
+
+    <#elseif minor.class == "IntervalYear">
+    @Override
+    public ${friendlyType} getObject(int index) {
+
+      final int value = get(index);
+
+      final int years  = (value / org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+      final int months = (value % org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+      final Period p = new Period();
+      return p.plusYears(years).plusMonths(months);
+    }
+
+    public StringBuilder getAsStringBuilder(int index) {
+
+      int months  = data.getInt(index);
+
+      final int years  = (months / org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+      months = (months % org.apache.drill.exec.expr.fn.impl.DateUtility.yearsToMonths);
+
+      final String yearString = (Math.abs(years) == 1) ? " year " : " years ";
+      final String monthString = (Math.abs(months) == 1) ? " month " : " months ";
+
+      return(new StringBuilder().
+             append(years).append(yearString).
+             append(months).append(monthString));
+    }
+
+    <#elseif minor.class == "Time">
+    @Override
+    public DateTime getObject(int index) {
+
+        org.joda.time.DateTime time = new org.joda.time.DateTime(get(index), org.joda.time.DateTimeZone.UTC);
+        time = time.withZoneRetainFields(org.joda.time.DateTimeZone.getDefault());
+        return time;
+    }
+
+    <#elseif minor.class == "Decimal9" || minor.class == "Decimal18">
+    @Override
+    public ${friendlyType} getObject(int index) {
+
+        final BigInteger value = BigInteger.valueOf(((${type.boxedType})get(index)).${type.javaType}Value());
+        return new BigDecimal(value, getField().getScale());
+    }
+
+    <#else>
+    @Override
+    public ${friendlyType} getObject(int index) {
+      return get(index);
+    }
+    public ${minor.javaType!type.javaType} getPrimitiveObject(int index) {
+      return get(index);
+    }
+    </#if>
+
+    public void get(int index, ${minor.class}Holder holder){
+      <#if minor.class.startsWith("Decimal")>
+      holder.scale = getField().getScale();
+      holder.precision = getField().getPrecision();
+      </#if>
+
+      holder.value = data.get${(minor.javaType!type.javaType)?cap_first}(index * ${type.width});
+    }
+
+    public void get(int index, Nullable${minor.class}Holder holder){
+      holder.isSet = 1;
+      holder.value = data.get${(minor.javaType!type.javaType)?cap_first}(index * ${type.width});
+    }
+
+
+   </#if> <#-- type.width -->
+ }
+
+ /**
+  * ${minor.class}.Mutator implements a mutable vector of fixed width values.  Elements in the
+  * vector are accessed by position from the logical start of the vector.  Values should be pushed
+  * onto the vector sequentially, but may be randomly accessed.
+  *   The width of each element is ${type.width} byte(s)
+  *   The equivalent Java primitive is '${minor.javaType!type.javaType}'
+  *
+  * NB: this class is automatically generated from ValueVectorTypes.tdd using FreeMarker.
+  */
+  public final class Mutator extends BaseDataValueVector.BaseMutator {
+
+    private Mutator(){};
+   /**
+    * Set the element at the given index to the given value.  Note that widths smaller than
+    * 32 bits are handled by the DrillBuf interface.
+    *
+    * @param index   position of the bit to set
+    * @param value   value to set
+    */
+  <#if (type.width > 8)>
+   public void set(int index, <#if (type.width > 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
+     data.setBytes(index * ${type.width}, value, 0, ${type.width});
+   }
+
+   public void setSafe(int index, <#if (type.width > 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     data.setBytes(index * ${type.width}, value, 0, ${type.width});
+   }
+
+  <#if (minor.class == "Interval")>
+   public void set(int index, int months, int days, int milliseconds){
+     final int offsetIndex = index * ${type.width};
+     data.setInt(offsetIndex, months);
+     data.setInt((offsetIndex + ${minor.daysOffset}), days);
+     data.setInt((offsetIndex + ${minor.millisecondsOffset}), milliseconds);
+   }
+
+   protected void set(int index, ${minor.class}Holder holder){
+     set(index, holder.months, holder.days, holder.milliseconds);
+   }
+
+   protected void set(int index, Nullable${minor.class}Holder holder){
+     set(index, holder.months, holder.days, holder.milliseconds);
+   }
+
+   public void setSafe(int index, int months, int days, int milliseconds){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, months, days, milliseconds);
+   }
+
+   public void setSafe(int index, Nullable${minor.class}Holder holder){
+     setSafe(index, holder.months, holder.days, holder.milliseconds);
+   }
+
+   public void setSafe(int index, ${minor.class}Holder holder){
+     setSafe(index, holder.months, holder.days, holder.milliseconds);
+   }
+
+   <#elseif (minor.class == "IntervalDay")>
+   public void set(int index, int days, int milliseconds){
+     final int offsetIndex = index * ${type.width};
+     data.setInt(offsetIndex, days);
+     data.setInt((offsetIndex + ${minor.millisecondsOffset}), milliseconds);
+   }
+
+   protected void set(int index, ${minor.class}Holder holder){
+     set(index, holder.days, holder.milliseconds);
+   }
+   protected void set(int index, Nullable${minor.class}Holder holder){
+     set(index, holder.days, holder.milliseconds);
+   }
+
+   public void setSafe(int index, int days, int milliseconds){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, days, milliseconds);
+   }
+
+   public void setSafe(int index, ${minor.class}Holder holder){
+     setSafe(index, holder.days, holder.milliseconds);
+   }
+
+   public void setSafe(int index, Nullable${minor.class}Holder holder){
+     setSafe(index, holder.days, holder.milliseconds);
+   }
+
+   <#elseif (minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse") || (minor.class == "Decimal28Dense") || (minor.class == "Decimal38Dense")>
+
+   public void set(int index, ${minor.class}Holder holder){
+     set(index, holder.start, holder.buffer);
+   }
+
+   void set(int index, Nullable${minor.class}Holder holder){
+     set(index, holder.start, holder.buffer);
+   }
+
+   public void setSafe(int index,  Nullable${minor.class}Holder holder){
+     setSafe(index, holder.start, holder.buffer);
+   }
+   public void setSafe(int index,  ${minor.class}Holder holder){
+     setSafe(index, holder.start, holder.buffer);
+   }
+
+   public void setSafe(int index, int start, DrillBuf buffer){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, start, buffer);
+   }
+
+   public void set(int index, int start, DrillBuf buffer){
+     data.setBytes(index * ${type.width}, buffer, start, ${type.width});
+   }
+
+   <#else>
+
+   protected void set(int index, ${minor.class}Holder holder){
+     set(index, holder.start, holder.buffer);
+   }
+
+   public void set(int index, Nullable${minor.class}Holder holder){
+     set(index, holder.start, holder.buffer);
+   }
+
+   public void set(int index, int start, DrillBuf buffer){
+     data.setBytes(index * ${type.width}, buffer, start, ${type.width});
+   }
+
+   public void setSafe(int index, ${minor.class}Holder holder){
+     setSafe(index, holder.start, holder.buffer);
+   }
+   public void setSafe(int index, Nullable${minor.class}Holder holder){
+     setSafe(index, holder.start, holder.buffer);
+   }
+
+   public void setSafe(int index, int start, DrillBuf buffer){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, holder);
+   }
+
+   public void set(int index, Nullable${minor.class}Holder holder){
+     data.setBytes(index * ${type.width}, holder.buffer, holder.start, ${type.width});
+   }
+   </#if>
+
+   @Override
+   public void generateTestData(int count) {
+     setValueCount(count);
+     boolean even = true;
+     final int valueCount = getAccessor().getValueCount();
+     for(int i = 0; i < valueCount; i++, even = !even) {
+       final byte b = even ? Byte.MIN_VALUE : Byte.MAX_VALUE;
+       for(int w = 0; w < ${type.width}; w++){
+         data.setByte(i + w, b);
+       }
+     }
+   }
+
+   <#else> <#-- type.width <= 8 -->
+   public void set(int index, <#if (type.width >= 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
+     data.set${(minor.javaType!type.javaType)?cap_first}(index * ${type.width}, value);
+   }
+
+   public void setSafe(int index, <#if (type.width >= 4)>${minor.javaType!type.javaType}<#else>int</#if> value) {
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, value);
+   }
+
+   protected void set(int index, ${minor.class}Holder holder){
+     data.set${(minor.javaType!type.javaType)?cap_first}(index * ${type.width}, holder.value);
+   }
+
+   public void setSafe(int index, ${minor.class}Holder holder){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, holder);
+   }
+
+   protected void set(int index, Nullable${minor.class}Holder holder){
+     data.set${(minor.javaType!type.javaType)?cap_first}(index * ${type.width}, holder.value);
+   }
+
+   public void setSafe(int index, Nullable${minor.class}Holder holder){
+     while(index >= getValueCapacity()) {
+       reAlloc();
+     }
+     set(index, holder);
+   }
+
+   @Override
+   public void generateTestData(int size) {
+     setValueCount(size);
+     boolean even = true;
+     final int valueCount = getAccessor().getValueCount();
+     for(int i = 0; i < valueCount; i++, even = !even) {
+       if(even){
+         set(i, ${minor.boxedType!type.boxedType}.MIN_VALUE);
+       }else{
+         set(i, ${minor.boxedType!type.boxedType}.MAX_VALUE);
+       }
+     }
+   }
+
+   public void generateTestDataAlt(int size) {
+     setValueCount(size);
+     boolean even = true;
+     final int valueCount = getAccessor().getValueCount();
+     for(int i = 0; i < valueCount; i++, even = !even) {
+       if(even){
+         set(i, (${(minor.javaType!type.javaType)}) 1);
+       }else{
+         set(i, (${(minor.javaType!type.javaType)}) 0);
+       }
+     }
+   }
+
+  </#if> <#-- type.width -->
+
+   @Override
+   public void setValueCount(int valueCount) {
+     final int currentValueCapacity = getValueCapacity();
+     final int idx = (${type.width} * valueCount);
+     while(valueCount > getValueCapacity()) {
+       reAlloc();
+     }
+     if (valueCount > 0 && currentValueCapacity > valueCount * 2) {
+       incrementAllocationMonitor();
+     } else if (allocationMonitor > 0) {
+       allocationMonitor = 0;
+     }
+     VectorTrimmer.trim(data, idx);
+     data.writerIndex(valueCount * ${type.width});
+   }
+ }
+}
+
+</#if> <#-- type.major -->
+</#list>
+</#list>

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/HolderReaderImpl.java b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
new file mode 100644
index 0000000..d0f5c4a
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
@@ -0,0 +1,292 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+<@pp.dropOutputFile />
+<#list vv.types as type>
+<#list type.minor as minor>
+<#list ["", "Nullable", "Repeated"] as holderMode>
+<#assign nullMode = holderMode />
+<#if holderMode == "Repeated"><#assign nullMode = "Nullable" /></#if>
+
+<#assign lowerName = minor.class?uncap_first />
+<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+<#assign name = minor.class?cap_first />
+<#assign javaType = (minor.javaType!type.javaType) />
+<#assign friendlyType = (minor.friendlyType!minor.boxedType!type.boxedType) />
+<#assign safeType=friendlyType />
+<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
+<#assign fields = minor.fields!type.fields />
+
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${holderMode}${name}HolderReaderImpl.java" />
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+
+<#include "/@includes/vv_imports.ftl" />
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.drill.exec.expr.holders.*;
+import org.apache.hadoop.io.Text;
+import org.joda.time.Period;
+
+// Source code generated using FreeMarker template ${.template_name}
+
+@SuppressWarnings("unused")
+public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
+
+  private ${nullMode}${name}Holder holder;
+<#if holderMode == "Repeated" >
+  private int index = -1;
+  private ${holderMode}${name}Holder repeatedHolder;
+</#if>
+
+  public ${holderMode}${name}HolderReaderImpl(${holderMode}${name}Holder holder) {
+<#if holderMode == "Repeated" >
+    this.holder = new ${nullMode}${name}Holder();
+    this.repeatedHolder = holder;
+<#else>
+    this.holder = holder;
+</#if>
+  }
+
+  @Override
+  public int size() {
+<#if holderMode == "Repeated">
+    return repeatedHolder.end - repeatedHolder.start;
+<#else>
+    throw new UnsupportedOperationException("You can't call size on a Holder value reader.");
+</#if>
+  }
+
+  @Override
+  public boolean next() {
+<#if holderMode == "Repeated">
+    if(index + 1 < repeatedHolder.end) {
+      index++;
+      repeatedHolder.vector.getAccessor().get(repeatedHolder.start + index, holder);
+      return true;
+    } else {
+      return false;
+    }
+<#else>
+    throw new UnsupportedOperationException("You can't call next on a single value reader.");
+</#if>
+
+  }
+
+  @Override
+  public void setPosition(int index) {
+    throw new UnsupportedOperationException("You can't call next on a single value reader.");
+  }
+
+  @Override
+  public MajorType getType() {
+<#if holderMode == "Repeated">
+    return this.repeatedHolder.TYPE;
+<#else>
+    return this.holder.TYPE;
+</#if>
+  }
+
+  @Override
+  public boolean isSet() {
+    <#if holderMode == "Repeated">
+    return this.repeatedHolder.end!=this.repeatedHolder.start;
+    <#elseif nullMode == "Nullable">
+    return this.holder.isSet == 1;
+    <#else>
+    return true;
+    </#if>
+    
+  }
+
+<#if holderMode != "Repeated">
+@Override
+  public void read(${name}Holder h) {
+  <#list fields as field>
+    h.${field.name} = holder.${field.name};
+  </#list>
+  }
+
+  @Override
+  public void read(Nullable${name}Holder h) {
+  <#list fields as field>
+    h.${field.name} = holder.${field.name};
+  </#list>
+    h.isSet = isSet() ? 1 : 0;
+  }
+</#if>
+
+<#if holderMode == "Repeated">
+  @Override
+  public ${friendlyType} read${safeType}(int index){
+    repeatedHolder.vector.getAccessor().get(repeatedHolder.start + index, holder);
+    ${friendlyType} value = read${safeType}();
+    if (this.index > -1) {
+      repeatedHolder.vector.getAccessor().get(repeatedHolder.start + this.index, holder);
+    }
+    return value;
+  }
+</#if>
+
+  @Override
+  public ${friendlyType} read${safeType}(){
+<#if nullMode == "Nullable">
+    if (!isSet()) {
+      return null;
+    }
+</#if>
+
+<#if type.major == "VarLen">
+
+      int length = holder.end - holder.start;
+      byte[] value = new byte [length];
+      holder.buffer.getBytes(holder.start, value, 0, length);
+
+<#if minor.class == "VarBinary">
+      return value;
+<#elseif minor.class == "Var16Char">
+      return new String(value);
+<#elseif minor.class == "VarChar">
+      Text text = new Text();
+      text.set(value);
+      return text;
+</#if>
+
+<#elseif minor.class == "Interval">
+      Period p = new Period();
+      return p.plusMonths(holder.months).plusDays(holder.days).plusMillis(holder.milliseconds);
+
+<#elseif minor.class == "IntervalDay">
+      Period p = new Period();
+      return p.plusDays(holder.days).plusMillis(holder.milliseconds);
+
+<#elseif minor.class == "Decimal9" ||
+         minor.class == "Decimal18" >
+      BigInteger value = BigInteger.valueOf(holder.value);
+      return new BigDecimal(value, holder.scale);
+
+<#elseif minor.class == "Decimal28Dense" ||
+         minor.class == "Decimal38Dense">
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDense(holder.buffer,
+                                                                                holder.start,
+                                                                                holder.nDecimalDigits,
+                                                                                holder.scale,
+                                                                                holder.maxPrecision,
+                                                                                holder.WIDTH);
+
+<#elseif minor.class == "Decimal28Sparse" ||
+         minor.class == "Decimal38Sparse">
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(holder.buffer,
+                                                                                 holder.start,
+                                                                                 holder.nDecimalDigits,
+                                                                                 holder.scale);
+
+<#elseif minor.class == "Bit" >
+      return new Boolean(holder.value != 0);
+<#else>
+      ${friendlyType} value = new ${friendlyType}(this.holder.value);
+      return value;
+</#if>
+
+  }
+
+  @Override
+  public Object readObject() {
+<#if holderMode == "Repeated" >
+    List<Object> valList = Lists.newArrayList();
+    for (int i = repeatedHolder.start; i < repeatedHolder.end; i++) {
+      valList.add(repeatedHolder.vector.getAccessor().getObject(i));
+    }
+    return valList;
+<#else>
+    return readSingleObject();
+</#if>
+  }
+
+  private Object readSingleObject() {
+<#if nullMode == "Nullable">
+    if (!isSet()) {
+      return null;
+    }
+</#if>
+
+<#if type.major == "VarLen">
+      int length = holder.end - holder.start;
+      byte[] value = new byte [length];
+      holder.buffer.getBytes(holder.start, value, 0, length);
+
+<#if minor.class == "VarBinary">
+      return value;
+<#elseif minor.class == "Var16Char">
+      return new String(value);
+<#elseif minor.class == "VarChar">
+      Text text = new Text();
+      text.set(value);
+      return text;
+</#if>
+
+<#elseif minor.class == "Interval">
+      Period p = new Period();
+      return p.plusMonths(holder.months).plusDays(holder.days).plusMillis(holder.milliseconds);
+
+<#elseif minor.class == "IntervalDay">
+      Period p = new Period();
+      return p.plusDays(holder.days).plusMillis(holder.milliseconds);
+
+<#elseif minor.class == "Decimal9" ||
+         minor.class == "Decimal18" >
+      BigInteger value = BigInteger.valueOf(holder.value);
+      return new BigDecimal(value, holder.scale);
+
+<#elseif minor.class == "Decimal28Dense" ||
+         minor.class == "Decimal38Dense">
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDense(holder.buffer,
+                                                                                holder.start,
+                                                                                holder.nDecimalDigits,
+                                                                                holder.scale,
+                                                                                holder.maxPrecision,
+                                                                                holder.WIDTH);
+
+<#elseif minor.class == "Decimal28Sparse" ||
+         minor.class == "Decimal38Sparse">
+      return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(holder.buffer,
+                                                                                 holder.start,
+                                                                                 holder.nDecimalDigits,
+                                                                                 holder.scale);
+
+<#elseif minor.class == "Bit" >
+      return new Boolean(holder.value != 0);
+<#else>
+      ${friendlyType} value = new ${friendlyType}(this.holder.value);
+      return value;
+</#if>
+  }
+
+<#if holderMode != "Repeated" && nullMode != "Nullable">
+  public void copyAsValue(${minor.class?cap_first}Writer writer){
+    writer.write(holder);
+  }
+</#if>
+}
+
+</#list>
+</#list>
+</#list>

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/ListWriters.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/ListWriters.java b/exec/vector/src/main/codegen/templates/ListWriters.java
new file mode 100644
index 0000000..16d41ec
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/ListWriters.java
@@ -0,0 +1,234 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+<@pp.dropOutputFile />
+
+<#list ["Single", "Repeated"] as mode>
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${mode}ListWriter.java" />
+
+
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+<#if mode == "Single">
+  <#assign containerClass = "AbstractContainerVector" />
+  <#assign index = "idx()">
+<#else>
+  <#assign containerClass = "RepeatedListVector" />
+  <#assign index = "currentChildIndex">
+</#if>
+
+
+<#include "/@includes/vv_imports.ftl" />
+
+/*
+ * This class is generated using FreeMarker and the ${.template_name} template.
+ */
+@SuppressWarnings("unused")
+public class ${mode}ListWriter extends AbstractFieldWriter {
+  private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${mode}ListWriter.class);
+
+  static enum Mode { INIT, IN_MAP, IN_LIST <#list vv.types as type><#list type.minor as minor>, IN_${minor.class?upper_case}</#list></#list> }
+
+  private final String name;
+  protected final ${containerClass} container;
+  private Mode mode = Mode.INIT;
+  private FieldWriter writer;
+  protected RepeatedValueVector innerVector;
+
+  <#if mode == "Repeated">private int currentChildIndex = 0;</#if>
+  public ${mode}ListWriter(String name, ${containerClass} container, FieldWriter parent){
+    super(parent);
+    this.name = name;
+    this.container = container;
+  }
+
+  public ${mode}ListWriter(${containerClass} container, FieldWriter parent){
+    super(parent);
+    this.name = null;
+    this.container = container;
+  }
+
+  @Override
+  public void allocate() {
+    if(writer != null) {
+      writer.allocate();
+    }
+
+    <#if mode == "Repeated">
+    container.allocateNew();
+    </#if>
+  }
+
+  @Override
+  public void clear() {
+    if (writer != null) {
+      writer.clear();
+    }
+  }
+
+  @Override
+  public void close() {
+    clear();
+    container.close();
+    if (innerVector != null) {
+      innerVector.close();
+    }
+  }
+
+  @Override
+  public int getValueCapacity() {
+    return innerVector == null ? 0 : innerVector.getValueCapacity();
+  }
+
+  public void setValueCount(int count){
+    if(innerVector != null) innerVector.getMutator().setValueCount(count);
+  }
+
+  @Override
+  public MapWriter map() {
+    switch(mode) {
+    case INIT:
+      int vectorCount = container.size();
+      final RepeatedMapVector vector = container.addOrGet(name, RepeatedMapVector.TYPE, RepeatedMapVector.class);
+      innerVector = vector;
+      writer = new RepeatedMapWriter(vector, this);
+      if(vectorCount != container.size()) {
+        writer.allocate();
+      }
+      writer.setPosition(${index});
+      mode = Mode.IN_MAP;
+      return writer;
+    case IN_MAP:
+      return writer;
+    }
+
+  throw UserException.unsupportedError().message(getUnsupportedErrorMsg("MAP", mode.name())).build(logger);
+
+  }
+
+  @Override
+  public ListWriter list() {
+    switch(mode) {
+    case INIT:
+      final int vectorCount = container.size();
+      final RepeatedListVector vector = container.addOrGet(name, RepeatedListVector.TYPE, RepeatedListVector.class);
+      innerVector = vector;
+      writer = new RepeatedListWriter(null, vector, this);
+      if(vectorCount != container.size()) {
+        writer.allocate();
+      }
+      writer.setPosition(${index});
+      mode = Mode.IN_LIST;
+      return writer;
+    case IN_LIST:
+      return writer;
+    }
+
+  throw UserException.unsupportedError().message(getUnsupportedErrorMsg("LIST", mode.name())).build(logger);
+
+  }
+
+  <#list vv.types as type><#list type.minor as minor>
+  <#assign lowerName = minor.class?uncap_first />
+  <#assign upperName = minor.class?upper_case />
+  <#assign capName = minor.class?cap_first />
+  <#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+
+  private static final MajorType ${upperName}_TYPE = Types.repeated(MinorType.${upperName});
+
+  @Override
+  public ${capName}Writer ${lowerName}() {
+    switch(mode) {
+    case INIT:
+      final int vectorCount = container.size();
+      final Repeated${capName}Vector vector = container.addOrGet(name, ${upperName}_TYPE, Repeated${capName}Vector.class);
+      innerVector = vector;
+      writer = new Repeated${capName}WriterImpl(vector, this);
+      if(vectorCount != container.size()) {
+        writer.allocate();
+      }
+      writer.setPosition(${index});
+      mode = Mode.IN_${upperName};
+      return writer;
+    case IN_${upperName}:
+      return writer;
+    }
+
+  throw UserException.unsupportedError().message(getUnsupportedErrorMsg("${upperName}", mode.name())).build(logger);
+
+  }
+  </#list></#list>
+
+  public MaterializedField getField() {
+    return container.getField();
+  }
+
+  <#if mode == "Repeated">
+
+  public void startList() {
+    final RepeatedListVector list = (RepeatedListVector) container;
+    final RepeatedListVector.RepeatedMutator mutator = list.getMutator();
+
+    // make sure that the current vector can support the end position of this list.
+    if(container.getValueCapacity() <= idx()) {
+      mutator.setValueCount(idx()+1);
+    }
+
+    // update the repeated vector to state that there is current+1 objects.
+    final RepeatedListHolder h = new RepeatedListHolder();
+    list.getAccessor().get(idx(), h);
+    if (h.start >= h.end) {
+      mutator.startNewValue(idx());
+    }
+    currentChildIndex = container.getMutator().add(idx());
+    if(writer != null) {
+      writer.setPosition(currentChildIndex);
+    }
+  }
+
+  public void endList() {
+    // noop, we initialize state at start rather than end.
+  }
+  <#else>
+
+  public void setPosition(int index) {
+    super.setPosition(index);
+    if(writer != null) {
+      writer.setPosition(index);
+    }
+  }
+
+  public void startList() {
+    // noop
+  }
+
+  public void endList() {
+    // noop
+  }
+  </#if>
+
+  private String getUnsupportedErrorMsg(String expected, String found) {
+    final String f = found.substring(3);
+    return String.format("In a list of type %s, encountered a value of type %s. "+
+      "Drill does not support lists of different types.",
+       f, expected
+    );
+  }
+}
+</#list>

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/MapWriters.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/MapWriters.java b/exec/vector/src/main/codegen/templates/MapWriters.java
new file mode 100644
index 0000000..93f2edb
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/MapWriters.java
@@ -0,0 +1,241 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+<@pp.dropOutputFile />
+<#list ["Single", "Repeated"] as mode>
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/${mode}MapWriter.java" />
+<#if mode == "Single">
+<#assign containerClass = "MapVector" />
+<#assign index = "idx()">
+<#else>
+<#assign containerClass = "RepeatedMapVector" />
+<#assign index = "currentChildIndex">
+</#if>
+
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+
+<#include "/@includes/vv_imports.ftl" />
+import java.util.Map;
+
+import org.apache.drill.common.types.TypeProtos.DataMode;
+import org.apache.drill.exec.expr.holders.RepeatedMapHolder;
+import org.apache.drill.exec.vector.AllocationHelper;
+import org.apache.drill.exec.vector.complex.reader.FieldReader;
+import org.apache.drill.exec.vector.complex.writer.FieldWriter;
+
+import com.google.common.collect.Maps;
+
+/*
+ * This class is generated using FreeMarker and the ${.template_name} template.
+ */
+@SuppressWarnings("unused")
+public class ${mode}MapWriter extends AbstractFieldWriter {
+
+  protected final ${containerClass} container;
+  private final Map<String, FieldWriter> fields = Maps.newHashMap();
+  <#if mode == "Repeated">private int currentChildIndex = 0;</#if>
+
+  private final boolean unionEnabled;
+
+  public ${mode}MapWriter(${containerClass} container, FieldWriter parent, boolean unionEnabled) {
+    super(parent);
+    this.container = container;
+    this.unionEnabled = unionEnabled;
+  }
+
+  public ${mode}MapWriter(${containerClass} container, FieldWriter parent) {
+    this(container, parent, false);
+  }
+
+  @Override
+  public int getValueCapacity() {
+    return container.getValueCapacity();
+  }
+
+  @Override
+  public boolean isEmptyMap() {
+    return 0 == container.size();
+  }
+
+  @Override
+  public MaterializedField getField() {
+      return container.getField();
+  }
+
+  @Override
+  public MapWriter map(String name) {
+      FieldWriter writer = fields.get(name.toLowerCase());
+    if(writer == null){
+      int vectorCount=container.size();
+        MapVector vector = container.addOrGet(name, MapVector.TYPE, MapVector.class);
+      if(!unionEnabled){
+        writer = new SingleMapWriter(vector, this);
+      } else {
+        writer = new PromotableWriter(vector, container);
+      }
+      if(vectorCount != container.size()) {
+        writer.allocate();
+      }
+      writer.setPosition(${index});
+      fields.put(name.toLowerCase(), writer);
+    }
+    return writer;
+  }
+
+  @Override
+  public void close() throws Exception {
+    clear();
+    container.close();
+  }
+
+  @Override
+  public void allocate() {
+    container.allocateNew();
+    for(final FieldWriter w : fields.values()) {
+      w.allocate();
+    }
+  }
+
+  @Override
+  public void clear() {
+    container.clear();
+    for(final FieldWriter w : fields.values()) {
+      w.clear();
+    }
+  }
+
+  @Override
+  public ListWriter list(String name) {
+    FieldWriter writer = fields.get(name.toLowerCase());
+    int vectorCount = container.size();
+    if(writer == null) {
+      if (!unionEnabled){
+        writer = new SingleListWriter(name,container,this);
+      } else{
+        writer = new PromotableWriter(container.addOrGet(name, Types.optional(MinorType.LIST), ListVector.class), container);
+      }
+      if (container.size() > vectorCount) {
+        writer.allocate();
+      }
+      writer.setPosition(${index});
+      fields.put(name.toLowerCase(), writer);
+    }
+    return writer;
+  }
+
+  <#if mode == "Repeated">
+  public void start() {
+      // update the repeated vector to state that there is current+1 objects.
+    final RepeatedMapHolder h = new RepeatedMapHolder();
+    final RepeatedMapVector map = (RepeatedMapVector) container;
+    final RepeatedMapVector.Mutator mutator = map.getMutator();
+
+    // Make sure that the current vector can support the end position of this list.
+    if(container.getValueCapacity() <= idx()) {
+      mutator.setValueCount(idx()+1);
+    }
+
+    map.getAccessor().get(idx(), h);
+    if (h.start >= h.end) {
+      container.getMutator().startNewValue(idx());
+    }
+    currentChildIndex = container.getMutator().add(idx());
+    for(final FieldWriter w : fields.values()) {
+      w.setPosition(currentChildIndex);
+    }
+  }
+
+
+  public void end() {
+    // noop
+  }
+  <#else>
+
+  public void setValueCount(int count) {
+    container.getMutator().setValueCount(count);
+  }
+
+  @Override
+  public void setPosition(int index) {
+    super.setPosition(index);
+    for(final FieldWriter w: fields.values()) {
+      w.setPosition(index);
+    }
+  }
+
+  @Override
+  public void start() {
+  }
+
+  @Override
+  public void end() {
+  }
+
+  </#if>
+
+  <#list vv.types as type><#list type.minor as minor>
+  <#assign lowerName = minor.class?uncap_first />
+  <#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+  <#assign upperName = minor.class?upper_case />
+  <#assign capName = minor.class?cap_first />
+  <#assign vectName = capName />
+  <#assign vectName = "Nullable${capName}" />
+
+  <#if minor.class?starts_with("Decimal") >
+  public ${minor.class}Writer ${lowerName}(String name) {
+    // returns existing writer
+    final FieldWriter writer = fields.get(name.toLowerCase());
+    assert writer != null;
+    return writer;
+  }
+
+  public ${minor.class}Writer ${lowerName}(String name, int scale, int precision) {
+    final MajorType ${upperName}_TYPE = Types.withScaleAndPrecision(MinorType.${upperName}, DataMode.OPTIONAL, scale, precision);
+  <#else>
+  private static final MajorType ${upperName}_TYPE = Types.optional(MinorType.${upperName});
+  @Override
+  public ${minor.class}Writer ${lowerName}(String name) {
+  </#if>
+    FieldWriter writer = fields.get(name.toLowerCase());
+    if(writer == null) {
+      ValueVector vector;
+      ValueVector currentVector = container.getChild(name);
+      if (unionEnabled){
+        ${vectName}Vector v = container.addOrGet(name, ${upperName}_TYPE, ${vectName}Vector.class);
+        writer = new PromotableWriter(v, container);
+        vector = v;
+      } else {
+        ${vectName}Vector v = container.addOrGet(name, ${upperName}_TYPE, ${vectName}Vector.class);
+        writer = new ${vectName}WriterImpl(v, this);
+        vector = v;
+      }
+      if (currentVector == null || currentVector != vector) {
+        vector.allocateNewSafe();
+      } 
+      writer.setPosition(${index});
+      fields.put(name.toLowerCase(), writer);
+    }
+    return writer;
+  }
+
+  </#list></#list>
+
+}
+</#list>

http://git-wip-us.apache.org/repos/asf/drill/blob/9969d8bd/exec/vector/src/main/codegen/templates/NullReader.java
----------------------------------------------------------------------
diff --git a/exec/vector/src/main/codegen/templates/NullReader.java b/exec/vector/src/main/codegen/templates/NullReader.java
new file mode 100644
index 0000000..62aa33e
--- /dev/null
+++ b/exec/vector/src/main/codegen/templates/NullReader.java
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+<@pp.dropOutputFile />
+<@pp.changeOutputFile name="/org/apache/drill/exec/vector/complex/impl/NullReader.java" />
+
+
+<#include "/@includes/license.ftl" />
+
+package org.apache.drill.exec.vector.complex.impl;
+
+<#include "/@includes/vv_imports.ftl" />
+
+import org.apache.drill.common.types.TypeProtos;
+
+
+@SuppressWarnings("unused")
+public class NullReader extends AbstractBaseReader implements FieldReader{
+  
+  public static final NullReader INSTANCE = new NullReader();
+  public static final NullReader EMPTY_LIST_INSTANCE = new NullReader(Types.repeated(TypeProtos.MinorType.NULL));
+  public static final NullReader EMPTY_MAP_INSTANCE = new NullReader(Types.required(TypeProtos.MinorType.MAP));
+  private MajorType type;
+  
+  private NullReader(){
+    super();
+    type = Types.NULL;
+  }
+
+  private NullReader(MajorType type){
+    super();
+    this.type = type;
+  }
+
+  @Override
+  public MajorType getType() {
+    return type;
+  }
+  
+  public void copyAsValue(MapWriter writer) {}
+
+  public void copyAsValue(ListWriter writer) {}
+
+  public void copyAsValue(UnionWriter writer) {}
+
+  <#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
+  public void read(${name}Holder holder){
+    throw new UnsupportedOperationException("NullReader cannot write into non-nullable holder");
+  }
+
+  public void read(Nullable${name}Holder holder){
+    holder.isSet = 0;
+  }
+
+  public void read(int arrayIndex, ${name}Holder holder){
+    throw new ArrayIndexOutOfBoundsException();
+  }
+  
+  public void copyAsValue(${minor.class}Writer writer){}
+  public void copyAsField(String name, ${minor.class}Writer writer){}
+
+  public void read(int arrayIndex, Nullable${name}Holder holder){
+    throw new ArrayIndexOutOfBoundsException();
+  }
+  </#list></#list>
+  
+  public int size(){
+    return 0;
+  }
+  
+  public boolean isSet(){
+    return false;
+  }
+  
+  public boolean next(){
+    return false;
+  }
+  
+  public RepeatedMapReader map(){
+    return this;
+  }
+  
+  public RepeatedListReader list(){
+    return this;
+  }
+  
+  public MapReader map(String name){
+    return this;
+  }
+  
+  public ListReader list(String name){
+    return this;
+  }
+  
+  public FieldReader reader(String name){
+    return this;
+  }
+  
+  public FieldReader reader(){
+    return this;
+  }
+  
+  private void fail(String name){
+    throw new IllegalArgumentException(String.format("You tried to read a %s type when you are using a ValueReader of type %s.", name, this.getClass().getSimpleName()));
+  }
+  
+  <#list ["Object", "BigDecimal", "Integer", "Long", "Boolean", 
+          "Character", "DateTime", "Period", "Double", "Float",
+          "Text", "String", "Byte", "Short", "byte[]"] as friendlyType>
+  <#assign safeType=friendlyType />
+  <#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
+  
+  public ${friendlyType} read${safeType}(int arrayIndex){
+    return null;
+  }
+  
+  public ${friendlyType} read${safeType}(){
+    return null;
+  }
+  </#list>
+  
+}
+
+
+


Mime
View raw message