From 373f4c4ff27966fa913feb1dfea89b75a0c27425 Mon Sep 17 00:00:00 2001
From: metamben <103100869+metamben@users.noreply.github.com>
Date: Mon, 20 Nov 2023 18:32:22 +0300
Subject: [PATCH] Add expression-name and with-expression-name (#35932)

---
 frontend/src/metabase-lib/expression.ts | 11 +++++++++++
 src/metabase/lib/core.cljc              |  2 ++
 src/metabase/lib/expression.cljc        | 14 ++++++++++++++
 src/metabase/lib/js.cljs                | 10 ++++++++++
 test/metabase/lib/expression_test.cljc  | 24 +++++++++++++++++++++++-
 5 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/frontend/src/metabase-lib/expression.ts b/frontend/src/metabase-lib/expression.ts
index d71965ec314..9930cbf466f 100644
--- a/frontend/src/metabase-lib/expression.ts
+++ b/frontend/src/metabase-lib/expression.ts
@@ -20,6 +20,17 @@ export function expression(
   return ML.expression(query, stageIndex, expressionName, clause);
 }
 
+export function expressionName(clause: ExpressionClause): string {
+  return ML.expression_name(clause);
+}
+
+export function withExpressionName(
+  clause: ExpressionClause,
+  newName: string,
+): ExpressionClause {
+  return ML.with_expression_name(clause, newName);
+}
+
 export function expressions(
   query: Query,
   stageIndex: number,
diff --git a/src/metabase/lib/core.cljc b/src/metabase/lib/core.cljc
index 3bb23b3cc58..1b3685a9d00 100644
--- a/src/metabase/lib/core.cljc
+++ b/src/metabase/lib/core.cljc
@@ -115,10 +115,12 @@
   find-matching-column]
  [lib.expression
   expression
+  expression-name
   expressions
   expressions-metadata
   expressionable-columns
   expression-ref
+  with-expression-name
   +
   -
   *
diff --git a/src/metabase/lib/expression.cljc b/src/metabase/lib/expression.cljc
index c4f344b6065..17d9436eea4 100644
--- a/src/metabase/lib/expression.cljc
+++ b/src/metabase/lib/expression.cljc
@@ -346,3 +346,17 @@
         (resolve-expression query stage-number)
         (expression-metadata query stage-number)
         lib.ref/ref)))
+
+(mu/defn expression-name :- :string
+  "Return the name of `an-expression-clause`."
+  [an-expression-clause :- ::lib.schema.expression/expression]
+  (-> an-expression-clause lib.options/options :lib/expression-name))
+
+(mu/defn with-expression-name :- ::lib.schema.expression/expression
+  "Return a new expression clause like `an-expression-clause` but with name `new-name`."
+  [an-expression-clause :- ::lib.schema.expression/expression
+   new-name :- :string]
+  (lib.options/update-options
+   an-expression-clause assoc
+   :lib/expression-name new-name
+   :lib/uuid (str (random-uuid))))
diff --git a/src/metabase/lib/js.cljs b/src/metabase/lib/js.cljs
index f3674192675..b5f79fb7e51 100644
--- a/src/metabase/lib/js.cljs
+++ b/src/metabase/lib/js.cljs
@@ -695,6 +695,16 @@
   [a-query stage-number expression-name an-expression-clause]
   (lib.core/expression a-query stage-number expression-name an-expression-clause))
 
+(defn ^:export expression-name
+  "Return the name of `an-expression-clause`."
+  [an-expression-clause]
+  (lib.core/expression-name an-expression-clause))
+
+(defn ^:export with-expression-name
+  "Return an new expressions clause like `an-expression-clause` but with name `new-name`."
+  [an-expression-clause new-name]
+  (lib.core/with-expression-name an-expression-clause new-name))
+
 (defn ^:export expressions
   "Get the expressions map from a given stage of a `query`."
   [a-query stage-number]
diff --git a/test/metabase/lib/expression_test.cljc b/test/metabase/lib/expression_test.cljc
index 2ff2c7b1c8f..73982654121 100644
--- a/test/metabase/lib/expression_test.cljc
+++ b/test/metabase/lib/expression_test.cljc
@@ -6,6 +6,7 @@
    [medley.core :as m]
    [metabase.lib.core :as lib]
    [metabase.lib.expression :as lib.expression]
+   [metabase.lib.options :as lib.options]
    [metabase.lib.schema :as lib.schema]
    [metabase.lib.schema.expression :as lib.schema.expression]
    [metabase.lib.test-metadata :as meta]
@@ -242,7 +243,12 @@
               :display-name "expr"}]
             (-> lib.tu/venues-query
                 (lib/expression "expr" (lib/absolute-datetime "2020" :month))
-                lib/expressions-metadata))))
+                lib/expressions-metadata)))
+    (is (= ["expr"]
+           (-> lib.tu/venues-query
+               (lib/expression "expr" (lib/absolute-datetime "2020" :month))
+               lib/expressions
+               (->> (map lib/expression-name))))))
   (testing "collisions with other column names are detected and rejected"
     (let [query (lib/query meta/metadata-provider (meta/table-metadata :categories))
           ex    (try
@@ -350,3 +356,19 @@
       (let [dropped (lib/remove-join query join)]
         (is (empty? (lib/joins dropped)))
         (is (empty? (lib/expressions dropped)))))))
+
+(deftest ^:parallel with-expression-name-test
+  (let [query (-> lib.tu/venues-query
+                  (lib/expression "expr" (lib/absolute-datetime "2020" :month)))
+        [orig-expr :as orig-exprs] (lib/expressions query)
+        expr (lib/with-expression-name orig-expr "newly-named-expression")]
+    (testing "expressions should include the original expression name"
+      (is (=? [{:name         "expr"
+                :display-name "expr"}]
+              (lib/expressions-metadata query)))
+      (is (= ["expr"]
+             (map lib/expression-name orig-exprs)))
+      (is (= "newly-named-expression"
+             (lib/expression-name expr)))
+      (is (not= (lib.options/uuid orig-expr)
+                (lib.options/uuid expr))))))
-- 
GitLab