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