Skip to content
Snippets Groups Projects
Commit 00f7db08 authored by Ryan Senior's avatar Ryan Senior
Browse files

Add dimension options to dates and coordinates on nested queries

This commit ensures nested queries include dimension options for
datetime and coordinate fields. Whether or not to include dimension
options is derived from the result metadata of the card.

Fixes #6166
parent 320b1bb3
No related branches found
No related tags found
No related merge requests found
......@@ -214,7 +214,7 @@
[id include_sensitive_fields]
{include_sensitive_fields (s/maybe su/BooleanString)}
(let [table (api/read-check Table id)
driver (driver/engine->driver (db/select-one-field :engine Database :id (:db_id table)))]
driver (driver/database-id->driver (:db_id table))]
(-> table
(hydrate :db [:fields :target :dimensions] :segments :metrics)
(update :fields with-normal-values)
......@@ -231,22 +231,26 @@
(defn- card-result-metadata->virtual-fields
"Return a sequence of 'virtual' fields metadata for the 'virtual' table for a Card in the Saved Questions 'virtual'
database."
[card-id metadata]
(for [col metadata]
(assoc col
:table_id (str "card__" card-id)
:id [:field-literal (:name col) (or (:base_type col) :type/*)]
;; don't return :special_type if it's a PK or FK because it confuses the frontend since it can't actually be
;; used that way IRL
:special_type (when-let [special-type (keyword (:special_type col))]
(when-not (or (isa? special-type :type/PK)
(isa? special-type :type/FK))
special-type)))))
[card-id database-id metadata]
(let [add-field-dimension-options #(assoc-field-dimension-options (driver/database-id->driver database-id) %)]
(for [col metadata]
(-> col
(update :base_type keyword)
(assoc
:table_id (str "card__" card-id)
:id [:field-literal (:name col) (or (:base_type col) :type/*)]
;; don't return :special_type if it's a PK or FK because it confuses the frontend since it can't actually be
;; used that way IRL
:special_type (when-let [special-type (keyword (:special_type col))]
(when-not (or (isa? special-type :type/PK)
(isa? special-type :type/FK))
special-type)))
add-field-dimension-options))))
(defn card->virtual-table
"Return metadata for a 'virtual' table for a CARD in the Saved Questions 'virtual' database. Optionally include
'virtual' fields as well."
[card & {:keys [include-fields?]}]
[{:keys [database_id] :as card} & {:keys [include-fields?]}]
;; if collection isn't already hydrated then do so
(let [card (hydrate card :colllection)]
(cond-> {:id (str "card__" (u/get-id card))
......@@ -254,14 +258,17 @@
:display_name (:name card)
:schema (get-in card [:collection :name] "Everything else")
:description (:description card)}
include-fields? (assoc :fields (card-result-metadata->virtual-fields (u/get-id card) (:result_metadata card))))))
include-fields? (assoc :fields (card-result-metadata->virtual-fields (u/get-id card) database_id (:result_metadata card))))))
(api/defendpoint GET "/card__:id/query_metadata"
"Return metadata for the 'virtual' table for a Card."
[id]
(-> (db/select-one [Card :id :dataset_query :result_metadata :name :description :collection_id], :id id)
api/read-check
(card->virtual-table :include-fields? true)))
(let [{:keys [database_id] :as card } (db/select-one [Card :id :dataset_query :result_metadata :name :description :collection_id :database_id]
:id id)]
(-> card
api/read-check
(card->virtual-table :include-fields? true)
(assoc-dimension-options (driver/database-id->driver database_id)))))
(api/defendpoint GET "/card__:id/fks"
"Return FK info for the 'virtual' table for a Card. This is always empty, so this endpoint
......
......@@ -481,10 +481,13 @@
:result_metadata [{:name "age_in_bird_years"}])]]
(saved-questions-virtual-db
(assoc (virtual-table-for-card card)
:fields [{:name "age_in_bird_years"
:table_id (str "card__" (u/get-id card))
:id ["field-literal" "age_in_bird_years" "type/*"]
:special_type nil}]))
:fields [{:name "age_in_bird_years"
:table_id (str "card__" (u/get-id card))
:id ["field-literal" "age_in_bird_years" "type/*"]
:special_type nil
:base_type nil
:default_dimension_option nil
:dimension_options []}]))
((user->client :crowberto) :get 200 (format "database/%d/metadata" database/virtual-id)))
;; if no eligible Saved Questions exist the virtual DB metadata endpoint should just return `nil`
......
......@@ -19,6 +19,7 @@
[permissions :as perms]
[permissions-group :as perms-group]
[table :as table :refer [Table]]]
[metabase.query-processor-test :as qpt]
[metabase.test
[data :as data]
[util :as tu :refer [match-$]]]
......@@ -158,11 +159,14 @@
(perms/delete-related-permissions! (perms-group/all-users) (perms/object-path database-id))
((user->client :rasta) :get 403 (str "table/" table-id))))
(defn- query-metadata-defaults []
(defn- default-dimension-options []
(->> #'table-api/dimension-options-for-response
var-get
walk/keywordize-keys
(assoc (table-defaults) :dimension_options)))
walk/keywordize-keys))
(defn- query-metadata-defaults []
(-> (table-defaults)
(assoc :dimension_options (default-dimension-options))))
;; ## GET /api/table/:id/query_metadata
(expect
......@@ -435,21 +439,59 @@
:type :native
:native {:query (format "SELECT NAME, ID, PRICE, LATITUDE FROM VENUES")}}}]]
(let [card-virtual-table-id (str "card__" (u/get-id card))]
{:display_name "Go Dubs!"
:schema "Everything else"
:db_id database/virtual-id
:id card-virtual-table-id
:description nil
:fields (for [[field-name display-name base-type] [["NAME" "Name" "type/Text"]
["ID" "ID" "type/Integer"]
["PRICE" "Price" "type/Integer"]
["LATITUDE" "Latitude" "type/Float"]]]
{:name field-name
:display_name display-name
:base_type base-type
:table_id card-virtual-table-id
:id ["field-literal" field-name base-type]
:special_type nil})})
{:display_name "Go Dubs!"
:schema "Everything else"
:db_id database/virtual-id
:id card-virtual-table-id
:description nil
:dimension_options (default-dimension-options)
:fields (for [[field-name display-name base-type] [["NAME" "Name" "type/Text"]
["ID" "ID" "type/Integer"]
["PRICE" "Price" "type/Integer"]
["LATITUDE" "Latitude" "type/Float"]]]
{:name field-name
:display_name display-name
:base_type base-type
:table_id card-virtual-table-id
:id ["field-literal" field-name base-type]
:special_type nil
:default_dimension_option nil
:dimension_options []})})
(do
;; run the Card which will populate its result_metadata column
((user->client :crowberto) :post 200 (format "card/%d/query" (u/get-id card)))
;; Now fetch the metadata for this "table"
((user->client :crowberto) :get 200 (format "table/card__%d/query_metadata" (u/get-id card)))))
;; Test date dimensions being included with a nested query
(tt/expect-with-temp [Card [card {:name "Users"
:database_id (data/id)
:dataset_query {:database (data/id)
:type :native
:native {:query (format "SELECT NAME, LAST_LOGIN FROM USERS")}}}]]
(let [card-virtual-table-id (str "card__" (u/get-id card))]
{:display_name "Users"
:schema "Everything else"
:db_id database/virtual-id
:id card-virtual-table-id
:description nil
:dimension_options (default-dimension-options)
:fields [{:name "NAME"
:display_name "Name"
:base_type "type/Text"
:table_id card-virtual-table-id
:id ["field-literal" "NAME" "type/Text"]
:special_type nil
:default_dimension_option nil
:dimension_options []}
{:name "LAST_LOGIN"
:display_name "Last Login"
:base_type "type/DateTime"
:table_id card-virtual-table-id
:id ["field-literal" "LAST_LOGIN" "type/DateTime"]
:special_type nil
:default_dimension_option (var-get #'table-api/date-default-index)
:dimension_options (var-get #'table-api/datetime-dimension-indexes)}]})
(do
;; run the Card which will populate its result_metadata column
((user->client :crowberto) :post 200 (format "card/%d/query" (u/get-id card)))
......
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