You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ra...@apache.org on 2015/07/16 17:44:40 UTC

phoenix git commit: PHOENIX-2067 Sort order incorrect for variable length DESC columns - ARRAY addendum (Dumindu Buddhika)

Repository: phoenix
Updated Branches:
  refs/heads/master ec93ec79c -> 33d60506c


PHOENIX-2067 Sort order incorrect for variable length DESC columns - ARRAY
addendum (Dumindu Buddhika)


Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/33d60506
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/33d60506
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/33d60506

Branch: refs/heads/master
Commit: 33d60506c5f2d4408a1df79f278d7a45d3401a27
Parents: ec93ec7
Author: ramkrishna <ra...@gmail.com>
Authored: Thu Jul 16 21:13:31 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Thu Jul 16 21:13:31 2015 +0530

----------------------------------------------------------------------
 .../phoenix/schema/types/PArrayDataType.java    |  14 +-
 .../expression/ArrayAppendFunctionTest.java     |  76 ++++++++---
 .../expression/ArrayConcatFunctionTest.java     | 129 +++++++++++++++++++
 .../expression/ArrayPrependFunctionTest.java    |  61 +++++++++
 .../schema/types/PDataTypeForArraysTest.java    |  70 +++++++++-
 5 files changed, 324 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/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 dd11569..9ca64c5 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
