From 18712b24e46e8b4e1dee496a1575888735e035e5 Mon Sep 17 00:00:00 2001 From: Ryan Senior <ryan@metabase.com> Date: Mon, 12 Jun 2017 18:02:42 -0500 Subject: [PATCH] Added dimension_options to the query_metadata response --- src/metabase/api/table.clj | 66 ++++++++++++++++++++++++++++++++ test/metabase/api/table_test.clj | 42 +++++++++++++------- 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/src/metabase/api/table.clj b/src/metabase/api/table.clj index 91909a55583..ed8ad5c484e 100644 --- a/src/metabase/api/table.clj +++ b/src/metabase/api/table.clj @@ -2,6 +2,7 @@ "/api/table endpoints." (:require [clojure.tools.logging :as log] [compojure.core :refer [GET PUT]] + [medley.core :as m] [metabase [sync-database :as sync-database] [util :as u]] @@ -76,6 +77,70 @@ (sync-database/sync-table! updated-table)) updated-table))) +(def ^:private dimension-options + (zipmap (map str (range)) + (concat + (map (fn [[name param]] + {:name name + :mbql ["datetime-field" nil param] + :type :type/DateTime}) + [["Minute" "minute"] + ["Minute of Hour" "minute-of-hour"] + ["Hour" "hour"] + ["Hour of Day" "hour-of-day"] + ["Day" "day"] + ["Day of Week" "day-of-week"] + ["Day of Month" "day-of-month"] + ["Day of Year" "day-of-year"] + ["Week" "week"] + ["Week of Year" "week-of-year"] + ["Month" "month"] + ["Month of Year" "month-of-year"] + ["Quarter" "quarter"] + ["Quarter of Year" "quarter-of-year"] + ["Year" "year"]]) + (map (fn [[name params]] + {:name name + :mbql (apply vector "binning-strategy" nil params) + :type :type/Numeric}) + [["Quantized by the default binning strategy for the field" ["default"]] + ["Quantized by the 10 equally sized bins" ["num-bins" 10]] + ["Quantized by the 50 equally sized bins" ["num-bins" 50]] + ["Quantized by the 100 equally sized bins" ["num-bins" 100]]])))) + +(def ^:private dimension-options-for-response + (m/map-vals #(dissoc % :type) dimension-options)) + +(def ^:private datetime-dimension-indexes + (->> dimension-options + (m/filter-kv (fn [k v] (isa? (:type v) :type/DateTime))) + keys + sort)) + +(def ^:private numeric-dimension-indexes + (->> dimension-options + (m/filter-kv (fn [k v] (isa? (:type v) :type/Numeric))) + keys + sort)) + +(defn- assoc-dimension-options [resp] + (-> resp + (assoc :dimension_options dimension-options-for-response) + (update :fields (fn [fields] + (mapv (fn [{:keys [base_type] :as field}] + (assoc field + :dimension_options + (cond + + (isa? base_type :type/Number) + numeric-dimension-indexes + + (isa? base_type :type/DateTime) + datetime-dimension-indexes + + :else + []))) + fields))))) (api/defendpoint GET "/:id/query_metadata" "Get metadata about a `Table` useful for running queries. @@ -87,6 +152,7 @@ {include_sensitive_fields (s/maybe su/BooleanString)} (-> (api/read-check Table id) (hydrate :db [:fields :target] :field_values :segments :metrics) + assoc-dimension-options (update-in [:fields] (if (Boolean/parseBoolean include_sensitive_fields) ;; If someone passes include_sensitive_fields return hydrated :fields as-is identity diff --git a/test/metabase/api/table_test.clj b/test/metabase/api/table_test.clj index 2074cad07d3..d1f1f67faa6 100644 --- a/test/metabase/api/table_test.clj +++ b/test/metabase/api/table_test.clj @@ -1,6 +1,7 @@ (ns metabase.api.table-test "Tests for /api/table endpoints." - (:require [expectations :refer :all] + (:require [clojure.walk :as walk] + [expectations :refer :all] [metabase [driver :as driver] [http-client :as http] @@ -23,6 +24,7 @@ [toucan.util.test :as tt])) (resolve-private-vars metabase.models.table pk-field-id) +(resolve-private-vars metabase.api.table dimension-options-for-response datetime-dimension-indexes numeric-dimension-indexes) ;; ## /api/org/* AUTHENTICATION Tests @@ -129,10 +131,15 @@ (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 [] + (->> dimension-options-for-response + var-get + walk/keywordize-keys + (assoc (table-defaults) :dimension_options))) ;; ## GET /api/table/:id/query_metadata (expect - (merge (table-defaults) + (merge (query-metadata-defaults) (match-$ (hydrate/hydrate (Table (id :categories)) :field_values) {:schema "PUBLIC" :name "CATEGORIES" @@ -151,7 +158,8 @@ :raw_column_id $ :last_analyzed $ :min_value 1.0 - :max_value 75.0})) + :max_value 75.0 + :dimension_options (var-get numeric-dimension-indexes)})) (merge defaults (match-$ (Field (id :categories :name)) {:special_type "type/Name" :name "NAME" @@ -163,7 +171,8 @@ :base_type "type/Text" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $}))]) + :last_analyzed $ + :dimension_options []}))]) :rows 75 :updated_at $ :id (id :categories) @@ -194,7 +203,7 @@ ;;; GET api/table/:id/query_metadata?include_sensitive_fields ;;; Make sure that getting the User table *does* include info about the password field, but not actual values themselves (expect - (merge (table-defaults) + (merge (query-metadata-defaults) (match-$ (Table (id :users)) {:schema "PUBLIC" :name "USERS" @@ -213,7 +222,8 @@ :raw_column_id $ :last_analyzed $ :min_value 1.0 - :max_value 15.0})) + :max_value 15.0 + :dimension_options (var-get numeric-dimension-indexes)})) (merge defaults (match-$ (Field (id :users :last_login)) {:special_type nil :name "LAST_LOGIN" @@ -225,7 +235,8 @@ :visibility_type "normal" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $})) + :last_analyzed $ + :dimension_options (var-get datetime-dimension-indexes)})) (merge defaults (match-$ (Field (id :users :name)) {:special_type "type/Name" :name "NAME" @@ -237,7 +248,8 @@ :visibility_type "normal" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $})) + :last_analyzed $ + :dimension_options []})) (merge defaults (match-$ (Field :table_id (id :users), :name "PASSWORD") {:special_type "type/Category" :name "PASSWORD" @@ -249,7 +261,8 @@ :visibility_type "sensitive" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $}))]) + :last_analyzed $ + :dimension_options []}))]) :rows 15 :updated_at $ :id (id :users) @@ -276,7 +289,7 @@ ;;; GET api/table/:id/query_metadata ;;; Make sure that getting the User table does *not* include password info (expect - (merge (table-defaults) + (merge (query-metadata-defaults) (match-$ (Table (id :users)) {:schema "PUBLIC" :name "USERS" @@ -294,7 +307,8 @@ :raw_column_id $ :last_analyzed $ :min_value 1.0 - :max_value 15.0})) + :max_value 15.0 + :dimension_options (var-get numeric-dimension-indexes)})) (merge defaults (match-$ (Field (id :users :last_login)) {:special_type nil :name "LAST_LOGIN" @@ -305,7 +319,8 @@ :base_type "type/DateTime" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $})) + :last_analyzed $ + :dimension_options (var-get datetime-dimension-indexes)})) (merge defaults (match-$ (Field (id :users :name)) {:special_type "type/Name" :name "NAME" @@ -316,7 +331,8 @@ :base_type "type/Text" :fk_target_field_id $ :raw_column_id $ - :last_analyzed $}))]) + :last_analyzed $ + :dimension_options []}))]) :rows 15 :updated_at $ :id (id :users) -- GitLab