Skip to content
Snippets Groups Projects
Commit d344843c authored by Tom Robinson's avatar Tom Robinson
Browse files

Merge branch 'dashboard-filters' of github.com:metabase/metabase into dashboard-filters

parents f9bff181 7c8018a0
No related branches found
No related tags found
Loading
......@@ -472,8 +472,9 @@
;; people can manually specifiy "foreign key" relationships in admin and everything should work correctly.
;; Since we can't infer any "FK" relationships during sync our normal FK tests are not appropriate for BigQuery, so they're disabled for the time being.
;; TODO - either write BigQuery-speciifc tests for FK functionality or add additional code to manually set up these FK relationships for FK tables
:features (constantly (when-not config/is-test?
#{:foreign-keys}))
:features (constantly (merge #{:native-parameters}
(when-not config/is-test?
:foreign-keys)))
:field-values-lazy-seq (u/drop-first-arg field-values-lazy-seq)
:mbql->native (u/drop-first-arg mbql->native)}))
......
......@@ -290,7 +290,8 @@
[driver]
(cond-> #{:standard-deviation-aggregations
:foreign-keys
:expressions}
:expressions
:native-parameters}
(set-timezone-sql driver) (conj :set-timezone)))
......
......@@ -3,7 +3,8 @@
[clojure.string :as s]
[clj-time.core :as t]
[clj-time.format :as tf]
[medley.core :as m]))
[medley.core :as m]
[metabase.driver :as driver]))
(def ^:private ^:const relative-dates
......@@ -135,13 +136,15 @@
sql))))
query-dict))
(defn- expand-params-native [query-dict params]
(let [report-timezone (get-in query-dict [:settings :report-timezone])
params (flatten (map (partial expand-date-range-param report-timezone) params))]
(-> (substitute-all-params query-dict params)
remove-incomplete-clauses
process-multi-clauses
process-single-clauses)))
(defn- expand-params-native [{:keys [driver], :as query-dict} params]
(if-not (driver/driver-supports? driver :native-parameters)
query-dict
(let [report-timezone (get-in query-dict [:settings :report-timezone])
params (flatten (map (partial expand-date-range-param report-timezone) params))]
(-> (substitute-all-params query-dict params)
remove-incomplete-clauses
process-multi-clauses
process-single-clauses))))
;;; +-------------------------------------------------------------------------------------------------------+
......
......@@ -2,6 +2,7 @@
(:require [clj-time.core :as t]
[clj-time.format :as tf]
[expectations :refer :all]
[metabase.driver :as driver]
[metabase.models.database :refer [Database]]
[metabase.models.metric :refer [Metric]]
[metabase.models.segment :refer [Segment]]
......@@ -19,13 +20,30 @@
;;; | NATIVE QUERIES |
;;; +-------------------------------------------------------------------------------------------------------+
(defrecord NativeParametersDriver []
clojure.lang.Named
(getName [_] "NativeParametersDriver"))
(extend NativeParametersDriver
driver/IDriver
{:features (constantly #{:native-parameters})})
(defrecord NonParametersDriver []
clojure.lang.Named
(getName [_] "NonParametersDriver"))
(extend NonParametersDriver
driver/IDriver
{:features (constantly #{})})
;; basic parameter substitution
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = 666"}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = {{foo}}"}
:parameters [{:hash "abc123"
......@@ -37,9 +55,11 @@
;; independent subclause substitution
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = 123 AND foo = 666"}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
:parameters [{:hash "abc123"
......@@ -51,9 +71,11 @@
;; multi-clause substitution (subclauses are joined by SQL "AND")
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE foo=666 AND bar='yipee'"}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
:parameters [{:hash "abc123"
......@@ -71,9 +93,11 @@
(expect
(let [yesterday (tf/unparse (tf/formatters :year-month-day) (t/yesterday))]
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query (str "SELECT * FROM table WHERE date BETWEEN '" yesterday "' AND '" yesterday "'")}})
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE date BETWEEN '{{foo:start}}' AND '{{foo:end}}'"}
:parameters [{:hash "abc123"
......@@ -85,9 +109,11 @@
;; if target is not appropriate then parameter is skipped
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = 123 "}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = 123 <AND foo = {{foo}}>"}
:parameters [{:hash "abc123"
......@@ -109,37 +135,61 @@
;; TODO: test for value escaping to prevent sql injection
;; if driver doesn't support :native-parameters then we skip any substitutions
(expect
{:database 1
:driver (NonParametersDriver.)
:type :native
:native {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}}
(expand-parameters {:database 1
:driver (NonParametersDriver.)
:type :native
:native {:query "SELECT * FROM table [[WHERE <foo={{foo}}> <bar='{{bar}}'>]]"}
:parameters [{:hash "abc123"
:name "foo"
:type "id"
:target ["parameter" "foo"]
:value "666"}]}))
;; incomplete clauses are removed (but unmatched individual variables are untouched)
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = {{foo}}"}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE id = {{foo}}"}}))
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE "}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table WHERE <id = {{foo}}>"}}))
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table "}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table [[WHERE id = {{foo}}]]"}}))
;; when only part of an outer-clause is substituted we remove the entire outer-clause
(expect
{:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table "}}
(expand-parameters {:database 1
:driver (NativeParametersDriver.)
:type :native
:native {:query "SELECT * FROM table [[WHERE <id = {{foo}}> <blah={{blah}}>]]"}
:parameters [{:hash "abc123"
......
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