github-actions[bot] commented on code in PR #69501:
URL: https://github.com/apache/doris/pull/69501#discussion_r4356914860


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java:
##########
@@ -743,14 +743,34 @@ protected void invalidateTableCache(String 
localTableName) {
         }
     }
 
+    /** Refreshes table membership and lookup identity without loading remote 
metadata. */
+    public void invalidateTableLookup(String tableName) {
+        if (!isInitialized()) {
+            return;
+        }
+        // In case-insensitive lookup mode an older spelling may still be 
loading while a refreshed
+        // names snapshot already contains the new spelling. Fence every 
object/ID load in this database.
+        if (isTableNamesCaseInsensitive()) {
+            invalidateAllTableCache();
+            return;
+        }
+        String localTableName = resolveTableNameForInvalidation(tableName);
+        try {
+            invalidateTableCache(localTableName);

Review Comment:
   [P2] Preserve ID publication for in-flight numeric lookups
   
   With enabled caches and ordinary `lower_case_table_names=0`, an 
`ExternalRowCountCache` worker can enter `getTableNullable(long)`, read the 
indexed name at line 779, and pause before `tables.get(name)`. This new 
per-table invalidation can then finish removing the object and its ID. When the 
worker resumes, `tables.get` acquires a fresh post-refresh generation and 
caches a replacement object, but that plain getter never restores the ID 
mapping. Subsequent numeric lookups fail despite the object being cached, and 
row-count/statistics callers return unknown until a lookup by name repairs it. 
Make numeric loads revalidate or publish their ID within the guarded 
object-publication action, and cover this capture/refresh/resume interleaving. 
This is distinct from the existing mode-2 late bulk-clear thread: it uses the 
single-key branch and publishes through the numeric path after ID removal has 
completed.



##########
fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java:
##########
@@ -301,18 +316,41 @@ public void refreshExternalTableFromEvent(String 
catalogName, String localDbName
     }
 
     public void refreshTableInternal(ExternalDatabase db, ExternalTable table, 
long updateTime) {
+        refreshTableInternal(db, table, updateTime, false);
+    }
+
+    private void refreshTableInternal(ExternalDatabase db, ExternalTable 
table, long updateTime,
+            boolean invalidateTableLookup) {
+        boolean invalidateDatabase = invalidateTableLookup && 
table.getCatalog().getLowerCaseTableNames() == 2;
         table.unsetObjectCreated();
         if (updateTime > 0) {
             table.setUpdateTime(updateTime);
         }
         // Connector metadata is the row-count source, so invalidate it before 
engine and row-count caches.
         try {
             if (table.getCatalog() instanceof PluginDrivenExternalCatalog) {
-                ((PluginDrivenExternalCatalog) 
table.getCatalog()).getConnector()
-                        .invalidateTable(db.getRemoteName(), 
table.getRemoteName());
+                if (invalidateDatabase) {
+                    // A refreshed local name may resolve to a different 
remote spelling in this database.
+                    ((PluginDrivenExternalCatalog) 
table.getCatalog()).getConnector()
+                            .invalidateDb(db.getRemoteName());
+                } else {
+                    ((PluginDrivenExternalCatalog) 
table.getCatalog()).getConnector()
+                            .invalidateTable(db.getRemoteName(), 
table.getRemoteName());
+                }
             }
         } finally {
-            Env.getCurrentEnv().getExtMetaCacheMgr().invalidateTable(table);
+            try {
+                if (invalidateTableLookup) {
+                    db.invalidateTableLookup(table.getName());

Review Comment:
   [P2] Retain the refresh timestamp for the replacement object
   
   `refreshTableInternal` writes `updateTime` onto the old table immediately 
above, but this call evicts that object. Its replacement starts with 
`ExternalTable.updateTime = 0`, so `REFRESH TABLE` followed by an 
`information_schema.tables` query projecting only `UPDATE_TIME` now returns 
NULL instead of the refresh time: `FrontendServiceImpl` reads the field 
directly, and the schema scanner converts zero to NULL. It stays unset until a 
later schema load calls `initSchemaAndUpdateTime`. Preserve the refresh time 
across replacement and test it before loading schema; the modified test 
currently checks the new timestamp only after `getFullSchema()`.



##########
fe/fe-core/src/main/java/org/apache/doris/catalog/RefreshManager.java:
##########
@@ -301,18 +316,41 @@ public void refreshExternalTableFromEvent(String 
catalogName, String localDbName
     }
 
     public void refreshTableInternal(ExternalDatabase db, ExternalTable table, 
long updateTime) {
+        refreshTableInternal(db, table, updateTime, false);
+    }
+
+    private void refreshTableInternal(ExternalDatabase db, ExternalTable 
table, long updateTime,
+            boolean invalidateTableLookup) {
+        boolean invalidateDatabase = invalidateTableLookup && 
table.getCatalog().getLowerCaseTableNames() == 2;

Review Comment:
   [P2] Invalidate historical remote spellings in mode 1 as well
   
   A local name can resolve to a different remote spelling with 
`lower_case_table_names=1` too. For example, configure FE object/name expiry 
shorter than the Iceberg connector table TTL, query remote `Foo` as local 
`foo`, externally replace it with `FOO`, and query `foo` after FE-only expiry. 
The FE now retains `FOO` while the independent connector entry for `Foo` 
survives. Externally replace `FOO` with a new `Foo` containing different data, 
then refresh before the FE `FOO` object expires: this condition is false, so 
only connector key `FOO` is invalidated. The refreshed names then resolve back 
to `Foo`, whose exact-case table/snapshot caches still describe the first 
incarnation, allowing stale schema/data after successful refresh. Extend the 
broad invalidation to naming modes that can change the remote spelling, and 
cover this historical-key reuse case.



-- 
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.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to