Skip to content

Commit

Permalink
Add Decimal Vector APIs to write Big Endian data
Browse files Browse the repository at this point in the history
  • Loading branch information
siddharthteotia committed Dec 8, 2017
1 parent c8b6467 commit 41b11bf
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ public void write(${name}Holder holder) {
public void write${minor.class}(${friendlyType} value) {
fail("${name}");
}

public void writeBigEndianBytesToDecimal(byte[] value) {
fail("${name}");
}
</#if>

</#list></#list>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* limitations under the License.
*/

import io.netty.buffer.ArrowBuf;
import org.apache.arrow.vector.types.Types;
import org.apache.drill.common.types.TypeProtos.MinorType;

<@pp.dropOutputFile />
Expand Down Expand Up @@ -82,6 +84,12 @@ public void write(${name}Holder holder) {
getWriter(MinorType.${name?upper_case}).write${minor.class}(<#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
}

<#if minor.class == "Decimal">
public void writeBigEndianBytesToDecimal(byte[] value) {
getWriter(Types.MinorType.DECIMAL).writeBigEndianBytesToDecimal(value);
}
</#if>

</#list></#list>
public void writeNull() {
}
Expand Down
7 changes: 7 additions & 0 deletions java/vector/src/main/codegen/templates/ComplexWriters.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public void write(Nullable${minor.class}Holder h) {
vector.setSafe(idx(), value);
vector.setValueCount(idx()+1);
}

public void writeBigEndianBytesToDecimal(byte[] value) {
vector.setBigEndianSafe(idx(), value);
vector.setValueCount(idx()+1);
}
</#if>

<#if mode == "Nullable">
Expand Down Expand Up @@ -148,6 +153,8 @@ public interface ${eName}Writer extends BaseWriter {
<#if minor.class == "Decimal">

public void write${minor.class}(${friendlyType} value);

public void writeBigEndianBytesToDecimal(byte[] value);
</#if>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.apache.arrow.vector;

import com.google.common.base.Preconditions;
import io.netty.buffer.ArrowBuf;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.complex.impl.DecimalReaderImpl;
Expand Down Expand Up @@ -199,6 +200,43 @@ public void set(int index, ArrowBuf buffer) {
valueBuffer.setBytes(index * TYPE_WIDTH, buffer, 0, TYPE_WIDTH);
}

/**
* Set the decimal element at given index to the provided array of bytes.
* Decimal is now implemented as Little Endian. This API allows the user
* to pass a decimal value in the form of byte array in BE byte order.
*
* Consumers of Arrow code can use this API instead of first swapping
* the source bytes (doing a write and read) and then finally writing to
* ArrowBuf of decimal vector.
*
* This method takes care of adding the necessary padding if the length
* of byte array is less then 16 (length of decimal type).
*
* @param index position of element
* @param value array of bytes containing decimal in big endian byte order.
*/
public void setBigEndian(int index, byte[] value) {
assert value.length <= TYPE_WIDTH;
BitVectorHelper.setValidityBitToOne(validityBuffer, index);
final int length = value.length;
int startIndex = index * TYPE_WIDTH;
if (length == TYPE_WIDTH) {
for (int i = TYPE_WIDTH - 1; i >= 3; i-=4) {
valueBuffer.setByte(startIndex, value[i]);
valueBuffer.setByte(startIndex + 1, value[i-1]);
valueBuffer.setByte(startIndex + 2, value[i-2]);
valueBuffer.setByte(startIndex + 3, value[i-3]);
startIndex += 4;
}
} else {
for (int i = length - 1; i >= 0; i--) {
valueBuffer.setByte(startIndex, value[i]);
startIndex++;
}
valueBuffer.setZero(startIndex, TYPE_WIDTH - length);
}
}

/**
* Set the element at the given index to the given value.
*
Expand Down Expand Up @@ -266,6 +304,16 @@ public void setSafe(int index, ArrowBuf buffer) {
set(index, buffer);
}

/**
* Same as {@link #setBigEndian(int, byte[])} except that it handles the
* case when index is greater than or equal to existing
* value capacity {@link #getValueCapacity()}.
*/
public void setBigEndianSafe(int index, byte[] value) {
handleSafe(index);
setBigEndian(index, value);
}

/**
* Same as {@link #set(int, int, ArrowBuf)} except that it handles the
* case when index is greater than or equal to existing
Expand Down

0 comments on commit 41b11bf

Please sign in to comment.