question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow deferral of unique constraints using definitions in Prisma schema

See original GitHub issue

Problem

Unique constraints are enforced during each statement in a database operation by default. However, it would be useful to defer this enforcement to the end of the full transaction in some cases where values are getting “shifted” and may be temporarily duplicated.

For example, take a table that represents an ordered list organized with an index column which is a unique identifier (only one row can occupy the index in the list.) If an item is to be “inserted” into the list, all the indexes need to adjust to accommodate this. However, if an updateMany method is used to increment the index, the default order of the update operation will cause a failure on the unique constraint because the index is already in use by another row. If the unique enforcement waited till the full transaction completed, this would not cause an issue.

A more specific example and use case is explained in my Q&A thread here: https://github.com/prisma/prisma/discussions/8789

This is possible in PostgreSQL and possibly other databases: https://www.postgresql.org/docs/9.1/sql-set-constraints.html

Suggested solution

Allow DEFERRED options to be defined in the Prisma schema, alongside the @unique declarations. This will allow prisma to keep the DEFERRED options in sync with the schema AND the database. It can currently be done directly in the database manually but will be overwritten when the schema is deployed with Migrate.

Possible example to match SQL syntax, probably a way that fits better with the prisma syntax:

@@unique([guildId, queueIndex], name: "queuePosition") DEFERRABLE INITIALLY DEFERRED

Alternatives

One early alternative I used was first querying all the rows to be affected, sorted in a way that would allow the unique constraint to be maintained (start at the highest index if they are to be incremented by 1.) Then, using a for loop, do a single update for each, maintaining the operations in the order that the query was sorted by. This works, but is not ideal for performance.

The next alternative I found was to manually add the DEFERRED options to the database. In order to get this to work, I had to:

  1. Drop the @unique constraint from the Prisma schema and migrate it to the database.
  2. Manually alter the constraint in the database directly with custom SQL to add the deferrals.
  3. Use prisma db pull to “rediscover” the unique constraint so it would be enforced in the code/typings. However, the database kept the DEFERRED options intact.

This will however be overwritten if prisma migrate dev for example is run in the future, so it’s not a sustainable solution.

Additional context

Please see the discussion thread I opened for a more specific example. As this is a general feature request, here I attempted to be more general so it can apply to all projects. https://github.com/prisma/prisma/discussions/8789

Other similar suggestions in the past

I found a few other mentions of this so I figured I’d link them: https://github.com/prisma/prisma/issues/3502 https://github.com/prisma/prisma/discussions/3495

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:13
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
janpiocommented, May 3, 2022

Allowing the part that you were missing (https://github.com/prisma/prisma/issues/13115#issuecomment-1115077872) is indeed content of this feature request here.

2reactions
vphoebecommented, Aug 19, 2021

Looks like it’s unsupported in MySQL and SQLite, unfortunately. Still trying to track down an answer for MongoDB. It doesn’t appear to have explicitly deferrable constraints, but I also don’t know how uniqueness is enforced by default (for example, if it’s already post-transaction this wouldn’t matter anyway.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Referential actions - Prisma
Referential actions are features of foreign key constraints that exist to preserve referential integrity in your database. When you define relationships ...
Read more >
Prisma schema API (Reference)
API reference documentation for the Prisma Schema Language (PSL).
Read more >
Column and table constraints | MySQL | Prisma's Data Guide
Constraints allow you to define qualities that all entries must have, with the server itself enforcing the restrictions upon data entry or update....
Read more >
Data model (Reference) - Prisma
When using the MongoDB provider in version 3.12.0 and later, you can define a unique constraint on a field of a composite type...
Read more >
Indexes - Prisma
Prisma allows configuration of database indexes, unique constraints and primary key constraints. This is in General Availability in versions 4.0.0 and later ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found