From f717e3eb96c4f694bc24bfc8f13e35637cd06c67 Mon Sep 17 00:00:00 2001 From: Stephan Renatus Date: Fri, 1 Nov 2024 12:07:42 +0100 Subject: [PATCH] ucast-prisma: handle 'or' with compound disjunct --- .changeset/small-bags-kiss.md | 5 ++++ packages/ucast-prisma/src/interpreter.ts | 12 +++++++-- packages/ucast-prisma/src/interpreters.ts | 8 +----- packages/ucast-prisma/tests/adapter.test.ts | 18 +++++++++++++ .../ucast-prisma/tests/interpreters.test.ts | 26 +++++++++++++++++-- 5 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 .changeset/small-bags-kiss.md diff --git a/.changeset/small-bags-kiss.md b/.changeset/small-bags-kiss.md new file mode 100644 index 00000000..689a28ab --- /dev/null +++ b/.changeset/small-bags-kiss.md @@ -0,0 +1,5 @@ +--- +"@styra/ucast-prisma": patch +--- + +handle 'or' correctly when including compound disjuncts diff --git a/packages/ucast-prisma/src/interpreter.ts b/packages/ucast-prisma/src/interpreter.ts index cee5da30..09349583 100644 --- a/packages/ucast-prisma/src/interpreter.ts +++ b/packages/ucast-prisma/src/interpreter.ts @@ -8,6 +8,7 @@ import merge from "lodash.merge"; export class Query { private _primary: string; private _tableConditions: Record = {}; + private _relatedConditions: Record = {}; constructor(primary: string) { this._primary = primary; @@ -23,7 +24,10 @@ export class Query { addCondition(table: string, cond: Object) { if (table !== this._primary) { - this._tableConditions[table] = merge(this._tableConditions[table], cond); + this._relatedConditions[table] = merge( + this._relatedConditions[table], + cond + ); } else { this._tableConditions = merge(this._tableConditions, cond); } @@ -39,11 +43,15 @@ export class Query { this._tableConditions, other._tableConditions ); + this._relatedConditions = merge( + this._relatedConditions, + other._relatedConditions + ); return this; } toJSON() { - return this._tableConditions; + return { ...this._tableConditions, ...this._relatedConditions }; } } diff --git a/packages/ucast-prisma/src/interpreters.ts b/packages/ucast-prisma/src/interpreters.ts index 09b91c58..808bbe88 100644 --- a/packages/ucast-prisma/src/interpreters.ts +++ b/packages/ucast-prisma/src/interpreters.ts @@ -40,13 +40,7 @@ export const or: PrismaOperator = ( condition.value.forEach((cond) => { const q = query.child(); interpret(cond, q); - for (const [tbl, c] of Object.entries(q.toJSON())) { - if (query.isPrimary(tbl)) { - or.push(c); - } else { - or.push({ [tbl]: c }); - } - } + or.push(q.toJSON()); }); if (or.length > 1) { diff --git a/packages/ucast-prisma/tests/adapter.test.ts b/packages/ucast-prisma/tests/adapter.test.ts index 6afeca2e..7f90b22b 100644 --- a/packages/ucast-prisma/tests/adapter.test.ts +++ b/packages/ucast-prisma/tests/adapter.test.ts @@ -42,5 +42,23 @@ describe("ucastToPrisma", () => { ], }); }); + + it("handles 'or' with multiple conditions in one disjunct", () => { + const p = ucastToPrisma( + { + or: [ + { "tickets.resolved": false, "tickets.private": true }, + { "users.name": "ceasar" }, + ], + }, + "tickets" + ); + expect(p).toStrictEqual({ + OR: [ + { resolved: { equals: false }, private: { equals: true } }, + { users: { name: { equals: "ceasar" } } }, + ], + }); + }); }); }); diff --git a/packages/ucast-prisma/tests/interpreters.test.ts b/packages/ucast-prisma/tests/interpreters.test.ts index c47315de..23b22620 100644 --- a/packages/ucast-prisma/tests/interpreters.test.ts +++ b/packages/ucast-prisma/tests/interpreters.test.ts @@ -86,11 +86,10 @@ describe("Condition interpreter", () => { expect(f).toStrictEqual({}); }); - it('generates query with OR for "or" per table', () => { + it('generates query with OR for "or", projected to primary table (user)', () => { const condition = new CompoundCondition("or", [ new FieldCondition("eq", "user.id", 12), new FieldCondition("gt", "user.age", 20), - // This OR will be dropped as for this table, there is only one condition. new FieldCondition("eq", "customer.id", 40), ]); const f = interpret(condition); @@ -117,5 +116,28 @@ describe("Condition interpreter", () => { ], }); }); + + it('can deal with "AND" within "OR"', () => { + const condition = new CompoundCondition("or", [ + new CompoundCondition("and", [ + new FieldCondition("eq", "user.id", 12), + new FieldCondition("gt", "user.age", 20), + ]), + new FieldCondition("eq", "customer.id", 40), + ]); + const f = interpret(condition); + + expect(f).toStrictEqual({ + OR: [ + { + id: { equals: 12 }, + age: { gt: 20 }, + }, + { + customer: { id: { equals: 40 } }, + }, + ], + }); + }); }); });