Repository: phoenix Updated Branches: refs/heads/master 9566c78bd -> 0bcb872ba
PHOENIX-4534 upsert/delete/upsert for the same row corrupts the indexes Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/0bcb872b Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/0bcb872b Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/0bcb872b Branch: refs/heads/master Commit: 0bcb872ba7bb74e3131a339440e38f9689471388 Parents: 9566c78 Author: Rajeshbabu Chintaguntla <[email protected]> Authored: Thu May 10 10:25:38 2018 -0700 Committer: ss77892 <[email protected]> Committed: Thu May 10 10:29:59 2018 -0700 ---------------------------------------------------------------------- .../phoenix/end2end/index/MutableIndexIT.java | 41 ++++++++++++++++++++ .../filter/ApplyAndFilterDeletesFilter.java | 7 ---- .../index/scanner/FilteredKeyValueScanner.java | 7 +++- 3 files changed, 47 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/0bcb872b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/MutableIndexIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/MutableIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/MutableIndexIT.java index e968e99..cfaed72 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/MutableIndexIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/MutableIndexIT.java @@ -910,6 +910,47 @@ public class MutableIndexIT extends ParallelStatsDisabledIT { } } + + @Test + public void testUpsertingDeletedRowShouldGiveProperDataWithIndexes() throws Exception { + testUpsertingDeletedRowShouldGiveProperDataWithIndexes(false); + } + + @Test + public void testUpsertingDeletedRowShouldGiveProperDataWithMultiCFIndexes() throws Exception { + testUpsertingDeletedRowShouldGiveProperDataWithIndexes(true); + } + + private void testUpsertingDeletedRowShouldGiveProperDataWithIndexes(boolean multiCf) throws Exception { + String tableName = "TBL_" + generateUniqueName(); + String indexName = "IDX_" + generateUniqueName(); + String columnFamily1 = "cf1"; + String columnFamily2 = "cf2"; + String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName); + try (Connection conn = getConnection()) { + conn.createStatement().execute( + "create table " + fullTableName + " (id integer primary key, " + + (multiCf ? columnFamily1 : "") + "f float, " + + (multiCf ? columnFamily2 : "") + "s varchar)" + tableDDLOptions); + conn.createStatement().execute( + "create index " + indexName + " on " + fullTableName + " (" + + (multiCf ? columnFamily1 : "") + "f) include ("+(multiCf ? columnFamily2 : "") +"s)"); + conn.createStatement().execute( + "upsert into " + fullTableName + " values (1, 0.5, 'foo')"); + conn.commit(); + conn.createStatement().execute("delete from " + fullTableName + " where id = 1"); + conn.commit(); + conn.createStatement().execute( + "upsert into " + fullTableName + " values (1, 0.5, 'foo')"); + conn.commit(); + ResultSet rs = conn.createStatement().executeQuery("select * from "+indexName); + assertTrue(rs.next()); + assertEquals(1, rs.getInt(2)); + assertEquals(0.5F, rs.getFloat(1), 0.0); + assertEquals("foo", rs.getString(3)); + } + } + private void upsertRow(String dml, Connection tenantConn, int i) throws SQLException { PreparedStatement stmt = tenantConn.prepareStatement(dml); stmt.setString(1, "00000000000000" + String.valueOf(i)); http://git-wip-us.apache.org/repos/asf/phoenix/blob/0bcb872b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/filter/ApplyAndFilterDeletesFilter.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/filter/ApplyAndFilterDeletesFilter.java b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/filter/ApplyAndFilterDeletesFilter.java index 17779ba..2e9878d 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/filter/ApplyAndFilterDeletesFilter.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/covered/filter/ApplyAndFilterDeletesFilter.java @@ -105,11 +105,6 @@ public class ApplyAndFilterDeletesFilter extends FilterBase { @Override public ReturnCode filterKeyValue(Cell next) { - // we marked ourselves done, but the END_ROW_KEY didn't manage to seek to the very last key - if (this.done) { - return ReturnCode.SKIP; - } - KeyValue nextKV = KeyValueUtil.ensureKeyValue(next); switch (KeyValue.Type.codeToType(next.getTypeByte())) { /* @@ -186,8 +181,6 @@ public class ApplyAndFilterDeletesFilter extends FilterBase { getNextFamily(new ImmutableBytesPtr(peeked.getBuffer(), peeked.getFamilyOffset(), peeked.getFamilyLength())); if (nextFamily == null) { - // no known next family, so we can be completely done - done = true; return KeyValue.LOWESTKEY; } // there is a valid family, so we should seek to that http://git-wip-us.apache.org/repos/asf/phoenix/blob/0bcb872b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/scanner/FilteredKeyValueScanner.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/scanner/FilteredKeyValueScanner.java b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/scanner/FilteredKeyValueScanner.java index 072b624..06e74a3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/scanner/FilteredKeyValueScanner.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/scanner/FilteredKeyValueScanner.java @@ -94,7 +94,12 @@ public class FilteredKeyValueScanner implements ReseekableScanner { break; // use a seek hint to find out where we should go case SEEK_NEXT_USING_HINT: - delegate.seek(KeyValueUtil.ensureKeyValue(filter.getNextCellHint(peeked))); + Cell nextCellHint = filter.getNextCellHint(peeked); + if(nextCellHint == KeyValue.LOWESTKEY) { + delegate.next(); + } else { + delegate.seek(KeyValueUtil.ensureKeyValue(nextCellHint)); + } } } }
