PHOENIX-1705 implement ARRAY_APPEND built in function (Dumindu Buddhika)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/986080f3 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/986080f3 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/986080f3 Branch: refs/heads/calcite Commit: 986080f3fb939252c01b8c79d0bcdb602e0ddd64 Parents: 1b45110 Author: ramkrishna <[email protected]> Authored: Tue Apr 14 23:26:22 2015 +0530 Committer: ramkrishna <[email protected]> Committed: Tue Apr 14 23:26:22 2015 +0530 ---------------------------------------------------------------------- .../phoenix/expression/ExpressionType.java | 4 +- .../phoenix/schema/types/PArrayDataType.java | 85 ++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/986080f3/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java index d562d6a..22778ce 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.phoenix.expression.function.ArrayAllComparisonExpression; import org.apache.phoenix.expression.function.ArrayAnyComparisonExpression; +import org.apache.phoenix.expression.function.ArrayAppendFunction; import org.apache.phoenix.expression.function.ArrayElemRefExpression; import org.apache.phoenix.expression.function.ArrayIndexFunction; import org.apache.phoenix.expression.function.ArrayLengthFunction; @@ -211,7 +212,8 @@ public enum ExpressionType { NowFunction(NowFunction.class), InstrFunction(InstrFunction.class), MinuteFunction(MinuteFunction.class), - DayOfMonthFunction(DayOfMonthFunction.class) + DayOfMonthFunction(DayOfMonthFunction.class), + ArrayAppendFunction(ArrayAppendFunction.class) ; ExpressionType(Class<? extends Expression> clazz) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/986080f3/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java index c183b7a..b6dce34 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java @@ -456,6 +456,91 @@ public abstract class PArrayDataType<T> extends PDataType<T> { return null; } + public static boolean appendItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes, PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) { + int elementLength = maxLength == null ? ptr.getLength() : maxLength; + + //padding + if (elementLength > ptr.getLength()) { + baseType.pad(ptr, elementLength, sortOrder); + } + + int elementOffset = ptr.getOffset(); + byte[] elementBytes = ptr.get(); + + byte[] newArray; + if (!baseType.isFixedWidth()) { + + int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT); + int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE; + + //checks whether offset array consists of shorts or integers + boolean useInt = offsetArrayLength / Math.abs(arrayLength) == Bytes.SIZEOF_INT; + boolean convertToInt = false; + + int newElementPosition = offsetArrayPosition - 2 * Bytes.SIZEOF_BYTE; + + if (!useInt) { + if (PArrayDataType.useShortForOffsetArray(newElementPosition)) { + newArray = new byte[length + elementLength + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE]; + } else { + newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE]; + convertToInt = true; + } + } else { + newArray = new byte[length + elementLength + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE]; + } + + int newOffsetArrayPosition = newElementPosition + elementLength + 3 * Bytes.SIZEOF_BYTE; + + System.arraycopy(arrayBytes, offset, newArray, 0, newElementPosition); + System.arraycopy(elementBytes, elementOffset, newArray, newElementPosition, elementLength); + + arrayLength = (Math.abs(arrayLength) + 1) * (int) Math.signum(arrayLength); + if (useInt) { + System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition, offsetArrayLength); + Bytes.putInt(newArray, newOffsetArrayPosition + offsetArrayLength, newElementPosition); + + writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset + length - 1], true); + } else { + if (!convertToInt) { + System.arraycopy(arrayBytes, offset + offsetArrayPosition, newArray, newOffsetArrayPosition, offsetArrayLength); + Bytes.putShort(newArray, newOffsetArrayPosition + offsetArrayLength, (short) (newElementPosition - Short.MAX_VALUE)); + + writeEndBytes(newArray, newOffsetArrayPosition, offsetArrayLength, arrayLength, arrayBytes[offset + length - 1], false); + } else { + int off = newOffsetArrayPosition; + for (int arrayIndex = 0; arrayIndex < Math.abs(arrayLength) - 1; arrayIndex++) { + Bytes.putInt(newArray, off, getOffset(arrayBytes, arrayIndex, true, offsetArrayPosition)); + off += Bytes.SIZEOF_INT; + } + + Bytes.putInt(newArray, off, newElementPosition); + Bytes.putInt(newArray, off + Bytes.SIZEOF_INT, newOffsetArrayPosition); + Bytes.putInt(newArray, off + 2 * Bytes.SIZEOF_INT, -arrayLength); + Bytes.putByte(newArray, off + 3 * Bytes.SIZEOF_INT, arrayBytes[offset + length - 1]); + + } + } + } else { + newArray = new byte[length + elementLength]; + + System.arraycopy(arrayBytes, offset, newArray, 0, length); + System.arraycopy(elementBytes, elementOffset, newArray, length, elementLength); + } + + ptr.set(newArray); + + return true; + } + + private static void writeEndBytes(byte[] array, int newOffsetArrayPosition, int offsetArrayLength, int arrayLength, byte header, boolean useInt) { + int byteSize = useInt ? Bytes.SIZEOF_INT : Bytes.SIZEOF_SHORT; + + Bytes.putInt(array, newOffsetArrayPosition + offsetArrayLength + byteSize, newOffsetArrayPosition); + Bytes.putInt(array, newOffsetArrayPosition + offsetArrayLength + byteSize + Bytes.SIZEOF_INT, arrayLength); + Bytes.putByte(array, newOffsetArrayPosition + offsetArrayLength + byteSize + 2 * Bytes.SIZEOF_INT, header); + } + public static int serailizeOffsetArrayIntoStream(DataOutputStream oStream, TrustedByteArrayOutputStream byteStream, int noOfElements, int maxOffset, int[] offsetPos) throws IOException { int offsetPosition = (byteStream.size());
