package com.g414.haildb;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.Arrays;
import com.g414.haildb.impl.jna.HailDB;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class TupleStorage {
public static Object coerceType(String value, ColumnType type) {
if (value == null) {
throw new IllegalArgumentException("Value must not be null");
}
Object toReturn = null;
switch (type) {
case BLOB:
case BINARY:
case VARBINARY:
toReturn = value.getBytes();
break;
case CHAR:
case CHAR_ANYCHARSET:
case VARCHAR:
case VARCHAR_ANYCHARSET:
toReturn = value;
break;
case INT:
toReturn = new BigInteger(value);
break;
case DECIMAL:
toReturn = value;
break;
case FLOAT:
case DOUBLE:
toReturn = new BigDecimal(value);
break;
default:
throw new IllegalArgumentException("Unsupported Type: " + type);
}
return toReturn;
}
public static boolean areEqual(Object a, Object b, ColumnType type) {
if (a == null && b == null) {
return true;
}
if ((a != null && b == null) || (a == null && b != null)) {
return false;
}
if (a instanceof String) {
a = coerceType((String) a, type);
}
if (b instanceof String) {
b = coerceType((String) b, type);
}
switch (type) {
case BLOB:
case BINARY:
case VARBINARY:
return Arrays.equals((byte[]) a, (byte[]) b);
case CHAR:
case CHAR_ANYCHARSET:
case VARCHAR:
case VARCHAR_ANYCHARSET:
return a.equals(b);
case INT:
return new BigInteger(a.toString()).equals(new BigInteger(b
.toString()));
case FLOAT:
case DOUBLE:
return new BigDecimal(a.toString()).equals(new BigDecimal(b
.toString()));
case DECIMAL:
return a.toString().equals(b.toString());
default:
throw new IllegalArgumentException("Unsupported Type: " + type);
}
}
public static Number loadInteger(Tuple tupl, int i, int length,
boolean signed) {
ByteBuffer buf = ByteBuffer.allocateDirect(length);
if (HailDB.ib_col_get_len(tupl.tupl, i) == HailDB.IB_SQL_NULL) {
return null;
}
switch (length) {
case 1:
Util.assertSuccess(HailDB.ib_tuple_read_u8(tupl.tupl, i, buf));
break;
case 2:
ShortBuffer sbuf = buf.asShortBuffer();
Util.assertSuccess(HailDB.ib_tuple_read_u16(tupl.tupl, i, sbuf));
break;
case 4:
IntBuffer ibuf = buf.asIntBuffer();
Util.assertSuccess(HailDB.ib_tuple_read_u32(tupl.tupl, i, ibuf));
break;
case 8:
LongBuffer lbuf = buf.asLongBuffer();
Util.assertSuccess(HailDB.ib_tuple_read_u64(tupl.tupl, i, lbuf));
break;
default:
throw new IllegalArgumentException("Invalid length: " + length);
}
byte[] theBytes = new byte[length];
int k = 0;
for (int j = length - 1; j >= 0; j--) {
theBytes[k] = buf.get(j);
k += 1;
}
return signed ? new BigInteger(theBytes) : new BigInteger(1, theBytes);
}
public static void storeInteger(Tuple tupl, ColumnDef colDef, int i,
Number numVal) {
switch (colDef.getLength()) {
case 1:
Util.assertSuccess(HailDB.ib_tuple_write_u8(tupl.tupl, i,
numVal.byteValue()));
break;
case 2:
Util.assertSuccess(HailDB.ib_tuple_write_u16(tupl.tupl, i,
numVal.shortValue()));
break;
case 4:
Util.assertSuccess(HailDB.ib_tuple_write_u32(tupl.tupl, i,
numVal.intValue()));
break;
case 8:
Util.assertSuccess(HailDB.ib_tuple_write_u64(tupl.tupl, i,
numVal.longValue()));
break;
default:
throw new IllegalArgumentException(
"integer type not supported for length: "
+ colDef.getLength());
}
}
public static void storeBytes(Tuple tupl, int i, byte[] val) {
Util.assertSuccess(HailDB.ib_col_set_value(tupl.tupl, i,
TupleStorage.getDirectMemoryBytes(val), val.length));
}
public static byte[] loadBytes(Tuple tupl, int index) {
int len = HailDB.ib_col_get_len(tupl.tupl, index);
if (len == HailDB.IB_SQL_NULL) {
return null;
}
return HailDB.ib_col_get_value(tupl.tupl, index).getByteArray(0, len);
}
public static void storeString(Tuple tupl, int i, String stringVal) {
try {
byte[] stringBytes = stringVal.getBytes("UTF-8");
Pointer stringPointer = TupleStorage
.getDirectMemoryString(stringBytes);
Util.assertSuccess(HailDB.ib_col_set_value(tupl.tupl, i,
stringPointer, stringBytes.length + 1));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Java doesn't recognize UTF-8?!");
}
}
public static String loadString(Tuple tupl, int index) {
int len = HailDB.ib_col_get_len(tupl.tupl, index);
if (len == HailDB.IB_SQL_NULL) {
return null;
}
return HailDB.ib_col_get_value(tupl.tupl, index).getString(0);
}
private static Pointer getDirectMemoryBytes(byte[] value) {
if (value == null || value.length == 0) {
return Pointer.NULL;
}
int len = value.length;
Memory m = new Memory(len);
m.getByteBuffer(0, len).put(value);
return Native.getDirectBufferPointer(m.getByteBuffer(0, len));
}
public static Pointer getDirectMemoryString(byte[] stringBytes) {
if (stringBytes == null || stringBytes.length == 0) {
return Pointer.NULL;
}
int length = stringBytes.length + 1;
Memory m = new Memory(length);
ByteBuffer buf = m.getByteBuffer(0, length).order(
ByteOrder.nativeOrder());
buf.put(stringBytes).put((byte) 0);
return Native.getDirectBufferPointer(buf);
}
}