Repository: phoenix Updated Branches: refs/heads/master d59f0e539 -> 8e2f087bd
PHOENIX-3494 ArrayIndexOutOfBoundsException with decimal desc key Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8e2f087b Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8e2f087b Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8e2f087b Branch: refs/heads/master Commit: 8e2f087bdb3b86fcbdf2e7e00918b8abb2ac8752 Parents: d59f0e5 Author: James Taylor <[email protected]> Authored: Thu Nov 17 16:12:44 2016 -0800 Committer: James Taylor <[email protected]> Committed: Thu Nov 17 16:12:44 2016 -0800 ---------------------------------------------------------------------- .../apache/phoenix/end2end/UpsertValuesIT.java | 22 ++++++++++++++++++++ .../apache/phoenix/schema/types/PDataType.java | 4 ++-- .../apache/phoenix/schema/types/PDecimal.java | 6 +++--- .../phoenix/schema/types/PDataTypeTest.java | 18 +++++++++++----- 4 files changed, 40 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/8e2f087b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpsertValuesIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpsertValuesIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpsertValuesIT.java index 498c4a3..eb81ae3 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpsertValuesIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpsertValuesIT.java @@ -162,6 +162,28 @@ public class UpsertValuesIT extends BaseClientManagedTimeIT { assertEquals("a", rs.getString(1)); assertEquals("2013-06-08 00:00:00.000", rs.getString(2)); } + + @Test + public void testUpsertValuesWithDescDecimal() throws Exception { + long ts = nextTimestamp(); + Properties props = new Properties(); + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts)); + Connection conn = DriverManager.getConnection(getUrl(), props); + conn.createStatement().execute("create table UpsertDecimalDescTest (k DECIMAL(12,3) NOT NULL PRIMARY KEY DESC)"); + conn.close(); + + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts+5)); + conn = DriverManager.getConnection(getUrl(), props); + conn.createStatement().execute("upsert into UpsertDecimalDescTest values (0.0)"); + conn.commit(); + conn.close(); + + props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts+10)); + conn = DriverManager.getConnection(getUrl(), props); + ResultSet rs = conn.createStatement().executeQuery("select k from UpsertDecimalDescTest"); + assertTrue(rs.next()); + assertEquals(0.0, rs.getDouble(1), 0.001); + } @Test public void testUpsertRandomValues() throws Exception { http://git-wip-us.apache.org/repos/asf/phoenix/blob/8e2f087b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java index 58018ac..18956e8 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java @@ -689,9 +689,9 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType< // Calculate the precision and scale of a raw decimal bytes. Returns the values as an int // array. The first value is precision, the second value is scale. // Default scope for testing - protected static int[] getDecimalPrecisionAndScale(byte[] bytes, int offset, int length) { + protected static int[] getDecimalPrecisionAndScale(byte[] bytes, int offset, int length, SortOrder sortOrder) { // 0, which should have no precision nor scale. - if (length == 1 && bytes[offset] == ZERO_BYTE) { return new int[] { 0, 0 }; } + if (length == 1 && sortOrder.normalize(bytes[offset]) == ZERO_BYTE) { return new int[] { 0, 0 }; } int signum = ((bytes[offset] & 0x80) == 0) ? -1 : 1; int scale; int index; http://git-wip-us.apache.org/repos/asf/phoenix/blob/8e2f087b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java index 9fff730..b76febb 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java @@ -321,8 +321,8 @@ public class PDecimal extends PRealNumber<BigDecimal> { maxLength = v.precision(); scale = v.scale(); } else { - this.coerceBytes(ptr, value, srcType, maxLength, scale, SortOrder.getDefault(), desiredMaxLength, desiredScale, sortOrder, true); - int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength()); + this.coerceBytes(ptr, value, srcType, maxLength, scale, sortOrder, desiredMaxLength, desiredScale, sortOrder, true); + int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder); maxLength = v[0]; scale = v[1]; } @@ -352,7 +352,7 @@ public class PDecimal extends PRealNumber<BigDecimal> { BigDecimal v = (BigDecimal) object; scale = v.scale(); } else { - int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength()); + int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength(), actualModifier); scale = v[1]; } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/8e2f087b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java index ba48a8a..d07364c 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/types/PDataTypeTest.java @@ -1537,7 +1537,14 @@ public class PDataTypeTest { // Special case for 0. BigDecimal bd = new BigDecimal("0"); byte[] b = PDecimal.INSTANCE.toBytes(bd); - int[] v = PDataType.getDecimalPrecisionAndScale(b, 0, b.length); + int[] v = PDataType.getDecimalPrecisionAndScale(b, 0, b.length, SortOrder.getDefault()); + assertEquals(0, v[0]); + assertEquals(0, v[1]); + + // Special case for 0 descending + bd = new BigDecimal("0"); + b = PDecimal.INSTANCE.toBytes(bd, SortOrder.DESC); + v = PDataType.getDecimalPrecisionAndScale(b, 0, b.length, SortOrder.DESC); assertEquals(0, v[0]); assertEquals(0, v[1]); @@ -1572,8 +1579,9 @@ public class PDataTypeTest { }; for (int i=0; i<bds.length; i++) { - testReadDecimalPrecisionAndScaleFromRawBytes(bds[i]); - testReadDecimalPrecisionAndScaleFromRawBytes(bds[i].negate()); + testReadDecimalPrecisionAndScaleFromRawBytes(bds[i], SortOrder.ASC); + testReadDecimalPrecisionAndScaleFromRawBytes(bds[i], SortOrder.DESC); + testReadDecimalPrecisionAndScaleFromRawBytes(bds[i].negate(), SortOrder.getDefault()); } assertTrue(new BigDecimal("5").remainder(BigDecimal.ONE).equals(BigDecimal.ZERO)); @@ -1662,9 +1670,9 @@ public class PDataTypeTest { } } - private void testReadDecimalPrecisionAndScaleFromRawBytes(BigDecimal bd) { + private void testReadDecimalPrecisionAndScaleFromRawBytes(BigDecimal bd, SortOrder sortOrder) { byte[] b = PDecimal.INSTANCE.toBytes(bd); - int[] v = PDataType.getDecimalPrecisionAndScale(b, 0, b.length); + int[] v = PDataType.getDecimalPrecisionAndScale(b, 0, b.length, sortOrder); assertEquals(bd.toString(), bd.precision(), v[0]); assertEquals(bd.toString(), bd.scale(), v[1]); }
