(ns metabase.query-processor.middleware.desugar (:require [medley.core :as m] [metabase.legacy-mbql.predicates :as mbql.preds] [metabase.legacy-mbql.schema :as mbql.s] [metabase.legacy-mbql.util :as mbql.u] [metabase.lib.metadata :as lib.metadata] [metabase.lib.util.match :as lib.util.match] [metabase.query-processor.store :as qp.store] [metabase.util.malli :as mu])) | |
Add base type to fields with id that are missing it. It is necessary for correct function of [[metabase.legacy-mbql.util/desugar-is-empty-and-not-empty]]. | (defn- add-missing-field-base-types
[query]
(lib.util.match/replace query
(field-clause :guard (fn [clause]
(and (mbql.preds/Field? clause)
(integer? (second clause))
(not (contains? (get clause 2) :base-type)))))
(let [id (second field-clause)
metadata (lib.metadata/field (qp.store/metadata-provider) id)
{:keys [base-type]} metadata]
(update field-clause 2 assoc
:base-type base-type
::desugar-added-base-type true)))) |
(defn- remove-desugar-added-base-types
[query]
(lib.util.match/replace query
(field-clause :guard (fn [clause]
(and (mbql.preds/Field? clause)
(integer? (second clause))
(get-in clause [2 ::desugar-added-base-type]))))
(update field-clause 2 (comp not-empty
#(dissoc % :base-type ::desugar-added-base-type))))) | |
(defn- desugar*
[query]
(lib.util.match/replace query
(filter-clause :guard mbql.preds/Filter?)
(mbql.u/desugar-filter-clause filter-clause)
(temporal-extract-clause :guard mbql.preds/DatetimeExpression?)
(mbql.u/desugar-temporal-extract temporal-extract-clause)
(expression :guard mbql.preds/FieldOrExpressionDef?)
(mbql.u/desugar-expression expression))) | |
(mu/defn desugar :- mbql.s/Query
"Middleware that uses MBQL lib functions to replace high-level 'syntactic sugar' clauses like `time-interval` and
`inside` with lower-level clauses like `between`. This is done to minimize the number of MBQL clauses individual
drivers need to support. Clauses replaced by this middleware are marked `^:sugar` in the MBQL schema."
[query]
;; Base types are added to field options for integer id fields that are missing those. Then original desugar
;; is performed. Later those base types (added for desugaring purposes [expanding is-empty, not-empty]) are removed.
(m/update-existing query :query (comp remove-desugar-added-base-types
desugar*
add-missing-field-base-types))) | |