[
https://issues.apache.org/jira/browse/PHOENIX-1875?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14527945#comment-14527945
]
ASF GitHub Bot commented on PHOENIX-1875:
-----------------------------------------
Github user ramkrish86 commented on a diff in the pull request:
https://github.com/apache/phoenix/pull/79#discussion_r29644654
--- Diff:
phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
---
@@ -543,6 +544,151 @@ private static void writeEndBytes(byte[] array, int
newOffsetArrayPosition, int
Bytes.putByte(array, newOffsetArrayPosition + offsetArrayLength +
byteSize + 2 * Bytes.SIZEOF_INT, header);
}
+ public static boolean prependItemToArray(ImmutableBytesWritable ptr,
int length, int offset, byte[] arrayBytes, PDataType baseType, int arrayLength,
Integer maxLength, SortOrder sortOrder) {
+ int elementLength = maxLength == null ? ptr.getLength() :
maxLength;
+ if (ptr.getLength() == 0) {
+ elementLength = 0;
+ }
+ //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;
+ arrayLength = Math.abs(arrayLength);
+
+ //checks whether offset array consists of shorts or integers
+ boolean useInt = offsetArrayLength / arrayLength ==
Bytes.SIZEOF_INT;
+ boolean convertToInt = false;
+ int endElementPosition = getOffset(arrayBytes, arrayLength -
1, !useInt, offsetArrayPosition + offset) + elementLength + Bytes.SIZEOF_BYTE;
+ int newOffsetArrayPosition;
+ int offsetShift;
+ int firstNonNullElementPosition = 0;
+ int currentPosition = 0;
+ //handle the case where prepended element is null
+ if (elementLength == 0) {
+ int nulls = 1;
+ //counts the number of nulls which are already at the
beginning of the array
+ for (int index = 0; index < arrayLength; index++) {
+ int currOffset = getOffset(arrayBytes, index, !useInt,
offsetArrayPosition + offset);
+ if (arrayBytes[offset + currOffset] ==
QueryConstants.SEPARATOR_BYTE) {
+ nulls++;
+ } else {
+ //gets the offset of the first element after nulls
at the beginning
+ firstNonNullElementPosition = currOffset;
+ break;
+ }
+ }
+
+ int nMultiplesOver255 = nulls / 255;
+ int nRemainingNulls = nulls % 255;
+ int bytesForRemainingNulls = nRemainingNulls == 0 ? 0:1;
+ endElementPosition = getOffset(arrayBytes, arrayLength -
1, !useInt, offsetArrayPosition + offset) + nMultiplesOver255 +
bytesForRemainingNulls + Bytes.SIZEOF_BYTE - firstNonNullElementPosition;
+ if (!useInt) {
+ if
(PArrayDataType.useShortForOffsetArray(endElementPosition)) {
+ newArray = new byte[length + Bytes.SIZEOF_SHORT +
nMultiplesOver255 + bytesForRemainingNulls + Bytes.SIZEOF_BYTE -
firstNonNullElementPosition];
+ } else {
+ newArray = new byte[length + arrayLength *
Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + nMultiplesOver255 +
bytesForRemainingNulls + Bytes.SIZEOF_BYTE - firstNonNullElementPosition];
+ convertToInt = true;
+ }
+ } else {
+ newArray = new byte[length + Bytes.SIZEOF_INT +
nMultiplesOver255 + bytesForRemainingNulls + Bytes.SIZEOF_BYTE -
firstNonNullElementPosition];
+ }
+ newArray[currentPosition] = QueryConstants.SEPARATOR_BYTE;
+ currentPosition++;
+
+ newOffsetArrayPosition = offsetArrayPosition +
bytesForRemainingNulls + nMultiplesOver255 + Bytes.SIZEOF_BYTE -
firstNonNullElementPosition;
+ offsetShift = nMultiplesOver255 + bytesForRemainingNulls +
Bytes.SIZEOF_BYTE - firstNonNullElementPosition;
+ while (nMultiplesOver255-- > 0) {
+ newArray[currentPosition] = (byte) 1;
+ currentPosition++;
+ }
+ // Write a byte for the remaining null elements
+ if (nRemainingNulls > 0) {
+ byte nNullByte = SortOrder.invert((byte)
(nRemainingNulls - 1));
+ newArray[currentPosition] = nNullByte; // Single byte
for repeating nulls
+ currentPosition++;
+ }
+ } else {
+ if (!useInt) {
+ if
(PArrayDataType.useShortForOffsetArray(endElementPosition)) {
+ 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];
+ }
+ newOffsetArrayPosition = offsetArrayPosition +
Bytes.SIZEOF_BYTE + elementLength;
+
+ offsetShift = elementLength + Bytes.SIZEOF_BYTE;
+ System.arraycopy(elementBytes, elementOffset, newArray, 0,
elementLength);
+ currentPosition += elementLength + Bytes.SIZEOF_BYTE;
+ }
+
+ System.arraycopy(arrayBytes, firstNonNullElementPosition +
offset, newArray, currentPosition, offsetArrayPosition);
+
+ arrayLength = arrayLength + 1;
+ //writes the new offset and changes the previous offsets
+ if (useInt || convertToInt) {
+ writeNewOffsets(arrayBytes, newArray, false, !useInt,
newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, offsetShift,
length);
+ } else {
+ writeNewOffsets(arrayBytes, newArray, true, true,
newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, offsetShift,
length);
+ }
+ } else {
+ newArray = new byte[length + elementLength];
+
+ System.arraycopy(elementBytes, elementOffset, newArray, 0,
elementLength);
+ System.arraycopy(arrayBytes, offset, newArray, elementLength,
length);
+ }
+
+ ptr.set(newArray);
+ return true;
+ }
+
+ private static void writeNewOffsets(byte[] arrayBytes, byte[]
newArray, boolean useShortNew, boolean useShortPrevious, int
newOffsetArrayPosition, int arrayLength, int offsetArrayPosition, int offset,
int offsetShift, int length) {
+ int currentPosition = newOffsetArrayPosition;
+ int offsetArrayElementSize = useShortNew ? Bytes.SIZEOF_SHORT :
Bytes.SIZEOF_INT;
+ if (useShortNew) {
+ Bytes.putShort(newArray, currentPosition, (short) (0 -
Short.MAX_VALUE));
+ } else {
+ Bytes.putInt(newArray, currentPosition, 0);
+ }
+
+ currentPosition += offsetArrayElementSize;
+ boolean isFirstNullGroup = true;
--- End diff --
Better name for this? Says 'nullsAtBeginning' (may be something better)?
> implement ARRAY_PREPEND built in function
> -----------------------------------------
>
> Key: PHOENIX-1875
> URL: https://issues.apache.org/jira/browse/PHOENIX-1875
> Project: Phoenix
> Issue Type: Sub-task
> Reporter: Dumindu Buddhika
> Assignee: Dumindu Buddhika
> Attachments: PHOENIX-1875-v2.patch
>
>
> ARRAY_PREPEND(1, ARRAY[2, 3]) = ARRAY[1, 2, 3]
> ARRAY_PREPEND("a", ARRAY["b", "c"]) = ARRAY["a", "b", "c"]
> ARRAY_PREPEND(null, ARRAY["b", "c"]) = ARRAY[null, "b", "c"]
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)