Found while fixing #859 (isIndexed: true emitting an invalid inline @index). Not a bug — filing so it doesn't evaporate.
The gap
isIndexed is declared on an arbitrary subset of field types:
Accepts isIndexed |
Does not |
text, decimal, calendarDay, relationship |
integer, timestamp, select, checkbox, json, password |
The split looks like historical accretion rather than a design decision. decimal and calendarDay have it while integer and timestamp don't, which is hard to justify on any axis — indexing a timestamp you filter or sort by is considerably more common than indexing a decimal.
Today timestamp({ isIndexed: true }) is a compile error. That's an honest failure and nowhere near as bad as what #859 fixed, so this isn't urgent — but it is a papercut for anyone coming from Keystone, where the option is uniform across field types.
Why this wasn't folded into #859
That PR is a bug fix (patch). Adding isIndexed to more field types is additive (minor), and it carries design questions of its own that deserve deciding rather than assuming.
Open questions
- Which types?
integer and timestamp seem clearly worth having. select is less obvious — it maps to a Prisma enum on Postgres and a String on SQLite, so it's worth confirming the index is well-defined on both before offering it.
json? Indexability is provider-specific (Postgres wants GIN and an expression, which @@index([field]) doesn't express). Probably out.
password? Indexing a bcrypt hash has no sensible use case. Probably out.
- Should
timestamp default to indexed? relationship defaults FKs to isIndexed: true for Keystone parity. Timestamps are a common sort key, but silently adding indexes to every existing table would be a surprising and non-trivial migration for existing users, so I'd lean no.
virtual must be excluded regardless — it has no column, so isIndexed there could only ever no-op. This is the main argument against simply hoisting isIndexed onto BaseFieldConfig to make it uniform: it would document an option that lies for at least one field type.
Implementation note
The mechanism already exists as of #859. getPrismaType() returns an optional index?: boolean | 'unique' and the generator emits @@index([field]) / @@unique([field]) from it. Extending a field type is therefore: add isIndexed?: boolean | 'unique' to its config type, and return index from its getPrismaType(). No generator changes needed.
Found while fixing #859 (
isIndexed: trueemitting an invalid inline@index). Not a bug — filing so it doesn't evaporate.The gap
isIndexedis declared on an arbitrary subset of field types:isIndexedtext,decimal,calendarDay,relationshipinteger,timestamp,select,checkbox,json,passwordThe split looks like historical accretion rather than a design decision.
decimalandcalendarDayhave it whileintegerandtimestampdon't, which is hard to justify on any axis — indexing a timestamp you filter or sort by is considerably more common than indexing a decimal.Today
timestamp({ isIndexed: true })is a compile error. That's an honest failure and nowhere near as bad as what #859 fixed, so this isn't urgent — but it is a papercut for anyone coming from Keystone, where the option is uniform across field types.Why this wasn't folded into #859
That PR is a bug fix (patch). Adding
isIndexedto more field types is additive (minor), and it carries design questions of its own that deserve deciding rather than assuming.Open questions
integerandtimestampseem clearly worth having.selectis less obvious — it maps to a Prisma enum on Postgres and aStringon SQLite, so it's worth confirming the index is well-defined on both before offering it.json? Indexability is provider-specific (Postgres wants GIN and an expression, which@@index([field])doesn't express). Probably out.password? Indexing a bcrypt hash has no sensible use case. Probably out.timestampdefault to indexed?relationshipdefaults FKs toisIndexed: truefor Keystone parity. Timestamps are a common sort key, but silently adding indexes to every existing table would be a surprising and non-trivial migration for existing users, so I'd lean no.virtualmust be excluded regardless — it has no column, soisIndexedthere could only ever no-op. This is the main argument against simply hoistingisIndexedontoBaseFieldConfigto make it uniform: it would document an option that lies for at least one field type.Implementation note
The mechanism already exists as of #859.
getPrismaType()returns an optionalindex?: boolean | 'unique'and the generator emits@@index([field])/@@unique([field])from it. Extending a field type is therefore: addisIndexed?: boolean | 'unique'to its config type, and returnindexfrom itsgetPrismaType(). No generator changes needed.