@@ -379,10 +379,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
                 int currOffset = getOffset(bytes, arrayIndex, useShort, indexOffset);
                 int elementLength = 0;
                 if (arrayIndex == (noOfElements - 1)) {
-                    elementLength = bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE ? 0 : indexOffset
+                    elementLength = (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : indexOffset
                             - (currOffset + initPos) - 3;
                 } else {
-                    elementLength = bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE ? 0 : getOffset(bytes,
+                    elementLength = (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : getOffset(bytes,
                             arrayIndex + 1, useShort, indexOffset) - currOffset - 1;
                 }
                 ptr.set(bytes, currOffset + initPos, elementLength);
@@ -426,10 +426,10 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
                 int currOffset = getOffset(bytes, arrayIndex, useShort, indexOffset);
                 int elementLength = 0;
                 if (arrayIndex == (noOfElements - 1)) {
-                    elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : indexOffset
+                    elementLength = (bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : indexOffset
                             - (currOffset + offset) - 3;
                 } else {
-                    elementLength = bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE ? 0 : getOffset(bytes,
+                    elementLength = (bytes[currOffset + offset] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) ? 0 : getOffset(bytes,
                             arrayIndex + 1, useShort, indexOffset) - currOffset - 1;
                 }
                 ptr.set(bytes, currOffset + offset, elementLength);
@@ -831,7 +831,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
             // count nulls at the end of array 1
             for (int index = actualLengthOfArray1 - 1; index > -1; index--) {
                 int offset = getOffset(array1Bytes, index, !useIntArray1, array1BytesOffset + offsetArrayPositionArray1);
-                if (array1Bytes[array1BytesOffset + offset] == QueryConstants.SEPARATOR_BYTE) {
+                if (array1Bytes[array1BytesOffset + offset] == QueryConstants.SEPARATOR_BYTE || array1Bytes[array1BytesOffset + offset] == QueryConstants.DESC_SEPARATOR_BYTE) {
                     nullsAtTheEndOfArray1++;
                 } else {
                     break;
@@ -1064,11 +1064,11 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
                         nextOff = getOffset(indexArr, countOfElementsRead + 1, useShort, indexOffset);
                     }
                     countOfElementsRead++;
-                    if ((bytes[currOffset + initPos] != QueryConstants.SEPARATOR_BYTE) && foundNull) {
+                    if ((bytes[currOffset + initPos] != QueryConstants.SEPARATOR_BYTE && bytes[currOffset + initPos] != QueryConstants.DESC_SEPARATOR_BYTE) && foundNull) {
                         // Found a non null element
                         foundNull = false;
                     }
-                    if (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE) {
+                    if (bytes[currOffset + initPos] == QueryConstants.SEPARATOR_BYTE || bytes[currOffset + initPos] == QueryConstants.DESC_SEPARATOR_BYTE) {
                         // Null element
                         foundNull = true;
                         i++;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
index 5405ef3..a98bccc 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayAppendFunctionTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.expression;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.math.BigDecimal;
@@ -27,21 +28,7 @@ import java.util.List;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.phoenix.expression.function.ArrayAppendFunction;
 import org.apache.phoenix.schema.SortOrder;
-import org.apache.phoenix.schema.types.PBoolean;
-import org.apache.phoenix.schema.types.PChar;
-import org.apache.phoenix.schema.types.PDataType;
-import org.apache.phoenix.schema.types.PDate;
-import org.apache.phoenix.schema.types.PDecimal;
-import org.apache.phoenix.schema.types.PDouble;
-import org.apache.phoenix.schema.types.PFloat;
-import org.apache.phoenix.schema.types.PInteger;
-import org.apache.phoenix.schema.types.PLong;
-import org.apache.phoenix.schema.types.PSmallint;
-import org.apache.phoenix.schema.types.PTime;
-import org.apache.phoenix.schema.types.PTimestamp;
-import org.apache.phoenix.schema.types.PTinyint;
-import org.apache.phoenix.schema.types.PVarchar;
-import org.apache.phoenix.schema.types.PhoenixArray;
+import org.apache.phoenix.schema.types.*;
 import org.junit.Test;
 
 import com.google.common.collect.Lists;
@@ -357,4 +344,63 @@ public class ArrayAppendFunctionTest {
         test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
     }
 
+    @Test
+    public void testForCorrectSeparatorBytes1() throws Exception {
+        Object[] o = new Object[]{"a", "b", "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+        expressions.add(elementLiteral);
+
+        Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayAppendFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes2() throws Exception {
+        Object[] o = new Object[]{"a", "b", "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+        expressions.add(elementLiteral);
+
+        Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayAppendFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-98, -1, -99, -1, -100, -1, -101, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes3() throws Exception {
+        Object[] o = new Object[]{"a", null, null, "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) arrayLiteral);
+        expressions.add(elementLiteral);
+
+        Expression arrayAppendFunction = new ArrayAppendFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayAppendFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-98, -1, 0, -2, -100, -1, -101, -1, -1, -1, -128, 1, -128, 3, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 5, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
index 75d0827..f23729e 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayConcatFunctionTest.java
@@ -18,6 +18,7 @@
 
 package org.apache.phoenix.expression;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 import java.math.BigDecimal;
@@ -485,6 +486,9 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
     }
 
     @Test
@@ -504,6 +508,9 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
     }
 
     @Test
@@ -523,6 +530,9 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
     }
 
     @Test
@@ -542,6 +552,9 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
     }
 
     @Test
@@ -561,6 +574,9 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
     }
 
     @Test
@@ -580,5 +596,118 @@ public class ArrayConcatFunctionTest {
         PhoenixArray arr2 = new PhoenixArray(base, o2);
         PhoenixArray expected = new PhoenixArray(base, e);
         test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+        test(arr1, arr2, type, null, null, type, null, null, expected, SortOrder.DESC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes1() throws Exception {
+        Object[] o1 = new Object[]{"a", "b"};
+        Object[] o2 = new Object[]{"c", "d", "e"};
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+
+        PhoenixArray arr1 = new PhoenixArray(base, o1);
+        PhoenixArray arr2 = new PhoenixArray(base, o2);
+        LiteralExpression array1Literal, array2Literal;
+        array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+        expressions.add(array2Literal);
+
+        Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayConcatFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes2() throws Exception {
+        Object[] o1 = new Object[]{"a", "b"};
+        Object[] o2 = new Object[]{"c", "d", "e"};
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+
+        PhoenixArray arr1 = new PhoenixArray(base, o1);
+        PhoenixArray arr2 = new PhoenixArray(base, o2);
+        LiteralExpression array1Literal, array2Literal;
+        array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+        expressions.add(array2Literal);
+
+        Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayConcatFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes3() throws Exception {
+        Object[] o1 = new Object[]{"a", "b"};
+        Object[] o2 = new Object[]{"c", "d", "e"};
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+
+        PhoenixArray arr1 = new PhoenixArray(base, o1);
+        PhoenixArray arr2 = new PhoenixArray(base, o2);
+        LiteralExpression array1Literal, array2Literal;
+        array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+        expressions.add(array2Literal);
+
+        Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayConcatFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-98, -1, -99, -1, -100, -1, -101, -1, -102, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, -128, 9, 0, 0, 0, 12, 0, 0, 0, 5, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes4() throws Exception {
+        Object[] o1 = new Object[]{"a", "b", null};
+        Object[] o2 = new Object[]{null, "c", "d", "e"};
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+
+        PhoenixArray arr1 = new PhoenixArray(base, o1);
+        PhoenixArray arr2 = new PhoenixArray(base, o2);
+        LiteralExpression array1Literal, array2Literal;
+        array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+        expressions.add(array2Literal);
+
+        Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayConcatFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{97, 0, 98, 0, 0, -2, 99, 0, 100, 0, 101, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 5, -128, 7, -128, 9, -128, 11, 0, 0, 0, 14, 0, 0, 0, 7, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes5() throws Exception {
+        Object[] o1 = new Object[]{"a", "b", null, null};
+        Object[] o2 = new Object[]{null, "c", "d", "e"};
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+
+        PhoenixArray arr1 = new PhoenixArray(base, o1);
+        PhoenixArray arr2 = new PhoenixArray(base, o2);
+        LiteralExpression array1Literal, array2Literal;
+        array1Literal = LiteralExpression.newConstant(arr1, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        array2Literal = LiteralExpression.newConstant(arr2, type, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) array1Literal);
+        expressions.add(array2Literal);
+
+        Expression arrayConcatFunction = new ArrayConcatFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayConcatFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-98, -1, -99, -1, 0, -3, -100, -1, -101, -1, -102, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 5, -128, 5, -128, 7, -128, 9, -128, 11, 0, 0, 0, 14, 0, 0, 0, 8, 1};
+        assertArrayEquals(expected, ptr.get());
     }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
index 4d2f960..b64f013 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.expression;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 import java.math.BigDecimal;
@@ -549,4 +550,64 @@ public class ArrayPrependFunctionTest {
         PhoenixArray expected = new PhoenixArray(baseType, o2);
         test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
     }
+
+    @Test
+    public void testForCorrectSeparatorBytes1() throws Exception {
+        Object[] o = new Object[]{"a", "b", "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+        expressions.add(arrayLiteral);
+
+        Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayPrependFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{100, 0, 97, 0, 98, 0, 99, 0, 0, 0, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes2() throws Exception {
+        Object[] o = new Object[]{"a", "b", "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+        expressions.add(arrayLiteral);
+
+        Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayPrependFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-101, -1, -98, -1, -99, -1, -100, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 4, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
+
+    @Test
+    public void testForCorrectSeparatorBytes3() throws Exception {
+        Object[] o = new Object[]{"a", null, null, "c"};
+        Object element = "d";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(arr, PVarcharArray.INSTANCE, null, null, SortOrder.DESC, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, baseType, null, null, SortOrder.ASC, Determinism.ALWAYS);
+        List<Expression> expressions = Lists.newArrayList((Expression) elementLiteral);
+        expressions.add(arrayLiteral);
+
+        Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayPrependFunction.evaluate(null, ptr);
+        byte[] expected = new byte[]{-101, -1, -98, -1, 0, -2, -100, -1, -1, -1, -128, 1, -128, 3, -128, 5, -128, 5, -128, 7, 0, 0, 0, 10, 0, 0, 0, 5, 1};
+        assertArrayEquals(expected, ptr.get());
+    }
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/33d60506/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
index 0610cda..7246020 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeForArraysTest.java
@@ -17,9 +17,6 @@
  */
 package org.apache.phoenix.schema.types;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 import java.math.BigDecimal;
 import java.sql.Date;
 import java.sql.Time;
@@ -27,6 +24,8 @@ import java.sql.Timestamp;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.types.PArrayDataType;
 import org.apache.phoenix.schema.types.PBoolean;
 import org.apache.phoenix.schema.types.PBooleanArray;
@@ -76,6 +75,8 @@ import org.apache.phoenix.schema.types.PhoenixArray;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import static org.junit.Assert.*;
+
 public class PDataTypeForArraysTest {
 	@Test
 	public void testForIntegerArray() {
@@ -1137,5 +1138,66 @@ public class PDataTypeForArraysTest {
         byte[] bytes2 = PVarcharArray.INSTANCE.toBytes(arr);
         assertTrue(Bytes.compareTo(bytes1, bytes2) == 0);
     }
-    
+
+    @Test
+    public void testIsRowKeyOrderOptimized1() {
+        Object[] objects = new Object[]{"a", "b", "c"};
+        PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+        byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.ASC);
+        assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.ASC, bytes, 0, bytes.length));
+    }
+
+    @Test
+    public void testIsRowKeyOrderOptimized2() {
+        Object[] objects = new Object[]{"a", "b", "c"};
+        PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+        byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, SortOrder.DESC);
+        assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, bytes, 0, bytes.length));
+    }
+
+    @Test
+    public void testIsRowKeyOrderOptimized3() {
+        Object[] objects = new Object[]{"a", "b", "c"};
+        PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+        byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, SortOrder.DESC);
+        for (int i = 0; i < bytes.length; i++) {
+            if (bytes[i] == QueryConstants.DESC_SEPARATOR_BYTE) {
+                bytes[i] = QueryConstants.SEPARATOR_BYTE;
+            }
+        }
+        assertFalse(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, bytes, 0, bytes.length));
+    }
+
+    @Test
+    public void testIsRowKeyOrderOptimized4() {
+        assertTrue(PArrayDataType.isRowKeyOrderOptimized(PVarcharArray.INSTANCE, SortOrder.DESC, null, 0, 0));
+    }
+
+    @Test
+    public void testIsRowKeyOrderOptimized5() {
+        Object[] objects = new Object[]{1, 2, 3};
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(PInteger.INSTANCE, objects);
+        byte[] bytes = PIntegerArray.INSTANCE.toBytes(arr, PInteger.INSTANCE, SortOrder.ASC);
+        assertTrue(PArrayDataType.isRowKeyOrderOptimized(PIntegerArray.INSTANCE, SortOrder.ASC, bytes, 0, bytes.length));
+    }
+
+    @Test
+    public void testVarcharArrayDesc(){
+        Object[] objects = new Object[]{"a", "b", null};
+        PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+        byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.DESC);
+        PhoenixArray arr2 = (PhoenixArray)PVarcharArray.INSTANCE.toObject(bytes, SortOrder.DESC);
+        assertEquals(arr, arr2);
+    }
+
+    @Test
+    public void testPositionAtArrayElementWithDescArray(){
+        Object[] objects = new Object[]{"a", "b", null};
+        PhoenixArray arr = new PhoenixArray(PVarchar.INSTANCE, objects);
+        byte[] bytes = PVarcharArray.INSTANCE.toBytes(arr, PVarchar.INSTANCE, SortOrder.DESC);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable(bytes);
+        PArrayDataType.positionAtArrayElement(ptr, 2, PVarchar.INSTANCE, null);
+        String value = (String)PVarchar.INSTANCE.toObject(ptr, SortOrder.DESC);
+        assertEquals(null, value);
+    }
 }