[
https://issues.apache.org/jira/browse/PHOENIX-7025?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17774654#comment-17774654
]
ASF GitHub Bot commented on PHOENIX-7025:
-----------------------------------------
shahrs87 commented on code in PR #1666:
URL: https://github.com/apache/phoenix/pull/1666#discussion_r1357251653
##########
phoenix-core/src/test/java/org/apache/phoenix/cache/ServerMetadataCacheTest.java:
##########
@@ -678,6 +677,139 @@ public void testSelectQueryOnSystemTables() throws
Exception {
}
}
+ /**
+ * Test query on index with stale last ddl timestamp.
+ * Client-1 creates a table and an index on it. Client-2 queries table
(with index hint) to populate its cache.
+ * Client-1 alters a property on the index. Client-2 queries the table
again.
+ * Verify that the second query works and the index metadata was updated
in the client cache.
+ */
+ @Test
+ public void testSelectQueryAfterAlterIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String url1 = QueryUtil.getConnectionUrl(props, config, "client1");
+ String url2 = QueryUtil.getConnectionUrl(props, config, "client2");
+ String tableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ ConnectionQueryServices spyCqs1 =
Mockito.spy(driver.getConnectionQueryServices(url1, props));
+ ConnectionQueryServices spyCqs2 =
Mockito.spy(driver.getConnectionQueryServices(url2, props));
+
+ try (Connection conn1 = spyCqs1.connect(url1, props);
+ Connection conn2 = spyCqs2.connect(url2, props)) {
+
+ //client-1 creates a table and an index on it
+ createTable(conn1, tableName, NEVER);
+ createIndex(conn1, tableName, indexName, "v1");
+ TestUtil.waitForIndexState(conn1, indexName, PIndexState.ACTIVE);
+
+ //client-2 populates its cache, 1 getTable&addTable call for the
table
+ //no getTable calls for Index since we add all indexes in the
cache from a table's PTable object
+ queryWithNoIndexHint(conn2, tableName);
+
+ //client-1 updates index property
+ alterIndexChangeStateToRebuild(conn1, tableName, indexName);
+
+ //client-2's query using the index should work
+ queryWithIndexHint(conn2, tableName, indexName);
+
+ //verify client-2 cache was updated with the index's base table
metadata
+ //this would have also updated the index metadata in its cache
+ Mockito.verify(spyCqs2, Mockito.times(2)).getTable(eq(null),
+ any(byte[].class),
eq(PVarchar.INSTANCE.toBytes(tableName)),
+ anyLong(), anyLong());
+ Mockito.verify(spyCqs2, Mockito.times(2))
+ .addTable(any(PTable.class), anyLong());
+
+ //client-2 queries again with latest metadata
+ //verify no more getTable/addTable calls
+ queryWithIndexHint(conn2, tableName, indexName);
+ Mockito.verify(spyCqs2, Mockito.times(2)).getTable(eq(null),
+ any(byte[].class),
eq(PVarchar.INSTANCE.toBytes(tableName)),
+ anyLong(), anyLong());
+ Mockito.verify(spyCqs2, Mockito.times(2))
+ .addTable(any(PTable.class), anyLong());
+ }
+ }
+
+ /**
+ * Test that a client can learn about a newly created index.
+ * Client-1 creates a table, client-2 queries the table to populate its
cache.
+ * Client-1 creates an index on the table. Client-2 queries the table
using the index.
+ * Verify that client-2 uses the index for the query.
+ */
+ @Test
+ public void testSelectQueryAddIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String url1 = QueryUtil.getConnectionUrl(props, config, "client1");
+ String url2 = QueryUtil.getConnectionUrl(props, config, "client2");
+ String tableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ ConnectionQueryServices spyCqs1 =
Mockito.spy(driver.getConnectionQueryServices(url1, props));
+ ConnectionQueryServices spyCqs2 =
Mockito.spy(driver.getConnectionQueryServices(url2, props));
+
+ try (Connection conn1 = spyCqs1.connect(url1, props);
+ Connection conn2 = spyCqs2.connect(url2, props)) {
+
+ //client-1 creates table
+ createTable(conn1, tableName, NEVER);
+
+ //client-2 populates its cache
+ query(conn2, tableName);
+
+ //client-1 creates an index on the table
+ createIndex(conn1, tableName, indexName, "v1");
+ TestUtil.waitForIndexState(conn1, indexName, PIndexState.ACTIVE);
+
+ //simulate changing table's ddl timestamp by altering it for now
+ //TODO: remove this when PHOENIX-7056 is committed.
+ alterTableAddColumn(conn1, tableName, "col1");
+
+ //client-2 query should be able to use this index
+ PhoenixStatement stmt =
conn2.createStatement().unwrap(PhoenixStatement.class);
+ ResultSet rs = stmt.executeQuery("SELECT /*+ INDEX(" + tableName +
" " + indexName + ") */ * FROM " + tableName + " WHERE v1=1");
+ Assert.assertEquals("", indexName,
stmt.getQueryPlan().getContext().getCurrentTable().getTable().getName().getString());
+ }
+ }
+
+ /**
+ * Test that a client can learn about a dropped index.
+ * Client-1 creates a table and an index, client-2 queries the table to
populate its cache.
+ * Client-1 drops the index. Client-2 queries the table with index hint.
+ * Verify that client-2 uses the data table for the query.
+ */
+ @Test
+ public void testSelectQueryDropIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String url1 = QueryUtil.getConnectionUrl(props, config, "client1");
+ String url2 = QueryUtil.getConnectionUrl(props, config, "client2");
+ String tableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ ConnectionQueryServices spyCqs1 =
Mockito.spy(driver.getConnectionQueryServices(url1, props));
+ ConnectionQueryServices spyCqs2 =
Mockito.spy(driver.getConnectionQueryServices(url2, props));
+
+ try (Connection conn1 = spyCqs1.connect(url1, props);
+ Connection conn2 = spyCqs2.connect(url2, props)) {
+
+ //client-1 creates table and index on it
+ createTable(conn1, tableName, NEVER);
+ createIndex(conn1, tableName, indexName, "v1");
+
+ //client-2 populates its cache
+ query(conn2, tableName);
+
+ //client-1 drops the index
+ dropIndex(conn1, tableName, indexName);
+
+ //simulate changing table's ddl timestamp by altering it for now
+ //TODO: remove this when PHOENIX-7056 is committed.
Review Comment:
@palashc PHOENIX-7056 is committed now. Can you rebase this PR?
> Create a new RPC to validate last ddl timestamp for read requests.
> ------------------------------------------------------------------
>
> Key: PHOENIX-7025
> URL: https://issues.apache.org/jira/browse/PHOENIX-7025
> Project: Phoenix
> Issue Type: Sub-task
> Reporter: Rushabh Shah
> Assignee: Palash Chauhan
> Priority: Major
>
> Introduce a new RPC request from phoenix client to any region server via
> PhoenixRegionServerEndpoint#validateLastDDLTimestamp. Since the last ddl
> timestamp cache is maintained by all the regionservers, you can choose any
> regionserver randomly. In future, we can make this rpc more resilient by
> sending this rpc to multiple regionservers simultaneously.
> If phoenix client throws StaleMetadataCacheException then invalidate the
> cache on the client side and retry executeQuery method while fetching the
> updated metadata from SYSCAT regionserver.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)