DRILL-1126: Support generic objects as workspace variables in UDAF

Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/669bd04d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/669bd04d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/669bd04d

Branch: refs/heads/master
Commit: 669bd04d4d0ade9533fb72228e57624bd457e580
Parents: e7b3d56
Author: Mehant Baid <[email protected]>
Authored: Tue Jul 22 19:42:08 2014 -0700
Committer: Aditya Kishore <[email protected]>
Committed: Thu Jul 24 16:16:02 2014 -0700

----------------------------------------------------------------------
 .../Decimal/DecimalAggrTypeFunctions1.java      |  28 +--
 .../Decimal/DecimalAggrTypeFunctions2.java      |  25 ++-
 .../src/main/codegen/templates/TypeHelper.java  |  14 ++
 .../templates/VarCharAggrFunctions1.java        |  46 ++--
 .../drill/exec/expr/holders/ObjectHolder.java   |  37 ++++
 .../apache/drill/exec/vector/ObjectVector.java  | 216 +++++++++++++++++++
 .../java/org/apache/drill/TestBugFixes.java     |   6 +
 .../apache/drill/common/types/TypeProtos.java   |  19 +-
 protocol/src/main/protobuf/Types.proto          |   1 +
 9 files changed, 343 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
 
b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
index 8588f76..e55362f 100644
--- 
a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
+++ 
b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
@@ -58,12 +58,12 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
 
   @Param ${type.inputType}Holder in;
   <#if aggrtype.funcName == "sum">
-  @Workspace java.math.BigDecimal value;
-  @Workspace int outputScale;
+  @Workspace ObjectHolder value;
+  @Workspace IntHolder outputScale;
   <#else>
   @Workspace ${type.runningType}Holder value;
-  </#if>
   @Workspace ByteBuf buffer;
+  </#if>
   @Output ${type.outputType}Holder out;
 
   public void setup(RecordBatch b) {
@@ -94,8 +94,8 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     value.value = ${type.initValue};
     </#if>
   <#elseif aggrtype.funcName == "sum">
-    value = java.math.BigDecimal.ZERO;
-    outputScale = Integer.MIN_VALUE;
+    value.obj = java.math.BigDecimal.ZERO;
+    outputScale.value = Integer.MIN_VALUE;
        </#if>
 
   }
@@ -163,9 +163,9 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     <#else>
     java.math.BigDecimal currentValue = 
org.apache.drill.common.util.DecimalUtility.getBigDecimalFromSparse(in.buffer, 
in.start, in.nDecimalDigits, in.scale);
     </#if>
-    value = value.add(currentValue);
-    if (outputScale == Integer.MIN_VALUE) {
-      outputScale = in.scale;
+    value.obj = ((java.math.BigDecimal)(value.obj)).add(currentValue);
+    if (outputScale.value == Integer.MIN_VALUE) {
+      outputScale.value = in.scale;
     }
     </#if>
        <#if type.inputType?starts_with("Nullable")>
@@ -178,15 +178,15 @@ public static class 
${type.inputType}${aggrtype.className} implements DrillAggFu
     <#if aggrtype.funcName == "count">
     out.value = value.value;
     <#elseif aggrtype.funcName == "sum">
-    buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[out.WIDTH]);
+    io.netty.buffer.ByteBuf buffer = 
io.netty.buffer.Unpooled.wrappedBuffer(new byte[out.WIDTH]);
     buffer = new io.netty.buffer.SwappedByteBuf(buffer);
     out.buffer = buffer;
     out.start  = 0;
-    out.scale = outputScale;
+    out.scale = outputScale.value;
     out.precision = 38;
