Skip to content
Snippets Groups Projects
Unverified Commit f72e985e authored by metamben's avatar metamben Committed by GitHub
Browse files

Add find-filter-for-legacy-filter conversion helper (#33426)

parent a66db9e9
No related branches found
No related tags found
No related merge requests found
import * as ML from "cljs/metabase.lib.js";
import type { FieldFilter } from "metabase-types/api";
import type {
ColumnMetadata,
ColumnWithOperators,
......@@ -59,3 +60,15 @@ export function filterParts(
): FilterParts {
return ML.filter_parts(query, stageIndex, filterClause);
}
export function findFilterForLegacyFilter(
query: Query,
stageIndex: number,
legacyFilterClause: FieldFilter,
): FilterClause {
return ML.find_filter_for_legacy_filter(
query,
stageIndex,
legacyFilterClause,
);
}
......@@ -159,6 +159,7 @@
filter-clause
filter-operator
filter-parts
find-filter-for-legacy-filter
and
or
not
......
......@@ -6,6 +6,7 @@
[clojure.string :as str]
[medley.core :as m]
[metabase.lib.common :as lib.common]
[metabase.lib.convert :as lib.convert]
[metabase.lib.dispatch :as lib.dispatch]
[metabase.lib.equality :as lib.equality]
[metabase.lib.filter.operator :as lib.filter.operator]
......@@ -250,6 +251,28 @@
(lib.filter.operator/filter-operators (ref->col col-ref)))
(lib.filter.operator/operator-def op)))))
(mu/defn find-filter-for-legacy-filter :- [:maybe ::lib.schema.expression/boolean]
"Return the filter clause in `query` at stage `stage-number` matching the legacy
filter clause `legacy-filter`, if any."
([query :- ::lib.schema/query
legacy-filter]
(find-filter-for-legacy-filter query -1 legacy-filter))
([query :- ::lib.schema/query
stage-number :- :int
legacy-filter]
(let [query-filters (vec (filters query stage-number))
matching-filters (clojure.core/filter #(clojure.core/= (lib.convert/->legacy-MBQL %)
legacy-filter)
query-filters)]
(when (seq matching-filters)
(if (next matching-filters)
(throw (ex-info "Multiple matching filters found" {:legacy-filter legacy-filter
:query-filters query-filters
:matching-filters matching-filters}))
(first matching-filters))))))
(def ^:private FilterParts
[:map
[:lib/type [:= :mbql/filter-parts]]
......
......@@ -394,6 +394,14 @@
[a-query stage-number]
(to-array (lib.core/filters a-query stage-number)))
(defn ^:export find-filter-for-legacy-filter
"Return the filter clause in `a-query` at stage `stage-number` matching the legacy
filter clause `legacy-filter`, if any."
[a-query stage-number legacy-filter]
(->> (js->clj legacy-filter :keywordize-keys true)
(mbql.normalize/normalize-fragment [:query :filter])
(lib.core/find-filter-for-legacy-filter a-query stage-number)))
(defn ^:export fields
"Get the current `:fields` in a query. Unlike the lib core version, this will return an empty sequence if `:fields` is
not specified rather than `nil` for JS-friendliness."
......
......@@ -2,6 +2,8 @@
(:require
#?@(:cljs ([metabase.test-runner.assert-exprs.approximately-equal]))
[clojure.test :refer [deftest is testing]]
[medley.core :as m]
[metabase.lib.convert :as lib.convert]
[metabase.lib.core :as lib]
[metabase.lib.metadata :as lib.metadata]
[metabase.lib.test-metadata :as meta]
......@@ -369,3 +371,36 @@
query' (lib/replace-clause query filter-clause external-op')]
(is (=? {:stages [{:filters [[:!= {} [:field {} (meta/id :users :id)] 515]]}]}
query'))))))
(deftest ^:parallel find-filter-for-legacy-filter-test
(testing "existing clauses"
(let [query (-> (lib/query meta/metadata-provider (meta/table-metadata :users))
(lib/expression "expr" (lib/absolute-datetime "2020" :month)))
filterable-cols (lib/filterable-columns query)
[first-col] filterable-cols
expr-col (m/find-first #(= (:name %) "expr") (lib/filterable-columns query))
first-filter (lib/filter-clause
(first (lib/filterable-column-operators first-col))
first-col
515)
query (-> query
(lib/filter first-filter)
(lib/filter (lib/filter-clause
(first (lib/filterable-column-operators expr-col))
expr-col
(meta/field-metadata :users :last-login))))
filter-clauses (lib/filters query)]
(testing "existing clauses"
(doseq [filter-clause filter-clauses]
(is (= filter-clause
(lib/find-filter-for-legacy-filter query (lib.convert/->legacy-MBQL filter-clause))))))
(testing "missing clause"
(let [filter-clause (assoc first-filter 2 43)]
(is (nil? (lib/find-filter-for-legacy-filter query (lib.convert/->legacy-MBQL filter-clause))))))
(testing "ambiguous match"
(let [query (lib/filter query (-> first-filter
(assoc-in [1 :lib/uuid] (str (random-uuid)))
(assoc-in [2 1 :lib/uuid] (str (random-uuid)))))]
(is (thrown-with-msg?
#?(:clj Exception :cljs :default) #"Multiple matching filters found"
(lib/find-filter-for-legacy-filter query (lib.convert/->legacy-MBQL (first filter-clauses))))))))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment