From 163b6a71df06d48adbfc7cb1de23be78045f07c8 Mon Sep 17 00:00:00 2001 From: Case Nelson <case@metabase.com> Date: Wed, 5 Apr 2023 11:18:58 -0600 Subject: [PATCH] [MLv2] Add direction arg to orderByClause (#29803) * Add direction arg to orderByClause * Update order_by.ts * Fix TypeScript error * Update order_by.ts --------- Co-authored-by: Anton Kulyk <kuliks.anton@gmail.com> --- frontend/src/metabase-lib/order_by.ts | 17 ++++++++--- .../src/metabase-lib/order_by.unit.spec.ts | 4 +-- frontend/src/metabase-lib/query.ts | 6 ++-- src/metabase/lib/js.cljs | 6 ++-- src/metabase/lib/order_by.cljc | 28 +++++++++++++------ test/metabase/lib/order_by_test.cljc | 13 ++++++--- 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/frontend/src/metabase-lib/order_by.ts b/frontend/src/metabase-lib/order_by.ts index de2d8d5a809..c9fec15c8eb 100644 --- a/frontend/src/metabase-lib/order_by.ts +++ b/frontend/src/metabase-lib/order_by.ts @@ -20,10 +20,19 @@ declare function OrderByFn( export const orderBy: typeof OrderByFn = ML.order_by; -export function orderByClause( +type OrderByDirection = "asc" | "desc"; + +declare function OrderByClauseFn( query: Query, stageNumber: number, field: Field, -): Field { - return ML.order_by_clause(query, stageNumber, field); -} + direction?: OrderByDirection, +): OrderByClause; +declare function OrderByClauseFn( + query: Query, + stageNumber: number, + field: Field, + direction?: OrderByDirection, +): OrderByClause; + +export const orderByClause: typeof OrderByClauseFn = ML.order_by_clause; diff --git a/frontend/src/metabase-lib/order_by.unit.spec.ts b/frontend/src/metabase-lib/order_by.unit.spec.ts index 467fcb2a384..1befda4610b 100644 --- a/frontend/src/metabase-lib/order_by.unit.spec.ts +++ b/frontend/src/metabase-lib/order_by.unit.spec.ts @@ -79,11 +79,11 @@ describe("order by", () => { const nextQuery = ML.replaceClause( orderedQuery, orderBys[0], - ML.orderByClause(orderedQuery, -1, productCategory as Field) as Field, + ML.orderByClause(orderedQuery, -1, productCategory as Field, "desc"), ); const nextOrderBys = ML.orderBys(nextQuery); expect(ML.displayName(nextQuery, nextOrderBys[0])).toBe( - "Category ascending", + "Category descending", ); expect(orderBys[0]).not.toEqual(nextOrderBys[0]); }); diff --git a/frontend/src/metabase-lib/query.ts b/frontend/src/metabase-lib/query.ts index 824dbd687e9..99af10d039c 100644 --- a/frontend/src/metabase-lib/query.ts +++ b/frontend/src/metabase-lib/query.ts @@ -1,5 +1,5 @@ import * as ML from "cljs/metabase.lib.js"; -import type { DatabaseId, DatasetQuery, Field } from "metabase-types/api"; +import type { DatabaseId, DatasetQuery } from "metabase-types/api"; import type { Clause, MetadataProvider, Query } from "./types"; export function fromLegacyQuery( @@ -30,13 +30,13 @@ export const removeClause: typeof RemoveClauseFn = ML.remove_clause; declare function ReplaceClauseFn( query: Query, targetClause: Clause, - newClause: Field, + newClause: Clause, ): Query; declare function ReplaceClauseFn( query: Query, stageIndex: number, targetClause: Clause, - newClause: Field, + newClause: Clause, ): Query; export const replaceClause: typeof ReplaceClauseFn = ML.replace_clause; diff --git a/src/metabase/lib/js.cljs b/src/metabase/lib/js.cljs index 782917d771f..79dffcd0562 100644 --- a/src/metabase/lib/js.cljs +++ b/src/metabase/lib/js.cljs @@ -106,8 +106,10 @@ (defn ^:export order-by-clause "Create an order-by clause independently of a query, e.g. for `replace` or whatever." - [a-query stage-number x] - (lib.order-by/order-by-clause a-query stage-number (lib.normalize/normalize (js->clj x :keywordize-keys true)))) + ([a-query stage-number x] + (order-by-clause a-query stage-number x nil)) + ([a-query stage-number x direction] + (lib.order-by/order-by-clause a-query stage-number (lib.normalize/normalize (js->clj x :keywordize-keys true)) direction))) (defn ^:export order-by "Add an `order-by` clause to `a-query`. Returns updated query." diff --git a/src/metabase/lib/order_by.cljc b/src/metabase/lib/order_by.cljc index 8edcbc7eadc..93d0b1c7905 100644 --- a/src/metabase/lib/order_by.cljc +++ b/src/metabase/lib/order_by.cljc @@ -56,20 +56,32 @@ [_query _stage-number x] (lib.options/ensure-uuid [:asc (lib.ref/ref x)])) -(defn order-by-clause - "Create an order-by clause independently of a query, e.g. for `replace` or whatever." - ([x] - (fn [query stage-number] - (order-by-clause query stage-number x))) - ([query stage-number x] - (->order-by-clause query stage-number x))) - (mu/defn ^:private with-direction :- ::lib.schema.order-by/order-by "Update the direction of an order by clause." [clause :- ::lib.schema.order-by/order-by direction :- ::lib.schema.order-by/direction] (assoc (vec clause) 0 direction)) +(mu/defn order-by-clause + "Create an order-by clause independently of a query, e.g. for `replace` or whatever." + ([x] + (fn [query stage-number] + (order-by-clause query stage-number x nil))) + ([x + direction :- [:maybe [:enum :asc :desc]]] + (fn [query stage-number] + (order-by-clause query stage-number x direction))) + ([query :- ::lib.schema/query + stage-number :- [:maybe :int] + x] + (order-by-clause query stage-number x nil)) + ([query :- ::lib.schema/query + stage-number :- [:maybe :int] + x + direction :- [:maybe [:enum :asc :desc]]] + (-> (->order-by-clause query (or stage-number -1) x) + (with-direction (or direction :asc))))) + (mu/defn order-by "Add an MBQL order-by clause (i.e., `:asc` or `:desc`) from something that you can theoretically sort by -- maybe a Field, or `:field` clause, or expression of some sort, etc. diff --git a/test/metabase/lib/order_by_test.cljc b/test/metabase/lib/order_by_test.cljc index 32e72626d93..4623dff7459 100644 --- a/test/metabase/lib/order_by_test.cljc +++ b/test/metabase/lib/order_by_test.cljc @@ -72,10 +72,15 @@ (deftest ^:parallel order-by-field-metadata-test (testing "Should be able to create an order by using raw Field metadata" - (is (=? [:asc - {:lib/uuid string?} - [:field {:lib/uuid string?} (meta/id :venues :id)]] - (lib/order-by-clause {} -1 (lib.metadata/field meta/metadata-provider nil "VENUES" "ID")))))) + (let [query (lib/query-for-table-name meta/metadata-provider "VENUES")] + (is (=? [:asc + {:lib/uuid string?} + [:field {:lib/uuid string?} (meta/id :venues :id)]] + (lib/order-by-clause query -1 (lib.metadata/field meta/metadata-provider nil "VENUES" "ID")))) + (is (=? [:desc + {:lib/uuid string?} + [:field {:lib/uuid string?} (meta/id :venues :id)]] + (lib/order-by-clause query -1 (lib.metadata/field meta/metadata-provider nil "VENUES" "ID") :desc)))))) (deftest ^:parallel append-order-by-field-metadata-test (testing "Should be able to add an order by using raw Field metadata" -- GitLab