From 918e360819933f10f6b3dd2c3fb0781372d7f29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cam=20Sa=C3=BCl?= <cammsaul@gmail.com> Date: Tue, 6 Sep 2016 21:33:29 -0700 Subject: [PATCH] Stop the insanity :scream_cat: :gun: --- src/metabase/models/field.clj | 91 +- src/metabase/query_processor/resolve.clj | 1 + src/metabase/sync_database/interface.clj | 44 +- test/metabase/api/table_test.clj | 809 ++++----- test/metabase/models/field_test.clj | 56 +- test/metabase/sync_database/analyze_test.clj | 25 +- .../sync_database/introspect_test.clj | 419 ++--- .../sync_database/sync_dynamic_test.clj | 393 ++--- test/metabase/sync_database/sync_test.clj | 246 +-- test/metabase/sync_database_test.clj | 290 +--- test/metabase/test/mock/moviedb.clj | 658 ++----- .../test/mock/schema_per_customer.clj | 1514 +++++------------ test/metabase/test/mock/toucanery.clj | 395 ++--- 13 files changed, 1505 insertions(+), 3436 deletions(-) diff --git a/src/metabase/models/field.clj b/src/metabase/models/field.clj index 958c6ac992c..935c74a6746 100644 --- a/src/metabase/models/field.clj +++ b/src/metabase/models/field.clj @@ -1,7 +1,7 @@ (ns metabase.models.field (:require (clojure [data :as d] [string :as s]) - [medley.core :as m] + [metabase.config :as config] [metabase.db :as db] (metabase.models [field-values :refer [FieldValues]] [humanization :as humanization] @@ -78,10 +78,20 @@ (i/defentity Field :metabase_field) +(defn- assert-valid-special-type [{special-type :special_type}] + (when special-type + (assert (contains? special-types (keyword special-type)) + (str "Invalid special type: " special-type)))) + (defn- pre-insert [field] + (assert-valid-special-type field) (let [defaults {:display_name (humanization/name->human-readable-name (:name field))}] (merge defaults field))) +(defn- pre-update [field] + (u/prog1 field + (assert-valid-special-type field))) + (defn- pre-cascade-delete [{:keys [id]}] (db/cascade-delete! Field :parent_id id) (db/cascade-delete! 'FieldValues :field_id id) @@ -98,6 +108,7 @@ :can-read? (constantly true) :can-write? i/superuser? :pre-insert pre-insert + :pre-update pre-update :pre-cascade-delete pre-cascade-delete})) @@ -167,7 +178,8 @@ ;;; ------------------------------------------------------------ Sync Util Type Inference Fns ------------------------------------------------------------ (def ^:private ^:const pattern+base-types+special-type - "Tuples of [pattern set-of-valid-base-types special-type] + "Tuples of `[name-pattern set-of-valid-base-types special-type]`. + Fields whose name matches the pattern and one of the base types should be given the special type. * Convert field name to lowercase before matching against a pattern * Consider a nil set-of-valid-base-types to mean \"match any base type\"" @@ -213,24 +225,23 @@ [#"^zipcode$" int-or-text :zip_code]])) ;; Check that all the pattern tuples are valid -(doseq [[name-pattern base-types special-type] pattern+base-types+special-type] - (assert (instance? java.util.regex.Pattern name-pattern)) - (assert (every? (partial contains? base-types) base-types)) - (assert (contains? special-types special-type))) +(when-not config/is-prod? + (doseq [[name-pattern base-types special-type] pattern+base-types+special-type] + (assert (instance? java.util.regex.Pattern name-pattern)) + (assert (every? (partial contains? base-types) base-types)) + (assert (contains? special-types special-type)))) (defn- infer-field-special-type "If `name` and `base-type` matches a known pattern, return the `special_type` we should assign to it." - [field-name base_type] + [field-name base-type] (when (and (string? field-name) - (keyword? base_type)) + (keyword? base-type)) (or (when (= "id" (s/lower-case field-name)) :id) - (when-let [matching-pattern (m/find-first (fn [[name-pattern valid-base-types]] - (and (or (nil? valid-base-types) - (contains? valid-base-types base_type)) - (re-matches name-pattern (s/lower-case field-name)))) - pattern+base-types+special-type)] - ;; the actual special-type is the last element of the pattern - (last matching-pattern))))) + (some (fn [[name-pattern valid-base-types special-type]] + (when (and (contains? valid-base-types base-type) + (re-matches name-pattern (s/lower-case field-name))) + special-type)) + pattern+base-types+special-type)))) ;;; ------------------------------------------------------------ Sync Util CRUD Fns ------------------------------------------------------------ @@ -238,26 +249,23 @@ (defn update-field! "Update an existing `Field` from the given FIELD-DEF." [{:keys [id], :as existing-field} {field-name :name, :keys [base-type special-type pk? parent-id]}] - (let [updated-field (assoc existing-field - :base_type base-type - :display_name (or (:display_name existing-field) - (humanization/name->human-readable-name field-name)) - :special_type (or (:special_type existing-field) - special-type - (when pk? :id) - (infer-field-special-type field-name base-type)) - - :parent_id parent-id) - [is-diff? _ _] (d/diff updated-field existing-field)] + (u/prog1 (assoc existing-field + :base_type base-type + :display_name (or (:display_name existing-field) + (humanization/name->human-readable-name field-name)) + :special_type (or (:special_type existing-field) + special-type + (when pk? :id) + (infer-field-special-type field-name base-type)) + + :parent_id parent-id) ;; if we have a different base-type or special-type, then update - (when is-diff? + (when (first (d/diff <> existing-field)) (db/update! Field id - :display_name (:display_name updated-field) + :display_name (:display_name <>) :base_type base-type - :special_type (:special_type updated-field) - :parent_id parent-id)) - ;; return the updated field when we are done - updated-field)) + :special_type (:special_type <>) + :parent_id parent-id)))) (defn create-field! @@ -266,13 +274,14 @@ {:pre [(integer? table-id) (string? field-name) (contains? base-types base-type)]} - (db/insert! Field - :table_id table-id - :raw_column_id raw-column-id - :name field-name - :display_name (humanization/name->human-readable-name field-name) - :base_type base-type - :special_type (or special-type + (let [special-type (or special-type (when pk? :id) - (infer-field-special-type field-name base-type)) - :parent_id parent-id)) + (infer-field-special-type field-name base-type))] + (db/insert! Field + :table_id table-id + :raw_column_id raw-column-id + :name field-name + :display_name (humanization/name->human-readable-name field-name) + :base_type base-type + :special_type special-type + :parent_id parent-id))) diff --git a/src/metabase/query_processor/resolve.clj b/src/metabase/query_processor/resolve.clj index eaa0628d5ce..e9d2af3833b 100644 --- a/src/metabase/query_processor/resolve.clj +++ b/src/metabase/query_processor/resolve.clj @@ -194,6 +194,7 @@ expanded-query-dict ;; Otherwise fetch + resolve the Fields in question (let [fields (->> (u/key-by :id (db/select [field/Field :name :display_name :base_type :special_type :visibility_type :table_id :parent_id :description :id] + :visibility_type [:not-in ["sensitive"]] :id [:in field-ids])) (m/map-vals rename-mb-field-keys) (m/map-vals #(assoc % :parent (when-let [parent-id (:parent-id %)] diff --git a/src/metabase/sync_database/interface.clj b/src/metabase/sync_database/interface.clj index 047151cd116..28c8b2491c3 100644 --- a/src/metabase/sync_database/interface.clj +++ b/src/metabase/sync_database/interface.clj @@ -1,39 +1,41 @@ (ns metabase.sync-database.interface - (:require [schema.core :as schema] - [metabase.models.field :as field])) + "Schemas describing the output expected from different DB sync functions." + (:require [schema.core :as s] + [metabase.models.field :as field] + [metabase.util.schema :as su])) (def AnalyzeTable "Schema for the expected output of `analyze-table`." - {(schema/optional-key :row_count) (schema/maybe schema/Int) - (schema/optional-key :fields) [{:id schema/Int - (schema/optional-key :special-type) (apply schema/enum field/special-types) - (schema/optional-key :preview-display) schema/Bool - (schema/optional-key :values) [schema/Any]}]}) + {(s/optional-key :row_count) (s/maybe s/Int) + (s/optional-key :fields) [{:id su/IntGreaterThanZero + (s/optional-key :special-type) (apply s/enum field/special-types) + (s/optional-key :preview-display) s/Bool + (s/optional-key :values) [s/Any]}]}) (def DescribeDatabase "Schema for the expected output of `describe-database`." - {:tables #{{:name schema/Str - :schema (schema/maybe schema/Str)}}}) + {:tables #{{:name s/Str + :schema (s/maybe s/Str)}}}) (def DescribeTableField "Schema for a given Field as provided in `describe-table` or `analyze-table`." - {:name schema/Str - :base-type (apply schema/enum field/base-types) - (schema/optional-key :special-type) (apply schema/enum field/special-types) - (schema/optional-key :pk?) schema/Bool - (schema/optional-key :nested-fields) #{(schema/recursive #'DescribeTableField)} - (schema/optional-key :custom) {schema/Any schema/Any}}) + {:name su/NonBlankString + :base-type (apply s/enum field/base-types) + (s/optional-key :special-type) (apply s/enum field/special-types) + (s/optional-key :pk?) s/Bool + (s/optional-key :nested-fields) #{(s/recursive #'DescribeTableField)} + (s/optional-key :custom) {s/Any s/Any}}) (def DescribeTable "Schema for the expected output of `describe-table`." - {:name schema/Str - :schema (schema/maybe schema/Str) + {:name su/NonBlankString + :schema (s/maybe su/NonBlankString) :fields #{DescribeTableField}}) (def DescribeTableFKs "Schema for the expected output of `describe-table-fks`." - (schema/maybe #{{:fk-column-name schema/Str - :dest-table {:name schema/Str - :schema (schema/maybe schema/Str)} - :dest-column-name schema/Str}})) + (s/maybe #{{:fk-column-name su/NonBlankString + :dest-table {:name su/NonBlankString + :schema (s/maybe su/NonBlankString)} + :dest-column-name su/NonBlankString}})) diff --git a/test/metabase/api/table_test.clj b/test/metabase/api/table_test.clj index a8f32ff2470..129e503b801 100644 --- a/test/metabase/api/table_test.clj +++ b/test/metabase/api/table_test.clj @@ -42,185 +42,142 @@ :points_of_interest nil :features (mapv name (driver/features (driver/engine->driver :h2)))})) +(defn- table-defaults [] + {:description nil + :caveats nil + :points_of_interest nil + :show_in_getting_started false + :entity_type nil + :visibility_type nil + :db (db-details) + :field_values {} + :entity_name nil + :active true + :db_id (id) + :segments [] + :metrics []}) + +(def ^:private ^:const field-defaults + {:description nil + :active true + :position 0 + :target nil + :preview_display true + :visibility_type "normal" + :caveats nil + :points_of_interest nil + :parent_id nil}) + ;; ## GET /api/table ;; These should come back in alphabetical order and include relevant metadata (expect - #{{:name (format-name "categories") - :display_name "Categories" - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :db_id (id) - :active true - :rows 75 - :id (id :categories)} - {:name (format-name "checkins") - :display_name "Checkins" - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :db_id (id) - :active true - :rows 1000 - :id (id :checkins)} - {:name (format-name "users") - :display_name "Users" - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :db_id (id) - :active true - :rows 15 - :id (id :users)} - {:name (format-name "venues") - :display_name "Venues" - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :db_id (id) - :active true - :rows 100 - :id (id :venues)}} + #{{:name (format-name "categories") + :display_name "Categories" + :rows 75 + :id (id :categories)} + {:name (format-name "checkins") + :display_name "Checkins" + :rows 1000 + :id (id :checkins)} + {:name (format-name "users") + :display_name "Users" + :rows 15 + :id (id :users)} + {:name (format-name "venues") + :display_name "Venues" + :rows 100 + :id (id :venues)}} (->> ((user->client :rasta) :get 200 "table") (filter #(= (:db_id %) (id))) ; prevent stray tables from affecting unit test results - (map #(dissoc % :raw_table_id :db :created_at :updated_at :schema :entity_name :description :entity_type :visibility_type)) + (map #(dissoc % + :raw_table_id :db :created_at :updated_at :schema :entity_name :description :entity_type :visibility_type + :caveats :points_of_interest :show_in_getting_started :db_id :active)) set)) + ;; ## GET /api/table/:id (expect - (match-$ (Table (id :venues)) - {:description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :visibility_type nil - :db (db-details) - :schema "PUBLIC" - :name "VENUES" - :display_name "Venues" - :rows 100 - :updated_at $ - :entity_name nil - :active true - :pk_field (pk-field-id $$) - :id (id :venues) - :db_id (id) - :raw_table_id $ - :created_at $}) + (merge (dissoc (table-defaults) :segments :field_values :metrics) + (match-$ (Table (id :venues)) + {:schema "PUBLIC" + :name "VENUES" + :display_name "Venues" + :rows 100 + :updated_at $ + :pk_field (pk-field-id $$) + :id (id :venues) + :db_id (id) + :raw_table_id $ + :created_at $})) ((user->client :rasta) :get 200 (format "table/%d" (id :venues)))) ;; ## GET /api/table/:id/fields (expect - [(match-$ (Field (id :categories :id)) - {:description nil - :table_id (id :categories) - :special_type "id" - :name "ID" - :display_name "ID" - :updated_at $ - :active true - :id (id :categories :id) - :position 0 - :preview_display true - :created_at $ - :base_type "BigIntegerField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :categories :name)) - {:description nil - :caveats nil - :points_of_interest nil - :table_id (id :categories) - :special_type "name" - :name "NAME" - :display_name "Name" - :updated_at $ - :active true - :id (id :categories :name) - :position 0 - :preview_display true - :created_at $ - :base_type "TextField" - :visibility_type "normal" - :fk_target_field_id $ - :parent_id nil - :raw_column_id $ - :last_analyzed $})] + (let [defaults (-> field-defaults + (assoc :table_id (id :categories)) + (dissoc :target))] + [(merge defaults (match-$ (Field (id :categories :id)) + {:special_type "id" + :name "ID" + :display_name "ID" + :updated_at $ + :id (id :categories :id) + :created_at $ + :base_type "BigIntegerField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :categories :name)) + {:special_type "name" + :name "NAME" + :display_name "Name" + :updated_at $ + :id (id :categories :name) + :created_at $ + :base_type "TextField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $}))]) ((user->client :rasta) :get 200 (format "table/%d/fields" (id :categories)))) ;; ## GET /api/table/:id/query_metadata (expect - (match-$ (Table (id :categories)) - {:description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :visibility_type nil - :db (db-details) - :schema "PUBLIC" - :name "CATEGORIES" - :display_name "Categories" - :fields [(match-$ (Field (id :categories :id)) - {:description nil - :caveats nil - :points_of_interest nil - :table_id (id :categories) - :special_type "id" - :name "ID" - :display_name "ID" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "BigIntegerField" - :visibility_type "normal" - :fk_target_field_id $ - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :categories :name)) - {:description nil - :caveats nil - :points_of_interest nil - :table_id (id :categories) - :special_type "name" - :name "NAME" - :display_name "Name" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "TextField" - :visibility_type "normal" - :fk_target_field_id $ - :parent_id nil - :raw_column_id $ - :last_analyzed $})] - :field_values {} - :rows 75 - :updated_at $ - :entity_name nil - :active true - :id (id :categories) - :db_id (id) - :raw_table_id $ - :segments [] - :metrics [] - :created_at $}) + (merge (table-defaults) + (match-$ (Table (id :categories)) + {:schema "PUBLIC" + :name "CATEGORIES" + :display_name "Categories" + :fields (let [defaults (assoc field-defaults :table_id (id :categories))] + [(merge defaults (match-$ (Field (id :categories :id)) + {:special_type "id" + :name "ID" + :display_name "ID" + :updated_at $ + :id $ + :position 0 + :created_at $ + :base_type "BigIntegerField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :categories :name)) + {:special_type "name" + :name "NAME" + :display_name "Name" + :updated_at $ + :id $ + :position 0 + :created_at $ + :base_type "TextField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $}))]) + :rows 75 + :updated_at $ + :id (id :categories) + :raw_table_id $ + :created_at $})) ((user->client :rasta) :get 200 (format "table/%d/query_metadata" (id :categories)))) @@ -245,269 +202,166 @@ ;;; 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 - (match-$ (Table (id :users)) - {:description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :visibility_type nil - :db (db-details) - :schema "PUBLIC" - :name "USERS" - :display_name "Users" - :fields [(match-$ (Field (id :users :id)) - {:description nil - :table_id (id :users) - :special_type "id" - :name "ID" - :display_name "ID" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "BigIntegerField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :users :last_login)) - {:description nil - :table_id (id :users) - :special_type nil - :name "LAST_LOGIN" - :display_name "Last Login" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "DateTimeField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :users :name)) - {:description nil - :table_id (id :users) - :special_type "name" - :name "NAME" - :display_name "Name" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "TextField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field :table_id (id :users), :name "PASSWORD") - {:description nil - :table_id (id :users) - :special_type "category" - :name "PASSWORD" - :display_name "Password" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "TextField" - :visibility_type "sensitive" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $})] - :rows 15 - :updated_at $ - :entity_name nil - :active true - :id (id :users) - :db_id (id) - :raw_table_id $ - :field_values {(keyword (str (id :users :name))) - ["Broen Olujimi" - "Conchúr Tihomir" - "Dwight Gresham" - "Felipinho Asklepios" - "Frans Hevel" - "Kaneonuskatew Eiran" - "Kfir Caj" - "Nils Gotam" - "Plato Yeshua" - "Quentin Sören" - "Rüstem Hebel" - "Shad Ferdynand" - "Simcha Yan" - "Spiros Teofil" - "Szymon Theutrich"]} - :segments [] - :metrics [] - :created_at $}) + (merge (table-defaults) + (match-$ (Table (id :users)) + {:schema "PUBLIC" + :name "USERS" + :display_name "Users" + :fields (let [defaults (assoc field-defaults :table_id (id :users))] + [(merge defaults (match-$ (Field (id :users :id)) + {:special_type "id" + :name "ID" + :display_name "ID" + :updated_at $ + :id $ + :created_at $ + :base_type "BigIntegerField" + :visibility_type "normal" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :users :last_login)) + {:special_type nil + :name "LAST_LOGIN" + :display_name "Last Login" + :updated_at $ + :id $ + :created_at $ + :base_type "DateTimeField" + :visibility_type "normal" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :users :name)) + {:special_type "name" + :name "NAME" + :display_name "Name" + :updated_at $ + :id $ + :created_at $ + :base_type "TextField" + :visibility_type "normal" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field :table_id (id :users), :name "PASSWORD") + {:special_type "category" + :name "PASSWORD" + :display_name "Password" + :updated_at $ + :id $ + :created_at $ + :base_type "TextField" + :visibility_type "sensitive" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $}))]) + :rows 15 + :updated_at $ + :id (id :users) + :raw_table_id $ + :field_values {(keyword (str (id :users :name))) + ["Broen Olujimi" + "Conchúr Tihomir" + "Dwight Gresham" + "Felipinho Asklepios" + "Frans Hevel" + "Kaneonuskatew Eiran" + "Kfir Caj" + "Nils Gotam" + "Plato Yeshua" + "Quentin Sören" + "Rüstem Hebel" + "Shad Ferdynand" + "Simcha Yan" + "Spiros Teofil" + "Szymon Theutrich"]} + :created_at $})) ((user->client :rasta) :get 200 (format "table/%d/query_metadata?include_sensitive_fields=true" (id :users)))) ;;; GET api/table/:id/query_metadata ;;; Make sure that getting the User table does *not* include password info (expect - (match-$ (Table (id :users)) - {:description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :visibility_type nil - :db (db-details) - :schema "PUBLIC" - :name "USERS" - :display_name "Users" - :fields [(match-$ (Field (id :users :id)) - {:description nil - :table_id (id :users) - :special_type "id" - :name "ID" - :display_name "ID" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "BigIntegerField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :users :last_login)) - {:description nil - :table_id (id :users) - :special_type nil - :name "LAST_LOGIN" - :display_name "Last Login" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "DateTimeField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $}) - (match-$ (Field (id :users :name)) - {:description nil - :table_id (id :users) - :special_type "name" - :name "NAME" - :display_name "Name" - :updated_at $ - :active true - :id $ - :position 0 - :target nil - :preview_display true - :created_at $ - :base_type "TextField" - :visibility_type "normal" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :parent_id nil - :raw_column_id $ - :last_analyzed $})] - :rows 15 - :updated_at $ - :entity_name nil - :active true - :id (id :users) - :db_id (id) - :raw_table_id $ - :field_values {(keyword (str (id :users :name))) - ["Broen Olujimi" - "Conchúr Tihomir" - "Dwight Gresham" - "Felipinho Asklepios" - "Frans Hevel" - "Kaneonuskatew Eiran" - "Kfir Caj" - "Nils Gotam" - "Plato Yeshua" - "Quentin Sören" - "Rüstem Hebel" - "Shad Ferdynand" - "Simcha Yan" - "Spiros Teofil" - "Szymon Theutrich"]} - :segments [] - :metrics [] - :created_at $}) + (merge (table-defaults) + (match-$ (Table (id :users)) + {:schema "PUBLIC" + :name "USERS" + :display_name "Users" + :fields (let [defaults (assoc field-defaults :table_id (id :users))] + [(merge defaults (match-$ (Field (id :users :id)) + {:special_type "id" + :name "ID" + :display_name "ID" + :updated_at $ + :id $ + :created_at $ + :base_type "BigIntegerField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :users :last_login)) + {:special_type nil + :name "LAST_LOGIN" + :display_name "Last Login" + :updated_at $ + :id $ + :created_at $ + :base_type "DateTimeField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $})) + (merge defaults (match-$ (Field (id :users :name)) + {:special_type "name" + :name "NAME" + :display_name "Name" + :updated_at $ + :id $ + :created_at $ + :base_type "TextField" + :fk_target_field_id $ + :raw_column_id $ + :last_analyzed $}))]) + :rows 15 + :updated_at $ + :id (id :users) + :raw_table_id $ + :field_values {(keyword (str (id :users :name))) + ["Broen Olujimi" + "Conchúr Tihomir" + "Dwight Gresham" + "Felipinho Asklepios" + "Frans Hevel" + "Kaneonuskatew Eiran" + "Kfir Caj" + "Nils Gotam" + "Plato Yeshua" + "Quentin Sören" + "Rüstem Hebel" + "Shad Ferdynand" + "Simcha Yan" + "Spiros Teofil" + "Szymon Theutrich"]} + :created_at $})) ((user->client :rasta) :get 200 (format "table/%d/query_metadata" (id :users)))) ;; ## PUT /api/table/:id (tu/expect-with-temp [Table [table {:rows 15}]] - (match-$ table - {:description "What a nice table!" - :entity_type "person" - :visibility_type "hidden" - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :db (match-$ (db) - {:description nil - :caveats nil - :points_of_interest nil - :organization_id $ - :name "test-data" - :is_sample false - :is_full_sync true - :updated_at $ - :details $ - :id $ - :engine "h2" - :created_at $ - :features (mapv name (driver/features (driver/engine->driver :h2)))}) - :schema $ - :name $ - :rows 15 - :entity_name nil - :display_name "Userz" - :active true - :pk_field (pk-field-id $$) - :id $ - :db_id (id) - :raw_table_id $ - :created_at $}) + (merge (-> (table-defaults) + (dissoc :segments :field_values :metrics) + (assoc-in [:db :details] {:short-lived? nil, :db "mem:test-data;USER=GUEST;PASSWORD=guest"})) + (match-$ table + {:description "What a nice table!" + :entity_type "person" + :visibility_type "hidden" + :schema $ + :name $ + :rows 15 + :display_name "Userz" + :pk_field (pk-field-id $$) + :id $ + :raw_table_id $ + :created_at $})) (do ((user->client :crowberto) :put 200 (format "table/%d" (:id table)) {:display_name "Userz" :entity_type "person" :visibility_type "hidden" @@ -524,83 +378,56 @@ [{:origin_id (:id checkins-user-field) :destination_id (:id users-id-field) :relationship "Mt1" - :origin (match-$ checkins-user-field - {:id $ - :table_id $ - :raw_column_id $ - :parent_id nil - :name "USER_ID" - :display_name "User ID" - :description nil - :base_type "IntegerField" - :visibility_type "normal" - :preview_display $ - :position $ - :active true - :special_type "fk" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :created_at $ - :updated_at $ - :last_analyzed $ - :table (match-$ (Table (id :checkins)) - {:description nil - :entity_type nil - :visibility_type nil - :schema "PUBLIC" - :name "CHECKINS" - :display_name "Checkins" - :rows 1000 - :updated_at $ - :entity_name nil - :show_in_getting_started false - :caveats nil - :points_of_interest nil - :active true - :id $ - :db_id $ - :raw_table_id $ - :created_at $ - :db (db-details)})}) - :destination (match-$ users-id-field - {:id $ - :table_id $ - :raw_column_id $ - :parent_id nil - :name "ID" - :display_name "ID" - :description nil - :base_type "BigIntegerField" - :visibility_type "normal" - :preview_display $ - :position $ - :active true - :special_type "id" - :fk_target_field_id $ - :caveats nil - :points_of_interest nil - :created_at $ - :updated_at $ - :last_analyzed $ - :table (match-$ (Table (id :users)) - {:description nil - :entity_type nil - :visibility_type nil - :schema "PUBLIC" - :name "USERS" - :display_name "Users" - :rows 15 - :updated_at $ - :entity_name nil - :show_in_getting_started false - :caveats nil - :points_of_interest nil - :active true - :id $ - :db_id $ - :raw_table_id $ - :created_at $})})}]) + :origin (merge (dissoc field-defaults :target) + (match-$ checkins-user-field + {:id $ + :table_id $ + :raw_column_id $ + :name "USER_ID" + :display_name "User ID" + :base_type "IntegerField" + :preview_display $ + :position $ + :special_type "fk" + :fk_target_field_id $ + :created_at $ + :updated_at $ + :last_analyzed $ + :table (merge (dissoc (table-defaults) :segments :field_values :metrics) + (match-$ (Table (id :checkins)) + {:schema "PUBLIC" + :name "CHECKINS" + :display_name "Checkins" + :rows 1000 + :updated_at $ + :id $ + :raw_table_id $ + :created_at $}))})) + :destination (merge (dissoc field-defaults :target) + (match-$ users-id-field + {:id $ + :table_id $ + :raw_column_id $ + :name "ID" + :display_name "ID" + :base_type "BigIntegerField" + :preview_display $ + :position $ + :special_type "id" + :fk_target_field_id $ + :created_at $ + :updated_at $ + :last_analyzed $ + :table (merge (dissoc (table-defaults) :db :segments :field_values :metrics) + (match-$ (Table (id :users)) + {:schema "PUBLIC" + :name "USERS" + :display_name "Users" + :rows 15 + :updated_at $ + :id $ + :raw_table_id $ + :created_at $}))}))}]) ((user->client :rasta) :get 200 (format "table/%d/fks" (id :users)))) diff --git a/test/metabase/models/field_test.clj b/test/metabase/models/field_test.clj index 4bd22bbc545..e0ad0474542 100644 --- a/test/metabase/models/field_test.clj +++ b/test/metabase/models/field_test.clj @@ -32,52 +32,52 @@ :special_type :category :visibility_type :details-only})) ;; date/time based fields should always be excluded -(expect false (field-should-have-field-values? {:base_type :DateField - :special_type :category +(expect false (field-should-have-field-values? {:base_type :DateField + :special_type :category :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :DateTimeField - :special_type :category +(expect false (field-should-have-field-values? {:base_type :DateTimeField + :special_type :category :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :TimeField - :special_type :category +(expect false (field-should-have-field-values? {:base_type :TimeField + :special_type :category :visibility_type :normal})) ;; most special types should be excluded (expect false (field-should-have-field-values? {:base_type :CharField :special_type :image :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :CharField - :special_type :id +(expect false (field-should-have-field-values? {:base_type :CharField + :special_type :id :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :CharField - :special_type :fk +(expect false (field-should-have-field-values? {:base_type :CharField + :special_type :fk :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :CharField - :special_type :latitude +(expect false (field-should-have-field-values? {:base_type :CharField + :special_type :latitude :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :CharField - :special_type :number +(expect false (field-should-have-field-values? {:base_type :CharField + :special_type :number :visibility_type :normal})) -(expect false (field-should-have-field-values? {:base_type :CharField - :special_type :timestamp_milliseconds +(expect false (field-should-have-field-values? {:base_type :CharField + :special_type :timestamp_milliseconds :visibility_type :normal})) ;; boolean fields + category/city/state/country fields are g2g -(expect true (field-should-have-field-values? {:base_type :BooleanField - :special_type :number +(expect true (field-should-have-field-values? {:base_type :BooleanField + :special_type :number :visibility_type :normal})) -(expect true (field-should-have-field-values? {:base_type :CharField - :special_type :category +(expect true (field-should-have-field-values? {:base_type :CharField + :special_type :category :visibility_type :normal})) -(expect true (field-should-have-field-values? {:base_type :TextField - :special_type :city +(expect true (field-should-have-field-values? {:base_type :TextField + :special_type :city :visibility_type :normal})) -(expect true (field-should-have-field-values? {:base_type :TextField - :special_type :state +(expect true (field-should-have-field-values? {:base_type :TextField + :special_type :state :visibility_type :normal})) -(expect true (field-should-have-field-values? {:base_type :TextField - :special_type :country +(expect true (field-should-have-field-values? {:base_type :TextField + :special_type :country :visibility_type :normal})) -(expect true (field-should-have-field-values? {:base_type :TextField - :special_type :name +(expect true (field-should-have-field-values? {:base_type :TextField + :special_type :name :visibility_type :normal})) diff --git a/test/metabase/sync_database/analyze_test.clj b/test/metabase/sync_database/analyze_test.clj index 23f22b5c3af..932bcd83b07 100644 --- a/test/metabase/sync_database/analyze_test.clj +++ b/test/metabase/sync_database/analyze_test.clj @@ -1,5 +1,7 @@ (ns metabase.sync-database.analyze-test - (:require [expectations :refer :all] + (:require [clojure.string :as str] + [expectations :refer :all] + [metabase.db.metadata-queries :as metadata-queries] [metabase.sync-database.analyze :refer :all] [metabase.test.util :as tu])) @@ -8,15 +10,13 @@ ;; (#2332) check that if field values are long we skip over them (expect {:values nil} - (with-redefs-fn {#'metabase.db.metadata-queries/field-distinct-values (fn [_ _] - [(clojure.string/join (repeat 5000 "A"))])} + (with-redefs-fn {#'metadata-queries/field-distinct-values (constantly [(str/join (repeat 5000 "A"))])} #(test:cardinality-and-extract-field-values {} {}))) (expect {:values [1 2 3 4] :special-type :category} - (with-redefs-fn {#'metabase.db.metadata-queries/field-distinct-values (fn [_ _] - [1 2 3 4])} + (with-redefs-fn {#'metadata-queries/field-distinct-values (constantly [1 2 3 4])} #(test:cardinality-and-extract-field-values {} {}))) @@ -28,40 +28,35 @@ "A sequence of values that should be marked is valid JSON.") ;; When all the values are valid JSON dicts they're valid JSON -(expect true +(expect (values-are-valid-json? ["{\"this\":\"is\",\"valid\":\"json\"}" "{\"this\":\"is\",\"valid\":\"json\"}" "{\"this\":\"is\",\"valid\":\"json\"}"])) ;; When all the values are valid JSON arrays they're valid JSON -(expect true +(expect (values-are-valid-json? ["[1, 2, 3, 4]" "[1, 2, 3, 4]" "[1, 2, 3, 4]"])) ;; Some combo of both can still be marked as JSON -(expect true +(expect (values-are-valid-json? ["{\"this\":\"is\",\"valid\":\"json\"}" "[1, 2, 3, 4]" "[1, 2, 3, 4]"])) ;; If the values have some valid JSON dicts but is mostly null, it's still valid JSON -(expect true +(expect (values-are-valid-json? ["{\"this\":\"is\",\"valid\":\"json\"}" nil nil])) ;; If every value is nil then the values should not be considered valid JSON (expect false - (values-are-valid-json? [nil, nil, nil])) + (values-are-valid-json? [nil nil nil])) ;; Check that things that aren't dictionaries or arrays aren't marked as JSON (expect false (values-are-valid-json? ["\"A JSON string should not cause a Field to be marked as JSON\""])) (expect false (values-are-valid-json? ["100"])) (expect false (values-are-valid-json? ["true"])) (expect false (values-are-valid-json? ["false"])) - - -;; TODO: analyze-table-data-shape! - -;; TODO: analyze-data-shape-for-tables! diff --git a/test/metabase/sync_database/introspect_test.clj b/test/metabase/sync_database/introspect_test.clj index e29a9035996..4fa464fb896 100644 --- a/test/metabase/sync_database/introspect_test.clj +++ b/test/metabase/sync_database/introspect_test.clj @@ -7,7 +7,8 @@ [raw-table :refer [RawTable]]) [metabase.sync-database.introspect :as introspect] [metabase.test.mock.moviedb :as moviedb] - [metabase.test.util :as tu])) + [metabase.test.util :as tu] + [metabase.util :as u])) (tu/resolve-private-fns metabase.sync-database.introspect save-all-table-columns! save-all-table-fks! create-raw-table! update-raw-table! disable-raw-tables!) @@ -20,89 +21,28 @@ (->> (hydrate/hydrate (RawTable :raw_table_id table-id) :columns) (mapv tu/boolean-ids-and-timestamps))) +(def ^:private ^:const field-defaults + {:id true + :raw_table_id true + :active true + :column_type nil + :is_pk false + :fk_target_column_id false + :details {} + :created_at true + :updated_at true}) + ;; save-all-table-fks ;; test case of multi schema with repeating table names (expect - [[{:id true - :raw_table_id true - :name "id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :name "user_id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :name "id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :name "user_id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id true - :details {} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :name "id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :name "user_id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :name "id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :name "user_id" - :active true - :column_type nil - :is_pk false - :fk_target_column_id true - :details {} - :created_at true - :updated_at true}]] + [[(merge field-defaults {:name "id"}) + (merge field-defaults {:name "user_id"})] + [(merge field-defaults {:name "id"}) + (merge field-defaults {:name "user_id", :fk_target_column_id true})] + [(merge field-defaults {:name "id"}) + (merge field-defaults {:name "user_id"})] + [(merge field-defaults {:name "id"}) + (merge field-defaults {:name "user_id", :fk_target_column_id true})]] (tu/with-temp* [Database [{database-id :id}] RawTable [{raw-table-id1 :id, :as table} {:database_id database-id, :schema "customer1", :name "photos"}] RawColumn [_ {:raw_table_id raw-table-id1, :name "id"}] @@ -136,76 +76,29 @@ ;; save-all-table-columns (expect [[] - [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk true - :fk_target_column_id false - :details {:inches 7, :special-type "category", :base-type "IntegerField"} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:inches 8, :base-type "IntegerField"} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :active true - :name "num_feathers" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:count 10000, :base-type "IntegerField"} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :active false - :name "beak_size" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:inches 8, :base-type "IntegerField"} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :active true - :name "num_feathers" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:count 12000, :base-type "IntegerField"} - :created_at true - :updated_at true}] - [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:inches 8, :base-type "IntegerField"} - :created_at true - :updated_at true} - {:id true - :raw_table_id true - :active true - :name "num_feathers" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {:count 12000, :base-type "IntegerField"} - :created_at true - :updated_at true}]] + [(merge field-defaults + {:name "beak_size" + :is_pk true + :details {:inches 7, :special-type "category", :base-type "IntegerField"}})] + [(merge field-defaults + {:name "beak_size" + :details {:inches 8, :base-type "IntegerField"}}) + (merge field-defaults + {:name "num_feathers" + :details {:count 10000, :base-type "IntegerField"}})] + [(merge field-defaults + {:name "beak_size" + :details {:inches 8, :base-type "IntegerField"} + :active false}) + (merge field-defaults + {:name "num_feathers" + :details {:count 12000, :base-type "IntegerField"}})] + [(merge field-defaults + {:name "beak_size" + :details {:inches 8, :base-type "IntegerField"}}) + (merge field-defaults + {:name "num_feathers" + :details {:count 12000, :base-type "IntegerField"}})]] (tu/with-temp* [Database [{database-id :id}] RawTable [{raw-table-id :id, :as table} {:database_id database-id}]] (let [get-columns #(->> (db/select RawColumn, :raw_table_id raw-table-id, {:order-by [:id]}) @@ -232,59 +125,49 @@ (get-columns))]))) ;; create-raw-table + +(def ^:private ^:const table-defaults + {:id true + :database_id true + :active true + :schema nil + :columns [] + :details {} + :created_at true + :updated_at true}) + + (expect [[] - [{:id true - :database_id true - :active true - :schema nil - :name "users" - :details {:a "b"} - :columns [] - :created_at true - :updated_at true}] - [{:id true - :database_id true - :active true - :schema nil - :name "users" - :details {:a "b"} - :columns [] - :created_at true - :updated_at true} - {:id true - :database_id true - :active true - :schema "aviary" - :name "toucanery" - :details {:owner "Cam"} - :columns [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk true - :fk_target_column_id false - :details {:inches 7, :base-type "IntegerField"} - :created_at true - :updated_at true}] - :created_at true - :updated_at true}]] + [(merge table-defaults + {:name "users" + :details {:a "b"}})] + [(merge table-defaults + {:name "users" + :details {:a "b"}}) + (merge table-defaults + {:schema "aviary" + :name "toucanery" + :details {:owner "Cam"} + :columns [(merge field-defaults + {:name "beak_size" + :is_pk true + :details {:inches 7, :base-type "IntegerField"}})]})]] (tu/with-temp* [Database [{database-id :id, :as db}]] [(get-tables database-id) ;; now add a table (do - (create-raw-table! database-id {:schema nil - :name "users" + (create-raw-table! database-id {:schema nil + :name "users" :details {:a "b"} - :fields []}) + :fields []}) (get-tables database-id)) ;; now add another table, this time with a couple columns and some fks (do - (create-raw-table! database-id {:schema "aviary" - :name "toucanery" + (create-raw-table! database-id {:schema "aviary" + :name "toucanery" :details {:owner "Cam"} - :fields [{:name "beak_size" + :fields [{:name "beak_size" :base-type :IntegerField :pk? true :details {:inches 7}}]}) @@ -293,38 +176,23 @@ ;; update-raw-table (expect - [[{:id true - :database_id true - :active true - :schema "aviary" - :name "toucanery" - :details {:owner "Cam"} - :columns [] - :created_at true - :updated_at true}] - [{:id true - :database_id true - :active true - :schema "aviary" - :name "toucanery" - :details {:owner "Cam", :sqft 10000} - :columns [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk true - :fk_target_column_id false - :details {:inches 7, :base-type "IntegerField"} - :created_at true - :updated_at true}] - :created_at true - :updated_at true}]] + [[(merge table-defaults + {:schema "aviary" + :name "toucanery" + :details {:owner "Cam"}})] + [(merge table-defaults + {:schema "aviary" + :name "toucanery" + :details {:owner "Cam", :sqft 10000} + :columns [(merge field-defaults + {:name "beak_size" + :is_pk true + :details {:inches 7, :base-type "IntegerField"}})]})]] (tu/with-temp* [Database [{database-id :id, :as db}] RawTable [table {:database_id database-id - :schema "aviary" - :name "toucanery" - :details {:owner "Cam"}}]] + :schema "aviary" + :name "toucanery" + :details {:owner "Cam"}}]] [(get-tables database-id) ;; now update the table (do @@ -332,86 +200,32 @@ :name "toucanery" :details {:owner "Cam", :sqft 10000} :fields [{:name "beak_size" - :base-type :IntegerField - :pk? true - :details {:inches 7}}]}) + :base-type :IntegerField + :pk? true + :details {:inches 7}}]}) (get-tables database-id))])) ;; disable-raw-tables (expect - [[{:id true - :database_id true - :active true - :schema "a" - :name "1" - :details {} - :columns [{:raw_table_id true - :name "size" - :fk_target_column_id false - :updated_at true - :details {} - :active true - :id true - :is_pk false - :created_at true - :column_type nil}] - :created_at true - :updated_at true} - {:id true - :database_id true - :active true - :schema "a" - :name "2" - :details {} - :columns [{:id true - :raw_table_id true - :active true - :name "beak_size" - :column_type nil - :is_pk false - :fk_target_column_id true - :details {} - :created_at true - :updated_at true}] - :created_at true - :updated_at true}] - [{:id true - :database_id true - :active false - :schema "a" - :name "1" - :details {} - :columns [{:raw_table_id true - :name "size" - :fk_target_column_id false - :updated_at true - :details {} - :active false - :id true - :is_pk false - :created_at true - :column_type nil}] - :created_at true - :updated_at true} - {:id true - :database_id true - :active false - :schema "a" - :name "2" - :details {} - :columns [{:id true - :raw_table_id true - :active false - :name "beak_size" - :column_type nil - :is_pk false - :fk_target_column_id false - :details {} - :created_at true - :updated_at true}] - :created_at true - :updated_at true}]] + [[(merge table-defaults + {:schema "a" + :name "1" + :columns [(merge field-defaults {:name "size"})]}) + (merge table-defaults + {:schema "a" + :name "2" + :columns [(merge field-defaults {:name "beak_size", :fk_target_column_id true})]})] + [(merge table-defaults + {:schema "a" + :name "1" + :columns [(merge field-defaults {:active false, :name "size"})] + :active false}) + (merge table-defaults + {:schema "a" + :name "2" + :columns [(merge field-defaults {:active false, :name "beak_size"})] + :active false})]] (tu/with-temp* [Database [{database-id :id, :as db}] RawTable [t1 {:database_id database-id, :schema "a", :name "1"}] RawColumn [c1 {:raw_table_id (:id t1), :name "size"}] @@ -438,10 +252,11 @@ (conj (vec (drop-last moviedb/moviedb-raw-tables)) (-> (last moviedb/moviedb-raw-tables) (assoc :active false) - (update :columns #(map (fn [col] - (assoc col - :active false - :fk_target_column_id false)) %))))] + (update :columns (fn [columns] + (for [column columns] + (assoc column + :active false + :fk_target_column_id false))))))] (tu/with-temp* [Database [{database-id :id, :as db} {:engine :moviedb}]] [(get-tables database-id) ;; first sync should add all the tables, fields, etc diff --git a/test/metabase/sync_database/sync_dynamic_test.clj b/test/metabase/sync_database/sync_dynamic_test.clj index 46e0b3b7253..cca8638b84d 100644 --- a/test/metabase/sync_database/sync_dynamic_test.clj +++ b/test/metabase/sync_database/sync_dynamic_test.clj @@ -18,307 +18,126 @@ (->> (hydrate/hydrate (db/select Table, :db_id database-id, {:order-by [:id]}) :fields) (mapv tu/boolean-ids-and-timestamps))) +(def ^:private ^:const field-defaults + {:id true + :table_id true + :raw_column_id false + :description nil + :caveats nil + :points_of_interest nil + :visibility_type :normal + :special_type nil + :parent_id false + :fk_target_field_id false + :last_analyzed false + :created_at true + :updated_at true}) ;; save-table-fields! (also covers save-nested-fields!) (expect [[] ;; initial sync - [{:id true, - :table_id true, - :raw_column_id false, - :name "First", - :display_name "First", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal, - :special_type :id, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Second", - :display_name "Second", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :category, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Third", - :display_name "Third", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal, - :special_type nil, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true}] + [(merge field-defaults {:base_type :IntegerField + :special_type :id + :name "First" + :display_name "First"}) + (merge field-defaults {:base_type :TextField + :name "Second" + :display_name "Second"}) + (merge field-defaults {:base_type :BooleanField + :special_type nil + :name "Third" + :display_name "Third"})] ;; add column, modify first column, add some nested fields - [{:id true, - :table_id true, - :raw_column_id false, - :name "First", - :display_name "First", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :DecimalField - :visibility_type :normal, - :special_type :id, ; existing special types are NOT modified - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Second", - :display_name "Second", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :category, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Third", - :display_name "Third", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal, - :special_type nil, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "rating", - :display_name "Rating", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal, - :special_type :category, ; should be infered from name - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "city", - :display_name "City", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :city, ; should be infered from name - :parent_id true, ; nested field - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "type", - :display_name "Type", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :category, ; manually specified - :parent_id true, ; nested field - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true}] + [(merge field-defaults {:base_type :DecimalField + :special_type :id + :name "First" + :display_name "First"}) + (merge field-defaults {:base_type :TextField + :name "Second" + :display_name "Second"}) + (merge field-defaults {:base_type :BooleanField + :name "Third" + :display_name "Third"}) + (merge field-defaults {:base_type :IntegerField + :special_type :category + :name "rating" + :display_name "Rating"}) + (merge field-defaults {:base_type :TextField + :special_type :city + :name "city" + :display_name "City" + :parent_id true}) + (merge field-defaults {:base_type :TextField + :special_type :category + :name "type" + :display_name "Type" + :parent_id true})] ;; first column retired, 3rd column now a pk, another nested field - [{:id true, - :table_id true, - :raw_column_id false, - :name "First", - :display_name "First", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :DecimalField - :visibility_type :normal, ; fields are NOT retired automatically in dynamic schemas - :special_type :id, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Second", - :display_name "Second", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :category, - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "Third", - :display_name "Third", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal, - :special_type :id, ; special type can be set if it was nil before - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "rating", - :display_name "Rating", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal, - :special_type :category, ; should be infered from name - :parent_id false, - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "city", - :display_name "City", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :city, ; should be infered from name - :parent_id true, ; nested field - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "type", - :display_name "Type", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal, - :special_type :category, ; manually specified - :parent_id true, ; nested field - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true} - {:id true, - :table_id true, - :raw_column_id false, - :name "new", - :display_name "New", - :description nil, - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal, - :special_type nil, - :parent_id true, ; nested field - :fk_target_field_id false, - :last_analyzed false - :created_at true, - :updated_at true}]] + [(merge field-defaults {:base_type :DecimalField + :special_type :id + :name "First" + :display_name "First"}) + (merge field-defaults {:base_type :TextField + :name "Second" + :display_name "Second"}) + (merge field-defaults {:base_type :BooleanField + :special_type :id + :name "Third" + :display_name "Third"}) + (merge field-defaults {:name "rating" + :display_name "Rating" + :base_type :IntegerField + :special_type :category}) + (merge field-defaults {:base_type :TextField + :special_type :city + :name "city" + :display_name "City" + :parent_id true}) + (merge field-defaults {:base_type :TextField + :special_type :category + :name "type" + :display_name "Type" + :parent_id true}) + (merge field-defaults {:base_type :BooleanField + :name "new" + :display_name "New" + :parent_id true})]] (tu/with-temp* [Database [{database-id :id}] - RawTable [{raw-table-id :id, :as table} {:database_id database-id}] - Table [{table-id :id, :as tbl} {:db_id database-id, :raw_table_id raw-table-id}]] - (let [get-fields (fn [] - (for [field (db/select Field, :table_id table-id, {:order-by [:id]})] - (dissoc (tu/boolean-ids-and-timestamps field) - :active :position :preview_display)))] + RawTable [{raw-table-id :id} {:database_id database-id}] + Table [{table-id :id, :as table} {:db_id database-id, :raw_table_id raw-table-id}]] + (let [get-fields (fn [] + (for [field (db/select Field, :table_id table-id, {:order-by [:id]})] + (dissoc (tu/boolean-ids-and-timestamps field) + :active :position :preview_display))) + save-fields! (fn [& fields] + (save-table-fields! table fields) + (get-fields))] ;; start with no fields [(get-fields) ;; first sync will add all the fields - (do - (save-table-fields! tbl [{:name "First", :base-type :IntegerField, :pk? true} - {:name "Second", :base-type :TextField, :special-type :category} - {:name "Third", :base-type :BooleanField}]) - (get-fields)) + (save-fields! {:name "First", :base-type :IntegerField, :pk? true} + {:name "Second", :base-type :TextField} + {:name "Third", :base-type :BooleanField}) ;; now add another column (with nested-fields!) and modify the first - (do - (save-table-fields! tbl [{:name "First", :base-type :DecimalField, :pk? false} - {:name "Second", :base-type :TextField, :special-type :category} - {:name "Third", :base-type :BooleanField} - {:name "rating", :base-type :IntegerField, :nested-fields [{:name "city", :base-type :TextField} - {:name "type", :base-type :TextField, :special-type :category}]}]) - (get-fields)) + (save-fields! {:name "First", :base-type :DecimalField, :pk? false} + {:name "Second", :base-type :TextField} + {:name "Third", :base-type :BooleanField} + {:name "rating", :base-type :IntegerField, :nested-fields [{:name "city", :base-type :TextField} + {:name "type", :base-type :TextField}]}) ;; now remove the first column (should have no effect), and make tweaks to the nested columns - (do - (save-table-fields! tbl [{:name "Second", :base-type :TextField, :special-type :category} - {:name "Third", :base-type :BooleanField, :pk? true} - {:name "rating", :base-type :IntegerField, :nested-fields [{:name "new", :base-type :BooleanField}]}]) - (get-fields))]))) + (save-fields! {:name "Second", :base-type :TextField} + {:name "Third", :base-type :BooleanField, :pk? true} + {:name "rating", :base-type :IntegerField, :nested-fields [{:name "new", :base-type :BooleanField}]})]))) ;; scan-table-and-update-data-model! (expect [[(last toucanery/toucanery-tables-and-fields)] [(last toucanery/toucanery-tables-and-fields)] - [(-> (last toucanery/toucanery-tables-and-fields) - (assoc :active false - :fields []))]] + [(assoc (last toucanery/toucanery-tables-and-fields) + :active false + :fields [])]] (tu/with-temp* [Database [{database-id :id, :as db} {:engine :toucanery}]] (let [driver (toucanery/->ToucaneryDriver)] ;; do a quick introspection to add the RawTables to the db @@ -330,7 +149,7 @@ :raw_table_id raw-table-id :name "transactions" :active true)] - [;; now lets run a sync and check what we got + [ ;; now lets run a sync and check what we got (do (scan-table-and-update-data-model! driver db tbl) (get-tables database-id)) @@ -353,15 +172,15 @@ toucanery/toucanery-tables-and-fields toucanery/toucanery-tables-and-fields (conj (vec (drop-last toucanery/toucanery-tables-and-fields)) - (-> (last toucanery/toucanery-tables-and-fields) - (assoc :active false - :fields [])))] + (assoc (last toucanery/toucanery-tables-and-fields) + :active false + :fields []))] (tu/with-temp* [Database [{database-id :id, :as db} {:engine :toucanery}]] (let [driver (toucanery/->ToucaneryDriver)] ;; do a quick introspection to add the RawTables to the db (introspect/introspect-database-and-update-raw-tables! driver db) - [;; first check that the raw tables stack up as expected, especially that fields were skipped because this is a :dynamic-schema db + [ ;; first check that the raw tables stack up as expected, especially that fields were skipped because this is a :dynamic-schema db (->> (hydrate/hydrate (db/select RawTable, :database_id database-id, {:order-by [:id]}) :columns) (mapv tu/boolean-ids-and-timestamps)) ;; now lets run a sync and check what we got diff --git a/test/metabase/sync_database/sync_test.clj b/test/metabase/sync_database/sync_test.clj index 59ef6f78e24..ea1ae9347f7 100644 --- a/test/metabase/sync_database/sync_test.clj +++ b/test/metabase/sync_database/sync_test.clj @@ -97,193 +97,74 @@ (get-table))]))) +(def ^:private ^:const field-defaults + {:id true + :table_id true + :raw_column_id true + :description nil + :caveats nil + :points_of_interest nil + :visibility_type :normal + :special_type nil + :parent_id false + :fk_target_field_id false + :last_analyzed false + :created_at true + :updated_at true}) + ;; save-table-fields! ;; this test also covers create-field! and update-field! (expect [[] ;; initial sync - [{:id true - :table_id true - :raw_column_id true - :name "First" - :display_name "First" - :description nil - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal - :special_type :id - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Second" - :display_name "Second" - :description nil - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal - :special_type :category - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Third" - :display_name "Third" - :description nil - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal - :special_type nil - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true}] + [(merge field-defaults {:name "First" + :display_name "First" + :base_type :IntegerField + :special_type :id}) + (merge field-defaults {:name "Second" + :display_name "Second" + :base_type :TextField}) + (merge field-defaults {:name "Third" + :display_name "Third" + :base_type :BooleanField + :special_type nil})] ;; add column, modify first column - [{:id true - :table_id true - :raw_column_id true - :name "First" - :display_name "First" - :description nil - :caveats nil - :points_of_interest nil - :base_type :DecimalField - :visibility_type :normal - :special_type :id ; existing special types are NOT modified - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Second" - :display_name "Second" - :description nil - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal - :special_type :category - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Third" - :display_name "Third" - :description nil - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal - :special_type nil - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "rating" - :display_name "Rating" - :description nil - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal - :special_type :category ; should be infered from name - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true}] + [(merge field-defaults {:name "First" + :display_name "First" + :base_type :DecimalField + :special_type :id}) ; existing special types are NOT modified + (merge field-defaults {:name "Second" + :display_name "Second" + :base_type :TextField}) + (merge field-defaults {:name "Third" + :display_name "Third" + :base_type :BooleanField + :special_type nil}) + (merge field-defaults {:name "rating" + :display_name "Rating" + :base_type :IntegerField + :special_type :category})] ;; first column retired, 3rd column now a pk - [{:id true - :table_id true - :raw_column_id true - :name "First" - :display_name "First" - :description nil - :caveats nil - :points_of_interest nil - :base_type :DecimalField - :visibility_type :retired ; field retired when RawColumn disabled - :special_type :id - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Second" - :display_name "Second" - :description nil - :caveats nil - :points_of_interest nil - :base_type :TextField - :visibility_type :normal - :special_type :category - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "Third" - :display_name "Third" - :description nil - :caveats nil - :points_of_interest nil - :base_type :BooleanField - :visibility_type :normal - :special_type :id, ; special type can be set if it was nil before - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true} - {:id true - :table_id true - :raw_column_id true - :name "rating" - :display_name "Rating" - :description nil - :caveats nil - :points_of_interest nil - :base_type :IntegerField - :visibility_type :normal - :special_type :category ; should be infered from name - :parent_id false - :fk_target_field_id false - :last_analyzed false - :created_at true - :updated_at true}]] + [(merge field-defaults {:name "First" + :display_name "First" + :base_type :DecimalField + :visibility_type :retired ; field retired when RawColumn disabled + :special_type :id}) + (merge field-defaults {:name "Second" + :display_name "Second" + :base_type :TextField}) + (merge field-defaults {:name "Third" + :display_name "Third" + :base_type :BooleanField + :special_type :id}) ; special type can be set if it was nil before + (merge field-defaults {:name "rating" + :display_name "Rating" + :base_type :IntegerField + :special_type :category})]] (tu/with-temp* [Database [{database-id :id}] RawTable [{raw-table-id :id, :as table} {:database_id database-id}] RawColumn [{raw-column-id1 :id} {:raw_table_id raw-table-id, :name "First", :is_pk true, :details {:base-type "IntegerField"}}] - RawColumn [{raw-column-id2 :id} {:raw_table_id raw-table-id, :name "Second", :details {:special-type :category, :base-type "TextField"}}] + RawColumn [{raw-column-id2 :id} {:raw_table_id raw-table-id, :name "Second", :details {:base-type "TextField"}}] RawColumn [{raw-column-id3 :id} {:raw_table_id raw-table-id, :name "Third", :details {:base-type "BooleanField"}}] Table [{table-id :id, :as tbl} {:db_id database-id, :raw_table_id raw-table-id}]] (let [get-fields #(->> (db/select Field, :table_id table-id, {:order-by [:id]}) @@ -314,11 +195,12 @@ ;; retire-tables! (expect - (let [disabled-movies-table (fn [tbl] - (if-not (= "movies" (:name tbl)) - tbl - (assoc tbl :active false - :fields [])))] + (let [disabled-movies-table (fn [table] + (if-not (= "movies" (:name table)) + table + (assoc table + :active false + :fields [])))] [moviedb/moviedb-tables-and-fields (mapv disabled-movies-table moviedb/moviedb-tables-and-fields)]) (tu/with-temp* [Database [{database-id :id, :as db} {:engine :moviedb}]] diff --git a/test/metabase/sync_database_test.clj b/test/metabase/sync_database_test.clj index 7970b39be0d..4c925016c19 100644 --- a/test/metabase/sync_database_test.clj +++ b/test/metabase/sync_database_test.clj @@ -62,154 +62,11 @@ (into {} (dissoc field :table :db :children :qualified-name :qualified-name-components :values :target)))) tu/boolean-ids-and-timestamps))) -;; ## SYNC DATABASE -(expect - [{:id true - :db_id true - :raw_table_id true - :schema "default" - :name "movie" - :display_name "Movie" - :description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :entity_name nil - :visibility_type nil - :rows nil - :active true - :created_at true - :updated_at true - :fields [{:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "ID" - :base_type :IntegerField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true} - {:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type :fk - :name "studio" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Studio" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id true - :created_at true - :updated_at true - :last_analyzed true} - {:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type nil - :name "title" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Title" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true}]} - {:id true - :db_id true - :raw_table_id true - :schema nil - :name "studio" - :display_name "Studio" - :description nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :entity_type nil - :entity_name nil - :visibility_type nil - :rows nil - :active true - :created_at true - :updated_at true - :fields [{:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Name" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true} - {:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type :id - :name "studio" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Studio" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true}]}] - (tu/with-temp Database [fake-db {:engine :sync-test}] - (sync-database! fake-db) - ;; we are purposely running the sync twice to test for possible logic issues which only manifest - ;; on resync of a database, such as adding tables that already exist or duplicating fields - (sync-database! fake-db) - (mapv table-details (db/select Table, :db_id (:id fake-db), {:order-by [:name]})))) - - -;; ## SYNC TABLE - -(expect +(def ^:private ^:const table-defaults {:id true :db_id true :raw_table_id true - :schema "default" - :name "movie" - :display_name "Movie" + :schema nil :description nil :caveats nil :points_of_interest nil @@ -220,64 +77,91 @@ :rows nil :active true :created_at true - :updated_at true - :fields [{:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "ID" - :base_type :IntegerField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true} - {:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type nil - :name "studio" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Studio" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true} - {:id true - :table_id true - :raw_column_id true - :description nil - :caveats nil - :points_of_interest nil - :special_type nil - :name "title" - :active true - :parent_id false - :position 0 - :preview_display true - :display_name "Title" - :base_type :TextField - :visibility_type :normal - :fk_target_field_id false - :created_at true - :updated_at true - :last_analyzed true}]} + :updated_at true}) + +(def ^:private ^:const field-defaults + {:id true + :table_id true + :raw_column_id true + :description nil + :caveats nil + :points_of_interest nil + :active true + :parent_id false + :position 0 + :preview_display true + :visibility_type :normal + :fk_target_field_id false + :created_at true + :updated_at true + :last_analyzed true}) + + +;; ## SYNC DATABASE +(expect + [(merge table-defaults + {:schema "default" + :name "movie" + :display_name "Movie" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :name "studio" + :display_name "Studio" + :base_type :TextField + :fk_target_field_id true}) + (merge field-defaults + {:special_type nil + :name "title" + :display_name "Title" + :base_type :TextField})]}) + (merge table-defaults + {:name "studio" + :display_name "Studio" + :fields [(merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField}) + (merge field-defaults + {:special_type :id + :name "studio" + :display_name "Studio" + :base_type :TextField})]})] + (tu/with-temp Database [fake-db {:engine :sync-test}] + (sync-database! fake-db) + ;; we are purposely running the sync twice to test for possible logic issues which only manifest + ;; on resync of a database, such as adding tables that already exist or duplicating fields + (sync-database! fake-db) + (mapv table-details (db/select Table, :db_id (:id fake-db), {:order-by [:name]})))) + + +;; ## SYNC TABLE + +(expect + (merge table-defaults + {:schema "default" + :name "movie" + :display_name "Movie" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type nil + :name "studio" + :display_name "Studio" + :base_type :TextField}) + (merge field-defaults + {:special_type nil + :name "title" + :display_name "Title" + :base_type :TextField})]}) (tu/with-temp* [Database [fake-db {:engine :sync-test}] RawTable [{raw-table-id :id} {:database_id (:id fake-db), :name "movie", :schema "default"}] Table [fake-table {:raw_table_id raw-table-id diff --git a/test/metabase/test/mock/moviedb.clj b/test/metabase/test/mock/moviedb.clj index e2ca8b37994..da84fafede4 100644 --- a/test/metabase/test/mock/moviedb.clj +++ b/test/metabase/test/mock/moviedb.clj @@ -78,485 +78,189 @@ (driver/register-driver! :moviedb (MovieDbDriver.)) +(def ^:private ^:const raw-table-defaults + {:schema nil + :database_id true + :updated_at true + :details {} + :active true + :id true + :created_at true}) + +(def ^:private ^:const raw-field-defaults + {:raw_table_id true + :fk_target_column_id false + :updated_at true + :active true + :id true + :is_pk false + :created_at true + :column_type nil}) + (def ^:const moviedb-raw-tables - [{:schema nil - :database_id true - :columns [{:raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil}] - :name "actors" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema nil - :database_id true - :columns [{:raw_table_id true - :name "filming" - :fk_target_column_id false - :updated_at true - :details {:base-type "BooleanField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "title" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil}] - :name "movies" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema nil - :database_id true - :columns [{:raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "movie_id" - :fk_target_column_id true - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "stars" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil}] - :name "reviews" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema nil - :database_id true - :columns [{:raw_table_id true - :name "actor_id" - :fk_target_column_id true - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "character" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "movie_id" - :fk_target_column_id true - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil} - {:raw_table_id true - :name "salary" - :fk_target_column_id false - :updated_at true - :details {:base-type "DecimalField"} - :active true - :id true - :is_pk false - :created_at true - :column_type nil}] - :name "roles" - :updated_at true - :details {} - :active true - :id true - :created_at true}]) + [(merge raw-table-defaults + {:columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField"}})] + :name "actors"}) + (merge raw-table-defaults + {:columns [(merge raw-field-defaults + {:name "filming" + :details {:base-type "BooleanField"}}) + (merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "title" + :details {:base-type "TextField"}})] + :name "movies"}) + (merge raw-table-defaults + {:columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "movie_id" + :details {:base-type "IntegerField"} + :fk_target_column_id true}) + (merge raw-field-defaults + {:name "stars" + :details {:base-type "IntegerField"}})] + :name "reviews"}) + (merge raw-table-defaults + {:columns [(merge raw-field-defaults + {:name "actor_id" + :details {:base-type "IntegerField"} + :fk_target_column_id true}) + (merge raw-field-defaults + {:name "character" + :details {:base-type "TextField"}}) + (merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "movie_id" + :details {:base-type "IntegerField"} + :fk_target_column_id true}) + (merge raw-field-defaults + {:name "salary" + :details {:base-type "DecimalField"}})] + :name "roles"})]) + +(def ^:private ^:const table-defaults + {:description nil + :entity_type nil + :caveats nil + :points_of_interest nil + :show_in_getting_started false + :schema nil + :raw_table_id true + :rows nil + :updated_at true + :entity_name nil + :active true + :id true + :db_id true + :visibility_type nil + :created_at true}) + +(def ^:privaet ^:const field-defaults + {:description nil + :table_id true + :caveats nil + :points_of_interest nil + :special_type nil + :fk_target_field_id false + :updated_at true + :active true + :parent_id false + :id true + :raw_column_id true + :last_analyzed false + :position 0 + :visibility_type :normal + :preview_display true + :created_at true}) (def ^:const moviedb-tables-and-fields - [{:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "actors" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Actors" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "movies" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "filming" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Filming" - :created_at true - :base_type :BooleanField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "title" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Title" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Movies" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "reviews" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "movie_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Movie ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "stars" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Stars" - :created_at true - :base_type :IntegerField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Reviews" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "roles" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "actor_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Actor ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "character" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Character" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "movie_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Movie ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "salary" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Salary" - :created_at true - :base_type :DecimalField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Roles" - :created_at true}]) + [(merge table-defaults + {:name "actors" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + + :display_name "Actors"}) + (merge table-defaults + {:name "movies" + :fields [(merge field-defaults + {:name "filming" + :display_name "Filming" + :base_type :BooleanField}) + (merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:name "title" + :display_name "Title" + :base_type :TextField})] + + :display_name "Movies"}) + (merge table-defaults + {:name "reviews" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :fk_target_field_id true + :name "movie_id" + :display_name "Movie ID" + :base_type :IntegerField}) + (merge field-defaults + {:name "stars" + :display_name "Stars" + :base_type :IntegerField})] + :display_name "Reviews"}) + (merge table-defaults + {:name "roles" + :fields [(merge field-defaults + {:special_type :fk + :fk_target_field_id true + :name "actor_id" + :display_name "Actor ID" + :base_type :IntegerField}) + (merge field-defaults + {:name "character" + :display_name "Character" + :base_type :TextField}) + (merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :fk_target_field_id true + :name "movie_id" + :display_name "Movie ID" + :base_type :IntegerField}) + (merge field-defaults + {:name "salary" + :display_name "Salary" + :base_type :DecimalField})] + :display_name "Roles"})]) diff --git a/test/metabase/test/mock/schema_per_customer.clj b/test/metabase/test/mock/schema_per_customer.clj index 03600191cc7..72d82fc0155 100644 --- a/test/metabase/test/mock/schema_per_customer.clj +++ b/test/metabase/test/mock/schema_per_customer.clj @@ -79,1116 +79,412 @@ (driver/register-driver! :schema-per-customer (SchemaPerCustomerDriver.)) +(def ^:private ^:const raw-table-defaults + {:schema nil + :database_id true + :columns [] + :updated_at true + :details {} + :active true + :id true + :created_at true}) + +(def ^:private ^:const raw-field-defaults + {:column_type nil + :raw_table_id true + :fk_target_column_id false + :updated_at true + :details {} + :active true + :id true + :is_pk false + :created_at true}) (def ^:const schema-per-customer-raw-tables - [{:schema "s3" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "city" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s2" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "reviewer_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "common", :name "user", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "text" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "venue_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s2", :name "venue", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true}] - :name "review" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s3" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "city_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s3", :name "city", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "venue" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s2" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "city" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s1" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "city_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s1", :name "city", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "venue" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "common" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField"} - :active true - :id true - :is_pk false - :created_at true}] - :name "user" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s3" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "reviewer_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "common", :name "user", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "text" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "venue_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s3", :name "venue", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true}] - :name "review" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s2" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "city_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s2", :name "city", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "venue" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s1" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "reviewer_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "common", :name "user", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "text" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true} - {:column_type nil - :raw_table_id true - :name "venue_id" - :fk_target_column_id true - :updated_at true - :fk_target_column {:schema "s1", :name "venue", :col-name "id"} - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk false - :created_at true}] - :name "review" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema "s1" - :database_id true - :columns [{:column_type nil - :raw_table_id true - :name "id" - :fk_target_column_id false - :updated_at true - :details {:base-type "IntegerField"} - :active true - :id true - :is_pk true - :created_at true} - {:column_type nil - :raw_table_id true - :name "name" - :fk_target_column_id false - :updated_at true - :details {:base-type "TextField", :special-type "name"} - :active true - :id true - :is_pk false - :created_at true}] - :name "city" - :updated_at true - :details {} - :active true - :id true - :created_at true}]) + [(merge raw-table-defaults + {:schema "s3" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "city"}) + (merge raw-table-defaults + {:schema "s2" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "reviewer_id" + :fk_target_column_id true + :fk_target_column {:schema "common", :name "user", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "text" + :details {:base-type "TextField", :special-type "name"}}) + (merge raw-field-defaults + {:name "venue_id" + :fk_target_column_id true + :fk_target_column {:schema "s2", :name "venue", :col-name "id"} + :details {:base-type "IntegerField"}})] + :name "review"}) + (merge raw-table-defaults + {:schema "s3" + :columns [(merge raw-field-defaults + {:name "city_id" + :fk_target_column_id true + :fk_target_column {:schema "s3", :name "city", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "venue"}) + (merge raw-table-defaults + {:schema "s2" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "city"}) + (merge raw-table-defaults + {:schema "s1" + :columns [(merge raw-field-defaults + {:name "city_id" + :fk_target_column_id true + :fk_target_column {:schema "s1", :name "city", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "venue"}) + (merge raw-table-defaults + {:schema "common" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField"}})] + :name "user"}) + (merge raw-table-defaults + {:schema "s3" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "reviewer_id" + :fk_target_column_id true + :fk_target_column {:schema "common", :name "user", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "text" + :details {:base-type "TextField", :special-type "name"}}) + (merge raw-field-defaults + {:name "venue_id" + :fk_target_column_id true + :fk_target_column {:schema "s3", :name "venue", :col-name "id"} + :details {:base-type "IntegerField"}})] + :name "review"}) + (merge raw-table-defaults + {:schema "s2" + :columns [(merge raw-field-defaults + {:name "city_id" + :fk_target_column_id true + :fk_target_column {:schema "s2", :name "city", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "venue"}) + (merge raw-table-defaults + {:schema "s1" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "reviewer_id" + :fk_target_column_id true + :fk_target_column {:schema "common", :name "user", :col-name "id"} + :details {:base-type "IntegerField"}}) + (merge raw-field-defaults + {:name "text" + :details {:base-type "TextField", :special-type "name"}}) + (merge raw-field-defaults + {:name "venue_id" + :fk_target_column_id true + :fk_target_column {:schema "s1", :name "venue", :col-name "id"} + :details {:base-type "IntegerField"}})] + :name "review"}) + (merge raw-table-defaults + {:schema "s1" + :columns [(merge raw-field-defaults + {:name "id" + :details {:base-type "IntegerField"} + :is_pk true}) + (merge raw-field-defaults + {:name "name" + :details {:base-type "TextField", :special-type "name"}})] + :name "city"})]) + + +(def ^:private ^:const table-defaults + {:description nil + :entity_type nil + :caveats nil + :points_of_interest nil + :show_in_getting_started false + :schema nil + :raw_table_id true + :fields [] + :rows nil + :updated_at true + :entity_name nil + :active true + :id true + :db_id true + :visibility_type nil + :created_at true}) + + +(def ^:private ^:const field-defaults + {:description nil + :table_id true + :caveats nil + :points_of_interest nil + :fk_target_field_id false + :updated_at true + :active true + :parent_id false + :id true + :raw_column_id true + :last_analyzed false + :position 0 + :visibility_type :normal + :preview_display true + :created_at true}) (def ^:const schema-per-customer-tables-and-fields - [{:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "common" - :raw_table_id true - :name "user" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "User" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s1" - :raw_table_id true - :name "city" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "City" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s1" - :raw_table_id true - :name "review" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "reviewer_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Reviewer ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "common", :name "user", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "text" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Text" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "venue_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Venue ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s1", :name "venue", :col-name "id"}}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Review" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s1" - :raw_table_id true - :name "venue" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "city_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "City ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s1", :name "city", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Venue" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s2" - :raw_table_id true - :name "city" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "City" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s2" - :raw_table_id true - :name "review" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "reviewer_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Reviewer ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "common", :name "user", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "text" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Text" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "venue_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Venue ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s2", :name "venue", :col-name "id"}}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Review" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s2" - :raw_table_id true - :name "venue" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "city_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "City ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s2", :name "city", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Venue" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s3" - :raw_table_id true - :name "city" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "City" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s3" - :raw_table_id true - :name "review" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "reviewer_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Reviewer ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "common", :name "user", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "text" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Text" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "venue_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Venue ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s3", :name "venue", :col-name "id"}}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Review" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema "s3" - :raw_table_id true - :name "venue" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :fk - :name "city_id" - :fk_target_field_id true - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "City ID" - :created_at true - :base_type :IntegerField - :fk_target_field {:schema "s3", :name "city", :col-name "id"}} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id true - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Venue" - :created_at true}]) + [(merge table-defaults + {:schema "common" + :name "user" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "User"}) + (merge table-defaults + {:schema "s1" + :name "city" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "City"}) + (merge table-defaults + {:schema "s1" + :name "review" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :name "reviewer_id" + :fk_target_field_id true + :display_name "Reviewer ID" + :base_type :IntegerField + :fk_target_field {:schema "common", :name "user", :col-name "id"}}) + (merge field-defaults + {:special_type :name + :name "text" + :display_name "Text" + :base_type :TextField}) + (merge field-defaults + {:special_type :fk + :name "venue_id" + :fk_target_field_id true + :display_name "Venue ID" + :base_type :IntegerField + :fk_target_field {:schema "s1", :name "venue", :col-name "id"}})] + :display_name "Review"}) + (merge table-defaults + {:schema "s1" + :name "venue" + :fields [(merge field-defaults + {:special_type :fk + :name "city_id" + :fk_target_field_id true + :display_name "City ID" + :base_type :IntegerField + :fk_target_field {:schema "s1", :name "city", :col-name "id"}}) + (merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "Venue"}) + (merge table-defaults + {:schema "s2" + :name "city" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "City"}) + (merge table-defaults + {:schema "s2" + :name "review" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :name "reviewer_id" + :fk_target_field_id true + :display_name "Reviewer ID" + :base_type :IntegerField + :fk_target_field {:schema "common", :name "user", :col-name "id"}}) + (merge field-defaults + {:special_type :name + :name "text" + :display_name "Text" + :base_type :TextField}) + (merge field-defaults + {:special_type :fk + :name "venue_id" + :fk_target_field_id true + :display_name "Venue ID" + :base_type :IntegerField + :fk_target_field {:schema "s2", :name "venue", :col-name "id"}})] + :display_name "Review"}) + (merge table-defaults + {:schema "s2" + :name "venue" + :fields [(merge field-defaults + {:special_type :fk + :name "city_id" + :fk_target_field_id true + :display_name "City ID" + :base_type :IntegerField + :fk_target_field {:schema "s2", :name "city", :col-name "id"}}) + (merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "Venue"}) + (merge table-defaults + {:schema "s3" + :name "city" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "City"}) + (merge table-defaults + {:schema "s3" + :name "review" + :fields [(merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :fk + :name "reviewer_id" + :fk_target_field_id true + :display_name "Reviewer ID" + :base_type :IntegerField + :fk_target_field {:schema "common", :name "user", :col-name "id"}}) + (merge field-defaults + {:special_type :name + :name "text" + :display_name "Text" + :base_type :TextField}) + (merge field-defaults + {:special_type :fk + :name "venue_id" + :fk_target_field_id true + :display_name "Venue ID" + :base_type :IntegerField + :fk_target_field {:schema "s3", :name "venue", :col-name "id"}})] + :display_name "Review"}) + (merge table-defaults + {:schema "s3" + :name "venue" + :fields [(merge field-defaults + {:special_type :fk + :name "city_id" + :fk_target_field_id true + :display_name "City ID" + :base_type :IntegerField + :fk_target_field {:schema "s3", :name "city", :col-name "id"}}) + (merge field-defaults + {:special_type :id + :name "id" + :display_name "ID" + :base_type :IntegerField}) + (merge field-defaults + {:special_type :name + :name "name" + :display_name "Name" + :base_type :TextField})] + :display_name "Venue"})]) diff --git a/test/metabase/test/mock/toucanery.clj b/test/metabase/test/mock/toucanery.clj index 33f66b846f0..5b28627efa2 100644 --- a/test/metabase/test/mock/toucanery.clj +++ b/test/metabase/test/mock/toucanery.clj @@ -60,287 +60,122 @@ (driver/register-driver! :toucanery (ToucaneryDriver.)) +(def ^:private ^:const raw-table-defaults + {:schema nil + :database_id true + :columns [] + :updated_at true + :details {} + :active true + :id true + :created_at true}) (def ^:const toucanery-raw-tables-and-columns - [{:schema nil - :database_id true - :columns [] - :name "employees" - :updated_at true - :details {} - :active true - :id true - :created_at true} - {:schema nil - :database_id true - :columns [] - :name "transactions" - :updated_at true - :details {} - :active true - :id true - :created_at true}]) + [(merge raw-table-defaults {:name "employees"}) + (merge raw-table-defaults {:name "transactions"})]) + + +(def ^:private ^:const table-defaults + {:description nil + :entity_type nil + :caveats nil + :points_of_interest nil + :show_in_getting_started false + :schema nil + :raw_table_id true + :fields [] + :rows nil + :updated_at true + :entity_name nil + :active true + :id true + :db_id true + :visibility_type nil + :created_at true}) + +(def ^:private ^:const field-defaults + {:description nil + :table_id true + :caveats nil + :points_of_interest nil + :fk_target_field_id false + :updated_at true + :active true + :parent_id false + :special_type nil + :id true + :raw_column_id false + :last_analyzed false + :position 0 + :visibility_type :normal + :preview_display true + :created_at true}) (def ^:const toucanery-tables-and-fields - [{:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "employees" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Employees" - :created_at true} - {:description nil - :entity_type nil - :caveats nil - :points_of_interest nil - :show_in_getting_started false - :schema nil - :raw_table_id true - :name "transactions" - :fields [{:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "age" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Age" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "buyer" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Buyer" - :created_at true - :base_type :DictionaryField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "cc" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Cc" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "details" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Details" - :created_at true - :base_type :DictionaryField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :id - :name "id" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "ID" - :created_at true - :base_type :IntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :name - :name "name" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Name" - :created_at true - :base_type :TextField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type nil - :name "toucan" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Toucan" - :created_at true - :base_type :DictionaryField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :timestamp_milliseconds - :name "ts" - :fk_target_field_id false - :updated_at true - :active true - :parent_id false - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Ts" - :created_at true - :base_type :BigIntegerField} - {:description nil - :table_id true - :caveats nil - :points_of_interest nil - :special_type :category - :name "weight" - :fk_target_field_id false - :updated_at true - :active true - :parent_id true - :id true - :raw_column_id false - :last_analyzed false - :position 0 - :visibility_type :normal - :preview_display true - :display_name "Weight" - :created_at true - :base_type :DecimalField}] - :rows nil - :updated_at true - :entity_name nil - :active true - :id true - :db_id true - :visibility_type nil - :display_name "Transactions" - :created_at true}]) + [(merge table-defaults + {:name "employees" + :fields [(merge field-defaults + {:name "id" + :display_name "ID" + :base_type :IntegerField + :special_type :id}) + (merge field-defaults + {:name "name" + :display_name "Name" + :base_type :TextField + :special_type :name})] + :display_name "Employees"}) + (merge table-defaults + {:name "transactions" + :fields [(merge field-defaults + {:name "age" + :display_name "Age" + :base_type :IntegerField + :parent_id true}) + (merge field-defaults + {:name "buyer" + :display_name "Buyer" + :base_type :DictionaryField}) + (merge field-defaults + {:name "cc" + :display_name "Cc" + :base_type :TextField + :parent_id true}) + (merge field-defaults + {:name "details" + :display_name "Details" + :base_type :DictionaryField + :parent_id true}) + (merge field-defaults + {:name "id" + :display_name "ID" + :base_type :IntegerField + :special_type :id}) + (merge field-defaults + {:name "name" + :display_name "Name" + :base_type :TextField + :parent_id true + :special_type :name}) + (merge field-defaults + {:name "name" + :display_name "Name" + :base_type :TextField + :parent_id true + :special_type :name}) + (merge field-defaults + {:name "toucan" + :display_name "Toucan" + :base_type :DictionaryField}) + (merge field-defaults + {:name "ts" + :display_name "Ts" + :base_type :BigIntegerField + :special_type :timestamp_milliseconds}) + (merge field-defaults + {:name "weight" + :display_name "Weight" + :base_type :DecimalField + :parent_id true + :special_type :category})] + :display_name "Transactions"})]) -- GitLab