Skip to content
Snippets Groups Projects
Unverified Commit 918e3608 authored by Cam Saül's avatar Cam Saül
Browse files

Stop the insanity :scream_cat: :gun:

parent afbe1deb
No related branches found
No related tags found
No related merge requests found
Showing
with 1505 additions and 3436 deletions
(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)))
......@@ -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 %)]
......
(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}}))
......@@ -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))))
......
......@@ -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}))
......
(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!
......@@ -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
......
......@@ -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
......
......@@ -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}]]
......
......@@ -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
......
......@@ -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"})])
......@@ -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"})])
......@@ -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"})])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment