From 5ce3ba19b1ec3de4eff8ba58eaac1efd0d9c3a05 Mon Sep 17 00:00:00 2001 From: john-metabase <92878045+john-metabase@users.noreply.github.com> Date: Tue, 23 May 2023 07:29:45 -0400 Subject: [PATCH] Adds support for options in template tags (#30901) --- shared/src/metabase/mbql/schema.cljc | 4 ++- .../driver/common/parameters/values.clj | 12 +++++--- .../driver/sql/parameters/substitute_test.clj | 28 +++++++++++++++++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/shared/src/metabase/mbql/schema.cljc b/shared/src/metabase/mbql/schema.cljc index 5fe28f8a9b4..c70614f6455 100644 --- a/shared/src/metabase/mbql/schema.cljc +++ b/shared/src/metabase/mbql/schema.cljc @@ -1145,7 +1145,9 @@ :dimension field ;; which type of widget the frontend should show for this Field Filter; this also affects which parameter types ;; are allowed to be specified for it. - :widget-type (s/recursive #'WidgetType)})) + :widget-type (s/recursive #'WidgetType) + ;; optional map to be appended to filter clause + (s/optional-key :options) {s/Keyword s/Any}})) (def raw-value-template-tag-types "Set of valid values of `:type` for raw value template tags." diff --git a/src/metabase/driver/common/parameters/values.clj b/src/metabase/driver/common/parameters/values.clj index 70ffaedbd52..103cb14cb1c 100644 --- a/src/metabase/driver/common/parameters/values.clj +++ b/src/metabase/driver/common/parameters/values.clj @@ -102,9 +102,12 @@ multiple values." [tag :- mbql.s/TemplateTag params :- (s/maybe [mbql.s/Parameter])] (let [matching-params (tag-params tag params) + tag-opts (:options tag) normalize-params (fn [params] - ;; remove `:target` which is no longer needed after this point. - (let [params (map #(dissoc % :target) params)] + ;; remove `:target` which is no longer needed after this point, and add any tag options + (let [params (map #(cond-> (dissoc % :target) + (seq tag-opts) (assoc :options tag-opts)) + params)] (if (= (count params) 1) (first params) params)))] @@ -115,8 +118,9 @@ (normalize-params matching-params)) ;; otherwise, attempt to fall back to the default value specified as part of the template tag. (when-let [tag-default (:default tag)] - {:type (:widget-type tag :dimension) ; widget-type is the actual type of the default value if set - :value tag-default}) + (cond-> {:type (:widget-type tag :dimension) ; widget-type is the actual type of the default value if set + :value tag-default} + tag-opts (assoc :options tag-opts))) ;; if that doesn't exist, see if the matching parameters specified default values This can be the case if the ;; parameters came from a Dashboard -- Dashboard parameter mappings can specify their own defaults -- but we want ;; the defaults specified in the template tag to take precedence if both are specified diff --git a/test/metabase/driver/sql/parameters/substitute_test.clj b/test/metabase/driver/sql/parameters/substitute_test.clj index 23e9483c941..b7ab05c6244 100644 --- a/test/metabase/driver/sql/parameters/substitute_test.clj +++ b/test/metabase/driver/sql/parameters/substitute_test.clj @@ -113,7 +113,7 @@ (testing "new operators" (testing "string operators" (let [query ["select * from venues where " (param "param")]] - (doseq [[operator {:keys [field value expected]}] + (doseq [[operator {:keys [field value expected options]}] (partition-all 2 [:string/contains {:field :name @@ -125,6 +125,16 @@ "where" " (\"PUBLIC\".\"VENUES\".\"NAME\" LIKE ?)"] ["%foo%"]]} + :string/contains {:field :name + :value ["FOO"] + :options {:case-sensitive false} + :expected [["select" + " *" + "from" + " venues" + "where" + " (LOWER(\"PUBLIC\".\"VENUES\".\"NAME\") LIKE ?)"] + ["%foo%"]]} :string/does-not-contain {:field :name :value ["foo"] :expected [["select" @@ -137,6 +147,19 @@ " OR (\"PUBLIC\".\"VENUES\".\"NAME\" IS NULL)" " )"] ["%foo%"]]} + :string/does-not-contain {:field :name + :value ["FOO"] + :options {:case-sensitive false} + :expected [["select" + " *" + "from" + " venues" + "where" + " (" + " NOT (LOWER(\"PUBLIC\".\"VENUES\".\"NAME\") LIKE ?)" + " OR (\"PUBLIC\".\"VENUES\".\"NAME\" IS NULL)" + " )"] + ["%foo%"]]} :string/starts-with {:field :name :value ["foo"] :expected [["select" @@ -265,7 +288,8 @@ (-> (substitute query {"param" (params/map->FieldFilter {:field (t2/select-one Field :id (mt/id :venues field)) :value {:type operator - :value value}})}) + :value value + :options options}})}) vec (update 0 mdb.query/format-sql :h2) (update 0 str/split-lines)))))))))) -- GitLab