PHOENIX-4933 DELETE FROM throws NPE when a local index is present.

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

Branch: refs/heads/4.14-cdh5.12
Commit: f4cf4612f0609613f5123231c71fdc30badb1dbc
Parents: 96afa0f
Author: Lars Hofhansl <la...@apache.org>
Authored: Mon Oct 1 19:57:44 2018 +0100
Committer: Pedro Boado <pbo...@apache.org>
Committed: Wed Oct 17 20:31:32 2018 +0100

----------------------------------------------------------------------
 .../phoenix/end2end/index/LocalIndexIT.java     | 22 +++++++++++++++++
 .../tuple/EncodedColumnQualiferCellsList.java   | 25 +++++++++++++-------
 2 files changed, 39 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/f4cf4612/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalIndexIT.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalIndexIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalIndexIT.java
index 0dcf1d5..796d5a2 100644
--- 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalIndexIT.java
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalIndexIT.java
@@ -78,7 +78,29 @@ public class LocalIndexIT extends BaseLocalIndexIT {
     public LocalIndexIT(boolean isNamespaceMapped) {
         super(isNamespaceMapped);
     }
+
+    @Test
+    public void testDeleteFromLocalIndex() throws Exception {
+        String tableName = schemaName + "." + generateUniqueName();
+        String indexName = "IDX_" + generateUniqueName();
     
+        Connection conn = getConnection();
+        conn.setAutoCommit(true);
+        if (isNamespaceMapped) {
+            conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + 
schemaName);
+        }
+
+        conn.createStatement().execute("CREATE TABLE " + tableName + " (pk 
INTEGER PRIMARY KEY, v1 FLOAT, v2 FLOAT)");
+        conn.createStatement().execute("CREATE LOCAL INDEX " + indexName + " 
ON " + tableName + "(v2)");
+        conn.createStatement().execute("UPSERT INTO " + tableName + " 
VALUES(1, rand(), rand())");
+        // This would fail with an NPE before PHOENIX-4933
+        conn.createStatement().execute("DELETE FROM " + tableName + " WHERE v1 
< 1");
+        ResultSet rs = conn.createStatement().executeQuery("SELECT COUNT(*) 
FROM "+tableName);
+        rs.next();
+        assertEquals(0, rs.getInt(1));
+        rs.close();
+    }
+
     @Test
     public void testLocalIndexRoundTrip() throws Exception {
         String tableName = schemaName + "." + generateUniqueName();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/f4cf4612/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
index 10329fb..db3647d 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/tuple/EncodedColumnQualiferCellsList.java
@@ -175,14 +175,7 @@ public class EncodedColumnQualiferCellsList implements 
List<Cell> {
                     firstNonNullElementIdx = -1;
                 } else if (firstNonNullElementIdx == i) {
                     // the element being removed was the first non-null 
element we knew
-                    while (i < array.length && (array[i]) == null) {
-                        i++;
-                    }
-                    if (i < array.length) {
-                        firstNonNullElementIdx = i;
-                    } else {
-                        firstNonNullElementIdx = -1;
-                    }
+                    adjustFirstNonNullElement();
                 }
                 modCount++;
                 return true;
@@ -383,6 +376,18 @@ public class EncodedColumnQualiferCellsList implements 
List<Cell> {
         return getCellForColumnQualifier(columnQualifier);
     }
 
+    private void adjustFirstNonNullElement() {
+        int i = firstNonNullElementIdx;
+        while (i < array.length && (array[i]) == null) {
+            i++;
+        }
+        if (i < array.length) {
+            firstNonNullElementIdx = i;
+        } else {
+            firstNonNullElementIdx = -1;
+        }
+
+    }
     private Cell getCellForColumnQualifier(int columnQualifier) {
         checkQualifierRange(columnQualifier);
         int idx = getArrayIndex(columnQualifier);
@@ -461,6 +466,10 @@ public class EncodedColumnQualiferCellsList implements 
List<Cell> {
             }
             checkForCoModification();
             array[lastRet] = null;
+            if (firstNonNullElementIdx == lastRet) {
+                // the element being removed was the first non-null element we 
knew
+                adjustFirstNonNullElement();
+            }
             lastRet = -1;
             numNonNullElements--;
             modCount++;

Reply via email to