Add Thrift-native metadata support - #1641
Conversation
There was a problem hiding this comment.
Verdict: 1 Low
Looks good — solid, well-tested opt-in feature with strong unit coverage across the native/legacy split, error-code/SQLState alignment, and JSON round-trip. One low-severity note about asymmetric native error propagation (listTables/listColumns propagate errors under native mode, but listFunctions/key-based ops still swallow object-not-found) — worth confirming it's intentional.
d535038 to
76205fa
Compare
There was a problem hiding this comment.
Verdict: 1 Medium · 1 Low
Solid, well-tested opt-in feature; native metadata routing delegates cleanly to existing row builders and the SQLState/errorCode alignment looks correct. One medium concern: the fallback-bypass guard keys off the connection flag rather than the actual result, so enabling EnableThriftNativeMetadata changes getColumns/getTables error semantics even for legacy (non-native) responses. One low note on a tautological test.
76205fa to
0a99a83
Compare
There was a problem hiding this comment.
Verdict: 1 Medium · 2 Low
Solid, well-tested feature addition — opt-in Thrift-native SEA metadata with the manifest flag as the authoritative switch, good coverage across builders and header wiring. Main concerns are around the enabled-flag error-handling path: enabling the flag disables old-DBR SHOW fallbacks for the whole connection (F1), an inconsistent SQLState between null vs empty table (F2), and the native-propagation guard not applied uniformly to key-based ops (F3). All are behavior/consistency questions rather than clear defects.
0750722 to
6eac609
Compare
There was a problem hiding this comment.
Verdict: 1 Low
Solid, well-structured feature with strong test coverage (manifest-flag gating, native vs SHOW paths, SQLState/error-code corrections, and the new post-filtering are all exercised). One low-severity robustness observation about the implicit positional-column contract between native results and the builders; otherwise the correctness, error-propagation, and JSON round-trip changes look correct.
6eac609 to
e22b219
Compare
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>
e22b219 to
9273799
Compare
There was a problem hiding this comment.
Verdict: 1 Medium
Solid, well-tested opt-in feature. The manifest-flag-authoritative design is clean and the new unit coverage (native-vs-thrift equivalence, filter preservation, SQLState corrections, header behavior) is thorough. One medium note about inconsistent error-fallback behavior between metadata operations when the flag is enabled.
There was a problem hiding this comment.
Verdict: 1 Medium · 1 Low
Solid, well-tested feature addition — the manifest-authoritative native-metadata path, SQLState corrections, and Thrift error-code preservation all carry matching unit coverage. One medium concern: the native error-propagation guard keys off the feature flag rather than the actual result, which can disable the legacy object-not-found/parse-error fallbacks (and make getTables/getColumns throw instead of returning empty) even for non-native SEA results; plus a low note on that policy being applied inconsistently vs. getFunctions.
| getResultSet(SQL, session, MetadataOperationType.GET_TABLES), validatedTableTypes); | ||
| resultSet, requestedCatalog, resultTableTypes); | ||
| } catch (SQLException e) { | ||
| if (isThriftNativeMetadataRequested()) { |
There was a problem hiding this comment.
🟡 Medium — The error-propagation guard keys off isThriftNativeMetadataRequested() (i.e. whether the feature flag is enabled) rather than whether the result was actually native. Because the exception is thrown by getResultSet(...) before any manifest is available, there is no way at this point to know if the server actually returned a native result. The PR design states the manifest flag is authoritative and legacy behavior is preserved when the server does not return a native result — but here, once EnableThriftNativeMetadata=1, both listTables (L176) and listColumns (L227) short-circuit all the legacy fallbacks, including isObjectNotFoundException(e).
Concrete consequence: with the flag enabled against a server that does not support native metadata (older DBR that ignores the header and runs the SHOW query, or a genuinely non-existent catalog/object), getTables/getColumns now throw instead of returning an empty ResultSet. Returning empty for object-not-found is the pre-existing JDBC-contract behavior for these calls. Enabling this opt-in flag therefore silently regresses the object-not-found and SHOW ... IN ALL CATALOGS parse-error fallbacks even when the server produced a legacy SEA result. Worth confirming this is the intended tradeoff (and documenting it), or gating the propagation on something closer to "native result was actually returned."
| getResultSet(SQL, session, MetadataOperationType.GET_FUNCTIONS); | ||
| return metadataResultSetBuilder.getFunctionsResult( | ||
| getResultSet(SQL, session, MetadataOperationType.GET_FUNCTIONS), catalog); | ||
| resultSet, resultSet.isThriftNativeMetadataResult() ? requestedCatalog : catalog); |
There was a problem hiding this comment.
🔵 Low — The native error-handling policy is applied inconsistently across the supported operations. listTables (L176) and listColumns (L227) rethrow immediately when isThriftNativeMetadataRequested(), bypassing their isObjectNotFoundException fallback, but listFunctions (here) keeps its isObjectNotFoundException(e) → empty-result fallback with no equivalent native guard. If the intent is Thrift-compatible propagation for native metadata, functions diverges from tables/columns; if returning empty on object-not-found is the desired native behavior, then tables/columns diverge instead. Please confirm the intended policy is uniform, or add a comment explaining why functions is treated differently.
(Anchored to the nearest changed line — see the description for the exact location.)
Summary
Adds opt-in
EnableThriftNativeMetadatasupport for metadata operations executed through SEA. The server can return Thrift-shaped metadata rows through the Statement Execution API, while the driver preserves the same filtering, normalization, error behavior, and JDBC metadata exposed by the Thrift client.Supported operations are catalogs, schemas, tables, columns, functions, primary keys, and cross references. Procedures and procedure columns continue to use the existing SEA path.
Request and result flow
The manifest flag is authoritative: neither the request header nor a native-looking schema changes how a result is processed. This keeps the feature opt-in and preserves legacy behavior when the server does not return a native result.
Requests requiring special handling
getTables: the native path sends catalog and types to runtime, then reapplies the JDBC filters to returned rows. This is necessary because runtime treats catalog as a pattern, may return temporary views outside the requested catalog, and does not consistently handle empty or exact table-type filters. SEA native results reuse this processing to preserve existing JDBC-over-Thrift behavior.typesbehaviornullaccepts every runtime-returned type, an empty array returns no rows, and a non-empty array is matched exactlynulluses the driver's supported default types because SHOW has no JDBCtypesargumentgetFunctions: the runtime paths have different catalog semantics:FUNCTION_CAT""DatabaseMetaData.getFunctionscatalog, includingnullThe driver therefore saves the original JDBC catalog before resolving a catalog for SQL construction and passes that original value only when rebuilding a manifest-confirmed native result. This preserves Thrift compatibility, but it is a column-label correction rather than catalog filtering: native rows can come from catalog A and be labeled as catalog B.
getCrossReference: the SQL query narrows only the foreign-key side, so the returned native rows are additionally filtered by the requested parent catalog, schema, and table.Native metadata failures use Thrift-compatible propagation and timeout codes instead of the legacy SHOW-query compatibility fallbacks.
SQLState correction
Key-based metadata validation now reports the applicable SQLState (
42000or08000) and keepsEXECUTE_STATEMENT_FAILED(1003) as the driver error code. Previously these errors were constructed withDatabricksDriverErrorCode.INVALID_STATE, which incorrectly exposedINVALID_STATEthroughSQLException.getSQLState().Tests:
mvn spotless:check; focused core metadata suites (331 tests).