From 19680bf09b5ad0e2d42fd3124c567d44e37e6ac4 Mon Sep 17 00:00:00 2001 From: lbrdnk <lbrdnk@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:35:58 +0100 Subject: [PATCH] Select only compatible fields from idFields (Mongo specific) (#49262) * Select only compatible fields from idFields * Use isComparableWith to filter target fields * Remove filter-comparable-fields * Add test --- .../src/metabase-lib/v1/metadata/Field.ts | 14 +++++++++ .../v1/metadata/Field.unit.spec.ts | 31 +++++++++++++++++++ .../SemanticTypeAndTargetPicker.tsx | 11 ++++--- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/frontend/src/metabase-lib/v1/metadata/Field.ts b/frontend/src/metabase-lib/v1/metadata/Field.ts index 6f733a7bea5..7b87b5aa19a 100644 --- a/frontend/src/metabase-lib/v1/metadata/Field.ts +++ b/frontend/src/metabase-lib/v1/metadata/Field.ts @@ -287,6 +287,20 @@ class FieldInner extends Base { ); } + /** + * Predicate to decide whether `this` is comparable with `field`. + * + * Currently only the MongoBSONID erroneous case is ruled out to fix the issue #49149. To the best of my knowledge + * there's no logic on FE to reliably decide whether two columns are comparable. Trying to come up with that in ad-hoc + * manner could disable some cases that users may depend on. + */ + isComparableWith(field) { + return this.effective_type === "type/MongoBSONID" || + field.effective_type === "type/MongoBSONID" + ? this.effective_type === field.effective_type + : true; + } + /** * @param {Field} field */ diff --git a/frontend/src/metabase-lib/v1/metadata/Field.unit.spec.ts b/frontend/src/metabase-lib/v1/metadata/Field.unit.spec.ts index c2e59f8bfec..f43c75fae3f 100644 --- a/frontend/src/metabase-lib/v1/metadata/Field.unit.spec.ts +++ b/frontend/src/metabase-lib/v1/metadata/Field.unit.spec.ts @@ -559,4 +559,35 @@ describe("Field", () => { }); }); }); + + describe("isComparableWith", () => { + const field = setup({ + fields: [ + createMockField({ + id: FIELD_ID, + effective_type: "type/MongoBSONID", + }), + createMockField({ + id: 2, + effective_type: "type/Integer", + }), + ], + }); + const metadata = field.metadata; + const mongoField = metadata?.field(FIELD_ID); + const integerField = metadata?.field(2); + + it("should return true for 2 MongoBSONID fields", () => { + expect(mongoField?.isComparableWith(mongoField)).toBe(true); + }); + + it("should return true for 2 non-MongoBSONID fields", () => { + expect(integerField?.isComparableWith(integerField)).toBe(true); + }); + + it("should return false for MongoBSONID field and other field", () => { + expect(mongoField?.isComparableWith(integerField)).toBe(false); + expect(integerField?.isComparableWith(mongoField)).toBe(false); + }); + }); }); diff --git a/frontend/src/metabase/admin/datamodel/metadata/components/SemanticTypeAndTargetPicker/SemanticTypeAndTargetPicker.tsx b/frontend/src/metabase/admin/datamodel/metadata/components/SemanticTypeAndTargetPicker/SemanticTypeAndTargetPicker.tsx index 916223759e8..ce1c3bb5ede 100644 --- a/frontend/src/metabase/admin/datamodel/metadata/components/SemanticTypeAndTargetPicker/SemanticTypeAndTargetPicker.tsx +++ b/frontend/src/metabase/admin/datamodel/metadata/components/SemanticTypeAndTargetPicker/SemanticTypeAndTargetPicker.tsx @@ -56,8 +56,11 @@ const SemanticTypeAndTargetPicker = ({ hasSeparator, onUpdateField, }: SemanticTypeAndTargetPickerProps) => { - const hasIdFields = idFields.length > 0; - const includeSchema = hasMultipleSchemas(idFields); + const comparableIdFields = idFields.filter((idField: Field) => + field.isComparableWith(idField), + ); + const hasIdFields = comparableIdFields.length > 0; + const includeSchema = hasMultipleSchemas(comparableIdFields); const showFKTargetSelect = field.isFK(); const showCurrencyTypeSelect = field.isCurrency(); @@ -148,11 +151,11 @@ const SemanticTypeAndTargetPicker = ({ hasSeparator ? CS.mt0 : CS.mt1, className, )} - placeholder={getFkFieldPlaceholder(field, idFields)} + placeholder={getFkFieldPlaceholder(field, comparableIdFields)} searchProp={SEARCH_PROPS} value={field.fk_target_field_id} onChange={handleChangeTarget} - options={idFields} + options={comparableIdFields} optionValueFn={getFieldId} optionNameFn={includeSchema ? getFieldNameWithSchema : getFieldName} optionIconFn={getFieldIcon} -- GitLab