aboutsummaryrefslogtreecommitdiff
path: root/exec/vector
diff options
context:
space:
mode:
authorVolodymyr Vysotskyi <vvovyk@gmail.com>2018-04-05 15:35:42 +0300
committerVolodymyr Vysotskyi <vvovyk@gmail.com>2018-05-04 20:30:50 +0300
commit4c4953bcab4886be14fc9b7f95a77caa86a7629f (patch)
treeb9ed1a17179063c47bd9f7a2e20f5601807b3580 /exec/vector
parent79e27eadb86dfaa0e2d8bc514f3069bf02dc2762 (diff)
DRILL-6094: Decimal data type enhancements
Add ExprVisitors for VARDECIMAL Modify writers/readers to support VARDECIMAL - Added usage of VarDecimal for parquet, hive, maprdb, jdbc; - Added options to store decimals as int32 and int64 or fixed_len_byte_array or binary; Add UDFs for VARDECIMAL data type - modify type inference rules - remove UDFs for obsolete DECIMAL types Enable DECIMAL data type by default Add unit tests for DECIMAL data type Fix mapping for NLJ when literal with non-primitive type is used in join conditions Refresh protobuf C++ source files Changes in C++ files Add support for decimal logical type in Avro. Add support for date, time and timestamp logical types. Update Avro version to 1.8.2.
Diffstat (limited to 'exec/vector')
-rw-r--r--exec/vector/src/main/codegen/data/ValueVectorTypes.tdd4
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractFieldReader.java46
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractFieldWriter.java15
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java24
-rw-r--r--exec/vector/src/main/codegen/templates/BaseWriter.java6
-rw-r--r--exec/vector/src/main/codegen/templates/BasicTypeHelper.java39
-rw-r--r--exec/vector/src/main/codegen/templates/ColumnAccessors.java38
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexCopier.java12
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexReaders.java66
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexWriters.java42
-rw-r--r--exec/vector/src/main/codegen/templates/HolderReaderImpl.java13
-rw-r--r--exec/vector/src/main/codegen/templates/ListWriters.java18
-rw-r--r--exec/vector/src/main/codegen/templates/MapWriters.java4
-rw-r--r--exec/vector/src/main/codegen/templates/NullReader.java48
-rw-r--r--exec/vector/src/main/codegen/templates/NullableValueVectors.java16
-rw-r--r--exec/vector/src/main/codegen/templates/RepeatedValueVectors.java18
-rw-r--r--exec/vector/src/main/codegen/templates/UnionListWriter.java12
-rw-r--r--exec/vector/src/main/codegen/templates/UnionWriter.java16
-rw-r--r--exec/vector/src/main/codegen/templates/ValueHolders.java141
-rw-r--r--exec/vector/src/main/codegen/templates/VariableLengthVectors.java22
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java204
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java19
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java5
23 files changed, 555 insertions, 273 deletions
diff --git a/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd b/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
index ca4653d3e..f6e1f1d09 100644
--- a/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
+++ b/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
@@ -183,7 +183,9 @@
javaType: "int",
boxedType: "DrillBuf",
minor: [
- { class: "VarDecimal", friendlyType: "BigDecimal", fields: [{name: "start", type: "int"}, {name: "end", type: "int"}, {name: "buffer", type: "DrillBuf"}, {name: "scale", type: "int", include: false}] }
+ { class: "VarDecimal", friendlyType: "BigDecimal", fields: [{name: "start", type: "int"},
+ {name: "end", type: "int"}, {name: "buffer", type: "DrillBuf"},
+ {name: "scale", type: "int", include: false}, {name: "precision", type: "int", include: false}] }
]
},
{
diff --git a/exec/vector/src/main/codegen/templates/AbstractFieldReader.java b/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
index f2e1eb0dd..2ed5a3b6d 100644
--- a/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
+++ b/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
@@ -29,10 +29,9 @@ package org.apache.drill.exec.vector.complex.impl;
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
-abstract class AbstractFieldReader extends AbstractBaseReader implements FieldReader{
+abstract class AbstractFieldReader extends AbstractBaseReader implements FieldReader {
- AbstractFieldReader(){
- super();
+ AbstractFieldReader() {
}
/**
@@ -49,78 +48,77 @@ abstract class AbstractFieldReader extends AbstractBaseReader implements FieldRe
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
fail("read${safeType}(int arrayIndex)");
return null;
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
fail("read${safeType}()");
return null;
}
</#list>
- public void copyAsValue(MapWriter writer){
+ public void copyAsValue(MapWriter writer) {
fail("CopyAsValue MapWriter");
}
- public void copyAsField(String name, MapWriter writer){
+ public void copyAsField(String name, MapWriter writer) {
fail("CopyAsField MapWriter");
}
- public void copyAsField(String name, ListWriter writer){
+ public void copyAsField(String name, ListWriter writer) {
fail("CopyAsFieldList");
}
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign boxedType = (minor.boxedType!type.boxedType) />
- public void read(${name}Holder holder){
+ public void read(${name}Holder holder) {
fail("${name}");
}
- public void read(Nullable${name}Holder holder){
+ public void read(Nullable${name}Holder holder) {
fail("${name}");
}
- public void read(int arrayIndex, ${name}Holder holder){
+ public void read(int arrayIndex, ${name}Holder holder) {
fail("Repeated${name}");
}
- public void read(int arrayIndex, Nullable${name}Holder holder){
+ public void read(int arrayIndex, Nullable${name}Holder holder) {
fail("Repeated${name}");
}
- public void copyAsValue(${name}Writer writer){
+ public void copyAsValue(${name}Writer writer) {
fail("CopyAsValue${name}");
}
- public void copyAsField(String name, ${name}Writer writer){
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${name}Writer writer, int scale, int precision) {
+ <#else>
+ public void copyAsField(String name, ${name}Writer writer) {
+ </#if>
fail("CopyAsField${name}");
}
</#list></#list>
- public FieldReader reader(String name){
+ public FieldReader reader(String name) {
fail("reader(String name)");
return null;
}
- public FieldReader reader(){
+ public FieldReader reader() {
fail("reader()");
return null;
-
}
- public int size(){
+ public int size() {
fail("size()");
return -1;
}
- private void fail(String name){
+ private void fail(String name) {
throw new IllegalArgumentException(String.format("You tried to read a [%s] type when you are using a field reader of type [%s].", name, this.getClass().getSimpleName()));
}
-
-
}
-
-
-
diff --git a/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java b/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
index 608420cce..dcf99d34b 100644
--- a/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
+++ b/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
@@ -65,6 +65,12 @@ abstract class AbstractFieldWriter extends AbstractBaseWriter implements FieldWr
fail("${name}");
}
+ <#if minor.class?contains("Decimal") >
+ public void write${minor.class}(BigDecimal value) {
+ fail("${name}");
+ }
+ </#if>
+
</#list></#list>
public void writeNull() {
@@ -111,11 +117,18 @@ abstract class AbstractFieldWriter extends AbstractBaseWriter implements FieldWr
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
+ @Override
public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
fail("${capName}");
return null;
}
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ fail("${capName}");
+ return null;
+ }
</#if>
@Override
diff --git a/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java b/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
index df7be39bd..96b45d329 100644
--- a/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
+++ b/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
@@ -75,12 +75,20 @@ abstract class AbstractPromotableFieldWriter extends AbstractFieldWriter {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
- <#if !minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("VarDecimal")>
+ @Override
+ public void write${minor.class}(BigDecimal value) {
+ getWriter(MinorType.${name?upper_case}).write${minor.class}(value);
+ }
+ </#if>
+
@Override
public void write(${name}Holder holder) {
getWriter(MinorType.${name?upper_case}).write(holder);
}
+ <#-- This condition was added to cover previous decimal functionality for new VarDecimal type -->
+ <#if !minor.class?contains("Decimal") || minor.class?contains("VarDecimal")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
getWriter(MinorType.${name?upper_case}).write${minor.class}(<#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
}
@@ -116,7 +124,19 @@ abstract class AbstractPromotableFieldWriter extends AbstractFieldWriter {
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if !minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal")>
+
+ @Override
+ public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
+ return getWriter(MinorType.MAP).${lowerName}(name, scale, precision);
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ return getWriter(MinorType.LIST).${lowerName}(scale, precision);
+ }
+
+ <#else>
@Override
public ${capName}Writer ${lowerName}(String name) {
diff --git a/exec/vector/src/main/codegen/templates/BaseWriter.java b/exec/vector/src/main/codegen/templates/BaseWriter.java
index ad9c44e1f..e65060976 100644
--- a/exec/vector/src/main/codegen/templates/BaseWriter.java
+++ b/exec/vector/src/main/codegen/templates/BaseWriter.java
@@ -53,7 +53,7 @@ package org.apache.drill.exec.vector.complex.writer;
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
${capName}Writer ${lowerName}(String name, int scale, int precision);
</#if>
${capName}Writer ${lowerName}(String name);
@@ -78,6 +78,9 @@ package org.apache.drill.exec.vector.complex.writer;
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
+ <#if minor.class?contains("Decimal") >
+ ${capName}Writer ${lowerName}(int scale, int precision);
+ </#if>
${capName}Writer ${lowerName}();
</#list></#list>
}
@@ -112,6 +115,7 @@ package org.apache.drill.exec.vector.complex.writer;
VarCharWriter varChar(String name);
Var16CharWriter var16Char(String name);
VarDecimalWriter varDecimal(String name);
+ VarDecimalWriter varDecimal(String name, int scale, int precision);
TinyIntWriter tinyInt(String name);
SmallIntWriter smallInt(String name);
IntWriter integer(String name);
diff --git a/exec/vector/src/main/codegen/templates/BasicTypeHelper.java b/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
index 8160dd59a..f818c236f 100644
--- a/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
+++ b/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
@@ -395,7 +395,9 @@ public class BasicTypeHelper {
MajorType type1 = v1.getField().getType();
MajorType type2 = v2.getField().getType();
- if (type1.getMinorType() != type2.getMinorType()) {
+ if (type1.getMinorType() != type2.getMinorType()
+ || type1.getScale() != type1.getScale()
+ || type1.getPrecision() != type1.getPrecision()) {
return false;
}
@@ -539,11 +541,19 @@ public class BasicTypeHelper {
}
<#list vv.types as type>
<#list type.minor as minor>
+ <#if minor.class.contains("Decimal")>
+ else if (holder instanceof ${minor.class}Holder) {
+ return getType((${minor.class}Holder) holder);
+ } else if (holder instanceof Nullable${minor.class}Holder) {
+ return getType((Nullable${minor.class}Holder) holder);
+ }
+ <#else>
else if (holder instanceof ${minor.class}Holder) {
return ((${minor.class}Holder) holder).TYPE;
} else if (holder instanceof Nullable${minor.class}Holder) {
return ((Nullable${minor.class}Holder) holder).TYPE;
}
+ </#if>
</#list>
</#list>
else if (holder instanceof UntypedNullHolder) {
@@ -553,4 +563,31 @@ public class BasicTypeHelper {
}
+ <#list vv.types as type>
+ <#list type.minor as minor>
+ <#if minor.class.contains("Decimal")>
+ <#list ["Nullable", "", "Repeated"] as dataMode>
+ public static MajorType getType(${dataMode}${minor.class}Holder holder) {
+ return MajorType.newBuilder()
+ .setMinorType(MinorType.${minor.class?upper_case})
+ <#if dataMode == "Nullable">
+ .setMode(DataMode.OPTIONAL)
+ .setScale(holder.scale)
+ .setPrecision(holder.precision)
+ <#elseif dataMode == "Repeated">
+ .setMode(DataMode.REPEATED)
+ .setScale(holder.vector.getField().getScale())
+ .setPrecision(holder.vector.getField().getPrecision())
+ <#else>
+ .setMode(DataMode.REQUIRED)
+ .setScale(holder.scale)
+ .setPrecision(holder.precision)
+ </#if>
+ .build();
+ }
+ </#list>
+ </#if>
+ </#list>
+ </#list>
+
}
diff --git a/exec/vector/src/main/codegen/templates/ColumnAccessors.java b/exec/vector/src/main/codegen/templates/ColumnAccessors.java
index 6068afa22..accf1b28d 100644
--- a/exec/vector/src/main/codegen/templates/ColumnAccessors.java
+++ b/exec/vector/src/main/codegen/templates/ColumnAccessors.java
@@ -28,6 +28,8 @@
return ValueType.INTEGER;
<#elseif drillType == "VarChar" || drillType == "Var16Char">
return ValueType.STRING;
+ <#elseif drillType == "VarDecimal">
+ return ValueType.DECIMAL;
<#else>
return ValueType.${label?upper_case};
</#if>
@@ -65,6 +67,7 @@
package org.apache.drill.exec.vector.accessor;
import java.math.BigDecimal;
+import java.math.BigInteger;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.exec.vector.DateUtilities;
@@ -141,12 +144,10 @@ public class ColumnAccessors {
private static final int VALUE_WIDTH = ${drillType}Vector.VALUE_WIDTH;
- <#if decimal>
- private MajorType type;
-
- </#if>
</#if>
<#if decimal>
+ private MajorType type;
+
@Override
public void bindVector(ColumnMetadata schema, VectorAccessor va) {
super.bindVector(schema, va);
@@ -234,6 +235,14 @@ public class ColumnAccessors {
public String getString() {
return new String(getBytes(${indexVar}), Charsets.UTF_16);
}
+ <#elseif drillType == "VarDecimal">
+
+ @Override
+ public BigDecimal getDecimal() {
+ byte[] bytes = getBytes();
+ BigInteger unscaledValue = bytes.length == 0 ? BigInteger.ZERO : new BigInteger(bytes);
+ return new BigDecimal(unscaledValue, type.getScale());
+ }
</#if>
}
@@ -269,20 +278,10 @@ public class ColumnAccessors {
</#if>
<@getType drillType label />
<#if ! varWidth>
-
</#if>
- @Override
- <#if drillType = "VarDecimal">
- public final void setDecimal(final BigDecimal bd) {
- byte[] barr = bd.unscaledValue().toByteArray();
- int len = barr.length;
- setBytes(barr, len);
- }
- public final void setBytes(final byte[] value, int len) {
- <#else>
+ @Override
public final void set${label}(final ${accessorType} value${putArgs}) {
- </#if>
<#-- Must compute the write offset first; can't be inline because the
writeOffset() function has a side effect of possibly changing the buffer
address (bufAddr). -->
@@ -347,6 +346,15 @@ public class ColumnAccessors {
final byte bytes[] = value.getBytes(Charsets.UTF_16);
setBytes(bytes, bytes.length);
}
+
+ <#elseif drillType = "VarDecimal">
+
+ @Override
+ public final void setDecimal(final BigDecimal bd) {
+ byte[] barr = bd.unscaledValue().toByteArray();
+ int len = barr.length;
+ setBytes(barr, len);
+ }
</#if>
}
diff --git a/exec/vector/src/main/codegen/templates/ComplexCopier.java b/exec/vector/src/main/codegen/templates/ComplexCopier.java
index 91e3ff645..6d7c7e607 100644
--- a/exec/vector/src/main/codegen/templates/ComplexCopier.java
+++ b/exec/vector/src/main/codegen/templates/ComplexCopier.java
@@ -97,9 +97,12 @@ public class ComplexCopier {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
- <#if !minor.class?starts_with("Decimal")>
+ <#if !minor.class?contains("Decimal")>
case ${name?upper_case}:
return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>(name);
+ <#elseif minor.class?contains("VarDecimal")>
+ case ${name?upper_case}:
+ return (FieldWriter) writer.${uncappedName}(name, reader.getType().getScale(), reader.getType().getPrecision());
</#if>
</#list></#list>
case MAP:
@@ -116,9 +119,12 @@ public class ComplexCopier {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
- <#if !minor.class?starts_with("Decimal")>
+ <#if !minor.class?contains("Decimal")>
+ case ${name?upper_case}:
+ return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>();
+ <#elseif minor.class?contains("VarDecimal")>
case ${name?upper_case}:
- return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>();
+ return (FieldWriter) writer.${uncappedName}(reader.getType().getScale(), reader.getType().getPrecision());
</#if>
</#list></#list>
case MAP:
diff --git a/exec/vector/src/main/codegen/templates/ComplexReaders.java b/exec/vector/src/main/codegen/templates/ComplexReaders.java
index 1f0b92b02..d72c7c696 100644
--- a/exec/vector/src/main/codegen/templates/ComplexReaders.java
+++ b/exec/vector/src/main/codegen/templates/ComplexReaders.java
@@ -53,20 +53,20 @@ public class ${nullMode}${name}ReaderImpl extends AbstractFieldReader {
private final ${nullMode}${name}Vector vector;
- public ${nullMode}${name}ReaderImpl(${nullMode}${name}Vector vector){
+ public ${nullMode}${name}ReaderImpl(${nullMode}${name}Vector vector) {
super();
this.vector = vector;
}
- public MajorType getType(){
+ public MajorType getType() {
return vector.getField().getType();
}
- public MaterializedField getField(){
+ public MaterializedField getField() {
return vector.getField();
}
- public boolean isSet(){
+ public boolean isSet() {
<#if nullMode == "Nullable">
return !vector.getAccessor().isNull(idx());
<#else>
@@ -74,76 +74,85 @@ public class ${nullMode}${name}ReaderImpl extends AbstractFieldReader {
</#if>
}
-
-
-
<#if mode == "Repeated">
- public void copyAsValue(${minor.class?cap_first}Writer writer){
+ 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}();
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, MapWriter writer, int scale, int precision) {
+ Repeated${minor.class?cap_first}WriterImpl impl
+ = (Repeated${minor.class?cap_first}WriterImpl) writer.list(name).${lowerName}(scale, precision);
+ <#else>
+ public void copyAsField(String name, MapWriter writer) {
+ Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl) writer.list(name).${lowerName}();
+ </#if>
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
- public int size(){
+ public int size() {
return vector.getAccessor().getInnerValueCountAt(idx());
}
- public void read(int arrayIndex, ${minor.class?cap_first}Holder h){
+ 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){
+
+ public void read(int arrayIndex, Nullable${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), arrayIndex, h);
}
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
return vector.getAccessor().getSingleObject(idx(), arrayIndex);
}
- public List<Object> readObject(){
+ public List<Object> readObject() {
return (List<Object>) (Object) vector.getAccessor().getObject(idx());
}
<#else>
- public void copyAsValue(${minor.class?cap_first}Writer writer){
+ 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){
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, MapWriter writer, int scale, int precision) {
+ ${nullMode}${minor.class?cap_first}WriterImpl impl
+ = (${nullMode}${minor.class?cap_first}WriterImpl) writer.${lowerName}(name, scale, precision);
+<#else>
+ public void copyAsField(String name, MapWriter writer) {
${nullMode}${minor.class?cap_first}WriterImpl impl = (${nullMode}${minor.class?cap_first}WriterImpl) writer.${lowerName}(name);
+ </#if>
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
<#if nullMode != "Nullable">
- public void read(${minor.class?cap_first}Holder h){
+ 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){
+ public void read(Nullable${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), h);
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
return vector.getAccessor().getObject(idx());
}
- public void copyValue(FieldWriter w){
+ public void copyValue(FieldWriter w) {
}
- public Object readObject(){
+ public Object readObject() {
return vector.getAccessor().getObject(idx());
}
-
</#if>
}
</#if>
@@ -155,7 +164,7 @@ package org.apache.drill.exec.vector.complex.reader;
<#include "/@includes/vv_imports.ftl" />
@SuppressWarnings("unused")
-public interface ${name}Reader extends BaseReader{
+public interface ${name}Reader extends BaseReader {
<#if mode == "Repeated">
public int size();
@@ -171,8 +180,11 @@ public interface ${name}Reader extends BaseReader{
</#if>
public boolean isSet();
public void copyAsValue(${minor.class}Writer writer);
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${minor.class}Writer writer, int scale, int precision);
+ <#else>
public void copyAsField(String name, ${minor.class}Writer writer);
-
+ </#if>
}
diff --git a/exec/vector/src/main/codegen/templates/ComplexWriters.java b/exec/vector/src/main/codegen/templates/ComplexWriters.java
index 6e1d8f3e2..f46b7958d 100644
--- a/exec/vector/src/main/codegen/templates/ComplexWriters.java
+++ b/exec/vector/src/main/codegen/templates/ComplexWriters.java
@@ -96,14 +96,10 @@ public class ${eName}WriterImpl extends AbstractFieldWriter {
vector.getMutator().setValueCount(idx()+1);
}
- <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+ <#if !minor.class?contains("Decimal") || minor.class?contains("VarDecimal")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
- <#if minor.class == "VarDecimal">
- mutator.addSafe(idx(), <#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>);
- <#else>
- mutator.addSafe(idx(), <#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- </#if>
- vector.getMutator().setValueCount(idx()+1);
+ mutator.addSafe(idx()<#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
+ vector.getMutator().setValueCount(idx() + 1);
}
</#if>
@@ -125,21 +121,23 @@ public class ${eName}WriterImpl extends AbstractFieldWriter {
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>) {
- <#if minor.class == "VarDecimal">
- mutator.setSafe(idx(), <#if mode == "Nullable">1, </#if><#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>);
- <#else>
- mutator.setSafe(idx(), <#if mode == "Nullable">1, </#if><#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- </#if>
- vector.getMutator().setValueCount(idx()+1);
- }
-
<#if mode == "Nullable">
-
public void writeNull() {
mutator.setNull(idx());
- vector.getMutator().setValueCount(idx()+1);
+ vector.getMutator().setValueCount(idx() + 1);
+ }
+ </#if>
+
+ <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
+ 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><#if field.include!true>, ${field.name}</#if></#list>);
+ vector.getMutator().setValueCount(idx() + 1);
+ }
+
+ <#if minor.class?contains("VarDecimal")>
+ public void write${minor.class}(BigDecimal value) {
+ mutator.setSafe(idx(), value);
+ vector.getMutator().setValueCount(idx() + 1);
}
</#if>
</#if>
@@ -156,9 +154,13 @@ package org.apache.drill.exec.vector.complex.writer;
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")>
+ <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>);
</#if>
+
+ <#if minor.class?contains("VarDecimal")>
+ public void write${minor.class}(BigDecimal value);
+ </#if>
}
</#list>
diff --git a/exec/vector/src/main/codegen/templates/HolderReaderImpl.java b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
index e46989ba5..4b7be4fd7 100644
--- a/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
+++ b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
@@ -42,6 +42,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.drill.exec.expr.holders.*;
+import org.apache.drill.exec.expr.BasicTypeHelper;
import org.joda.time.Period;
// Source code generated using FreeMarker template ${.template_name}
@@ -96,10 +97,14 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
@Override
public MajorType getType() {
-<#if holderMode == "Repeated">
- return this.repeatedHolder.TYPE;
+<#if name?contains("Decimal")>
+ return BasicTypeHelper.getType(holder);
<#else>
+ <#if holderMode == "Repeated">
+ return this.repeatedHolder.TYPE;
+ <#else>
return this.holder.TYPE;
+ </#if>
</#if>
}
@@ -161,7 +166,7 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
<#if minor.class == "VarBinary">
return value;
<#elseif minor.class == "VarDecimal">
- return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end-holder.start, holder.scale);
+ return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end - holder.start, holder.scale);
<#elseif minor.class == "Var16Char">
return new String(value);
<#elseif minor.class == "VarChar">
@@ -236,7 +241,7 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
<#if minor.class == "VarBinary">
return value;
<#elseif minor.class == "VarDecimal">
- return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end-holder.start, holder.scale);
+ return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end - holder.start, holder.scale);
<#elseif minor.class == "Var16Char">
return new String(value);
<#elseif minor.class == "VarChar">
diff --git a/exec/vector/src/main/codegen/templates/ListWriters.java b/exec/vector/src/main/codegen/templates/ListWriters.java
index d7a66f75d..cab8772a7 100644
--- a/exec/vector/src/main/codegen/templates/ListWriters.java
+++ b/exec/vector/src/main/codegen/templates/ListWriters.java
@@ -156,10 +156,24 @@ public class ${mode}ListWriter extends AbstractFieldWriter {
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+
+ <#if minor.class?contains("Decimal") >
+ @Override
+ public ${capName}Writer ${lowerName}() {
+ // returns existing writer
+ assert mode == Mode.IN_${upperName};
+ return writer;
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ final MajorType ${upperName}_TYPE = Types.withScaleAndPrecision(MinorType.${upperName}, DataMode.REPEATED, scale, precision);
+ <#else>
private static final MajorType ${upperName}_TYPE = Types.repeated(MinorType.${upperName});
@Override
public ${capName}Writer ${lowerName}() {
+ </#if>
switch (mode) {
case INIT:
final int vectorCount = container.size();
@@ -181,14 +195,14 @@ public class ${mode}ListWriter extends AbstractFieldWriter {
.build(logger);
}
}
-
+
</#list></#list>
@Override
public MaterializedField getField() {
return container.getField();
}
<#if mode == "Repeated">
-
+
@Override
public void startList() {
final RepeatedListVector list = (RepeatedListVector) container;
diff --git a/exec/vector/src/main/codegen/templates/MapWriters.java b/exec/vector/src/main/codegen/templates/MapWriters.java
index 0f0552817..9074293d7 100644
--- a/exec/vector/src/main/codegen/templates/MapWriters.java
+++ b/exec/vector/src/main/codegen/templates/MapWriters.java
@@ -197,7 +197,8 @@ public class ${mode}MapWriter extends AbstractFieldWriter {
<#assign vectName = capName />
<#assign vectName = "Nullable${capName}" />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
+ @Override
public ${minor.class}Writer ${lowerName}(String name) {
// returns existing writer
final FieldWriter writer = fields.get(name.toLowerCase());
@@ -205,6 +206,7 @@ public class ${mode}MapWriter extends AbstractFieldWriter {
return writer;
}
+ @Override
public ${minor.class}Writer ${lowerName}(String name, int scale, int precision) {
final MajorType ${upperName}_TYPE = Types.withScaleAndPrecision(MinorType.${upperName}, DataMode.OPTIONAL, scale, precision);
<#else>
diff --git a/exec/vector/src/main/codegen/templates/NullReader.java b/exec/vector/src/main/codegen/templates/NullReader.java
index 32ee9b9b9..4d867baa4 100644
--- a/exec/vector/src/main/codegen/templates/NullReader.java
+++ b/exec/vector/src/main/codegen/templates/NullReader.java
@@ -31,20 +31,18 @@ import org.apache.drill.common.types.TypeProtos;
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
-public class NullReader extends AbstractBaseReader implements FieldReader{
+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();
+ private NullReader() {
type = Types.NULL;
}
- private NullReader(MajorType type){
- super();
+ private NullReader(MajorType type) {
this.type = type;
}
@@ -60,63 +58,67 @@ public class NullReader extends AbstractBaseReader implements FieldReader{
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){
+ public void read(${name}Holder holder) {
throw new UnsupportedOperationException("NullReader cannot write into non-nullable holder");
}
- public void read(Nullable${name}Holder holder){
+ public void read(Nullable${name}Holder holder) {
holder.isSet = 0;
}
- public void read(int arrayIndex, ${name}Holder holder){
+ 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 copyAsValue(${minor.class}Writer writer) {}
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${minor.class}Writer writer, int scale, int precision) {}
+ <#else>
+ public void copyAsField(String name, ${minor.class}Writer writer) {}
+ </#if>
- public void read(int arrayIndex, Nullable${name}Holder holder){
+ public void read(int arrayIndex, Nullable${name}Holder holder) {
throw new ArrayIndexOutOfBoundsException();
}
</#list></#list>
- public int size(){
+ public int size() {
return 0;
}
- public boolean isSet(){
+ public boolean isSet() {
return false;
}
- public boolean next(){
+ public boolean next() {
return false;
}
- public RepeatedMapReader map(){
+ public RepeatedMapReader map() {
return this;
}
- public RepeatedListReader list(){
+ public RepeatedListReader list() {
return this;
}
- public MapReader map(String name){
+ public MapReader map(String name) {
return this;
}
- public ListReader list(String name){
+ public ListReader list(String name) {
return this;
}
- public FieldReader reader(String name){
+ public FieldReader reader(String name) {
return this;
}
- public FieldReader reader(){
+ public FieldReader reader() {
return this;
}
- private void fail(String name){
+ 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()));
}
@@ -126,11 +128,11 @@ public class NullReader extends AbstractBaseReader implements FieldReader{
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
return null;
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
return null;
}
</#list>
diff --git a/exec/vector/src/main/codegen/templates/NullableValueVectors.java b/exec/vector/src/main/codegen/templates/NullableValueVectors.java
index 8be5c8b86..c9c098743 100644
--- a/exec/vector/src/main/codegen/templates/NullableValueVectors.java
+++ b/exec/vector/src/main/codegen/templates/NullableValueVectors.java
@@ -482,7 +482,7 @@ public final class ${className} extends BaseDataValueVector implements <#if type
vAccessor.get(index, holder);
holder.isSet = bAccessor.get(index);
- <#if minor.class.startsWith("Decimal")>
+ <#if minor.class.contains("Decimal")>
holder.scale = getField().getScale();
holder.precision = getField().getPrecision();
</#if>
@@ -694,17 +694,29 @@ public final class ${className} extends BaseDataValueVector implements <#if type
}
</#if>
- <#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse">
+ <#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "VarDecimal">
public void set(int index, BigDecimal value) {
+ <#if type.major == "VarLen">
+ if (index > lastSet + 1) {
+ fillEmpties(index);
+ }
+ </#if>
bits.getMutator().set(index, 1);
values.getMutator().set(index, value);
setCount++;
+ <#if type.major == "VarLen">lastSet = index;</#if>
}
public void setSafe(int index, BigDecimal value) {
+ <#if type.major == "VarLen">
+ if (index > lastSet + 1) {
+ fillEmpties(index);
+ }
+ </#if>
bits.getMutator().setSafe(index, 1);
values.getMutator().setSafe(index, value);
setCount++;
+ <#if type.major == "VarLen">lastSet = index;</#if>
}
</#if>
diff --git a/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java b/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
index 2b2b6bd9a..e9884208f 100644
--- a/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
+++ b/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
@@ -404,20 +404,14 @@ public final class Repeated${minor.class}Vector extends BaseRepeatedValueVector
}
}
- <#if (fields?size > 1) && !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
- <#if minor.class == "VarDecimal">
- public void addSafe(int arrayIndex, <#list fields as field><#if field.name == "scale"><#break></#if>${field.type} ${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>) {
- int nextOffset = offsets.getAccessor().get(arrayIndex+1);
- values.getMutator().setSafe(nextOffset, <#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale">, </#if></#list>);
- offsets.getMutator().setSafe(arrayIndex+1, nextOffset+1);
- }
- <#else>
- public void addSafe(int rowIndex, <#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+ <#if (fields?size > 1) && !(minor.class == "Decimal9" || minor.class == "Decimal18"
+ || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense"
+ || minor.class == "Decimal38Dense") || minor.class == "VarDecimal">
+ public void addSafe(int rowIndex<#list fields as field><#if field.include!true>, ${field.type} ${field.name}</#if></#list>) {
final int nextOffset = offsets.getAccessor().get(rowIndex+1);
- values.getMutator().setSafe(nextOffset, <#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- offsets.getMutator().setSafe(rowIndex+1, nextOffset+1);
+ values.getMutator().setSafe(nextOffset<#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
+ offsets.getMutator().setSafe(rowIndex + 1, nextOffset + 1);
}
- </#if>
</#if>
<#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse">
diff --git a/exec/vector/src/main/codegen/templates/UnionListWriter.java b/exec/vector/src/main/codegen/templates/UnionListWriter.java
index a0d26a020..4ea907d1b 100644
--- a/exec/vector/src/main/codegen/templates/UnionListWriter.java
+++ b/exec/vector/src/main/codegen/templates/UnionListWriter.java
@@ -81,6 +81,17 @@ public class UnionListWriter extends AbstractFieldWriter {
return this;
}
+ <#if minor.class == "VarDecimal">
+ @Override
+ public ${name}Writer <#if uncappedName == "int">integer<#else>${uncappedName}</#if>(String name, int scale, int precision) {
+ assert inMap;
+ final int nextOffset = offsets.getAccessor().get(idx() + 1);
+ vector.getMutator().setNotNull(idx());
+ writer.setPosition(nextOffset);
+ ${name}Writer ${uncappedName}Writer = writer.${uncappedName}(name, scale, precision);
+ return ${uncappedName}Writer;
+ }
+ <#else>
@Override
public ${name}Writer <#if uncappedName == "int">integer<#else>${uncappedName}</#if>(String name) {
assert inMap;
@@ -91,6 +102,7 @@ public class UnionListWriter extends AbstractFieldWriter {
return ${uncappedName}Writer;
}
</#if>
+ </#if>
</#list></#list>
@Override
diff --git a/exec/vector/src/main/codegen/templates/UnionWriter.java b/exec/vector/src/main/codegen/templates/UnionWriter.java
index 961810e3a..13c093acf 100644
--- a/exec/vector/src/main/codegen/templates/UnionWriter.java
+++ b/exec/vector/src/main/codegen/templates/UnionWriter.java
@@ -181,7 +181,21 @@ public class UnionWriter extends AbstractFieldWriter implements FieldWriter {
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if !minor.class?starts_with("Decimal")>
+ <#if minor.class == "VarDecimal">
+ @Override
+ public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
+ data.getMutator().setType(idx(), MinorType.MAP);
+ getMapWriter().setPosition(idx());
+ return getMapWriter().${lowerName}(name, scale, precision);
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ data.getMutator().setType(idx(), MinorType.LIST);
+ getListWriter().setPosition(idx());
+ return getListWriter().${lowerName}(scale, precision);
+ }
+ <#else>
@Override
public ${capName}Writer ${lowerName}(String name) {
data.getMutator().setType(idx(), MinorType.MAP);
diff --git a/exec/vector/src/main/codegen/templates/ValueHolders.java b/exec/vector/src/main/codegen/templates/ValueHolders.java
index d5b4342df..7635895be 100644
--- a/exec/vector/src/main/codegen/templates/ValueHolders.java
+++ b/exec/vector/src/main/codegen/templates/ValueHolders.java
@@ -32,99 +32,90 @@ package org.apache.drill.exec.expr.holders;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
-public final class ${className} implements ValueHolder{
-
+<#if minor.class.contains("Decimal") && !minor.class.contains("VarDecimal")>
+/**
+ * Old decimal types are deprecated. Please use {@link VarDecimalHolder} holder instead.
+ */
+@Deprecated
+</#if>
+public final class ${className} implements ValueHolder {
+
+ <#if minor.class.contains("Decimal")>
+ @Deprecated
+ </#if>
public static final MajorType TYPE = Types.${mode.name?lower_case}(MinorType.${minor.class?upper_case});
- <#if mode.name == "Repeated">
+ <#if mode.name == "Repeated">
- /** The first index (inclusive) into the Vector. **/
- public int start;
+ /** The first index (inclusive) into the Vector. **/
+ public int start;
- /** The last index (exclusive) into the Vector. **/
- public int end;
+ /** The last index (exclusive) into the Vector. **/
+ public int end;
- /** The Vector holding the actual values. **/
- public ${minor.class}Vector vector;
+ /** The Vector holding the actual values. **/
+ public ${minor.class}Vector vector;
- <#else>
- public static final int WIDTH = ${type.width};
+ <#else>
+ public static final int WIDTH = ${type.width};
- <#if mode.name == "Optional">public int isSet;</#if>
- <#assign fields = minor.fields!type.fields />
- <#list fields as field>
- public ${field.type} ${field.name};
- </#list>
+ <#if mode.name == "Optional">public int isSet;</#if>
+ <#assign fields = minor.fields!type.fields />
+ <#list fields as field>
+ public ${field.type} ${field.name};
+ </#list>
- <#if minor.class.startsWith("Decimal")>
- public static final int maxPrecision = ${minor.maxPrecisionDigits};
- <#if minor.class.startsWith("Decimal28") || minor.class.startsWith("Decimal38")>
- public static final int nDecimalDigits = ${minor.nDecimalDigits};
+ <#if minor.class.startsWith("Decimal")>
+ public static final int maxPrecision = ${minor.maxPrecisionDigits};
+ <#if minor.class.startsWith("Decimal28") || minor.class.startsWith("Decimal38")>
+ public static final int nDecimalDigits = ${minor.nDecimalDigits};
- public static int getInteger(int index, int start, DrillBuf buffer) {
- int value = buffer.getInt(start + (index * 4));
+ public static int getInteger(int index, int start, DrillBuf buffer) {
+ int value = buffer.getInt(start + (index * 4));
- if (index == 0) {
- /* the first byte contains sign bit, return value without it */
- <#if minor.class.endsWith("Sparse")>
- value = (value & 0x7FFFFFFF);
- <#elseif minor.class.endsWith("Dense")>
- value = (value & 0x0000007F);
- </#if>
- }
- return value;
+ if (index == 0) {
+ /* the first byte contains sign bit, return value without it */
+ <#if minor.class.endsWith("Sparse")>
+ value = (value & 0x7FFFFFFF);
+ <#elseif minor.class.endsWith("Dense")>
+ value = (value & 0x0000007F);
+ </#if>
}
+ return value;
+ }
- public static void setInteger(int index, int value, int start, DrillBuf buffer) {
- buffer.setInt(start + (index * 4), value);
- }
+ public static void setInteger(int index, int value, int start, DrillBuf buffer) {
+ buffer.setInt(start + (index * 4), value);
+ }
- public static void setSign(boolean sign, int start, DrillBuf buffer) {
- // Set MSB to 1 if sign is negative
- if (sign == true) {
- int value = getInteger(0, start, buffer);
- setInteger(0, (value | 0x80000000), start, buffer);
- }
+ public static void setSign(boolean sign, int start, DrillBuf buffer) {
+ // Set MSB to 1 if sign is negative
+ if (sign == true) {
+ int value = getInteger(0, start, buffer);
+ setInteger(0, (value | 0x80000000), start, buffer);
}
+ }
- public static boolean getSign(int start, DrillBuf buffer) {
- return ((buffer.getInt(start) & 0x80000000) != 0);
- }
-
- public java.math.BigDecimal getBigDecimal() {
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(buffer, start, nDecimalDigits, scale);
- return currentValue;
- }
- </#if></#if>
-
- <#if minor.class.startsWith("VarDecimal")>
- public java.math.BigDecimal getBigDecimal() {
- //System.out.println("valueHolder start " + start + " end " + " end " + " scale " + scale);
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(buffer, start, end-start, scale);
- return currentValue;
- }
- </#if>
+ public static boolean getSign(int start, DrillBuf buffer) {
+ return ((buffer.getInt(start) & 0x80000000) != 0);
+ }
- @Deprecated
- public int hashCode(){
- throw new UnsupportedOperationException();
- }
+ </#if></#if>
+ @Deprecated
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
- /*
- * Reason for deprecation is that ValueHolders are potential scalar replacements
- * and hence we don't want any methods to be invoked on them.
- */
- @Deprecated
- public String toString(){
- throw new UnsupportedOperationException();
- }
- </#if>
-
-
-
-
+ /*
+ * Reason for deprecation is that ValueHolders are potential scalar replacements
+ * and hence we don't want any methods to be invoked on them.
+ */
+ @Deprecated
+ public String toString() {
+ throw new UnsupportedOperationException();
+ }
+ </#if>
}
-
</#list>
</#list>
</#list>
diff --git a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
index 8ab4c3a48..6a67772ce 100644
--- a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
+++ b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
@@ -464,6 +464,10 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
holder.start = oAccessor.get(index);
holder.end = oAccessor.get(index + 1);
holder.buffer = data;
+ <#if minor.class.contains("Decimal")>
+ holder.scale = field.getScale();
+ holder.precision = field.getPrecision();
+ </#if>
}
public void get(int index, Nullable${minor.class}Holder holder){
@@ -471,6 +475,10 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
holder.start = oAccessor.get(index);
holder.end = oAccessor.get(index + 1);
holder.buffer = data;
+ <#if minor.class.contains("Decimal")>
+ holder.scale = field.getScale();
+ holder.precision = field.getPrecision();
+ </#if>
}
<#switch minor.class>
@@ -478,7 +486,7 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
@Override
public ${friendlyType} getObject(int index) {
byte[] b = get(index);
- BigInteger bi = b.length == 0 ? new BigInteger("0") : new BigInteger(b);
+ BigInteger bi = b.length == 0 ? BigInteger.ZERO : new BigInteger(b);
BigDecimal bd = new BigDecimal(bi, getField().getScale());
return bd;
}
@@ -672,6 +680,18 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
offsetVector.getMutator().setSafe(index + 1, outputStart + len);
}
+ <#if minor.class == "VarDecimal">
+ public void set(int index, BigDecimal value) {
+ byte[] bytes = value.unscaledValue().toByteArray();
+ set(index, bytes, 0, bytes.length);
+ }
+
+ public void setSafe(int index, BigDecimal value) {
+ byte[] bytes = value.unscaledValue().toByteArray();
+ setSafe(index, bytes, 0, bytes.length);
+ }
+ </#if>
+
public void setSafe(int index, ${minor.class}Holder holder) {
final int start = holder.start;
final int end = holder.end;
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java b/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
index 82809547d..a451b974f 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
@@ -17,20 +17,23 @@
*/
package org.apache.drill.exec.util;
+import com.google.common.math.BigIntegerMath;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DrillBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.util.CoreDecimalUtility;
import org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers;
import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-public class DecimalUtility extends CoreDecimalUtility{
+public class DecimalUtility extends CoreDecimalUtility {
public final static int MAX_DIGITS = 9;
public final static int MAX_DIGITS_INT = 10;
@@ -152,18 +155,18 @@ public class DecimalUtility extends CoreDecimalUtility{
return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, false);
}
- public static BigDecimal getBigDecimalFromSparse(DrillBuf data, int startIndex, int nDecimalDigits, int scale) {
+ public static BigDecimal getBigDecimalFromSparse(DrillBuf data, int startIndex, int nDecimalDigits, int scale) {
- // In the sparse representation we pad the scale with zeroes for ease of arithmetic, need to truncate
- return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, true);
- }
+ // In the sparse representation we pad the scale with zeroes for ease of arithmetic, need to truncate
+ return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, true);
+ }
- public static BigDecimal getBigDecimalFromDrillBuf(DrillBuf bytebuf, int start, int length, int scale) {
- byte[] value = new byte[length];
- bytebuf.getBytes(start, value, 0, length);
- BigInteger unscaledValue = new BigInteger(value);
- return new BigDecimal(unscaledValue, scale);
- }
+ public static BigDecimal getBigDecimalFromDrillBuf(DrillBuf bytebuf, int start, int length, int scale) {
+ byte[] value = new byte[length];
+ bytebuf.getBytes(start, value, 0, length);
+ BigInteger unscaledValue = new BigInteger(value);
+ return new BigDecimal(unscaledValue, scale);
+ }
public static BigDecimal getBigDecimalFromByteBuffer(ByteBuffer bytebuf, int start, int length, int scale) {
byte[] value = new byte[length];
@@ -355,29 +358,27 @@ public class DecimalUtility extends CoreDecimalUtility{
scale -= MAX_DIGITS;
}
- // Set the negative sign
- if (sign == true) {
- data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
- }
-
+ // Set the negative sign
+ if (sign) {
+ data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
}
+ }
- /**
- * Converts from an input BigDecimal into varying width "VarDecimal" representation.
- * The object that manages the "data" is assumed to already have the proper scale set,
- * matching that of input.scale().
- * @param input input decimal number to be stored
- * @param data destination buffer to store the byte array representation of input
- * @param startIndex starting index in data to hold the bytes
- * @return startIndex + length of bytes stored (i.e., the next startIndex in the data buffer)
- */
- public static int getVarDecimalFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex) {
- byte[] bytes = input.unscaledValue().toByteArray();
- int len = bytes.length;
- data.setBytes(startIndex, bytes);
- //System.out.println("getVarDecimal start " + startIndex + " len " + len + " value " + input);
- return startIndex + len;
- }
+ /**
+ * Converts from an input BigDecimal into varying width "VarDecimal" representation.
+ * The object that manages the "data" is assumed to already have the proper scale set,
+ * matching that of input.scale().
+ * @param input input decimal number to be stored
+ * @param data destination buffer to store the byte array representation of input
+ * @param startIndex starting index in data to hold the bytes
+ * @return startIndex + length of bytes stored (i.e., the next startIndex in the data buffer)
+ */
+ public static int getVarDecimalFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex) {
+ byte[] bytes = input.unscaledValue().toByteArray();
+ int len = bytes.length;
+ data.setBytes(startIndex, bytes);
+ return startIndex + len;
+ }
public static long getDecimal18FromBigDecimal(BigDecimal input, int scale, int precision) {
// Truncate or pad to set the input to the correct scale
@@ -451,31 +452,52 @@ public class DecimalUtility extends CoreDecimalUtility{
buffer.setInt(start + (index * 4), value);
}
- /**
- * Compares two VarDecimal values, still stored in their respective Drill buffers
- * @param left left value Drill buffer
- * @param leftStart start offset of left value
- * @param leftEnd end offset of left value
- * @param leftScale scale of left value
- * @param right right value Drill buffer
- * @param rightStart start offset of right value
- * @param rightEnd end offset of right value
- * @param rightScale scale of right value
- * @param absCompare comparison of absolute values is done iff this is true
- * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
- * scales (e.g., 2.00 and 2), are considered equal.
- */
- public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, DrillBuf right, int rightStart, int rightEnd, int rightScale, boolean absCompare) {
- java.math.BigDecimal bdLeft = getBigDecimalFromDrillBuf(left, leftStart, leftEnd - leftStart, leftScale);
- java.math.BigDecimal bdRight = getBigDecimalFromDrillBuf(right, rightStart, rightEnd - rightStart, rightScale);
- if (absCompare) {
- bdLeft = bdLeft.abs();
- bdRight = bdRight.abs();
- }
- return bdLeft.compareTo(bdRight);
- }
+ /**
+ * Compares two VarDecimal values, still stored in their respective Drill buffers
+ *
+ * @param left left value Drill buffer
+ * @param leftStart start offset of left value
+ * @param leftEnd end offset of left value
+ * @param leftScale scale of left value
+ * @param right right value Drill buffer
+ * @param rightStart start offset of right value
+ * @param rightEnd end offset of right value
+ * @param rightScale scale of right value
+ * @param absCompare comparison of absolute values is done iff this is true
+ * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
+ * scales (e.g., 2.00 and 2), are considered equal.
+ */
+ public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, DrillBuf right, int rightStart, int rightEnd, int rightScale, boolean absCompare) {
+ byte[] rightBytes = new byte[rightEnd - rightStart];
+ right.getBytes(rightStart, rightBytes, 0, rightEnd - rightStart);
+
+ return compareVarLenBytes(left, leftStart, leftEnd, leftScale, rightBytes, rightScale, absCompare);
+ }
+
+ /**
+ * Compares two VarDecimal values, still stored in Drill buffer and byte array
+ *
+ * @param left left value Drill buffer
+ * @param leftStart start offset of left value
+ * @param leftEnd end offset of left value
+ * @param leftScale scale of left value
+ * @param right right value byte array
+ * @param rightScale scale of right value
+ * @param absCompare comparison of absolute values is done iff this is true
+ * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
+ * scales (e.g., 2.00 and 2), are considered equal.
+ */
+ public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, byte right[], int rightScale, boolean absCompare) {
+ java.math.BigDecimal bdLeft = getBigDecimalFromDrillBuf(left, leftStart, leftEnd - leftStart, leftScale);
+ java.math.BigDecimal bdRight = new BigDecimal(new BigInteger(right), rightScale);
+ if (absCompare) {
+ bdLeft = bdLeft.abs();
+ bdRight = bdRight.abs();
+ }
+ return bdLeft.compareTo(bdRight);
+ }
- public static int compareSparseBytes(DrillBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, DrillBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits, boolean absCompare) {
+ public static int compareSparseBytes(DrillBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, DrillBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits, boolean absCompare) {
int invert = 1;
@@ -782,5 +804,73 @@ public class DecimalUtility extends CoreDecimalUtility{
}
return cmp * invert;
}
-}
+ /**
+ * Returns max length of byte array, required to store value with specified precision.
+ *
+ * @param precision the precision of value
+ *
+ * @return max length of byte array
+ */
+ public static int getMaxBytesSizeForPrecision(int precision) {
+ if (precision == 0) {
+ return 0;
+ }
+ if (precision < 300) { // normal case, use exact heuristic formula
+ return (int) Math.ceil((Math.log(Math.pow(10, precision) - 1) / Math.log(2) + 1) / Byte.SIZE);
+ } else {
+ // for values greater than 304 Math.pow(10, precision) returns Infinity, therefore 1 is neglected in Math.log()
+ return (int) Math.ceil((precision * Math.log(10) / Math.log(2) + 1) / Byte.SIZE);
+ }
+ }
+
+ /**
+ * Calculates and returns square root for specified BigDecimal
+ * with specified number of digits alter decimal point.
+ *
+ * @param in BigDecimal which square root should be calculated
+ * @param scale number of digits alter decimal point in the result value.
+ * @return square root for specified BigDecimal
+ */
+ public static BigDecimal sqrt(BigDecimal in, int scale) {
+ // unscaled BigInteger value from specified BigDecimal with doubled number of digits after decimal point
+ // was used to calculate sqrt using Guava's BigIntegerMath.
+ BigInteger valueWithDoubleMaxPrecision =
+ in.multiply(BigDecimal.TEN.pow(scale * 2)).setScale(0, RoundingMode.HALF_UP).unscaledValue();
+ return new BigDecimal(
+ BigIntegerMath.sqrt(valueWithDoubleMaxPrecision, RoundingMode.HALF_UP), scale);
+ }
+
+ /**
+ * Checks that specified decimal minorType is obsolete.
+ *
+ * @param minorType type to check
+ * @return true if specified decimal minorType is obsolete.
+ */
+ public static boolean isObsoleteDecimalType(TypeProtos.MinorType minorType) {
+ return minorType == TypeProtos.MinorType.DECIMAL9 ||
+ minorType == TypeProtos.MinorType.DECIMAL18 ||
+ minorType == TypeProtos.MinorType.DECIMAL28SPARSE ||
+ minorType == TypeProtos.MinorType.DECIMAL38SPARSE;
+ }
+
+ /**
+ * Returns default precision for specified {@link TypeProtos.MinorType}
+ * or returns specified defaultPrecision if {@link TypeProtos.MinorType} isn't
+ * {@link TypeProtos.MinorType#INT} or {@link TypeProtos.MinorType#BIGINT}.
+ *
+ * @param minorType type wich precision should be received
+ * @param defaultPrecision default value for precision
+ * @return default precision for specified {@link TypeProtos.MinorType}
+ */
+ public static int getDefaultPrecision(TypeProtos.MinorType minorType, int defaultPrecision) {
+ switch (minorType) {
+ case INT:
+ return MAX_DIGITS_INT;
+ case BIGINT:
+ return MAX_DIGITS_BIGINT;
+ default:
+ return defaultPrecision;
+ }
+ }
+}
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
index 73b2b551e..d1cc3b4a1 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
@@ -37,6 +37,7 @@ import org.apache.drill.exec.expr.holders.NullableBitHolder;
import org.apache.drill.exec.expr.holders.TimeHolder;
import org.apache.drill.exec.expr.holders.TimeStampHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
+import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.memory.BufferAllocator;
import org.apache.drill.exec.util.DecimalUtility;
@@ -200,4 +201,22 @@ public class ValueHolderHelper {
return dch;
}
+
+ public static VarDecimalHolder getVarDecimalHolder(DrillBuf buf, String decimal) {
+ VarDecimalHolder dch = new VarDecimalHolder();
+
+ BigDecimal bigDecimal = new BigDecimal(decimal);
+
+ byte[] bytes = bigDecimal.unscaledValue().toByteArray();
+ int length = bytes.length;
+
+ dch.scale = bigDecimal.scale();
+ dch.precision = bigDecimal.precision();
+ dch.start = 0;
+ dch.end = length;
+ dch.buffer = buf.reallocIfNeeded(length);
+ dch.buffer.setBytes(0, bytes);
+
+ return dch;
+ }
}
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
index 1fa785748..937df8603 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
@@ -229,6 +229,11 @@ public class MapOrListWriterImpl implements MapOrListWriter {
}
@Override
+ public VarDecimalWriter varDecimal(String name, int scale, int precision) {
+ return (map != null) ? map.varDecimal(name, scale, precision) : list.varDecimal(scale, precision);
+ }
+
+ @Override
public Decimal38SparseWriter decimal38Sparse(String name) {
return (map != null) ? map.decimal38Sparse(name) : list.decimal38Sparse();
}