From bca22d9766fd665e46700b325db17717f8e21f28 Mon Sep 17 00:00:00 2001 From: Jeff Evans <jeff303@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:16:46 -0500 Subject: [PATCH] Fix BigQuery Percentile and Median expressions not using correct backtick quoting (#17979) Fix BigQuery Percentile and Median expressions not using correct backtick quoting Ensure the identifier components are quoted by reifying `ToSql` for the `APPROX_QUANTILES` expression Add test to ensure query is created properly Mark `:percentile-aggregations` as being supported in the new driver --- .../metabase/driver/bigquery_cloud_sdk.clj | 2 +- .../bigquery_cloud_sdk/query_processor.clj | 22 +++++++++++++++---- .../query_processor_test.clj | 15 +++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj index 75330103412..60827be18eb 100644 --- a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj +++ b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj @@ -286,7 +286,7 @@ ;;; | Other Driver Method Impls | ;;; +----------------------------------------------------------------------------------------------------------------+ -(defmethod driver/supports? [:bigquery-cloud-sdk :percentile-aggregations] [_ _] false) +(defmethod driver/supports? [:bigquery-cloud-sdk :percentile-aggregations] [_ _] true) (defmethod driver/supports? [:bigquery-cloud-sdk :expressions] [_ _] true) diff --git a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj index 2ed3d53f37e..7ff0259293e 100644 --- a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj +++ b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk/query_processor.clj @@ -23,6 +23,7 @@ [metabase.util.date-2 :as u.date] [metabase.util.honeysql-extensions :as hx] [metabase.util.i18n :refer [tru]] + [pretty.core :refer [PrettyPrintable]] [schema.core :as s] [toucan.db :as db]) (:import [com.google.cloud.bigquery Field$Mode FieldValue] @@ -415,13 +416,26 @@ [(Math/round x) (Math/round (Math/pow 10 power))] (recur (* 10 x) (inc power))))) +(defn- approx-quantiles + "HoneySQL form for the APPROX_QUANTILES invocation. The [OFFSET(...)] part after the function call is odd and + needs special treatment." + [driver expr offset quantiles] + (let [expr-hsql (sql.qp/->honeysql driver expr)] + (reify + hformat/ToSql + (to-sql [_] + (format "APPROX_QUANTILES(%s, %s)[OFFSET(%s)]" + (hformat/to-sql expr-hsql) + quantiles + offset)) + PrettyPrintable + (pretty [_] + (format "APPROX_QUANTILES(%s, %s)[OFFSET(%s)]" (pr-str expr) (pr-str quantiles) (pr-str offset)))))) + (defmethod sql.qp/->honeysql [:bigquery-cloud-sdk :percentile] [driver [_ arg p]] (let [[offset quantiles] (percentile->quantile p)] - (hsql/raw (format "APPROX_QUANTILES(%s, %s)[OFFSET(%s)]" - (hformat/to-sql (sql.qp/->honeysql driver arg)) - quantiles - offset)))) + (approx-quantiles driver arg offset quantiles))) (defmethod sql.qp/->honeysql [:bigquery-cloud-sdk :median] [driver [_ arg]] diff --git a/modules/drivers/bigquery-cloud-sdk/test/metabase/driver/bigquery_cloud_sdk/query_processor_test.clj b/modules/drivers/bigquery-cloud-sdk/test/metabase/driver/bigquery_cloud_sdk/query_processor_test.clj index d3405ab6bb7..870b80d5266 100644 --- a/modules/drivers/bigquery-cloud-sdk/test/metabase/driver/bigquery_cloud_sdk/query_processor_test.clj +++ b/modules/drivers/bigquery-cloud-sdk/test/metabase/driver/bigquery_cloud_sdk/query_processor_test.clj @@ -821,3 +821,18 @@ :source-query {:source-table (mt/id :checkins) :aggregation [[:count]] :breakout [!month.date]}}))))))) + +(deftest custom-expression-args-quoted + (mt/test-driver :bigquery-cloud-sdk + (mt/dataset sample-dataset + (testing "Arguments to custom aggregation expression functions have backticks applied properly" + (is (= {:mbql? true + :params nil + :table-name "orders" + :query (str "SELECT APPROX_QUANTILES(`v3_sample_dataset.orders`.`quantity`, 10)[OFFSET(5)] AS `CE`" + " FROM `v3_sample_dataset.orders` LIMIT 10")} + (qp/query->native (mt/mbql-query orders + {:aggregation [[:aggregation-options + [:percentile $orders.quantity 0.5] + {:name "CE", :display-name "CE"}]] + :limit 10})))))))) -- GitLab