-    value = value.setScale(out.scale, java.math.BigDecimal.ROUND_HALF_UP);
-    org.apache.drill.common.util.DecimalUtility.getSparseFromBigDecimal(value, 
out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
-    <#else>
+    value.obj = ((java.math.BigDecimal) (value.obj)).setScale(out.scale, 
java.math.BigDecimal.ROUND_HALF_UP);
+    
org.apache.drill.common.util.DecimalUtility.getSparseFromBigDecimal((java.math.BigDecimal)
 value.obj, out.buffer, out.start, out.scale, out.precision, 
out.nDecimalDigits);
+   <#else>
     <#if type.outputType.endsWith("Dense") || 
type.outputType.endsWith("Sparse") || aggrtype.funcName == "sum">
     out.buffer = value.buffer;
     out.start = value.start;
@@ -223,7 +223,7 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     value.value = ${type.initValue};
     </#if>
   <#elseif aggrtype.funcName == "sum">
-    value = java.math.BigDecimal.ZERO;
+    value.obj = java.math.BigDecimal.ZERO;
        </#if>
 
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
 
b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
index f036655..0ddff6c 100644
--- 
a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
+++ 
b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
@@ -55,17 +55,16 @@ public class Decimal${aggrtype.className}Functions {
 public static class ${type.inputType}${aggrtype.className} implements 
DrillAggFunc{
 
   @Param ${type.inputType}Holder in;
-  @Workspace java.math.BigDecimal value;
+  @Workspace ObjectHolder value;
   @Workspace ${type.countRunningType}Holder count;
-  @Workspace ByteBuf buffer;
-  @Workspace int outputScale;
+  @Workspace IntHolder outputScale;
   @Output ${type.outputType}Holder out;
 
   public void setup(RecordBatch b) {
-    value = java.math.BigDecimal.ZERO;
+    value.obj = java.math.BigDecimal.ZERO;
     count = new ${type.countRunningType}Holder();
     count.value = 0;
-    outputScale = Integer.MIN_VALUE;
+    outputScale.value = Integer.MIN_VALUE;
   }
 
   @Override
@@ -83,9 +82,9 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     <#else>
     java.math.BigDecimal currentValue = 
org.apache.drill.common.util.DecimalUtility.getBigDecimalFromSparse(in.buffer, 
in.start, in.nDecimalDigits, in.scale);
     </#if>
-    value = value.add(currentValue);
-    if (outputScale == Integer.MIN_VALUE) {
-      outputScale = in.scale;
+    value.obj = ((java.math.BigDecimal)(value.obj)).add(currentValue);
+    if (outputScale.value == Integer.MIN_VALUE) {
+      outputScale.value = in.scale;
     }
        <#if type.inputType?starts_with("Nullable")>
     } // end of sout block
@@ -94,22 +93,22 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
 
   @Override
   public void output() {
-    buffer = io.netty.buffer.Unpooled.wrappedBuffer(new byte[out.WIDTH]);
+    io.netty.buffer.ByteBuf buffer = 
io.netty.buffer.Unpooled.wrappedBuffer(new byte[out.WIDTH]);
     buffer = new io.netty.buffer.SwappedByteBuf(buffer);
     out.buffer = buffer;
     out.start  = 0;
-    out.scale = outputScale;
+    out.scale = outputScale.value;
     out.precision = 38;
-    java.math.BigDecimal average = 
value.divide(java.math.BigDecimal.valueOf(count.value, 0), out.scale, 
java.math.BigDecimal.ROUND_HALF_UP);
+    java.math.BigDecimal average = 
((java.math.BigDecimal)(value.obj)).divide(java.math.BigDecimal.valueOf(count.value,
 0), out.scale, java.math.BigDecimal.ROUND_HALF_UP);
     
org.apache.drill.common.util.DecimalUtility.getSparseFromBigDecimal(average, 
out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
   }
 
   @Override
   public void reset() {
-    value = java.math.BigDecimal.ZERO;
+    value.obj = java.math.BigDecimal.ZERO;
     count = new ${type.countRunningType}Holder();
     count.value = 0;
-    outputScale = Integer.MIN_VALUE;
+    outputScale.value = Integer.MIN_VALUE;
   }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/codegen/templates/TypeHelper.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/TypeHelper.java 
b/exec/java-exec/src/main/codegen/templates/TypeHelper.java
index 28cc428..9bb2507 100644
--- a/exec/java-exec/src/main/codegen/templates/TypeHelper.java
+++ b/exec/java-exec/src/main/codegen/templates/TypeHelper.java
@@ -15,6 +15,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 <@pp.dropOutputFile />
 <@pp.changeOutputFile name="/org/apache/drill/exec/expr/TypeHelper.java" />
 
@@ -110,6 +111,8 @@ public class TypeHelper {
         }
   </#list>
 </#list>
+    case GENERIC_OBJECT      :
+      return ObjectVector.class  ;
     default:
       break;
     }
@@ -245,6 +248,8 @@ public class TypeHelper {
         }
   </#list>
 </#list>
+      case GENERIC_OBJECT:
+        return model._ref(ObjectHolder.class);
       default:
         break;
       }
@@ -282,6 +287,8 @@ public class TypeHelper {
       }
   </#list>
 </#list>
+    case GENERIC_OBJECT:
+      return new ObjectVector(field, allocator)        ;
     default:
       break;
     }
@@ -306,6 +313,10 @@ public class TypeHelper {
       </#if>
   </#list>
 </#list>
+    case GENERIC_OBJECT:
+      holder = new ObjectHolder();
+      ((ObjectHolder)holder).obj = ((ObjectVector) 
vector).getAccessor().getObject(index)         ;
+      break;
     default:
       throw new UnsupportedOperationException(type.getMinorType() + " type is 
not supported."); 
     }
@@ -323,6 +334,9 @@ public class TypeHelper {
       break;
   </#list>
 </#list>
+    case GENERIC_OBJECT:
+      ((ObjectVector) vector).getMutator().setSafe(index, (ObjectHolder) 
holder);
+      break          ;
     default:
       throw new UnsupportedOperationException(type.getMinorType() + " type is 
not supported.");    
     }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java 
b/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
index b5b5010..08f5732 100644
--- a/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
+++ b/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
@@ -55,21 +55,28 @@ public class ${aggrtype.className}VarBytesFunctions {
 public static class ${type.inputType}${aggrtype.className} implements 
DrillAggFunc{
 
   @Param ${type.inputType}Holder in;
-  @Workspace ${type.runningType}Holder value;
+  <#if aggrtype.funcName == "max" || aggrtype.funcName == "min">
+  @Workspace ObjectHolder value;
+  <#else>
+  @Workspace  ${type.runningType}Holder value;
+  </#if>
   @Output ${type.outputType}Holder out;
 
   public void setup(RecordBatch b) {
-    value = new ${type.runningType}Holder();
     <#if aggrtype.funcName == "max" || aggrtype.funcName == "min">
-    value.start = 0;
-    value.end = ${type.bufferEnd};
+    value = new ObjectHolder();
+    ${type.runningType}Holder tmp = new ${type.runningType}Holder();
+    tmp.start = 0;
+    tmp.end = ${type.bufferEnd};
     io.netty.buffer.ByteBuf buffer = 
io.netty.buffer.Unpooled.wrappedBuffer(new byte [65536]);
     for (int i = 0; i < 65536; i++) {
       buffer.setByte(i, ${type.initialValue});
     }
-    value.buffer = buffer;
+    tmp.buffer = buffer;
+    value.obj = tmp;
 
     <#else>
+    value = new ${type.runningType}Holder();
     value.value = 0;
     </#if>
   }
@@ -84,13 +91,14 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     }
     </#if>
     <#if aggrtype.funcName == "max" || aggrtype.funcName == "min">
+    ${type.runningType}Holder tmp = (${type.runningType}Holder)value.obj;
     int cmp = 0;
     boolean swap = false;
 
     // Compare the bytes
-    for (int l = in.start, r = value.start; l < in.end && r < value.end; l++, 
r++) {
+    for (int l = in.start, r = tmp.start; l < in.end && r < tmp.end; l++, r++) 
{
       byte leftByte = in.buffer.getByte(l);
-      byte rightByte = value.buffer.getByte(r);
+      byte rightByte = tmp.buffer.getByte(r);
       if (leftByte != rightByte) {
         cmp = ((leftByte & 0xFF) - (rightByte & 0xFF)) > 0 ? 1 : -1;
         break;
@@ -98,7 +106,7 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
     }
 
     if (cmp == 0) {
-      int l = (in.end - in.start) - (value.end - value.start);
+      int l = (in.end - in.start) - (tmp.end - tmp.start);
       if (l > 0) {
         cmp = 1;
       } else {
@@ -114,8 +122,8 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
 
     if (swap) {
       int length = in.end - in.start;
-      in.buffer.getBytes(in.start, value.buffer, 0, length);
-      value.end = length;
+      in.buffer.getBytes(in.start, tmp.buffer, 0, length);
+      tmp.end = length;
     }
     <#else>
     value.value++;
@@ -128,9 +136,10 @@ public static class ${type.inputType}${aggrtype.className} 
implements DrillAggFu
   @Override
   public void output() {
     <#if aggrtype.funcName == "max" || aggrtype.funcName == "min">
-    out.start  = value.start;
-    out.end    = value.end;
-    out.buffer = value.buffer;
+    ${type.runningType}Holder tmp = (${type.runningType}Holder)value.obj;
+    out.start  = tmp.start;
+    out.end    = tmp.end;
+    out.buffer = tmp.buffer;
     <#else>
     out.value = value.value;
     </#if>
@@ -138,16 +147,19 @@ public static class 
${type.inputType}${aggrtype.className} implements DrillAggFu
 
   @Override
   public void reset() {
-    value = new ${type.runningType}Holder();
     <#if aggrtype.funcName == "max" || aggrtype.funcName == "min">
-    value.start = 0;
-    value.end = ${type.bufferEnd};
+    value = new ObjectHolder();
+    ${type.runningType}Holder tmp = new ${type.runningType}Holder();
+    tmp.start = 0;
+    tmp.end = ${type.bufferEnd};
     io.netty.buffer.ByteBuf buffer = 
io.netty.buffer.Unpooled.wrappedBuffer(new byte [65536]);
     for (int i = 0; i < 65536; i++) {
       buffer.setByte(i, ${type.initialValue});
     }
-    value.buffer = buffer;
+    tmp.buffer = buffer;
+    value.obj = tmp;
     <#else>
+    value = new ${type.runningType}Holder();
     value.value = 0;
     </#if>
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/java/org/apache/drill/exec/expr/holders/ObjectHolder.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/holders/ObjectHolder.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/holders/ObjectHolder.java
new file mode 100644
index 0000000..391a795
--- /dev/null
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/holders/ObjectHolder.java
@@ -0,0 +1,37 @@
+/**
+ * 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.
+ */
+
+package org.apache.drill.exec.expr.holders;
+
+import org.apache.drill.common.types.TypeProtos;
+import org.apache.drill.common.types.Types;
+
+/*
+ * Holder class for the vector ObjectVector. This holder internally stores a
+ * reference to an object. The ObjectVector maintains an array of these 
objects.
+ * This holder can be used only as workspace variables in aggregate functions.
+ * Using this holder should be avoided and we should stick to native holder 
types.
+ */
+@Deprecated
+public class ObjectHolder implements ValueHolder {
+  public static final TypeProtos.MajorType TYPE = 
Types.required(TypeProtos.MinorType.GENERIC_OBJECT);
+
+  public TypeProtos.MajorType getType() {return TYPE;}
+
+  public Object obj;
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/main/java/org/apache/drill/exec/vector/ObjectVector.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/vector/ObjectVector.java 
b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/ObjectVector.java
new file mode 100644
index 0000000..6998a74
--- /dev/null
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/ObjectVector.java
@@ -0,0 +1,216 @@
+/**
+ * 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.
+ */
+package org.apache.drill.exec.vector;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.drill.common.expression.FieldReference;
+import org.apache.drill.exec.expr.holders.ObjectHolder;
+import org.apache.drill.exec.memory.BufferAllocator;
+import org.apache.drill.exec.memory.OutOfMemoryRuntimeException;
+import org.apache.drill.exec.proto.UserBitShared;
+import org.apache.drill.exec.record.MaterializedField;
+import org.apache.drill.exec.record.TransferPair;
+import org.apache.drill.exec.vector.complex.reader.FieldReader;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ObjectVector extends BaseValueVector{
+
+  private Accessor accessor = new Accessor();
+  private Mutator mutator = new Mutator();
+  private int maxCount = 0;
+  private int count = 0;
+  private int allocationSize = 4024;
+
+  private List<Object[]> objectArrayList = new ArrayList<>();
+
+  public ObjectVector(MaterializedField field, BufferAllocator allocator) {
+    super(field, allocator);
+  }
+
+  public void addNewArray() {
+    objectArrayList.add(new Object[allocationSize]);
+    maxCount += allocationSize;
+  }
+
+  public final class Mutator implements ValueVector.Mutator {
+
+    public void set(int index, Object obj) {
+      int listOffset = index / allocationSize;
+      if (listOffset > objectArrayList.size()) {
+        addNewArray();
+      }
+      objectArrayList.get(listOffset)[index % allocationSize] = obj;
+    }
+
+    public boolean setSafe(int index, long value) {
+      set(index, value);
+      return true;
+    }
+
+    protected void set(int index, ObjectHolder holder) {
+      set(index, holder.obj);
+    }
+
+    public boolean setSafe(int index, ObjectHolder holder){
+      set(index, holder);
+      return true;
+    }
+
+    @Override
+    public void setValueCount(int valueCount) {
+      count = valueCount;
+    }
+
+    @Override
+    public void reset() {
+      count = 0;
+      maxCount = 0;
+      objectArrayList = new ArrayList<>();
+      addNewArray();
+    }
+
+    @Override
+    public void generateTestData(int values) {
+    }
+  }
+  @Override
+  public void allocateNew() throws OutOfMemoryRuntimeException {
+    addNewArray();
+  }
+
+  @Override
+  public boolean allocateNewSafe() {
+    allocateNew();
+    return true;
+  }
+
+  @Override
+  public int getBufferSize() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public void close() {
+    clear();
+  }
+
+  @Override
+  public void clear() {
+    objectArrayList.clear();
+    maxCount = 0;
+    count = 0;
+  }
+
+  @Override
+  public MaterializedField getField() {
+    return field;
+  }
+
+  @Override
+  public ByteBuf getData() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public TransferPair getTransferPair() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public TransferPair makeTransferPair(ValueVector to) {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public TransferPair getTransferPair(FieldReference ref) {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public int getValueCapacity() {
+    return maxCount;
+  }
+
+  @Override
+  public Accessor getAccessor() {
+    return accessor;
+  }
+
+  @Override
+  public ByteBuf[] getBuffers() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public void load(UserBitShared.SerializedField metadata, ByteBuf buffer) {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public UserBitShared.SerializedField getMetadata() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  @Override
+  public Mutator getMutator() {
+    return mutator;
+  }
+
+  @Override
+  public Iterator<ValueVector> iterator() {
+    throw new UnsupportedOperationException("ObjectVector does not support 
this");
+  }
+
+  public final class Accessor extends BaseAccessor {
+
+    @Override
+    public Object getObject(int index) {
+      int listOffset = index / allocationSize;
+      if (listOffset > objectArrayList.size()) {
+        addNewArray();
+      }
+      return objectArrayList.get(listOffset)[index % allocationSize];
+    }
+
+    @Override
+    public int getValueCount() {
+      return count;
+    }
+
+    @Override
+    public boolean isNull(int index) {
+      return false;
+    }
+
+    @Override
+    public FieldReader getReader() {
+      throw new UnsupportedOperationException("ObjectVector does not support 
this");
+    }
+
+    public Object get(int index) {
+      return getObject(index);
+    }
+
+    public void get(int index, ObjectHolder holder){
+      holder.obj = getObject(index);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/exec/java-exec/src/test/java/org/apache/drill/TestBugFixes.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestBugFixes.java 
b/exec/java-exec/src/test/java/org/apache/drill/TestBugFixes.java
index 8348d79..e6d698a 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestBugFixes.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestBugFixes.java
@@ -54,4 +54,10 @@ public class TestBugFixes extends BaseTestQuery {
     String query = "select foo.mycol.x as COMPLEX_COL from (select 
convert_from('{ x : [1,2], y : 100 }', 'JSON') as mycol from 
cp.`tpch/nation.parquet`) as foo(mycol) limit 1";
     test(query);
   }
+
+  @Test
+  public void DRILL1126() throws Exception {
+    String query = "select sum(cast(employee_id as decimal(38, 18))), 
avg(cast(employee_id as decimal(38, 18))) from cp.`employee.json` group by 
(department_id)";
+    test(query);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/protocol/src/main/java/org/apache/drill/common/types/TypeProtos.java
----------------------------------------------------------------------
diff --git 
a/protocol/src/main/java/org/apache/drill/common/types/TypeProtos.java 
b/protocol/src/main/java/org/apache/drill/common/types/TypeProtos.java
index a2e97d1..74ac444 100644
--- a/protocol/src/main/java/org/apache/drill/common/types/TypeProtos.java
+++ b/protocol/src/main/java/org/apache/drill/common/types/TypeProtos.java
@@ -313,6 +313,10 @@ public final class TypeProtos {
      * <code>LIST = 40;</code>
      */
     LIST(35, 40),
+    /**
+     * <code>GENERIC_OBJECT = 41;</code>
+     */
+    GENERIC_OBJECT(36, 41),
     ;
 
     /**
@@ -598,6 +602,10 @@ public final class TypeProtos {
      * <code>LIST = 40;</code>
      */
     public static final int LIST_VALUE = 40;
+    /**
+     * <code>GENERIC_OBJECT = 41;</code>
+     */
+    public static final int GENERIC_OBJECT_VALUE = 41;
 
 
     public final int getNumber() { return value; }
@@ -640,6 +648,7 @@ public final class TypeProtos {
         case 38: return INTERVALYEAR;
         case 39: return INTERVALDAY;
         case 40: return LIST;
+        case 41: return GENERIC_OBJECT;
         default: return null;
       }
     }
@@ -1771,7 +1780,7 @@ public final class TypeProtos {
       "inor_type\030\001 \001(\0162\021.common.MinorType\022\036\n\004mo" +
       "de\030\002 \001(\0162\020.common.DataMode\022\r\n\005width\030\003 
\001(" +
       "\005\022\021\n\tprecision\030\004 \001(\005\022\r\n\005scale\030\005 
\001(\005\022\020\n\010t" +
-      "imeZone\030\006 
\001(\005*\366\003\n\tMinorType\022\010\n\004LATE\020\000\022\007\n" +
+      "imeZone\030\006 
\001(\005*\212\004\n\tMinorType\022\010\n\004LATE\020\000\022\007\n" +
       
"\003MAP\020\001\022\013\n\007TINYINT\020\003\022\014\n\010SMALLINT\020\004\022\007\n\003INT"
 +
       
"\020\005\022\n\n\006BIGINT\020\006\022\014\n\010DECIMAL9\020\007\022\r\n\tDECIMAL1"
 +
       "8\020\010\022\023\n\017DECIMAL28SPARSE\020\t\022\023\n\017DECIMAL38SPA" 
+
@@ -1783,10 +1792,10 @@ public final class TypeProtos {
       
"AR\020\031\022\r\n\tVARBINARY\020\032\022\t\n\005UINT1\020\035\022\t\n\005UINT2\020"
 +
       "\036\022\t\n\005UINT4\020\037\022\t\n\005UINT8\020 
\022\022\n\016DECIMAL28DENS" +
       
"E\020!\022\022\n\016DECIMAL38DENSE\020\"\022\010\n\004NULL\020%\022\020\n\014INT"
 +
-      "ERVALYEAR\020&\022\017\n\013INTERVALDAY\020\'\022\010\n\004LIST\020(*4" 
+
-      
"\n\010DataMode\022\014\n\010OPTIONAL\020\000\022\014\n\010REQUIRED\020\001\022\014"
 +
-      "\n\010REPEATED\020\002B-\n\035org.apache.drill.common." +
-      "typesB\nTypeProtosH\001"
+      
"ERVALYEAR\020&\022\017\n\013INTERVALDAY\020\'\022\010\n\004LIST\020(\022\022" +
+      "\n\016GENERIC_OBJECT\020)*4\n\010DataMode\022\014\n\010OPTION" +
+      
"AL\020\000\022\014\n\010REQUIRED\020\001\022\014\n\010REPEATED\020\002B-\n\035org."
 +
+      "apache.drill.common.typesB\nTypeProtosH\001"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner 
assigner =
       new 
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/669bd04d/protocol/src/main/protobuf/Types.proto
----------------------------------------------------------------------
diff --git a/protocol/src/main/protobuf/Types.proto 
b/protocol/src/main/protobuf/Types.proto
index 3d5ac38..d93bcb5 100644
--- a/protocol/src/main/protobuf/Types.proto
+++ b/protocol/src/main/protobuf/Types.proto
@@ -63,6 +63,7 @@ enum MinorType {
     INTERVALYEAR = 38; // Interval type specifying YEAR to MONTH
     INTERVALDAY = 39; // Interval type specifying DAY to SECONDS
     LIST = 40;
+    GENERIC_OBJECT = 41;
 }
 
 message MajorType {

Reply via email to