Doris-Breakwater commented on issue #67365:
URL: https://github.com/apache/doris/issues/67365#issuecomment-5490548672

   Breakwater-GitHub-Analysis-Slot: slot_ba4943dd2476
   
   ## Initial assessment
   
   This is a credible FE/JDBC metadata error-contract issue, but the 
cross-version description needs one important correction before implementation. 
The issue is currently unlabelled and unassigned; it should be routed to the FE 
external-catalog/JDBC maintainers.
   
   ### Code-verified facts
   
   - **`branch-4.0` (`8a99617`)**: the reported NPE chain is valid. 
`JdbcExternalTable.initSchema()` returns `Optional.empty()` for null/empty 
columns; `ExternalSchemaCache` stores that `Optional` value; 
`ExternalTable.getFullSchema()` converts it to `null`; and 
`LogicalCatalogRelation.computeOutput()` calls `.stream()` without a null 
check. The negative result remains cached subject to the schema-cache 
expiry/refresh policy.
   - **`branch-4.1` (`6f4c6a4`)**: the reported empty-schema NPE/negative-cache 
behavior is **not** the normal behavior at this SHA. This commit already 
contains the `branch-4.1` version of #66633 (`9a7174edb22`). 
`DefaultExternalMetaCache.loadSchemaCacheValue()` converts 
`ExternalCatalog.getSchema(...)=Optional.empty()` into `CacheException`. 
Consequently, null/empty JDBC columns fail during the cache load, the failure 
is not retained as a negative entry, and repeated statements can reload remote 
metadata. With preload enabled the exception is raised by the preload 
`getBaseSchema()` call; without preload it is raised by the later schema 
access. For this condition, the value does not normally reach 
`LogicalCatalogRelation.getBaseSchema().stream()` as `null`.
   - **`master` (`feb9e04`)**: a missing connector table handle follows the 
same generic `CacheException`/uncached-failure path. A valid handle with an 
empty `ConnectorTableSchema` is different: `ConnectorTableSchema` normalizes 
null columns to an empty list, `PluginDrivenExternalTable` creates a present 
cache value, and `SchemaCacheValue.validateSchema()` does not reject an empty 
schema. `computeOutput()` then streams an empty list; the report does not yet 
demonstrate the resulting user-visible failure or incorrect plan.
   - `PreloadExternalMetadata` only calls the table metadata APIs. It does not 
invalidate the schema cache or catch/suppress their exceptions. The 
repeated-load behavior comes from the failed cache load not producing a 
cacheable value, not from preload invalidating the entry.
   
   ### Evidence still needed
   
   1. Full FE exception/stack trace for each claimed SHA, with preload enabled 
and disabled. In particular, an NPE observed on `6f4c6a4` would indicate 
another cache route or race and needs a complete stack trace.
   2. A deterministic reproducer or unit-test fixture identifying which 
condition is exercised: legacy `listColumns()` returns null/empty, connector 
`getTableHandle()` returns empty, or a valid handle returns zero columns.
   3. JDBC database/driver name and version, metadata permissions, and whether 
the remote table was concurrently dropped/recreated.
   4. Remote-call counters or debug logs for repeated statements, separating 
table-existence/handle resolution from column-metadata reads, plus the 
effective schema-cache TTL/capacity settings and any explicit `REFRESH` 
operations.
   5. For the `master` zero-column case, the actual analysis result/stack trace 
and expected contract. The current code proves that an empty schema is 
accepted, but not by itself that it produces the same failure as a missing 
handle.
   
   ### Recommended next steps
   
   1. Correct the issue's version matrix: `branch-4.0` has the nullable-schema 
NPE and cached absence; `branch-4.1` and `master` have generic uncached loader 
failures for missing schema/handle after #66633.
   2. Add failing tests first for the three distinct cases above. Assert 
exception type/message, preload on/off parity, and remote-call count across 
repeated statements. Keep a normal non-empty schema control case.
   3. Fix the branches separately:
      - On `branch-4.0`, preserve the bounded cached absence but convert it at 
the JDBC table schema-consumption boundary into an actionable 
`JdbcClientException` containing catalog and remote database/table names; no 
required schema API should return `null`.
      - On `branch-4.1` and `master`, an override that only checks 
`getFullSchema()` is insufficient because the unified loader throws before 
returning. Introduce a non-null, bounded negative result (or a dedicated 
failure cache/result type) with expiry and explicit-refresh invalidation, then 
translate it to the contextual JDBC error at the consumption boundary.
      - On `master`, explicitly define whether a normal JDBC table may ever 
have zero columns. If not, reject that state with JDBC table context before 
publishing a normal schema cache value; avoid applying a blanket rule to 
connector paths that intentionally use empty schemas unless their contracts are 
checked.
   4. Keep `PreloadExternalMetadata` generic unless a separate preload-specific 
defect is reproduced; the schema provider/cache boundary should own consistent 
error semantics.
   
   No code changes were made during this triage.
   


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