prisma-engines
prisma-engines copied to clipboard
feat: support referencing field in filters
TODO BEFORE MERGING
- [ ] Merge Quaint PR
- [ ] Update Quaint
Overview
fixes https://github.com/prisma/prisma/issues/14664
- Supports referencing fields in (not unique) filters (meaning in
*WhereInputs) - Adds a
fieldReferencepreview feature
Refactors
- Refactored the MongoDB filter renderer
- Refactored the Scalar filter extractor
Unrelated bug fixes
- fixes https://github.com/prisma/prisma/issues/14664 (I know it should've ideally been fixed in a separate PR, but excluding MongoDB from all the insensitive field reference tests felt too painful... It's a 10-line fix anyway, you can find it in my own review down below)
- fixes https://github.com/prisma/prisma-engines/issues/3132 (a14f56b)
- fixes https://github.com/prisma/prisma-engines/issues/3133 (a14f56b)
- fixes https://github.com/prisma/prisma/issues/14663 (6e15e95)
- fixes https://github.com/prisma/prisma-engines/issues/3115 (4a205a1)
Notes
- We've disabled referencing field on alphanumeric json filters for MySQL & MariaDB
- If you traverse a relation in a filter, you can currently only reference fields from that relation and not from the parent model.
- Referenced fields in
havingfilters need to be put in thebyargument like scalars are. @SevInf Ideally, this should be type-safe.
Schema Additions
Given this datamodel
model User {
id Int @id
}
schema Query {
findManyUser(where: UserWhereInput)
}
input UserWhereInput {
id: IntFilter
}
// Notice the additional FieldRefInputs
input IntFilter {
equals: Int | IntFieldRefInput
gt: Int | IntFieldRefInput
gte: Int | IntFieldRefInput
lt: Int | IntFieldRefInput
lte: Int | IntFieldRefInput
in: Int[] | IntListFieldRefInput
notIn: Int[] | IntListFieldRefInput
}
input IntFieldRefInput {
_ref: String
}
input IntListFieldRefInput {
_ref: String
}
DMMF Additions
Given this datamodel
model User {
id Int @id
}
See how IntFilter is affected with the addition of the field ref inputπ
{
"name": "IntFilter",
"constraints": {
"maxNumFields": null,
"minNumFields": null
},
"fields": [
{
"name": "equals",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "IntFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "in",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": true
},
{
"type": "IntListFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "notIn",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": true
},
{
"type": "IntListFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "lt",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "IntFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "lte",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "IntFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "gt",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "IntFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "gte",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "IntFieldRefInput",
"namespace": "prisma",
"location": "fieldRefTypes",
"isList": false
}
]
},
{
"name": "not",
"isRequired": false,
"isNullable": false,
"inputTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
},
{
"type": "NestedIntFilter",
"namespace": "prisma",
"location": "inputObjectTypes",
"isList": false
}
]
}
]
}
Additionally, we have a new "location" called "fieldRefTypes" where all field ref input types are located π
{
"datamodel": {
"enums": [],
"models": [],
"types": []
},
"schema": {
"inputObjectTypes": {},
"outputObjectTypes": {},
"enumTypes": {},
"fieldRefTypes": {
"prisma": [
{
"name": "IntFieldRefInput",
"allowTypes": [
{
"type": "Int",
"location": "scalar",
"isList": false
}
],
"fields": [
{
"name": "_ref",
"isRequired": true,
"isNullable": false,
"inputTypes": [
{
"type": "String",
"location": "scalar",
"isList": false
}
]
}
]
},
{
"name": "IntListFieldRefInput",
"allowTypes": [
{
"type": "Int",
"location": "scalar",
"isList": true
}
],
"fields": [
{
"name": "_ref",
"isRequired": true,
"isNullable": false,
"inputTypes": [
{
"type": "String",
"location": "scalar",
"isList": false
}
]
}
]
}
]
}
},
"mappings": {}
}
Finally, all <Model>WhereInput get a new meta.source field. eg:
{
"name": "UserWhereInput",
"meta": {
// source designates the model or composite type from which this type was derived. It's required to help the TS client pass the right generic. See notion doc & proposal #4 to understand more why this is needed.
"source": "User"
},
"constraints": {
"maxNumFields": null,
"minNumFields": null
},
"fields": []
}