diff --git a/frontend/src/metabase-lib/order_by.ts b/frontend/src/metabase-lib/order_by.ts index cad71031d30aba4986acdde503527e2d12e3d2e2..de2d8d5a809a01b5b8a235460fe3fc3766791cca 100644 --- a/frontend/src/metabase-lib/order_by.ts +++ b/frontend/src/metabase-lib/order_by.ts @@ -19,3 +19,11 @@ declare function OrderByFn( ): Query; export const orderBy: typeof OrderByFn = ML.order_by; + +export function orderByClause( + query: Query, + stageNumber: number, + field: Field, +): Field { + return ML.order_by_clause(query, stageNumber, field); +} diff --git a/frontend/src/metabase-lib/order_by.unit.spec.ts b/frontend/src/metabase-lib/order_by.unit.spec.ts index 7dc1a0905e023a570ef127546b5364cd7e9d38c2..467fcb2a38499f127b55f6b0b556c0223e86968d 100644 --- a/frontend/src/metabase-lib/order_by.unit.spec.ts +++ b/frontend/src/metabase-lib/order_by.unit.spec.ts @@ -59,4 +59,51 @@ describe("order by", () => { expect(ML.displayName(nextQuery, orderBys[0])).toBe("Title ascending"); }); }); + + describe("replace order by", () => { + const query = createQuery(); + + it("should update the query", () => { + const columns = ML.orderableColumns(query); + const productTitle = columns.find( + column => column.id === SAMPLE_DATABASE.PRODUCTS.TITLE.id, + ); + + const productCategory = columns.find( + column => column.id === SAMPLE_DATABASE.PRODUCTS.CATEGORY.id, + ); + const orderedQuery = ML.orderBy(query, productTitle as Field); + const orderBys = ML.orderBys(orderedQuery); + + expect(orderBys).toHaveLength(1); + const nextQuery = ML.replaceClause( + orderedQuery, + orderBys[0], + ML.orderByClause(orderedQuery, -1, productCategory as Field) as Field, + ); + const nextOrderBys = ML.orderBys(nextQuery); + expect(ML.displayName(nextQuery, nextOrderBys[0])).toBe( + "Category ascending", + ); + expect(orderBys[0]).not.toEqual(nextOrderBys[0]); + }); + }); + + describe("remove order by", () => { + const query = createQuery(); + + it("should update the query", () => { + const columns = ML.orderableColumns(query); + const productTitle = columns.find( + column => column.id === SAMPLE_DATABASE.PRODUCTS.TITLE.id, + ); + + const orderedQuery = ML.orderBy(query, productTitle as Field); + const orderBys = ML.orderBys(orderedQuery); + expect(orderBys).toHaveLength(1); + + const nextQuery = ML.removeClause(orderedQuery, orderBys[0]); + expect(ML.orderBys(nextQuery)).toHaveLength(0); + }); + }); }); diff --git a/frontend/src/metabase-lib/query.ts b/frontend/src/metabase-lib/query.ts index d8bb3b3a2690df1992e70b6e9a36f299bdc88232..824dbd687e95b23045696406073507c980a5928c 100644 --- a/frontend/src/metabase-lib/query.ts +++ b/frontend/src/metabase-lib/query.ts @@ -1,6 +1,6 @@ import * as ML from "cljs/metabase.lib.js"; -import type { DatabaseId, DatasetQuery } from "metabase-types/api"; -import type { MetadataProvider, Query } from "./types"; +import type { DatabaseId, DatasetQuery, Field } from "metabase-types/api"; +import type { Clause, MetadataProvider, Query } from "./types"; export function fromLegacyQuery( databaseId: DatabaseId, @@ -17,3 +17,26 @@ export function toLegacyQuery(query: Query): DatasetQuery { export function suggestedName(query: Query): string { return ML.suggestedName(query); } + +declare function RemoveClauseFn(query: Query, targetClause: Clause): Query; +declare function RemoveClauseFn( + query: Query, + stageIndex: number, + targetClause: Clause, +): Query; + +export const removeClause: typeof RemoveClauseFn = ML.remove_clause; + +declare function ReplaceClauseFn( + query: Query, + targetClause: Clause, + newClause: Field, +): Query; +declare function ReplaceClauseFn( + query: Query, + stageIndex: number, + targetClause: Clause, + newClause: Field, +): Query; + +export const replaceClause: typeof ReplaceClauseFn = ML.replace_clause; diff --git a/src/metabase/lib/js.cljs b/src/metabase/lib/js.cljs index 3598fd6689f47d4e6ccd6f5c915ed224664e4626..782917d771fea68ed87b5abecb9767b71be15bf6 100644 --- a/src/metabase/lib/js.cljs +++ b/src/metabase/lib/js.cljs @@ -104,6 +104,11 @@ (-> (lib.order-by/orderable-columns a-query stage-number) (clj->js :keyword-fn u/qualified-name)))) +(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)))) + (defn ^:export order-by "Add an `order-by` clause to `a-query`. Returns updated query." ([a-query x] @@ -128,3 +133,22 @@ (some-> (lib.order-by/order-bys a-query stage-number) not-empty to-array))) + +(defn ^:export remove-clause + "Removes the `target-clause` in the filter of the `query`." + ([a-query clause] + (remove-clause a-query -1 clause)) + ([a-query stage-number clause] + (lib.query/remove-clause + a-query stage-number + (lib.normalize/normalize (js->clj clause :keywordize-keys true))))) + +(defn ^:export replace-clause + "Replaces the `target-clause` with `new-clause` in the `query` stage." + ([a-query target-clause new-clause] + (replace-clause a-query -1 target-clause new-clause)) + ([a-query stage-number target-clause new-clause] + (lib.query/replace-clause + a-query stage-number + (lib.normalize/normalize (js->clj target-clause :keywordize-keys true)) + (lib.normalize/normalize (js->clj new-clause :keywordize-keys true))))) diff --git a/src/metabase/lib/order_by.cljc b/src/metabase/lib/order_by.cljc index d65decbde0eb42048fd5ffba2640e486a8199077..fdb8618045ed80d7d9949f7fd07c16367b33444a 100644 --- a/src/metabase/lib/order_by.cljc +++ b/src/metabase/lib/order_by.cljc @@ -90,7 +90,7 @@ (lib.util/update-query-stage query stage-number update :order-by (fn [order-bys] (conj (vec order-bys) new-order-by)))))) -(mu/defn ^:export order-bys :- [:maybe [:sequential ::lib.schema.order-by/order-by]] +(mu/defn order-bys :- [:maybe [:sequential ::lib.schema.order-by/order-by]] "Get the order-by clauses in a query." ([query :- ::lib.schema/query] (order-bys query -1)) diff --git a/src/metabase/lib/query.cljc b/src/metabase/lib/query.cljc index 9604659e98137383d3bb3d009b0535c634e84162..778a5a75aedd288b1b6c42c1316778075023871f 100644 --- a/src/metabase/lib/query.cljc +++ b/src/metabase/lib/query.cljc @@ -14,7 +14,7 @@ [metabase.util.malli :as mu])) (mu/defn replace-clause :- :metabase.lib.schema/query - "Replaces the `target-clause` with `new-clase` in the `query` stage." + "Replaces the `target-clause` with `new-clause` in the `query` stage." ([query :- :metabase.lib.schema/query target-clause new-clause]