LEGACY IMPLEMENTATION of [[metabase.query-processor.middleware.fetch-source-query]], will be removed soon. | (ns ^:deprecated metabase.query-processor.middleware.fetch-source-query-legacy (:require [clojure.set :as set] [metabase.driver.ddl.interface :as ddl.i] [metabase.driver.util :as driver.u] [metabase.legacy-mbql.normalize :as mbql.normalize] [metabase.legacy-mbql.schema :as mbql.s] [metabase.lib.core :as lib] [metabase.lib.metadata :as lib.metadata] [metabase.lib.schema.id :as lib.schema.id] [metabase.public-settings :as public-settings] [metabase.query-processor.store :as qp.store] [metabase.query-processor.util.persisted-cache :as qp.persisted] [metabase.util :as u] [metabase.util.i18n :refer [tru]] [metabase.util.log :as log] [metabase.util.malli :as mu])) |
(set! *warn-on-reflection* true) | |
These next two schemas are for validating the intermediate stages of the middleware. We don't need to validate the entire query | (def ^:private SourceQueryAndMetadata [:map [:source-query mbql.s/SourceQuery] [:database ::mbql.s/DatabaseID] [:source-metadata [:maybe [:sequential mbql.s/SourceQueryMetadata]]] [:source-query/model? {:optional true} :boolean] [:persisted-info/native {:optional true} :string]]) |
Get the query to be run from the card | (defn- source-query [{dataset-query :dataset-query, card-id :id, :as card}] (let [dataset-query (cond-> dataset-query (:lib/type dataset-query) lib/->legacy-MBQL) {db-id :database mbql-query :query {template-tags :template-tags :as native-query} :native} dataset-query] (or mbql-query ;; rename `:query` to `:native` because source queries have a slightly different shape (when-some [native-query (set/rename-keys native-query {:query :native})] (let [mongo? (= (driver.u/database->driver db-id) :mongo)] (cond-> native-query ;; MongoDB native queries consist of a collection and a pipelne (query) mongo? (update :native (fn [pipeline] {:collection (:collection native-query) :query pipeline})) (empty? template-tags) (dissoc :template-tags)))) (throw (ex-info (tru "Missing source query in Card {0}" card-id) {:card card, :dataset-query dataset-query}))))) |
(mu/defn card-id->source-query-and-metadata :- SourceQueryAndMetadata "Return the source query info for Card with `card-id`. Pass true as the optional second arg `log?` to enable logging. (The circularity check calls this and will print more than desired)" ([card-id :- ::lib.schema.id/card] (card-id->source-query-and-metadata card-id false)) ([card-id :- ::lib.schema.id/card log? :- :boolean] (let [;; todo: we need to cache this. We are running this in preprocess, compile, and then again card (or (lib.metadata/card (qp.store/metadata-provider) card-id) (throw (ex-info (tru "Card {0} does not exist." card-id) {:card-id card-id}))) persisted-info (:lib/persisted-info card) {{database-id :database} :dataset-query result-metadata :result-metadata card-type :type} card persisted? (qp.persisted/can-substitute? card persisted-info) source-query (source-query card)] (when (and persisted? log?) (log/infof "Found substitute cached query for card %s from %s.%s" card-id (ddl.i/schema-name {:id database-id} (public-settings/site-uuid)) (:table-name persisted-info))) ;; log the query at this point, it's useful for some purposes (log/debugf "Fetched source query from Card %s:\n%s" card-id (u/pprint-to-str 'yellow source-query)) (cond-> {:source-query (cond-> source-query ;; This will be applied, if still appropriate, by the peristence middleware persisted? (assoc :persisted-info/native (qp.persisted/persisted-info-native-query (u/the-id (lib.metadata/database (qp.store/metadata-provider))) persisted-info))) :database database-id :source-metadata (sequence (comp (map mbql.normalize/normalize-source-metadata) (remove :remapped_from)) result-metadata)} (= card-type :model) (assoc :source-query/model? true))))) | |