Skip to content

Commit ed6ea50

Browse files
authored
fix(cli): regular relation fields are incorrectly recognized as self-relation (#1790)
2 parents c39f596 + 10c2f7b commit ed6ea50

File tree

2 files changed

+14
-46
lines changed

2 files changed

+14
-46
lines changed

packages/schema/src/language-server/validator/datamodel-validator.ts

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,7 @@ import {
77
isEnum,
88
isStringLiteral,
99
} from '@zenstackhq/language/ast';
10-
import {
11-
getLiteral,
12-
getModelFieldsWithBases,
13-
getModelIdFields,
14-
getModelUniqueFields,
15-
isDelegateModel,
16-
} from '@zenstackhq/sdk';
10+
import { getModelFieldsWithBases, getModelIdFields, getModelUniqueFields, isDelegateModel } from '@zenstackhq/sdk';
1711
import { AstNode, DiagnosticInfo, ValidationAcceptor, getDocument } from 'langium';
1812
import { findUpInheritance } from '../../utils/ast-utils';
1913
import { IssueCodes, SCALAR_TYPES } from '../constants';
@@ -147,15 +141,15 @@ export default class DataModelValidator implements AstValidator<DataModel> {
147141
}
148142
}
149143

144+
if (!fields && !references) {
145+
return { attr: relAttr, name, fields, references, valid: true };
146+
}
147+
150148
if (!fields || !references) {
151-
if (this.isSelfRelation(field, name)) {
152-
// self relations are partial
153-
// https://www.prisma.io/docs/concepts/components/prisma-schema/relations/self-relations
154-
} else {
155-
if (accept) {
156-
accept('error', `Both "fields" and "references" must be provided`, { node: relAttr });
157-
}
149+
if (accept) {
150+
accept('error', `"fields" and "references" must be provided together`, { node: relAttr });
158151
}
152+
// }
159153
} else {
160154
// validate "fields" and "references" typing consistency
161155
if (fields.length !== references.length) {
@@ -203,34 +197,8 @@ export default class DataModelValidator implements AstValidator<DataModel> {
203197
return { attr: relAttr, name, fields, references, valid };
204198
}
205199

206-
private isSelfRelation(field: DataModelField, relationName?: string) {
207-
if (field.type.reference?.ref === field.$container) {
208-
// field directly references back to its type
209-
return true;
210-
}
211-
212-
if (relationName) {
213-
// field's relation points to another type, and that type's opposite relation field
214-
// points back
215-
const oppositeModel = field.type.reference?.ref as DataModel;
216-
if (oppositeModel) {
217-
const oppositeModelFields = getModelFieldsWithBases(oppositeModel);
218-
for (const oppositeField of oppositeModelFields) {
219-
// find the opposite relation with the matching name
220-
const relAttr = oppositeField.attributes.find((a) => a.decl.ref?.name === '@relation');
221-
if (relAttr) {
222-
const relNameExpr = relAttr.args.find((a) => !a.name || a.name === 'name');
223-
const relName = getLiteral<string>(relNameExpr?.value);
224-
if (relName === relationName && oppositeField.type.reference?.ref === field.$container) {
225-
// found an opposite relation field that points back to this field's type
226-
return true;
227-
}
228-
}
229-
}
230-
}
231-
}
232-
233-
return false;
200+
private isSelfRelation(field: DataModelField) {
201+
return field.type.reference?.ref === field.$container;
234202
}
235203

236204
private validateRelationField(contextModel: DataModel, field: DataModelField, accept: ValidationAcceptor) {
@@ -330,10 +298,10 @@ export default class DataModelValidator implements AstValidator<DataModel> {
330298
// if both the field is array, then it's an implicit many-to-many relation
331299
if (!(field.type.array && oppositeField.type.array)) {
332300
[field, oppositeField].forEach((f) => {
333-
if (!this.isSelfRelation(f, thisRelation.name)) {
301+
if (!this.isSelfRelation(f)) {
334302
accept(
335303
'error',
336-
'Field for one side of relation must carry @relation attribute with both "fields" and "references" fields',
304+
'Field for one side of relation must carry @relation attribute with both "fields" and "references"',
337305
{ node: f }
338306
);
339307
}

packages/schema/tests/schema/validation/datamodel-validation.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ describe('Data Model Validation Tests', () => {
451451
aId String
452452
}
453453
`)
454-
).toMatchObject(errorLike(`Both "fields" and "references" must be provided`));
454+
).toMatchObject(errorLike(`"fields" and "references" must be provided together`));
455455

456456
// one-to-one inconsistent attribute
457457
expect(
@@ -541,7 +541,7 @@ describe('Data Model Validation Tests', () => {
541541
`)
542542
).toMatchObject(
543543
errorLike(
544-
`Field for one side of relation must carry @relation attribute with both "fields" and "references" fields`
544+
`Field for one side of relation must carry @relation attribute with both "fields" and "references"`
545545
)
546546
);
547547

0 commit comments

Comments
 (0)