fix: Unique constraint should account for soft deleted records (#11048)

FIXES FRMW-2878

**What**
Currently, the `one-to-one` unique constraints does not account for deleted record. This prevents from inserting a new record wth the same fk if another one is deleted.

**Caveat**
`hasOne` with FK option is meant to be a special case, for example a many to one - one to many without defining the other side of the relation. In that case we don't handle this behaviour and keep it as it is
This commit is contained in:
Adrien de Peretti
2025-01-22 08:42:06 +01:00
committed by GitHub
parent ecc8efcb04
commit da3906efa4
22 changed files with 361 additions and 217 deletions

View File

@@ -1,5 +1,7 @@
{
"namespaces": ["public"],
"namespaces": [
"public"
],
"name": "public",
"tables": [
{
@@ -87,9 +89,19 @@
"name": "notification_provider",
"schema": "public",
"indexes": [
{
"keyName": "IDX_notification_provider_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_deleted_at\" ON \"notification_provider\" (deleted_at) WHERE deleted_at IS NULL"
},
{
"keyName": "notification_provider_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -216,7 +228,11 @@
"primary": false,
"nullable": false,
"default": "'pending'",
"enumItems": ["pending", "success", "failure"],
"enumItems": [
"pending",
"success",
"failure"
],
"mappedType": "enum"
},
"provider_id": {
@@ -288,9 +304,19 @@
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_id\" ON \"notification\" (provider_id) WHERE deleted_at IS NULL"
},
{
"keyName": "IDX_notification_deleted_at",
"columnNames": [],
"composite": false,
"primary": false,
"unique": false,
"expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_deleted_at\" ON \"notification\" (deleted_at) WHERE deleted_at IS NULL"
},
{
"keyName": "notification_pkey",
"columnNames": ["id"],
"columnNames": [
"id"
],
"composite": false,
"primary": true,
"unique": true
@@ -300,9 +326,13 @@
"foreignKeys": {
"notification_provider_id_foreign": {
"constraintName": "notification_provider_id_foreign",
"columnNames": ["provider_id"],
"columnNames": [
"provider_id"
],
"localTableName": "public.notification",
"referencedColumnNames": ["id"],
"referencedColumnNames": [
"id"
],
"referencedTableName": "public.notification_provider",
"deleteRule": "set null",
"updateRule": "cascade"

View File

@@ -0,0 +1,17 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20250120110514 extends Migration {
async up(): Promise<void> {
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_notification_provider_deleted_at" ON "notification_provider" (deleted_at) WHERE deleted_at IS NULL;');
this.addSql('CREATE INDEX IF NOT EXISTS "IDX_notification_deleted_at" ON "notification" (deleted_at) WHERE deleted_at IS NULL;');
}
async down(): Promise<void> {
this.addSql('drop index if exists "IDX_notification_provider_deleted_at";');
this.addSql('drop index if exists "IDX_notification_deleted_at";');
}
}