Skip to content

Commit d1a1b17

Browse files
ymc9claude
andcommitted
fix(policy): use dialect.fieldRef for post-update before-join on id fields
The post-update policy check joins the current table with a VALUES table ($before) on id fields. When an id field has @db.Uuid, the raw column is uuid while the VALUES table casts to text, causing a type mismatch. Use dialect.fieldRef() for both sides of the join so the uuid column gets cast to text. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent be227e1 commit d1a1b17

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

packages/plugins/policy/src/policy-handler.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,18 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
311311
() => new ExpressionWrapper(beforeUpdateTable!).as('$before'),
312312
(join) => {
313313
const idFields = QueryUtils.requireIdFields(this.client.$schema, model);
314-
return idFields.reduce((acc, f) => acc.onRef(`${model}.${f}`, '=', `$before.${f}`), join);
314+
const eb = expressionBuilder<any, any>();
315+
return idFields.reduce(
316+
(acc, f) =>
317+
acc.on(() =>
318+
eb(
319+
this.dialect.fieldRef(model, f, model, false),
320+
'=',
321+
this.dialect.fieldRef(model, f, '$before', false),
322+
),
323+
),
324+
join,
325+
);
315326
},
316327
),
317328
);

tests/regression/test/issue-2394.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,24 @@ model Foo {
2121
await db.$unuseAll().foo.create({ data: { x: uuid() } });
2222
await expect(db.foo.findMany()).toResolveTruthy();
2323
});
24+
25+
it('works with post-update policies', async () => {
26+
const db = await createPolicyTestClient(
27+
`
28+
model ExchangeRequest {
29+
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
30+
status String
31+
32+
@@allow('all', true)
33+
@@deny('post-update', before().status == status) // triggers buildValuesTableSelect
34+
}
35+
`,
36+
{ provider: 'postgresql', usePrismaPush: true, debug: true },
37+
);
38+
39+
const request = await db.exchangeRequest.create({ data: { status: 'pending' } });
40+
await expect(
41+
db.exchangeRequest.update({ where: { id: request.id }, data: { status: 'done' } }),
42+
).toResolveTruthy();
43+
});
2444
});

0 commit comments

Comments
 (0)