diff --git a/frontend/src/metabase-lib/fields.ts b/frontend/src/metabase-lib/fields.ts index dc7f188a91a608785b6294eb873b0db529cde7a0..dc5f52b2c1de72e86e8d35425cf97ff21fabd48c 100644 --- a/frontend/src/metabase-lib/fields.ts +++ b/frontend/src/metabase-lib/fields.ts @@ -1,4 +1,5 @@ import * as ML from "cljs/metabase.lib.js"; +import type { FieldReference } from "metabase-types/api"; import type { Clause, ColumnMetadata, Query } from "./types"; export function fields(query: Query, stageIndex: number): Clause[] { @@ -30,3 +31,11 @@ export function fieldableColumns( export function _fieldId(column: ColumnMetadata): number | null { return ML.field_id(column); } + +export function findVisibleColumnForLegacyRef( + query: Query, + stageIndex: number, + fieldRef: FieldReference, +): ColumnMetadata | null { + return ML.find_visible_column_for_legacy_ref(query, stageIndex, fieldRef); +} diff --git a/src/metabase/lib/core.cljc b/src/metabase/lib/core.cljc index 3e5e9821d8958176de1c457e2d8a864371015c2d..ae0befbcefe5fa46f7c86fd76b857385863b93b3 100644 --- a/src/metabase/lib/core.cljc +++ b/src/metabase/lib/core.cljc @@ -148,6 +148,7 @@ field-id fieldable-columns fields + find-visible-column-for-ref remove-field with-fields] [lib.filter diff --git a/src/metabase/lib/field.cljc b/src/metabase/lib/field.cljc index d6303d83c2455cbe6e0db242921bf793a27a6ded..d303edcef8b40d1a8cd030f5303334a41f2da61a 100644 --- a/src/metabase/lib/field.cljc +++ b/src/metabase/lib/field.cljc @@ -705,3 +705,18 @@ :source/native (throw (ex-info (native-query-fields-edit-error) {:query query :stage stage-number})) ;; Default case: do nothing and return the query unchaged. query))) + +(mu/defn find-visible-column-for-ref :- [:maybe lib.metadata/ColumnMetadata] + "Return the visible column in `query` at `stage-number` referenced by `field-ref`. + If `stage-number` is omitted, the last stage is used." + ([query field-ref] + (find-visible-column-for-ref query -1 field-ref)) + + ([query :- ::lib.schema/query + stage-number :- :int + field-ref] + (let [stage (lib.util/query-stage query stage-number) + columns (lib.metadata.calculation/visible-columns query stage-number stage) + ref->col (zipmap (map lib.ref/ref columns) columns) + col-ref (lib.equality/find-closest-matching-ref query field-ref (keys ref->col))] + (ref->col col-ref)))) diff --git a/src/metabase/lib/js.cljs b/src/metabase/lib/js.cljs index ef5966fc96ed4eda6548624e29f0b6d3b12c304d..ed78f6e11cae776cbce4f61a345c922c0d8cdadf 100644 --- a/src/metabase/lib/js.cljs +++ b/src/metabase/lib/js.cljs @@ -427,6 +427,15 @@ [a-query stage-number column] (lib.core/remove-field a-query stage-number column)) +(defn ^:export find-visible-column-for-legacy-ref + "Return the visible column in `a-query` at `stage-number` referenced by `legacy-ref`." + [a-query stage-number legacy-ref] + (let [ref (-> legacy-ref + (js->clj :keywordize-keys true) + (update 0 keyword) + convert/->pMBQL)] + (lib.core/find-visible-column-for-ref a-query stage-number ref))) + (defn ^:export join-strategy "Get the strategy (type) of a given join as an opaque JoinStrategy object." [a-join] diff --git a/test/metabase/lib/field_test.cljc b/test/metabase/lib/field_test.cljc index 32284d50d6a12133c1fcde343b2b489409e7f5c1..9f8993fa0ecb0f9c2264e864a55d32f49a72c223 100644 --- a/test/metabase/lib/field_test.cljc +++ b/test/metabase/lib/field_test.cljc @@ -1251,3 +1251,34 @@ (lib/add-field -1 (second columns)) (lib.util/query-stage -1) :fields))))))) + +(deftest ^:parallel find-visible-column-for-ref-test + (testing "precise references" + (doseq [query-var [#'lib.tu/query-with-expression + #'lib.tu/query-with-join-with-explicit-fields + #'lib.tu/query-with-source-card] + :let [query @query-var] + col (lib/visible-columns query) + :let [col-ref (lib/ref col)]] + (testing (str "ref " col-ref " of " (symbol query-var)) + (is (= (dissoc col :lib/source-uuid) + (dissoc (lib/find-visible-column-for-ref query col-ref) :lib/source-uuid)))))) + (testing "reference by ID instead of name" + (let [query lib.tu/query-with-source-card + col-ref [:field + {:lib/uuid "ae24a9b0-cbb5-40b6-bace-c8a5ac6a7e42" + :base-type :type/Integer + :effective-type :type/Integer} + (meta/id :checkins :user-id)]] + (is (=? {:lib/type :metadata/column + :base-type :type/Integer + :semantic-type :type/FK + :name "USER_ID" + :lib/card-id 1 + :lib/source :source/card + :lib/source-column-alias "USER_ID" + :effective-type :type/Integer + :id (meta/id :checkins :user-id) + :lib/desired-column-alias "USER_ID" + :display-name "User ID"} + (lib/find-visible-column-for-ref query col-ref))))))