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/calcite Commit: 33d60506c5f2d4408a1df79f278d7a45d3401a27 Parents: ec93ec7 Author: ramkrishna <[email protected]> Authored: Thu Jul 16 21:13:31 2015 +0530 Committer: ramkrishna <[email protected]> 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); + } }
