in serde/src/java/org/apache/hadoop/hive/serde2/binarysortable/fast/BinarySortableDeserializeRead.java [238:495]
private boolean readPrimitive(Field field) throws IOException {
final int fieldIndex = root.index;
field.start = inputByteBuffer.tell();
/*
* We have a field and are positioned to it. Read it.
*/
switch (field.primitiveCategory) {
case BOOLEAN:
currentBoolean = (inputByteBuffer.read(columnSortOrderIsDesc[fieldIndex]) == 2);
return true;
case BYTE:
currentByte = (byte) (inputByteBuffer.read(columnSortOrderIsDesc[fieldIndex]) ^ 0x80);
return true;
case SHORT:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int v = inputByteBuffer.read(invert) ^ 0x80;
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
currentShort = (short) v;
}
return true;
case INT:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int v = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 3; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
currentInt = v;
}
return true;
case LONG:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
long v = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 7; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
currentLong = v;
}
return true;
case DATE:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int v = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 3; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
currentDateWritable.set(v);
}
return true;
case TIMESTAMP:
{
if (tempTimestampBytes == null) {
tempTimestampBytes = new byte[TimestampWritableV2.BINARY_SORTABLE_LENGTH];
}
final boolean invert = columnSortOrderIsDesc[fieldIndex];
for (int i = 0; i < tempTimestampBytes.length; i++) {
tempTimestampBytes[i] = inputByteBuffer.read(invert);
}
currentTimestampWritable.setBinarySortable(tempTimestampBytes, 0);
}
return true;
case FLOAT:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int v = 0;
for (int i = 0; i < 4; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
if ((v & (1 << 31)) == 0) {
// negative number, flip all bits
v = ~v;
} else {
// positive number, flip the first bit
v = v ^ (1 << 31);
}
currentFloat = Float.intBitsToFloat(v);
}
return true;
case DOUBLE:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
long v = 0;
for (int i = 0; i < 8; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
if ((v & (1L << 63)) == 0) {
// negative number, flip all bits
v = ~v;
} else {
// positive number, flip the first bit
v = v ^ (1L << 63);
}
currentDouble = Double.longBitsToDouble(v);
}
return true;
case BINARY:
case STRING:
case CHAR:
case VARCHAR:
{
/*
* This code is a modified version of BinarySortableSerDe.deserializeText that lets us
* detect if we can return a reference to the bytes directly.
*/
// Get the actual length first
bytesStart = inputByteBuffer.tell();
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int length = 0;
do {
byte b = inputByteBuffer.read(invert);
if (b == 0) {
// end of string
break;
}
if (b == 1) {
// the last char is an escape char. read the actual char
inputByteBuffer.read(invert);
}
length++;
} while (true);
if (length == 0 ||
(!invert && length == inputByteBuffer.tell() - bytesStart - 1)) {
// No inversion or escaping happened, so we are can reference directly.
currentExternalBufferNeeded = false;
currentBytes = inputByteBuffer.getData();
currentBytesStart = bytesStart;
currentBytesLength = length;
} else {
// We are now positioned at the end of this field's bytes.
if (useExternalBuffer) {
// If we decided not to reposition and re-read the buffer to copy it with
// copyToExternalBuffer, we we will still be correctly positioned for the next field.
currentExternalBufferNeeded = true;
currentExternalBufferNeededLen = length;
} else {
// The copyToBuffer will reposition and re-read the input buffer.
currentExternalBufferNeeded = false;
if (internalBufferLen < length) {
internalBufferLen = length;
internalBuffer = new byte[internalBufferLen];
}
copyToBuffer(internalBuffer, 0, length);
currentBytes = internalBuffer;
currentBytesStart = 0;
currentBytesLength = length;
}
}
}
return true;
case INTERVAL_YEAR_MONTH:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int v = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 3; i++) {
v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
}
currentHiveIntervalYearMonthWritable.set(v);
}
return true;
case INTERVAL_DAY_TIME:
{
final boolean invert = columnSortOrderIsDesc[fieldIndex];
long totalSecs = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 7; i++) {
totalSecs = (totalSecs << 8) + (inputByteBuffer.read(invert) & 0xff);
}
int nanos = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 3; i++) {
nanos = (nanos << 8) + (inputByteBuffer.read(invert) & 0xff);
}
currentHiveIntervalDayTimeWritable.set(totalSecs, nanos);
}
return true;
case DECIMAL:
{
// Since enforcing precision and scale can cause a HiveDecimal to become NULL,
// we must read it, enforce it here, and either return NULL or buffer the result.
final boolean invert = columnSortOrderIsDesc[fieldIndex];
int b = inputByteBuffer.read(invert) - 1;
if (!(b == 1 || b == -1 || b == 0)) {
throw new IOException("Unexpected byte value " + (int)b + " in binary sortable format data (invert " + invert + ")");
}
final boolean positive = b != -1;
int factor = inputByteBuffer.read(invert) ^ 0x80;
for (int i = 0; i < 3; i++) {
factor = (factor << 8) + (inputByteBuffer.read(invert) & 0xff);
}
if (!positive) {
factor = -factor;
}
final int decimalStart = inputByteBuffer.tell();
int length = 0;
do {
b = inputByteBuffer.read(positive ? invert : !invert);
if (b == 1) {
throw new IOException("Expected -1 and found byte value " + (int)b + " in binary sortable format data (invert " + invert + ")");
}
if (b == 0) {
// end of digits
break;
}
length++;
} while (true);
// CONSIDER: Allocate a larger initial size.
if(tempDecimalBuffer == null || tempDecimalBuffer.length < length) {
tempDecimalBuffer = new byte[length];
}
inputByteBuffer.seek(decimalStart);
for (int i = 0; i < length; ++i) {
tempDecimalBuffer[i] = inputByteBuffer.read(positive ? invert : !invert);
}
// read the null byte again
inputByteBuffer.read(positive ? invert : !invert);
// Set the value of the writable from the decimal digits that were written with no dot.
final int scale = length - factor;
currentHiveDecimalWritable.setFromDigitsOnlyBytesWithScale(
!positive, tempDecimalBuffer, 0, length, scale);
boolean decimalIsNull = !currentHiveDecimalWritable.isSet();
if (!decimalIsNull) {
// We have a decimal. After we enforce precision and scale, will it become a NULL?
final DecimalTypeInfo decimalTypeInfo = (DecimalTypeInfo) field.typeInfo;
final int enforcePrecision = decimalTypeInfo.getPrecision();
final int enforceScale = decimalTypeInfo.getScale();
decimalIsNull =
!currentHiveDecimalWritable.mutateEnforcePrecisionScale(
enforcePrecision, enforceScale);
}
if (decimalIsNull) {
return false;
}
}
return true;
default:
throw new RuntimeException("Unexpected primitive type category " + field.primitiveCategory);
}
}