kadirozde commented on a change in pull request #611: PHOENIX-5535 Replay 
delete markers during server side global index re…
URL: https://github.com/apache/phoenix/pull/611#discussion_r340266698
 
 

 ##########
 File path: phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolIT.java
 ##########
 @@ -157,6 +162,70 @@ public static void setup() throws Exception {
         return TestUtil.filterTxParamData(list,0);
     }
 
+    private void setEveryNthRowWithNull(int nrows, int nthRowNull, 
PreparedStatement stmt) throws Exception {
+        for (int i = 1; i <= nrows; i++) {
+            stmt.setInt(1, i);
+            stmt.setInt(2, i + 1);
+            if (i % nthRowNull != 0) {
+                stmt.setInt(3, i * i);
+            } else {
+                stmt.setNull(3, Types.INTEGER);
+            }
+            stmt.execute();
+        }
+    }
+
+    @Test
+    public void testWithSetNull() throws Exception {
+        // This test is for building non-transactional mutable global indexes 
with direct api
+        if (localIndex || transactional || !mutable || !directApi || 
useSnapshot) {
+            return;
+        }
+        // This tests the cases where a column having a null value is 
overwritten with a not null value and vice versa;
+        // and after that the index table is still rebuilt correctly
+        final int NROWS = 2 * 3 * 5 * 7;
+        String schemaName = generateUniqueName();
+        String dataTableName = generateUniqueName();
+        String dataTableFullName = SchemaUtil.getTableName(schemaName, 
dataTableName);
+        String indexTableName = generateUniqueName();
+        String indexTableFullName = SchemaUtil.getTableName(schemaName, 
indexTableName);
+        Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+        try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+            conn.createStatement().execute("CREATE TABLE " + dataTableFullName
+                    + " (ID INTEGER NOT NULL PRIMARY KEY, VAL1 INTEGER, VAL2 
INTEGER) "
+                    + tableDDLOptions);
+            String upsertStmt = "UPSERT INTO " + dataTableFullName + " 
VALUES(?,?,?)";
+            PreparedStatement stmt = conn.prepareStatement(upsertStmt);
+            setEveryNthRowWithNull(NROWS, 2, stmt);
+            conn.commit();
+            setEveryNthRowWithNull(NROWS, 3, stmt);
+            conn.commit();
+            conn.createStatement().execute(String.format(
+                    "CREATE %s INDEX %s ON %s (VAL1) INCLUDE (VAL2) ASYNC ",
+                    (localIndex ? "LOCAL" : ""), indexTableName, 
dataTableFullName));
+            // Run the index MR job and verify that the index table is built 
correctly
+            IndexTool indexTool = runIndexTool(directApi, useSnapshot, 
schemaName, dataTableName, indexTableName, null, 0, new String[0]);
+            assertEquals(NROWS, 
indexTool.getJob().getCounters().findCounter(INPUT_RECORDS).getValue());
+            long actualRowCount = IndexScrutiny.scrutinizeIndex(conn, 
dataTableFullName, indexTableFullName);
+            assertEquals(NROWS, actualRowCount);
+            // Check after compaction
+            TestUtil.doMajorCompaction(conn, dataTableFullName);
+            actualRowCount = IndexScrutiny.scrutinizeIndex(conn, 
dataTableFullName, indexTableFullName);
+            assertEquals(NROWS, actualRowCount);
+            setEveryNthRowWithNull(NROWS, 5, stmt);
+            conn.commit();
+            actualRowCount = IndexScrutiny.scrutinizeIndex(conn, 
dataTableFullName, indexTableFullName);
+            assertEquals(NROWS, actualRowCount);
+            setEveryNthRowWithNull(NROWS, 7, stmt);
+            conn.commit();
+            actualRowCount = IndexScrutiny.scrutinizeIndex(conn, 
dataTableFullName, indexTableFullName);
+            assertEquals(NROWS, actualRowCount);
+            TestUtil.doMajorCompaction(conn, dataTableFullName);
+            actualRowCount = IndexScrutiny.scrutinizeIndex(conn, 
dataTableFullName, indexTableFullName);
+            assertEquals(NROWS, actualRowCount);
 
 Review comment:
   Got it. The loop is for getting the maximum timestamp for the mutation of a  
given row and using the max timestamp for the delete markers for the missing 
columns. Since we do not read delete markers, we do not know exactly when the 
delete markers are added or if the row is created with missing columns without 
delete markers in the first place. Even if we attempt to get the delete 
markers, we may not find them because they were not added in the first place or 
were removed by compaction.  So reading delete markers does not help either. 
Now, why we do insert these delete markers here, you may ask. It is to make 
sure that index rebuild code on IndexRegionObserver passes these delete markers 
to the index table. If these markers are not there in the index table for 
missing columns and there is a wrong/stale row in the index table before 
rebuild, the missing columns will inherit these stale/wrong values. 
   Please note that the test for delete markers is pretty involved. It creates 
210 rows and overwrites these rows with different null patterns three times and 
checks if the index table is correct with and without compaction.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to