Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 48a9555

Browse files
committed
fix name mapper
1 parent 634b4f8 commit 48a9555

3 files changed

Lines changed: 37 additions & 27 deletions

File tree

packages/orm/src/client/executor/name-mapper.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,19 @@ export class QueryNameMapper extends OperationNodeTransformer {
7878
// process "from" clauses
7979
const processedFroms = node.from.froms.map((from) => this.processSelectTable(from));
8080

81-
// process "join" clauses, note that "from" needs to be added as scopes since join conditions
82-
// can refer to "from" tables
83-
const processedJoins = this.withScopes([...processedFroms.map(({ scope }) => scope)], () =>
84-
(node.joins ?? []).map((join) => this.processSelectTable(join.table)),
85-
);
81+
// process "join" clauses, note that "from" and previous joins need to be added as scopes since join conditions
82+
// can refer to "from" tables and previous joins
83+
const processedJoins: ReturnType<typeof this.processSelectTable>[] = [];
84+
const cumulativeScopes = [...processedFroms.map(({ scope }) => scope)];
85+
for (const join of node.joins ?? []) {
86+
const processedJoin = this.withScopes(cumulativeScopes, () => this.processSelectTable(join.table));
87+
processedJoins.push(processedJoin);
88+
cumulativeScopes.push(processedJoin.scope);
89+
}
8690

8791
// merge the scopes of froms and joins since they're all visible in the query body
88-
const scopes = [...processedFroms.map(({ scope }) => scope), ...processedJoins.map(({ scope }) => scope)];
8992

90-
return this.withScopes(scopes, () => {
93+
return this.withScopes(cumulativeScopes, () => {
9194
// transform join clauses, "on" is transformed within the scopes
9295
const joins = node.joins
9396
? node.joins.map((join, i) => ({

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
9898
// reject non-existing model
9999
this.tryRejectNonexistentModel(mutationModel);
100100

101-
// --- Pre mutation work ---
101+
// #region Pre mutation work
102102

103103
if (InsertQueryNode.is(node)) {
104104
// pre-create policy evaluation happens before execution of the query
@@ -128,11 +128,15 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
128128
beforeUpdateInfo = await this.loadBeforeUpdateEntities(mutationModel, node.where, proceed);
129129
}
130130

131-
// proceed with query
131+
// #endregion
132+
133+
// #region query execution
132134

133135
const result = await proceed(this.transformNode(node));
134136

135-
// --- Post mutation work ---
137+
// #endregion
138+
139+
// #region Post mutation work
136140

137141
if (hasPostUpdatePolicies && result.rows.length > 0) {
138142
// verify if before-update rows and post-update rows still id-match
@@ -210,9 +214,11 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
210214
'some or all updated rows failed to pass post-update policy check',
211215
);
212216
}
217+
218+
// #endregion
213219
}
214220

215-
// --- Read back ---
221+
// #region Read back
216222

217223
if (!node.returning || this.onlyReturningId(node)) {
218224
// no need to check read back
@@ -228,6 +234,8 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
228234
}
229235
return readBackResult;
230236
}
237+
238+
// #endregion
231239
}
232240

233241
// #endregion
@@ -292,8 +300,8 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
292300
// when there's no field-level policies, we merge model-level policy filters into where clause directly
293301
// for generating simpler SQL
294302

295-
let whereNode = this.transformNode(node.where);
296-
const policyFilter = this.createPolicyFilterForFrom(node.from);
303+
let whereNode = result.where;
304+
const policyFilter = this.createPolicyFilterForFrom(result.from);
297305
if (policyFilter && !isTrueNode(policyFilter)) {
298306
whereNode = WhereNode.create(
299307
whereNode?.where ? conjunction(this.dialect, [whereNode.where, policyFilter]) : policyFilter,
@@ -538,7 +546,10 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
538546
selections,
539547
};
540548

541-
return { hasPolicies, query: AliasNode.create(nestedQuery, IdentifierNode.create(alias ?? model)) };
549+
return {
550+
hasPolicies,
551+
query: AliasNode.create(ParensNode.create(nestedQuery), IdentifierNode.create(alias ?? model)),
552+
};
542553
}
543554

544555
private createFieldSelectionWithPolicy(model: string, field: string, operation: FieldLevelPolicyOperations) {
@@ -559,7 +570,7 @@ export class PolicyHandler<Schema extends SchemaDef> extends OperationNodeTransf
559570
return { hasPolicies: true, selection: SelectionNode.create(selection) };
560571
}
561572

562-
private hasFieldLevelPolicies(model: string): unknown {
573+
private hasFieldLevelPolicies(model: string) {
563574
const modelDef = QueryUtils.getModel(this.client.$schema, model);
564575
if (!modelDef) {
565576
return false;

tests/e2e/orm/policy/migrated/field-level-policy.test.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('field-level policy tests', () => {
3131

3232
let r;
3333

34-
// y and x are unreadable
34+
// y and z are unreadable
3535

3636
// create read-back
3737
r = await db.model.create({
@@ -472,7 +472,7 @@ describe('field-level policy tests', () => {
472472
let r;
473473

474474
// y is unreadable
475-
r = await db.model.create({
475+
await db.model.create({
476476
data: {
477477
id: 1,
478478
x: 0,
@@ -590,7 +590,7 @@ describe('field-level policy tests', () => {
590590
});
591591

592592
describe.skip('update tests', () => {
593-
it('update simple', async () => {
593+
it('works with simple updates', async () => {
594594
const db = await createPolicyTestClient(
595595
`
596596
model User {
@@ -625,13 +625,7 @@ describe('field-level policy tests', () => {
625625
where: { id: 1 },
626626
data: { y: 2 },
627627
}),
628-
).toBeRejectedByPolicy();
629-
await expect(
630-
db.model.update({
631-
where: { id: 1 },
632-
data: { x: 2 },
633-
}),
634-
).toBeRejectedByPolicy();
628+
).toBeRejectedNotFound();
635629

636630
await db.model.create({
637631
data: { id: 2, x: 0, y: 1, ownerId: 1 },
@@ -660,7 +654,8 @@ describe('field-level policy tests', () => {
660654
).toResolveTruthy();
661655
});
662656

663-
it('update with override', async () => {
657+
// TODO: field-level policy override
658+
it.skip('update with override', async () => {
664659
const db = await createPolicyTestClient(
665660
`
666661
model Model {
@@ -1143,7 +1138,8 @@ describe('field-level policy tests', () => {
11431138
);
11441139
});
11451140

1146-
it('updateMany override', async () => {
1141+
// TODO: field-level policy override
1142+
it.skip('updateMany override', async () => {
11471143
const db = await createPolicyTestClient(
11481144
`
11491145
model Model {

0 commit comments

Comments
 (0)