/*------------------------------------------------------------------------------------------------- _______ __ _ _______ _______ ______ ______ |_____| | \ | | |______ | \ |_____] | | | \_| | ______| |_____/ |_____] Copyright (c) 2016, antsdb.com and/or its affiliates. All rights reserved. *-xguo0<@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU GNU Lesser General Public License, version 3, as published by the Free Software Foundation. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/lgpl-3.0.en.html> -------------------------------------------------------------------------------------------------*/ package com.antsdb.saltedfish.sql.vdm; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.NotImplementedException; import com.antsdb.saltedfish.sql.DataType; import com.antsdb.saltedfish.sql.meta.ColumnMeta; import com.antsdb.saltedfish.util.UberUtil; import com.google.common.primitives.UnsignedBytes; /** * * - Lexicographic. to be compatible with hbase * * @author xguo * */ class KeyUtil { /** * return the number of bytes that the key uses * * @param columns * @return */ static int getSize(List<ColumnMeta> columns) { int size = 0; for (ColumnMeta i:columns) { DataType type = i.getDataType(); if (type.getJavaType() == Integer.class) { size += 4; } else if (type.getJavaType() == Long.class) { size += 8; } else { throw new NotImplementedException(type + " is not supported to particiate in index"); } } return size; } static void toBytes(List<ColumnMeta> columns, byte[] bytes, List<Object> values, byte filler) { int pos = 0; for (int i=0; i<columns.size(); i++) { ColumnMeta column = columns.get(i); if (i < values.size()) { Object value = values.get(i); pos += write(column, bytes, pos, value); } else { Arrays.fill(bytes, pos, bytes.length, filler); } } } /** * * @param column * @param bytes * @param pos * @param obj * @return number of bytes written */ static int write(ColumnMeta column, byte[] bytes, int pos, Object obj) { DataType type = column.getDataType(); if (obj == null) { throw new NotImplementedException("null is not supported as part of key for now"); } if (type.getJavaType() == Integer.class) { Integer value = 0; if (obj != null) { value = UberUtil.toObject(Integer.class, obj); } if (value < 0) { throw new NotImplementedException("negtive number is not yet supported"); } bytes[pos+0] = (byte) (value >> 24); bytes[pos+1] = (byte) (value >> 16); bytes[pos+2] = (byte) (value >> 8); bytes[pos+3] = (byte) (int)value; return 4; } else if (type.getJavaType() == Long.class) { Long value = 0l; if (obj != null) { value = UberUtil.toObject(Long.class, obj); } if (value < 0) { throw new NotImplementedException("negtive number is not yet supported"); } for (int i = 7; i >= 0; i--) { bytes[pos+i] = (byte) (value & 0xffL); value >>= 8; } return 8; } else { throw new NotImplementedException(type + " is not supported to particiate in index"); } } public static void add(byte[] bytes, byte n) { int overflow = 0; for (int i = bytes.length-1; i >= 0; i--) { int v = (bytes[i] & 0xff) + n + overflow; bytes[i] = (byte) v; overflow = v >>> 8; if (overflow == 0) { break; } n = 0; } if (overflow > 0) { Arrays.fill(bytes, (byte)0xff); } else if (overflow < 0) { Arrays.fill(bytes, (byte)0); } } public static byte[] max(byte[] value1, byte[] value2) { if (value1 == null) { return value2; } else if (value2 == null) { return value1; } else { int result = UnsignedBytes.lexicographicalComparator().compare(value1, value2); return (result >= 0) ? value1 : value2; } } public static byte[] min(byte[] value1, byte[] value2) { if (value1 == null) { return value2; } else if (value2 == null) { return value1; } else { int result = UnsignedBytes.lexicographicalComparator().compare(value1, value2); return (result <= 0) ? value1 : value2; } } }