From 604da7e263b3f7ad5d9f848498f7c0670a6c5aed Mon Sep 17 00:00:00 2001
From: Cam Saul <cammsaul@gmail.com>
Date: Tue, 6 Nov 2018 17:57:25 -0800
Subject: [PATCH] Simplify SparkSQL driver; fix nested query support [ci
 drivers]

---
 src/metabase/driver/sparksql.clj              | 62 ++++---------------
 .../nested_queries_test.clj                   | 19 ++++++
 2 files changed, 31 insertions(+), 50 deletions(-)

diff --git a/src/metabase/driver/sparksql.clj b/src/metabase/driver/sparksql.clj
index a429e0a53ce..67a2bdb0c8d 100644
--- a/src/metabase/driver/sparksql.clj
+++ b/src/metabase/driver/sparksql.clj
@@ -15,7 +15,6 @@
              [generic-sql :as sql]
              [hive-like :as hive-like]]
             [metabase.driver.generic-sql.query-processor :as sqlqp]
-            [metabase.mbql.util :as mbql.u]
             [metabase.models.field :refer [Field]]
             [metabase.query-processor
              [store :as qp.store]
@@ -34,54 +33,18 @@
 
 ;;; ------------------------------------------ Custom HoneySQL Clause Impls ------------------------------------------
 
-(def ^:private source-table-alias "t1")
-
-(defn- resolve-table-alias [{field-name :name, special-type :special_type, table-id :table_id, :as field}]
-  (let [{schema-name :schema, table-name :name} (qp.store/table table-id)
-        source-table                            (qp.store/table (mbql.u/query->source-table-id sqlqp/*query*))
-        matching-join-table                     (some (fn [{:keys [table-id]}]
-                                                        (let [join-table (qp.store/table table-id)]
-                                                          (when (and (= schema-name (:schema join-table))
-                                                                     (= table-name (:name join-table)))
-                                                            join-table)))
-                                                      (get-in sqlqp/*query* [:query :join-tables]))]
-    (cond
-      (and (= schema-name (:schema source-table))
-           (= table-name (:name source-table)))
-      (assoc field :schema nil, :table source-table-alias)
-
-      matching-join-table
-      (assoc field :schema nil, :table (:join-alias matching-join-table))
-
-      :else
-      field)))
-
-(defmethod  sqlqp/->honeysql [SparkSQLDriver (class Field)]
-  [driver field-before-aliasing]
-  (let [{schema-name  :schema
-         table-name   :table
-         special-type :special_type
-         field-name   :name} (resolve-table-alias field-before-aliasing)
-        field                (keyword (hx/qualify-and-escape-dots schema-name table-name field-name))]
-    (cond
-      (isa? special-type :type/UNIXTimestampSeconds)      (sql/unix-timestamp->timestamp driver field :seconds)
-      (isa? special-type :type/UNIXTimestampMilliseconds) (sql/unix-timestamp->timestamp driver field :milliseconds)
-      :else                                               field)))
-
-(defn- apply-join-tables
-  [honeysql-form {join-tables :join-tables}]
-  (loop [honeysql-form honeysql-form, [{:keys [table-id pk-field-id fk-field-id schema join-alias]} & more] join-tables]
-    (let [{table-name :name} (qp.store/table table-id)
-          source-field       (qp.store/field fk-field-id)
-          pk-field           (qp.store/field pk-field-id)
-          honeysql-form      (h/merge-left-join honeysql-form
-                                                [(hx/qualify-and-escape-dots schema table-name) (keyword join-alias)]
-                                                [:=
-                                                 (hx/qualify-and-escape-dots source-table-alias (:field-name source-field))
-                                                 (hx/qualify-and-escape-dots join-alias         (:field-name pk-field))])]
-      (if (seq more)
-        (recur honeysql-form more)
-        honeysql-form))))
+(def ^:private source-table-alias
+  "Default alias for all source tables. (Not for source queries; those still use the default SQL QP alias of `source`.)"
+  "t1")
+
+(defmethod sqlqp/->honeysql [SparkSQLDriver (class Field)]
+  [driver field]
+  (let [table            (qp.store/table (:table_id field))
+        table-name       (if (:alias? table)
+                           (:name table)
+                           source-table-alias)
+        field-identifier (keyword (hx/qualify-and-escape-dots table-name (:name field)))]
+    (sqlqp/cast-unix-timestamp-field-if-needed driver field field-identifier)))
 
 (defn- apply-page-using-row-number-for-offset
   "Apply `page` clause to HONEYSQL-FROM, using row_number() for drivers that do not support offsets"
@@ -203,7 +166,6 @@
   (merge (sql/ISQLDriverDefaultsMixin)
          {:apply-page                (u/drop-first-arg apply-page-using-row-number-for-offset)
           :apply-source-table        (u/drop-first-arg apply-source-table)
-          :apply-join-tables         (u/drop-first-arg apply-join-tables)
           :column->base-type         (u/drop-first-arg hive-like/column->base-type)
           :connection-details->spec  (u/drop-first-arg connection-details->spec)
           :date                      (u/drop-first-arg hive-like/date)
diff --git a/test/metabase/query_processor_test/nested_queries_test.clj b/test/metabase/query_processor_test/nested_queries_test.clj
index a7f6705523c..c657c0e6a1d 100644
--- a/test/metabase/query_processor_test/nested_queries_test.clj
+++ b/test/metabase/query_processor_test/nested_queries_test.clj
@@ -646,3 +646,22 @@
                       Collection [dest-card-collection]]
         (perms/grant-collection-read-permissions! (group/all-users) source-card-collection)
         (save-card-via-API-with-native-source-query! 403 db source-card-collection dest-card-collection)))))
+
+;; make sure that if we refer to a Field that is actually inside the source query, the QP is smart enough to figure
+;; out what you were referring to and behave appropriately
+(datasets/expect-with-engines (non-timeseries-engines-with-feature :nested-queries)
+  [[10]]
+  (format-rows-by [int]
+    (rows
+      (qp/process-query
+        {:database (data/id)
+         :type     :query
+         :query    {:source-query {:source-table (data/id :venues)
+                                   :fields       [(data/id :venues :id)
+                                                  (data/id :venues :name)
+                                                  (data/id :venues :category_id)
+                                                  (data/id :venues :latitude)
+                                                  (data/id :venues :longitude)
+                                                  (data/id :venues :price)]}
+                    :aggregation  [[:count]]
+                    :filter       [:= [:field-id (data/id :venues :category_id)] 50]}}))))
-- 
GitLab