fix(prisma): add unique constraint to Chat model in Postgres
๐ Description
Fixes a critical bug affecting PostgreSQL users where label operations fail with PrismaClientKnownRequestError (Code 42P10).
The issue occurs because addLabel and removeLabel methods rely on an ON CONFLICT clause that requires a unique constraint on (instanceId, remoteJid). This PR adds the missing @@unique constraint to the Chat model in postgresql-schema.prisma and includes the necessary SQL migration to align behavior with MySQL.
๐ Related Issue
Closes #2152
๐งช Type of Change
- [x] ๐ Bug fix (non-breaking change which fixes an issue)
- [ ] โจ New feature (non-breaking change which adds functionality)
- [ ] ๐ฅ Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] ๐ Documentation update
- [ ] ๐ง Refactoring (no functional changes)
- [ ] โก Performance improvement
- [ ] ๐งน Code cleanup
- [ ] ๐ Security fix
๐งช Testing
- [x] Manual testing completed
- [x] Functionality verified in development environment
- [x] No breaking changes introduced
- [ ] Tested with different connection types (if applicable)
Manually verified by applying the migration to a clean PostgreSQL container. Confirmed via psql that the unique index "Chat_instanceId_remoteJid_key" was successfully created in the database structure.
โ Checklist
- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have manually tested my changes thoroughly
- [x] I have verified the changes work with different scenarios
- [ ] Any dependent changes have been merged and published
๐ Additional Notes
The migration file was generated using prisma migrate dev --create-only and populated manually with the specific CREATE UNIQUE INDEX command. This ensures a clean migration path without generating unnecessary SQL for existing tables.
Summary by Sourcery
Add a unique constraint for Chat records in the PostgreSQL schema to align behavior with other databases and prevent label operation failures.
Bug Fixes:
- Resolve PostgreSQL label operation failures caused by missing uniqueness on Chat instance and remote JID combinations.
Build:
- Introduce a Prisma PostgreSQL migration that creates a unique index on Chat(instanceId, remoteJid) to enforce the new constraint.
Reviewer's guide (collapsed on small PRs)
Reviewer's Guide
Adds a missing unique constraint on (instanceId, remoteJid) for the Chat model in the PostgreSQL Prisma schema and introduces a corresponding migration to create the unique index in the database, aligning Postgres behavior with MySQL and fixing ON CONFLICT label operations.
Sequence diagram for label operations using ON CONFLICT with the new Chat unique index
sequenceDiagram
actor "User" as User
participant "API Server" as Api
participant "Prisma Client" as Prisma
participant "PostgreSQL" as Postgres
"User" ->> "API Server": "Request to add or remove label on chat (instanceId, remoteJid)"
"API Server" ->> "Prisma Client": "call addLabel/removeLabel(chatId, labelId)"
"Prisma Client" ->> "PostgreSQL": "INSERT label mapping WITH ON CONFLICT (instanceId, remoteJid) DO UPDATE"
"PostgreSQL" ->> "PostgreSQL": "Use unique index \"Chat_instanceId_remoteJid_key\" to resolve conflict"
"PostgreSQL" -->> "Prisma Client": "Successful upsert of label mapping (no 42P10 error)"
"Prisma Client" -->> "API Server": "Operation result (success)"
"API Server" -->> "User": "Label operation completed successfully"
Entity relationship diagram for Chat model with composite unique constraint
erDiagram
Chat {
string id
string instanceId
string remoteJid
string otherChatFields
string UNIQUE_instanceId_remoteJid
}
File-Level Changes
| Change | Details | Files |
|---|---|---|
| Add unique composite constraint for Chat to support ON CONFLICT in label operations on PostgreSQL. |
|
prisma/postgresql-schema.prismaprisma/postgresql-migrations/20251122003044_add_chat_instance_remotejid_unique/migration.sql |
Assessment against linked issues
| Issue | Objective | Addressed | Explanation |
|---|---|---|---|
| https://github.com/EvolutionAPI/evolution-api/issues/2152 | Add a UNIQUE constraint (or unique index) on ("instanceId", "remoteJid") to the Postgres "Chat" table so that the ON CONFLICT clause used by addLabel/removeLabel works correctly. | โ | |
| https://github.com/EvolutionAPI/evolution-api/issues/2152 | Update the Prisma/Postgres schema and migrations so that the Chat model enforces uniqueness on (instanceId, remoteJid) and can be applied via Prisma tooling. | โ |
Possibly linked issues
- #2152: PR adds the unique constraint on Chat(instanceId, remoteJid) that the issue identifies as missing and required.
- #2152: PR implements the suggested unique constraint and migration to fix the Chat upsert 42P10 error in Postgres.
- #2152: PR adds required unique constraint on Chat to resolve the PostgreSQL ON CONFLICT 42P10 label error.
Tips and commands
Interacting with Sourcery
-
Trigger a new review: Comment
@sourcery-ai reviewon the pull request. - Continue discussions: Reply directly to Sourcery's review comments.
-
Generate a GitHub issue from a review comment: Ask Sourcery to create an
issue from a review comment by replying to it. You can also reply to a
review comment with
@sourcery-ai issueto create an issue from it. -
Generate a pull request title: Write
@sourcery-aianywhere in the pull request title to generate a title at any time. You can also comment@sourcery-ai titleon the pull request to (re-)generate the title at any time. -
Generate a pull request summary: Write
@sourcery-ai summaryanywhere in the pull request body to generate a PR summary at any time exactly where you want it. You can also comment@sourcery-ai summaryon the pull request to (re-)generate the summary at any time. -
Generate reviewer's guide: Comment
@sourcery-ai guideon the pull request to (re-)generate the reviewer's guide at any time. -
Resolve all Sourcery comments: Comment
@sourcery-ai resolveon the pull request to resolve all Sourcery comments. Useful if you've already addressed all the comments and don't want to see them anymore. -
Dismiss all Sourcery reviews: Comment
@sourcery-ai dismisson the pull request to dismiss all existing Sourcery reviews. Especially useful if you want to start fresh with a new review - don't forget to comment@sourcery-ai reviewto trigger a new review!
Customizing Your Experience
Access your dashboard to:
- Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.
Getting Help
- Contact our support team for questions or feedback.
- Visit our documentation for detailed guides and information.
- Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.