[ 
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)

Reply via email to