fix(drizzle)!: localized fields uniqueness per locale (#8230)

Previously, this worked with MongoDB but failed with Postgres / SQLite
when the `slug` field has both `localized: true` and `unique: true`.

```ts
await payload.create({
  collection: "posts",
  locale: "en",
  data: {
    slug: "my-post"
  }
})

await payload.create({
  collection: "posts",
  locale: "de",
  data: {
    slug: "my-post"
  }
})
```

Now, we build unique constraints and indexes in combination with the
_locale column. This should also improve query performance for fields
with both index: true and localized: true.

### Migration steps (Postgres/SQLite only)
This change updates the database schema and requires a migration (if you
have any localized fields). To apply it, run the following commands:

```sh
pnpm payload migration:create locale_unique_indexes
pnpm payload migrate
```

Note that if you use `db.push: true` which is a default, you don't have
to run `pnpm payload migrate` in the development mode, only in the
production, as Payload automatically pushes the schema to your DB with
it.
This commit is contained in:
Sasha
2024-09-16 21:47:13 +03:00
committed by GitHub
parent f72fd8543b
commit b7db53cef4
5 changed files with 48 additions and 4 deletions

View File

@@ -111,6 +111,12 @@ export default buildConfigWithDefaults({
],
type: 'group',
},
{
name: 'unique',
type: 'text',
localized: true,
unique: true,
},
],
},
ArrayCollection,

View File

@@ -1,6 +1,5 @@
import type { Payload, Where } from 'payload'
import path from 'path'
import { type Payload, type Where } from 'payload'
import { fileURLToPath } from 'url'
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
@@ -1954,6 +1953,44 @@ describe('Localization', () => {
expect(retrieved.array.es[0].text).toEqual(['hola', 'adios'])
})
})
describe('localized with unique', () => {
it('localized with unique should work for each locale', async () => {
await payload.create({
collection: 'localized-posts',
locale: 'ar',
data: {
unique: 'text',
},
})
await payload.create({
collection: 'localized-posts',
locale: 'en',
data: {
unique: 'text',
},
})
await payload.create({
collection: 'localized-posts',
locale: 'es',
data: {
unique: 'text',
},
})
await expect(
payload.create({
collection: 'localized-posts',
locale: 'en',
data: {
unique: 'text',
},
}),
).rejects.toBeTruthy()
})
})
})
async function createLocalizedPost(data: {

View File

@@ -137,6 +137,7 @@ export interface LocalizedPost {
group?: {
children?: string | null;
};
unique?: string | null;
updatedAt: string;
createdAt: string;
}