fix(db-postgres): ensure deletion of numbers and texts in upsertRow (#11787)

### What?
This PR fixes an issue while using `text` & `number` fields with
`hasMany: true` where the last entry would be unreachable, and thus
undeletable, because the `transformForWrite` function did not track
these rows for deletion. This causes values that should've been deleted
to remain in the edit view form, as well as the db, after a submission.

This PR also properly threads the placeholder value from
`admin.placeholder` to `text` & `number` `hasMany: true` fields.

### Why?
To remove rows from the db when a submission is made where these fields
are empty arrays, and to properly show an appropriate placeholder when
one is set in config.

### How?
Adjusting `transformForWrite` and the `traverseFields` to keep track of
rows for deletion.

Fixes #11781

Before:


[Editing---Post-dbpg-before--Payload.webm](https://github.com/user-attachments/assets/5ba1708a-2672-4b36-ac68-05212f3aa6cb)

After:


[Editing---Post--dbpg-hasmany-after-Payload.webm](https://github.com/user-attachments/assets/1292e998-83ff-49d0-aa86-6199be319937)
This commit is contained in:
Said Akhrarov
2025-06-04 10:13:46 -04:00
committed by GitHub
parent c08cdff498
commit bd512f1eda
10 changed files with 158 additions and 17 deletions

View File

@@ -33,6 +33,7 @@ import {
checkboxFieldsSlug,
collapsibleFieldsSlug,
groupFieldsSlug,
numberFieldsSlug,
relationshipFieldsSlug,
tabsFieldsSlug,
textFieldsSlug,
@@ -401,6 +402,31 @@ describe('Fields', () => {
expect(resInSecond.totalDocs).toBe(1)
})
it('should delete rows when updating hasMany with empty array', async () => {
const { id: createdDocId } = await payload.create({
collection: textFieldsSlug,
data: {
text: 'hasMany deletion test',
hasMany: ['one', 'two', 'three'],
},
})
await payload.update({
collection: textFieldsSlug,
id: createdDocId,
data: {
hasMany: [],
},
})
const resultingDoc = await payload.findByID({
collection: textFieldsSlug,
id: createdDocId,
})
expect(resultingDoc.hasMany).toHaveLength(0)
})
})
describe('relationship', () => {
@@ -1042,6 +1068,30 @@ describe('Fields', () => {
expect(numbersNotExists.docs).toHaveLength(1)
})
it('should delete rows when updating hasMany with empty array', async () => {
const { id: createdDocId } = await payload.create({
collection: numberFieldsSlug,
data: {
localizedHasMany: [1, 2, 3],
},
})
await payload.update({
collection: numberFieldsSlug,
id: createdDocId,
data: {
localizedHasMany: [],
},
})
const resultingDoc = await payload.findByID({
collection: numberFieldsSlug,
id: createdDocId,
})
expect(resultingDoc.localizedHasMany).toHaveLength(0)
})
})
it('should query hasMany within an array', async () => {