简单记录下query-processor过程,直接在源代码上汇聚相关function的说明
;; ▼▼▼ POST-PROCESSING ▼▼▼ happens from TOP-TO-BOTTOM, e.g. the results of `f` are (eventually) passed to `limit`
(def default-middleware
"The default set of middleware applied to queries ran via `process-query`."
[#'mbql-to-native/mbql->native ;; call driver's sql execution
#'check-features/check-features ;; "Middleware that checks that drivers support the `:features` required to use certain clauses, like `:stddev`."
#'limit/limit ;; "Add an implicit `limit` clause to MBQL queries without any aggregations, and limit the maximum number of rows that can be returned in post-processing."
#'cache/maybe-return-cached-results ;;Middleware for caching results of a query if applicable
#'optimize-datetime-filters/optimize-datetime-filters ;;Middlware that optimizes equality (`=` and `!=`) and comparison (`<`, `between`, etc.) filter clauses against
bucketed datetime fields
#'auto-parse-filter-values/auto-parse-filter-values ;;Automatically parse String filter clause values to the appropriate type
#'wrap-value-literals/wrap-value-literals ;;wraps ran value literals in `:value` (for integers, strings, etc.) or `:absolute-datetime` (for
datetime strings, etc.)
#'annotate/add-column-info ;;Middleware for adding type information about the columns in the query results (the `:cols` key)
#'perms/check-query-permissions ;;check that the current user has permissions to run the current query. This only applies if
`*current-user-id*` is bound
#'pre-alias-ags/pre-alias-aggregations ;;Middleware that generates aliases for all aggregations anywhere in a query, and makes sure they're unique.
#'cumulative-ags/handle-cumulative-aggregations ;;Middleware that implements `cum-count` and `cum-sum` aggregations. These clauses are replaced with `count` and `sum`
;; yes, this is called a second time, because we need to handle any joins that got added
(resolve 'ee.sandbox.rows/apply-row-level-permissions) ;;enterprise feature ,add row permissions of non-native query
#'resolve-joined-fields/resolve-joined-fields ;;Wrap field references in `:joined-field` clauses where needed.
#'resolve-joins/resolve-joins ;;Add any Tables and Fields referenced by the `:joins` clause to the QP store.
#'add-implicit-joins/add-implicit-joins ;;Fetch and store any Tables other than the source Table referred to by `fk->` clauses in an MBQL query, and add a
`:join-tables` key
#'large-int-id/convert-id-to-string ;;Converts any ID (:type/PK and :type/FK) in a result to a string
#'format-rows/format-rows ;;Format individual query result values as needed. Ex: format temporal values as ISO-8601 strings w/ timezone offset.
#'desugar/desugar ;;uses MBQL lib functions to replace high-level 'syntactic sugar' clauses like `time-interval` and
`inside` with lower-level clauses like `between`.
#'binning/update-binning-strategy ;;When a binned field is found, it might need to be updated if a relevant query criteria affects the min/max value of
the binned field
#'resolve-fields/resolve-fields ;;Fetch the Fields referenced by `:field-id` clauses in a query and store them in the Query Processor Store for the
duration of the Query Execution.
#'add-dim/add-remapping ;;Delgates to
`add-fk-remaps` for making remapping changes to the query (before executing the query). Then delegates to
`remap-results` to munge the results after query execution
#'implicit-clauses/add-implicit-clauses ;;Add an implicit `fields` clause to queries with no `:aggregation`, `breakout`, or explicit `:fields` clauses.
Add implicit `:order-by` clauses for fields specified in a `:breakout`
(resolve 'ee.sandbox.rows/apply-row-level-permissions) ;;enterprise feature ,add row permissions of non-native query
#'add-source-metadata/add-source-metadata-for-source-queries ;;Middleware that attempts to recursively add `:source-metadata`, if not already present, to any maps with a
`:source-query`
(resolve 'ee.sandbox.columns/maybe-apply-column-level-perms-check) ;; enterprise feature
#'reconcile-bucketing/reconcile-breakout-and-order-by-bucketing ;;Replace any unwrapped Field clauses (`:field-id`, `:field-literal`, or `:fk->`) in the `order-by` clause with
corresponding wrapped clauses (`:datetime-field` or `:binning-strategy`) used for the same Field in the `breakout`
clause
#'bucket-datetime/auto-bucket-datetimes ;; Applies to any unbucketed Field in a breakout, or fields in a filter clause being compared against `yyyy-MM-dd`
format datetime strings
#'resolve-source-table/resolve-source-tables ;;take any `:source-table`s (integer IDs) anywhere in the query and fetch and save the
corresponding Table in the Query Processor Store
#'parameters/substitute-parameters ;;Substitute Dashboard or Card-supplied parameters in a query, replacing the param placeholers with appropriate values
#'resolve-referenced/resolve-referenced-card-resources ;;Resolves tables and fields referenced in card query template tags.
#'expand-macros/expand-macros ;;Middleware that looks for `:metric` and `:segment` macros in an unexpanded MBQL query and substitute the macros for
their contents.
#'add-timezone-info/add-timezone-info ;;Add `:results_timezone` and `:requested_timezone` info to query results.
#'splice-params-in-response/splice-params-in-response ;;Splice prepared statement (or equivalent) parameters directly into the
native query
#'resolve-database-and-driver/resolve-database-and-driver ;;resolves the Database referenced by the query under that `:database` key and stores it in the QP
Store.
#'fetch-source-query/resolve-card-id-source-tables ;;assocs the `:source-query` for this query if it was specified using the shorthand `:source-table`
`card__n` format
#'store/initialize-store ;;initialize the QP Store (resolved objects cache) for this query execution
#'validate/validate-query ;;Compiled schema validator for an [outer] Metabase query. (Pre-compling a validator is more efficient; use this
instead of calling `(s/validate Query query)` or similar
#'normalize/normalize ;;converts a query into a normalized, canonical form, including things like converting all identifiers
into standard `lisp-case` ones
#'add-rows-truncated/add-rows-truncated ;;Add `:rows_truncated` to the result if the results were truncated because of the query's constraints. Only affects QP
results that are reduced to a map
(resolve 'ee.audit/handle-internal-queries);;sql audit , enterprise feature
#'results-metadata/record-and-return-metadata!]) ;;records metadata about the columns returned when running the query.
;; ▲▲▲ PRE-PROCESSING ▲▲▲ happens from BOTTOM-TO-TOP, e.g. the results of `expand-macros` are passed to
;; `substitute-parameters
这个middleware的调用入口是如下函数
(defn- base-qp [middleware]
(letfn [(qp []
(qp.reducible/async-qp (qp.reducible/combine-middleware middleware)))]
(if config/is-dev?
(fn [& args]
(apply (qp) args))
(qp))))