Fetch metadata functions fetch 'snapshots' of the schema for a data warehouse database, including information about tables, schemas, and fields, and their types. For example, with SQL databases, these functions use the JDBC DatabaseMetaData to get this information. | (ns metabase.sync.fetch-metadata (:require [clojure.set :as set] [metabase.driver :as driver] [metabase.driver.sql-jdbc.sync :as sql-jdbc.sync] [metabase.driver.util :as driver.u] [metabase.sync.interface :as i] [metabase.sync.util :as sync-util] [metabase.util.log :as log] [metabase.util.malli :as mu] [metabase.util.malli.fn :as mu.fn])) |
Logs an error message if an exception is thrown while executing the body. | (defmacro log-if-error {:style/indent 1} [function-name & body] `(try ~@body (catch Throwable e# (log/errorf e# "Error while fetching metdata with '%s'" ~function-name) (throw e#)))) |
(mu/defn db-metadata :- i/DatabaseMetadata "Get basic Metadata about a `database` and its Tables. Doesn't include information about the Fields." [database :- i/DatabaseInstance] (log-if-error "db-metadata" (driver/describe-database (driver.u/database->driver database) database))) | |
Add nested-field-columns for table to set of fields. | (defn include-nested-fields-for-table [fields database table] (let [driver (driver.u/database->driver database)] (cond-> fields (driver.u/supports? driver :nested-field-columns database) (set/union (sql-jdbc.sync/describe-nested-field-columns driver database table))))) |
(mu/defn table-fields-metadata :- [:set i/TableMetadataField] "Fetch metadata about Fields belonging to a given `table` directly from an external database by calling its driver's implementation of [[driver/describe-table]], or [[driver/describe-fields]] if implemented. Also includes nested field column metadata." [database :- i/DatabaseInstance table :- i/TableInstance] (log-if-error "table-fields-metadata" (let [driver (driver.u/database->driver database) result (if (driver.u/supports? driver :describe-fields database) (set (driver/describe-fields driver database :table-names [(:name table)] :schema-names [(:schema table)])) (:fields (driver/describe-table driver database table)))] result))) | |
Replaces [[metabase.driver/describe-fields]] for drivers that haven't implemented it. Uses [[driver/describe-table]] instead. Also includes nested field column metadata. | (defn- describe-fields-using-describe-table [_driver database & {:keys [schema-names table-names]}] (let [tables (sync-util/reducible-sync-tables database :schema-names schema-names :table-names table-names)] (eduction (mapcat (fn [table] (for [x (table-fields-metadata database table)] (assoc x :table-schema (:schema table) :table-name (:name table))))) tables))) |
Effectively a wrapper for [[metabase.driver/describe-fields]] that also validates the output against the schema. If the driver doesn't support [[metabase.driver/describe-fields]] it uses [[driver/describe-table]] instead. This will be deprecated in | (mu/defn fields-metadata [database :- i/DatabaseInstance & {:as args}] (log-if-error "fields-metadata" (let [driver (driver.u/database->driver database) describe-fields-fn (if (driver.u/supports? driver :describe-fields database) driver/describe-fields ;; In a future version we may remove [[driver/describe-table]] ;; and we'll just use [[driver/describe-fields]] here describe-fields-using-describe-table)] (cond->> (describe-fields-fn driver database args) ;; This is a workaround for the fact that [[mu/defn]] can't check reducible collections yet (mu.fn/instrument-ns? *ns*) (eduction (map #(mu.fn/validate-output {} i/FieldMetadataEntry %))))))) |
Replaces [[metabase.driver/describe-fks]] for drivers that haven't implemented it. Uses [[driver/describe-table-fks]] which is deprecated. | (defn- describe-fks-using-describe-table-fks [driver database & {:keys [schema-names table-names]}] (let [tables (sync-util/reducible-sync-tables database :schema-names schema-names :table-names table-names)] (eduction (mapcat (fn [table] #_{:clj-kondo/ignore [:deprecated-var]} (for [x (driver/describe-table-fks driver database table)] {:fk-table-name (:name table) :fk-table-schema (:schema table) :fk-column-name (:fk-column-name x) :pk-table-name (:name (:dest-table x)) :pk-table-schema (:schema (:dest-table x)) :pk-column-name (:dest-column-name x)}))) tables))) |
Effectively a wrapper for [[metabase.driver/describe-fks]] that also validates the output against the schema. If the driver doesn't support [[metabase.driver/describe-fks]] it uses [[driver/describe-table-fks]] instead. This will be deprecated in | (mu/defn fk-metadata [database :- i/DatabaseInstance & {:as args}] (log-if-error "fk-metadata" (let [driver (driver.u/database->driver database)] (when (driver.u/supports? driver :metadata/key-constraints database) (let [describe-fks-fn (if (driver.u/supports? driver :describe-fks database) driver/describe-fks ;; In version 52 we'll remove [[driver/describe-table-fks]] ;; and we'll just use [[driver/describe-fks]] here describe-fks-using-describe-table-fks)] (cond->> (describe-fks-fn driver database args) ;; This is a workaround for the fact that [[mu/defn]] can't check reducible collections yet (mu.fn/instrument-ns? *ns*) (eduction (map #(mu.fn/validate-output {} i/FKMetadataEntry %))))))))) |
(mu/defn index-metadata :- [:maybe i/TableIndexMetadata] "Get information about the indexes belonging to `table`." [database :- i/DatabaseInstance table :- i/TableInstance] (log-if-error "index-metadata" (driver/describe-table-indexes (driver.u/database->driver database) database table))) | |