Skip to content

fix: implement describe-fields to fix field sync on Metabase v0.49+#14

Open
jake-mahon-netwrix wants to merge 4 commits into
databendcloud:mainfrom
jake-mahon-netwrix:main
Open

fix: implement describe-fields to fix field sync on Metabase v0.49+#14
jake-mahon-netwrix wants to merge 4 commits into
databendcloud:mainfrom
jake-mahon-netwrix:main

Conversation

@jake-mahon-netwrix

Copy link
Copy Markdown

Problem

On Metabase v0.49.1+, field sync calls driver/describe-fields (not driver/describe-table). Since :databend inherits from :sql-jdbc, it used the default :sql-jdbc implementation, which calls DatabaseMetaData.getColumns(). Against Databend, getColumns() returns no rows — leaving every table with zero fields and breaking all MBQL queries.

Root causes (three separate issues)

1. Wrong method: sync-fields! calls describe-fields, not describe-table. The :databend driver needs its own describe-fields defmethod, and :describe-fields true must be added to database-supports?.

2. do-with-connection-with-options returns 0 rows: The same information_schema.columns SQL that returns 850 rows via clojure.java.jdbc/query returns 0 rows when executed through do-with-connection-with-options + PreparedStatement against the Databend JDBC driver. Root cause is unclear (likely a Databend JDBC driver behavior); jdbc/query (same pattern used by db-default-timezone) works correctly.

3. :table-schema nil, not "": Databend's JDBC getTables() returns TABLE_SCHEM="", causing Metabase to store schema = NULL in its Postgres app DB. Metabase's sync code matches fields to tables via (some-> table-schema lower-case-en)nil generates WHERE schema IS NULL (correct), but "" generates WHERE lower(schema) = '' (finds nothing).

Fix

  • Add (defmethod driver/describe-fields :databend ...) that queries information_schema.columns directly via jdbc/query.
  • Add :describe-fields true to the database-supports? doseq.
  • Return :table-schema nil in every field map.

Tests

New standalone unit test file (test/metabase/driver/databend_describe_fields_test.clj) — runs without a live Databend server. Covers:

  • Early exit on empty schema-names / table-names
  • db-name fallback (nil schema-names → :details :dbname"default")
  • Correct field map shape including :table-schema nil
  • AggregateFunction column filtering
  • nil data_type handling
  • IN-clause parameterization when table-names is provided
  • database-supports? :describe-fields returns true
  • Exception path returns [] without rethrowing

Also fixes the test alias in project.clj (was ["with-profile" "test"] — missing +provided and the task name).

Verified

Deployed to Metabase v0.61.3.5. 850 fields across 56 tables auto-populate on every sync. MBQL queries via MCP return real data.

Design notes

  • Single-schema assumption: schema-names uses the first non-blank value. Databend is a single-schema warehouse; multi-schema setups are unsupported by the existing driver anyway.
  • Error swallowing: The catch returns [] rather than rethrowing, keeping sync from failing entirely on a transient error. Happy to change this to propagate if the project prefers that behavior.

jake-mahon-netwrix and others added 4 commits June 5, 2026 13:15
DatabaseMetaData.getColumns() via JDBC returns no rows against Databend,
causing Metabase to store zero field metadata for all tables. MBQL queries
then fail with "Generated program is invalid" because there are no field IDs.

Replaces the broken JDBC metadata path with a direct SQL query to
information_schema.columns, which returns complete column metadata correctly.
Removes duplicate database-type->base-type defmethod.

Also upgrades databend-jdbc from 0.4.2 to 0.4.6, pins Clojure to 1.11.1,
and changes :aot :all to :aot [metabase.driver.databend] to avoid compiling
provided Metabase core namespaces at build time.

Generated with AI

Co-Authored-By: Claude Code <ai@netwrix.com>
…a_type

- Remove the simple database-type->base-type defmethod that shadowed the
  Nullable-stripping one, restoring correct type mapping for JDBC paths
- Guard data_type nil in describe-table-fields-via-sql to prevent NPE on
  virtual/computed columns and skip rows with empty type

Generated with AI

Co-Authored-By: Claude Code <ai@netwrix.com>
DatabaseMetaData.getColumns() returns no rows against Databend, so
Metabase stores zero field metadata causing all MBQL queries to fail.

Two fixes:
1. Add driver/describe-fields :databend using jdbc/query against
   information_schema.columns (faster path used by Metabase v0.49+).
   Returns :table-schema nil to match Postgres schema=NULL stored by
   describe-database (JDBC getTables() returns TABLE_SCHEM="").
2. Update describe-table to use the same direct SQL path as fallback.

Also upgrades databend-jdbc from 0.4.2 to 0.4.6 and declares
:describe-fields support explicitly in database-supports?.

Generated with AI

Co-Authored-By: Claude Code <ai@netwrix.com>
Covers early exit on empty schema/table-names, db-name fallback logic,
:table-schema nil invariant, type filtering (AggregateFunction and nil),
IN-clause parameterization, database-supports? registration, and the
exception-handling path.

Also fixes the test alias (was missing +provided and the task name) and
removes four stale cljc.java-time requires that blocked test loading.
Integration tests available via `lein test-integration`.

Generated with AI

Co-Authored-By: Claude Code <ai@netwrix.com>
@jake-mahon-netwrix

Copy link
Copy Markdown
Author

This PR was made using sonnet 4.6 with opus 4.8 plan review and code review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant