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


##########
fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java:
##########
@@ -779,17 +779,8 @@ public ExternalDatabase<? extends ExternalTable> 
getDbNullable(String dbName) {
         if (StringUtils.isEmpty(dbName)) {
             return null;
         }
-        try {
-            makeSureInitialized();
-        } catch (Exception e) {
-            String diagnosticTrace = initErrorStackTrace(e);
-            if (diagnosticTrace != null) {
-                LOG.warn("failed to get db {} in catalog {}: {}", dbName, 
name, diagnosticTrace);
-            } else {
-                LOG.warn("failed to get db {} in catalog {}", dbName, name, e);
-            }
-            return null;
-        }
+        // Initialization errors do not establish that the requested database 
is absent.
+        makeSureInitialized();

Review Comment:
   [P2] Restore the thread-local context when MV setup fails
   
   With materialized-view rewrite enabled, select `a.db` in a Remote Doris 
catalog while healthy, then reset that catalog while its remote cluster is 
unavailable and query a healthy internal table with a visible sync MV/rollup, 
e.g. `SELECT k, SUM(v) FROM internal.db.t GROUP BY k`. 
`MTMVPlanUtil.createBasicMvContext()` installs a fresh context as the 
thread-local before copying the parent catalog/database via `setDatabase()`. 
The Remote Doris health check now propagates its initialization failure through 
this lookup, exiting before `MTMVCache.from()`, whose `finally` normally 
restores the original context. `createSyncMvContexts()` catches and logs the 
error, then `getMaterializationContextByHint()` dereferences the leaked 
context's null `StatementContext` and throws an NPE, failing the unrelated 
internal query. Previously the null fallback allowed setup to reach the 
restoration. Guard the whole context construction with restoration, or copy 
namespace state without metadata lookup, an
 d add a failing-default-catalog/sync-MV regression.



##########
fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java:
##########
@@ -1008,6 +1008,12 @@ public void setDatabase(String db) {
         currentDbId = dbInstance.map(DatabaseIf::getId).orElse(-1L);

Review Comment:
   [P2] Publish the selected database only after lookup succeeds
   
   For a same-catalog `USE db_new` with `db_old` selected, `Env.changeDb()` 
first validates `getDbOrDdlException(db_new)` and then calls `setDatabase()`, 
which performs another lookup. A concurrent catalog refresh can invalidate the 
mode-0 caches between those calls; if the metastore is then unavailable, that 
second lookup now throws. `setDatabase()` has already assigned `currentDb = 
db_new` but has not updated `currentDbId`, so USE returns ERR while the session 
points at `db_new` with `db_old`'s ID. No caller restores the old selection. 
Previously the null fallback let the setter finish with ID -1 and USE returned 
OK. Resolve the requested database before assigning either session field, and 
cover a refresh/failure between validation and assignment so a failed USE 
preserves a consistent prior namespace.



##########
fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java:
##########
@@ -1098,42 +1089,14 @@ protected ExternalDatabase<? extends ExternalTable> 
buildDbForInit(String remote
         // When running ut, disable this check to make ut pass.
         // Because in ut, the database is not created in remote system.
         if (checkExists && (!FeConstants.runningUnitTest || this instanceof 
TestExternalCatalog)) {
-            try {
-                final String lookupLocalDbName = localDbName;
-                // Reuse the shared names lookup helper so existence checks 
follow the same miss-refresh policy.
-                Boolean exists = 
resolveDatabaseNameFromSnapshot(lookupLocalDbName, false,
-                        namesValue -> 
namesValue.containsLocalName(lookupLocalDbName) ? Boolean.TRUE : null);
-                if (!Boolean.TRUE.equals(exists)) {
-                    LOG.warn("Database {} does not exist in the remote system. 
Skipping initialization.",
-                            localDbName);
-                    return null;
-                }
-            } catch (RuntimeException e) {
-                // Handle "Found conflicting" exception explicitly
-                if (e.getMessage().contains(FOUND_CONFLICTING)) {
-                    LOG.error(e.getMessage());
-                    throw e; // Rethrow to let the caller handle this critical 
issue
-                } else {
-                    // Any errors other than name conflicts, we default to not 
finding the database
-                    String diagnosticTrace = initErrorStackTrace(e);
-                    if (diagnosticTrace != null) {
-                        LOG.warn("Failed to check db {} exist in remote 
system, ignore it: {}",
-                                localDbName, diagnosticTrace);
-                    } else {
-                        LOG.warn("Failed to check db {} exist in remote 
system, ignore it.", localDbName, e);
-                    }
-                    return null;
-                }
-            } catch (Exception e) {
-                // If connection failed, it will throw exception.
-                // ignore it and treat it as not exist.
-                String diagnosticTrace = initErrorStackTrace(e);
-                if (diagnosticTrace != null) {
-                    LOG.warn("Failed to check db {} exist in remote system, 
ignore it: {}",
-                            localDbName, diagnosticTrace);
-                } else {
-                    LOG.warn("Failed to check db {} exist in remote system, 
ignore it.", localDbName, e);
-                }
+            // Authentication and connection failures must propagate; only a 
successful lookup can prove absence.
+            final String lookupLocalDbName = localDbName;
+            // Reuse the shared names lookup helper so existence checks follow 
the same miss-refresh policy.
+            Boolean exists = 
resolveDatabaseNameFromSnapshot(lookupLocalDbName, false,

Review Comment:
   [P2] Make external-view namespace switches exception safe
   
   After a session selects `a.db`, reset its mode-0 cache and make its 
metastore unavailable, then query a healthy external view with `SELECT * FROM 
b.db.v`. `BindRelation.parseAndAnalyzeExternalView()` analyzes the view under 
`b`, but its `finally` calls `ctx.setDatabase(previousDb)`, which now 
propagates this lookup failure from unrelated catalog `a` and rejects the valid 
query. Previously the failed lookup returned null and restoration completed. 
This is distinct from the fixed forwarded-statement restoration.
   
   The same method also calls `setDatabase(externalDb)` before entering its 
`try`: a concurrent refresh of `b` followed by lookup failure there now skips 
restoration and leaves the session switched to `b` after the failed SELECT. 
Protect the entire namespace switch with cleanup and restore saved namespace 
state without reloading remote metadata. Cover both failed entry and 
restoration in cross-catalog view tests.



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