diff --git a/enterprise/backend/test/metabase_enterprise/serialization/v2/extract_test.clj b/enterprise/backend/test/metabase_enterprise/serialization/v2/extract_test.clj index 461403fd6d8952ce52cbc71b99ba8f2815e13bb3..ada774d8a6c6449482ab676e9358bf8ff8a33024 100644 --- a/enterprise/backend/test/metabase_enterprise/serialization/v2/extract_test.clj +++ b/enterprise/backend/test/metabase_enterprise/serialization/v2/extract_test.clj @@ -1658,24 +1658,33 @@ (map serdes/path) set))))))))) -(deftest foreign-key-field-test +(deftest field-references-test (mt/with-empty-h2-app-db - (ts/with-temp-dpc [Database {db-id :id} {:name "My Database"} - Table {no-schema-id :id} {:name "Schemaless Table" :db_id db-id} - Field {some-field-id :id} {:name "Some Field" :table_id no-schema-id} - Table {schema-id :id} {:name "Schema'd Table" + (ts/with-temp-dpc [Database {db-id :id} {:name "My Database"} + Table {no-schema-id :id} {:name "Schemaless Table" :db_id db-id} + Field {some-field-id :id} {:name "Some Field" :table_id no-schema-id} + Table {schema-id :id} {:name "Schema'd Table" :db_id db-id :schema "PUBLIC"} - Field _ {:name "Other Field" :table_id schema-id} - Field {fk-id :id} {:name "Foreign Key" + Field {other-field-id :id} {:name "Other Field" :table_id schema-id} + Field {fk-id :id} {:name "Foreign Key" :table_id schema-id - :fk_target_field_id some-field-id}] + :fk_target_field_id some-field-id} + Field {nested-id :id} {:name "Nested Field" + :table_id schema-id + :parent_id other-field-id}] (testing "fields that reference foreign keys are properly exported as Field references" (is (= ["My Database" nil "Schemaless Table" "Some Field"] (->> (t2/select-one Field :id fk-id) (serdes/extract-one "Field" {}) - :fk_target_field_id))))))) + :fk_target_field_id)))) + + (testing "Fields that reference parents are properly exported as Field references" + (is (= ["My Database" "PUBLIC" "Schema'd Table" "Other Field"] + (->> (t2/select-one Field :id nested-id) + (serdes/extract-one "Field" {}) + :parent_id))))))) (deftest escape-report-test (mt/with-empty-h2-app-db diff --git a/enterprise/backend/test/metabase_enterprise/serialization/v2/load_test.clj b/enterprise/backend/test/metabase_enterprise/serialization/v2/load_test.clj index d5afe756b73fbc50a8a9b972c9fa5115fded661a..800452df524761c7c1723ba3ec30bab74206877f 100644 --- a/enterprise/backend/test/metabase_enterprise/serialization/v2/load_test.clj +++ b/enterprise/backend/test/metabase_enterprise/serialization/v2/load_test.clj @@ -126,7 +126,8 @@ t1s (atom nil) t2s (atom nil) f1s (atom nil) - f2s (atom nil)] + f2s (atom nil) + f3s (atom nil)] (ts/with-dbs [source-db dest-db] (testing "serializing the two databases" (ts/with-db source-db @@ -136,6 +137,7 @@ (reset! t2s (ts/create! Table :name "posts" :db_id (:id @db2s))) ; Deliberately the same name! (reset! f1s (ts/create! Field :name "Target Field" :table_id (:id @t1s))) (reset! f2s (ts/create! Field :name "Foreign Key" :table_id (:id @t2s) :fk_target_field_id (:id @f1s))) + (reset! f3s (ts/create! Field :name "Nested Field" :table_id (:id @t1s) :parent_id (:id @f1s))) (reset! serialized (into [] (serdes.extract/extract {}))))) (testing "serialization of databases is based on the :name" @@ -152,10 +154,16 @@ (testing "foreign key references are serialized as a field path" (is (= ["db1" nil "posts" "Target Field"] (->> @serialized - (filter #(-> % :serdes/meta last :model (= "Field"))) - (filter #(-> % :table_id (= ["db2" nil "posts"]))) - (keep :fk_target_field_id) - first)))) + (u/seek #(and (-> % :serdes/meta last :model (= "Field")) + (-> % :name (= "Foreign Key")))) + :fk_target_field_id)))) + + (testing "Parent field references are serialized as a field path" + (is (= ["db1" nil "posts" "Target Field"] + (->> @serialized + (u/seek #(and (-> % :serdes/meta last :model (= "Field")) + (-> % :name (= "Nested Field")))) + :parent_id)))) (testing "deserialization works properly, keeping the same-named tables apart" (ts/with-db dest-db @@ -170,7 +178,11 @@ (is (= #{(:id @db1d) (:id @db2d)} (t2/select-fn-set :db_id Table :name "posts"))) (is (t2/exists? Table :name "posts" :db_id (:id @db1d))) - (is (t2/exists? Table :name "posts" :db_id (:id @db2d))))))))) + (is (t2/exists? Table :name "posts" :db_id (:id @db2d))) + (is (= (t2/select-one-fn :id Field :name (:name @f1s)) + (t2/select-one-fn :fk_target_field_id Field :name (:name @f2s)))) + (is (= (t2/select-one-fn :id Field :name (:name @f1s)) + (t2/select-one-fn :parent_id Field :name (:name @f3s)))))))))) (deftest card-dataset-query-test ;; Card.dataset_query is a JSON-encoded MBQL query, which contain database, table, and field IDs - these need to be diff --git a/src/metabase/models/field.clj b/src/metabase/models/field.clj index b5d845378bfe11579b47fea43a2e8fed06d0a5eb..d970ce804129bbc84b77cff76424766b34c726e1 100644 --- a/src/metabase/models/field.clj +++ b/src/metabase/models/field.clj @@ -398,13 +398,15 @@ (update :dimensions extract-dimensions) (update :table_id serdes/*export-table-fk*) (update :fk_target_field_id serdes/*export-field-fk*) + (update :parent_id serdes/*export-field-fk*) (dissoc :fingerprint :last_analyzed :fingerprint_version)))) (defmethod serdes/load-xform "Field" [field] (-> (serdes/load-xform-basics field) (update :table_id serdes/*import-table-fk*) - (update :fk_target_field_id serdes/*import-field-fk*))) + (update :fk_target_field_id serdes/*import-field-fk*) + (update :parent_id serdes/*import-field-fk*))) (defmethod serdes/load-find-local "Field" [path]