From dad00648a79f529a252c221ecc5d4e6fb1d1b41f Mon Sep 17 00:00:00 2001
From: Cam Saul <1455846+camsaul@users.noreply.github.com>
Date: Fri, 11 Feb 2022 15:15:50 -0800
Subject: [PATCH] BigQuery should qualify columns from source query with
 `source` in the `SELECT` clause (#20434)

* Fix BigQuery not qualifying source columns

* Don't fix on 42 for the deprecated BigQuery driver

* You know what I'll fix it after all. Why not.

* Oops I updated the wrong part of the test
---
 .../bigquery_cloud_sdk/query_processor.clj    |  8 +-
 .../query_processor_test.clj                  | 31 ++++----
 .../explicit_joins_test.clj                   | 75 ++++++++++---------
 3 files changed, 58 insertions(+), 56 deletions(-)

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 61ca55437dd..5b4d2f0086e 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
@@ -511,12 +511,8 @@
     ;; if the Field is from a join or source table, record this fact so that we know never to qualify it with the
     ;; project ID no matter what
     (binding [*field-is-from-join-or-source-query?* (not (integer? source-table))]
-      ;; if this Field is from a source table DO NOT qualify it at all.
-      (let [field-clause (cond-> field-clause
-                           (= source-table ::add/source)
-                           (mbql.u/update-field-options assoc ::add/source-table ::add/none))]
-        (-> (parent-method driver field-clause)
-            (with-temporal-type (temporal-type field-clause)))))))
+      (-> (parent-method driver field-clause)
+          (with-temporal-type (temporal-type field-clause))))))
 
 (defmethod sql.qp/->honeysql [:bigquery-cloud-sdk :relative-datetime]
   [driver clause]
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 0fcc601694a..0ed1631cf95 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
@@ -787,8 +787,8 @@
                                     :breakout     [!month.date]}
                      :limit        2})]
         (mt/with-native-query-testing-context query
-          (is (sql= {:select   '[count        AS count
-                                 count (*)    AS count_2]
+          (is (sql= {:select   '[source.count  AS count
+                                 count (*)     AS count_2]
                      :from     [(let [prefix (project-id-prefix-if-set)]
                                   {:select   ['date_trunc (list (symbol (str prefix 'v3_test_data.checkins.date)) 'month) 'AS 'date
                                               'count '(*)                                                                 'AS 'count]
@@ -819,17 +819,20 @@
                                              {:name "CE", :display-name "CE"}]]
                               :limit       10}))))))))
 
-
 (deftest no-qualify-breakout-field-name-with-subquery-test
   (mt/test-driver :bigquery-cloud-sdk
-    (testing "Breakout field name is not qualified if it is from source query (#18742)"
-      (is (sql= '{:select   [source    AS source
-                             count (*) AS count]
-                  :from     [(select 1 as val "2" as source)
-                             source]
-                  :group-by [source]
-                  :order-by [source ASC]}
-                (mt/mbql-query checkins
-                  {:aggregation  [[:count]]
-                   :breakout     [[:field "source" {:base-type :type/Text}]],
-                   :source-query {:native "select 1 as `val`, '2' as `source`"}}))))))
+    (testing "Make sure columns name `source` in source query work correctly (#18742)"
+      (let [query (mt/mbql-query checkins
+                    {:aggregation  [[:count]]
+                     :breakout     [[:field "source" {:base-type :type/Text}]],
+                     :source-query {:native "select 1 as `val`, '2' as `source`"}})]
+        (is (sql= '{:select   [source.source    AS source
+                               count (*)        AS count]
+                    :from     [(select 1 as val "2" as source)
+                               source]
+                    :group-by [source]
+                    :order-by [source ASC]}
+                  query))
+        (mt/with-native-query-testing-context query
+          (is (= [["2" 1]]
+                 (mt/rows (qp/process-query query)))))))))
diff --git a/test/metabase/query_processor_test/explicit_joins_test.clj b/test/metabase/query_processor_test/explicit_joins_test.clj
index ed4ab22bb2a..e1c7221b6fb 100644
--- a/test/metabase/query_processor_test/explicit_joins_test.clj
+++ b/test/metabase/query_processor_test/explicit_joins_test.clj
@@ -690,39 +690,42 @@
                      (qp/process-query query))))))))))
 
 (deftest join-against-multiple-saved-questions-with-same-column-test
-  (testing "Should be able to join multiple against saved questions on the same column (#15863)"
-    (mt/dataset sample-dataset
-      (let [q1         (mt/mbql-query products {:breakout [$category], :aggregation [[:count]]})
-            q2         (mt/mbql-query products {:breakout [$category], :aggregation [[:sum $price]]})
-            q3         (mt/mbql-query products {:breakout [$category], :aggregation [[:avg $rating]]})
-            metadata   (fn [query]
-                         {:post [(some? %)]}
-                         (-> query qp/process-query :data :results_metadata :columns))
-            query-card (fn [query]
-                         {:dataset_query query, :result_metadata (metadata query)})]
-        (mt/with-temp* [Card [{card-1-id :id} (query-card q1)]
-                        Card [{card-2-id :id} (query-card q2)]
-                        Card [{card-3-id :id} (query-card q3)]]
-          (let [query (mt/mbql-query products
-                        {:source-table (format "card__%d" card-1-id)
-                         :joins        [{:fields       :all
-                                         :source-table (format "card__%d" card-2-id)
-                                         :condition    [:=
-                                                        $category
-                                                        &Q2.category]
-                                         :alias        "Q2"}
-                                        {:fields       :all
-                                         :source-table (format "card__%d" card-3-id)
-                                         :condition    [:=
-                                                        $category
-                                                        &Q3.category]
-                                         :alias        "Q3"}]})]
-            (mt/with-native-query-testing-context query
-              (let [results (qp/process-query query)]
-                (is (= ["Category" "Count" "Q2 → Category" "Q2 → Sum" "Q3 → Category" "Q3 → Avg"]
-                       (map :display_name (get-in results [:data :results_metadata :columns]))))
-                (is (= [["Doohickey" 42 "Doohickey" 2185.89 "Doohickey" 3.73]
-                        ["Gadget"    53 "Gadget"    3019.2  "Gadget"    3.43]
-                        ["Gizmo"     51 "Gizmo"     2834.88 "Gizmo"     3.64]
-                        ["Widget"    54 "Widget"    3109.31 "Widget"    3.15]]
-                       (mt/formatted-rows [str int str 2.0 str 2.0] results)))))))))))
+  (testing "Should be able to join multiple against saved questions on the same column (#15863, #20362, #20413)"
+    (mt/test-drivers (mt/normal-drivers-with-feature :nested-queries :left-join)
+      (mt/dataset sample-dataset
+        (let [q1         (mt/mbql-query products {:breakout [$category], :aggregation [[:count]]})
+              q2         (mt/mbql-query products {:breakout [$category], :aggregation [[:sum $price]]})
+              q3         (mt/mbql-query products {:breakout [$category], :aggregation [[:avg $rating]]})
+              metadata   (fn [query]
+                           {:post [(some? %)]}
+                           (-> query qp/process-query :data :results_metadata :columns))
+              query-card (fn [query]
+                           {:dataset_query query, :result_metadata (metadata query)})]
+          (mt/with-temp* [Card [{card-1-id :id} (query-card q1)]
+                          Card [{card-2-id :id} (query-card q2)]
+                          Card [{card-3-id :id} (query-card q3)]]
+            (let [query (mt/mbql-query products
+                          {:source-table (format "card__%d" card-1-id)
+                           :joins        [{:fields       :all
+                                           :source-table (format "card__%d" card-2-id)
+                                           :condition    [:=
+                                                          $category
+                                                          &Q2.category]
+                                           :alias        "Q2"}
+                                          {:fields       :all
+                                           :source-table (format "card__%d" card-3-id)
+                                           :condition    [:=
+                                                          $category
+                                                          &Q3.category]
+                                           :alias        "Q3"}]
+                           :order-by     [[:asc $category]]})]
+              (mt/with-native-query-testing-context query
+                (let [results (qp/process-query query)]
+                  (when (#{:postgres :h2} driver/*driver*)
+                    (is (= ["Category" "Count" "Q2 → Category" "Q2 → Sum" "Q3 → Category" "Q3 → Avg"]
+                           (map :display_name (get-in results [:data :results_metadata :columns])))))
+                  (is (= [["Doohickey" 42 "Doohickey" 2185.89 "Doohickey" 3.73]
+                          ["Gadget"    53 "Gadget"    3019.2  "Gadget"    3.43]
+                          ["Gizmo"     51 "Gizmo"     2834.88 "Gizmo"     3.64]
+                          ["Widget"    54 "Widget"    3109.31 "Widget"    3.15]]
+                         (mt/formatted-rows [str int str 2.0 str 2.0] results))))))))))))
-- 
GitLab