Skip to content

Commit 09782be

Browse files
authored
fix(db-postgres): long array field table aliases cause error even when dbName is used (#11995)
Fixes #11975 Previously, this configuration was causing errors in postgres due to long names, even though `dbName` is used: ``` { slug: 'aliases', fields: [ { name: 'thisIsALongFieldNameThatWillCauseAPostgresErrorEvenThoughWeSetAShorterDBName', dbName: 'shortname', type: 'array', fields: [ { name: 'nested_field_1', type: 'array', dbName: 'short_nested_1', fields: [], }, { name: 'nested_field_2', type: 'text', }, ], }, ], }, ``` This is because we were generating Drizzle relation name (for arrays) always based on the field path and internally, drizzle uses this name for aliasing. Now, if `dbName` is present, we use `_{dbName}` instead for the relation name.
1 parent b270901 commit 09782be

File tree

10 files changed

+144
-3
lines changed

10 files changed

+144
-3
lines changed

packages/drizzle/src/deleteOne.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const deleteOne: DeleteOne = async function deleteOne(
7272
data: docToDelete,
7373
fields: collection.flattenedFields,
7474
joinQuery: false,
75+
tableName,
7576
})
7677

7778
await this.deleteWhere({

packages/drizzle/src/find/findMany.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export const findMany = async function find({
158158
data,
159159
fields,
160160
joinQuery,
161+
tableName,
161162
})
162163
})
163164

packages/drizzle/src/find/traverseFields.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ export const traverseFields = ({
196196
}
197197
}
198198

199-
currentArgs.with[`${path}${field.name}`] = withArray
199+
const relationName = field.dbName ? `_${arrayTableName}` : `${path}${field.name}`
200+
currentArgs.with[relationName] = withArray
200201

201202
traverseFields({
202203
_locales: withArray.with._locales,

packages/drizzle/src/schema/traverseFields.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { CompoundIndex, FlattenedField } from 'payload'
22

33
import { InvalidConfiguration } from 'payload'
44
import {
5+
array,
56
fieldAffectsData,
67
fieldIsVirtual,
78
fieldShouldBeLocalized,
@@ -287,7 +288,9 @@ export const traverseFields = ({
287288
}
288289
}
289290

290-
relationsToBuild.set(fieldName, {
291+
const relationName = field.dbName ? `_${arrayTableName}` : fieldName
292+
293+
relationsToBuild.set(relationName, {
291294
type: 'many',
292295
// arrays have their own localized table, independent of the base table.
293296
localized: false,
@@ -304,7 +307,7 @@ export const traverseFields = ({
304307
},
305308
],
306309
references: ['id'],
307-
relationName: fieldName,
310+
relationName,
308311
to: parentTableName,
309312
},
310313
}

packages/drizzle/src/transform/read/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type TransformArgs = {
1515
joinQuery?: JoinQuery
1616
locale?: string
1717
parentIsLocalized?: boolean
18+
tableName: string
1819
}
1920

2021
// This is the entry point to transform Drizzle output data
@@ -26,6 +27,7 @@ export const transform = <T extends Record<string, unknown> | TypeWithID>({
2627
fields,
2728
joinQuery,
2829
parentIsLocalized,
30+
tableName,
2931
}: TransformArgs): T => {
3032
let relationships: Record<string, Record<string, unknown>[]> = {}
3133
let texts: Record<string, Record<string, unknown>[]> = {}
@@ -53,6 +55,7 @@ export const transform = <T extends Record<string, unknown> | TypeWithID>({
5355
adapter,
5456
blocks,
5557
config,
58+
currentTableName: tableName,
5659
dataRef: {
5760
id: data.id,
5861
},
@@ -65,7 +68,9 @@ export const transform = <T extends Record<string, unknown> | TypeWithID>({
6568
path: '',
6669
relationships,
6770
table: data,
71+
tablePath: '',
6872
texts,
73+
topLevelTableName: tableName,
6974
})
7075

7176
deletions.forEach((deletion) => deletion())

packages/drizzle/src/transform/read/traverseFields.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { FlattenedBlock, FlattenedField, JoinQuery, SanitizedConfig } from 'payload'
22

33
import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'
4+
import toSnakeCase from 'to-snake-case'
45

56
import type { DrizzleAdapter } from '../../types.js'
67
import type { BlocksMap } from '../../utilities/createBlocksMap.js'
@@ -22,6 +23,7 @@ type TraverseFieldsArgs = {
2223
* The full Payload config
2324
*/
2425
config: SanitizedConfig
26+
currentTableName: string
2527
/**
2628
* The data reference to be mutated within this recursive function
2729
*/
@@ -59,10 +61,12 @@ type TraverseFieldsArgs = {
5961
* Data structure representing the nearest table from db
6062
*/
6163
table: Record<string, unknown>
64+
tablePath: string
6265
/**
6366
* All hasMany text fields, as returned by Drizzle, keyed on an object by field path
6467
*/
6568
texts: Record<string, Record<string, unknown>[]>
69+
topLevelTableName: string
6670
/**
6771
* Set to a locale if this group of fields is within a localized array or block.
6872
*/
@@ -75,6 +79,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
7579
adapter,
7680
blocks,
7781
config,
82+
currentTableName,
7883
dataRef,
7984
deletions,
8085
fieldPrefix,
@@ -85,7 +90,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
8590
path,
8691
relationships,
8792
table,
93+
tablePath,
8894
texts,
95+
topLevelTableName,
8996
withinArrayOrBlockLocale,
9097
}: TraverseFieldsArgs): T => {
9198
const sanitizedPath = path ? `${path}.` : path
@@ -110,6 +117,14 @@ export const traverseFields = <T extends Record<string, unknown>>({
110117
const isLocalized = fieldShouldBeLocalized({ field, parentIsLocalized })
111118

112119
if (field.type === 'array') {
120+
const arrayTableName = adapter.tableNameMap.get(
121+
`${currentTableName}_${tablePath}${toSnakeCase(field.name)}`,
122+
)
123+
124+
if (field.dbName) {
125+
fieldData = table[`_${arrayTableName}`]
126+
}
127+
113128
if (Array.isArray(fieldData)) {
114129
if (isLocalized) {
115130
result[field.name] = fieldData.reduce((arrayResult, row) => {
@@ -129,6 +144,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
129144
adapter,
130145
blocks,
131146
config,
147+
currentTableName: arrayTableName,
132148
dataRef: data,
133149
deletions,
134150
fieldPrefix: '',
@@ -138,7 +154,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
138154
path: `${sanitizedPath}${field.name}.${row._order - 1}`,
139155
relationships,
140156
table: row,
157+
tablePath: '',
141158
texts,
159+
topLevelTableName,
142160
withinArrayOrBlockLocale: locale,
143161
})
144162

@@ -175,6 +193,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
175193
adapter,
176194
blocks,
177195
config,
196+
currentTableName: arrayTableName,
178197
dataRef: row,
179198
deletions,
180199
fieldPrefix: '',
@@ -184,7 +203,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
184203
path: `${sanitizedPath}${field.name}.${i}`,
185204
relationships,
186205
table: row,
206+
tablePath: '',
187207
texts,
208+
topLevelTableName,
188209
withinArrayOrBlockLocale,
189210
}),
190211
)
@@ -228,11 +249,16 @@ export const traverseFields = <T extends Record<string, unknown>>({
228249
(block) => typeof block !== 'string' && block.slug === row.blockType,
229250
) as FlattenedBlock | undefined)
230251

252+
const tableName = adapter.tableNameMap.get(
253+
`${topLevelTableName}_blocks_${toSnakeCase(block.slug)}`,
254+
)
255+
231256
if (block) {
232257
const blockResult = traverseFields<T>({
233258
adapter,
234259
blocks,
235260
config,
261+
currentTableName: tableName,
236262
dataRef: row,
237263
deletions,
238264
fieldPrefix: '',
@@ -242,7 +268,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
242268
path: `${blockFieldPath}.${row._order - 1}`,
243269
relationships,
244270
table: row,
271+
tablePath: '',
245272
texts,
273+
topLevelTableName,
246274
withinArrayOrBlockLocale: locale,
247275
})
248276

@@ -300,11 +328,16 @@ export const traverseFields = <T extends Record<string, unknown>>({
300328
delete row._index
301329
}
302330

331+
const tableName = adapter.tableNameMap.get(
332+
`${topLevelTableName}_blocks_${toSnakeCase(block.slug)}`,
333+
)
334+
303335
acc.push(
304336
traverseFields<T>({
305337
adapter,
306338
blocks,
307339
config,
340+
currentTableName: tableName,
308341
dataRef: row,
309342
deletions,
310343
fieldPrefix: '',
@@ -314,7 +347,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
314347
path: `${blockFieldPath}.${i}`,
315348
relationships,
316349
table: row,
350+
tablePath: '',
317351
texts,
352+
topLevelTableName,
318353
withinArrayOrBlockLocale,
319354
}),
320355
)
@@ -614,6 +649,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
614649
adapter,
615650
blocks,
616651
config,
652+
currentTableName,
617653
dataRef: groupData as Record<string, unknown>,
618654
deletions,
619655
fieldPrefix: groupFieldPrefix,
@@ -624,7 +660,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
624660
path: `${sanitizedPath}${field.name}`,
625661
relationships,
626662
table,
663+
tablePath: `${tablePath}${toSnakeCase(field.name)}_`,
627664
texts,
665+
topLevelTableName,
628666
withinArrayOrBlockLocale: locale || withinArrayOrBlockLocale,
629667
})
630668

packages/drizzle/src/upsertRow/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
467467
data: doc,
468468
fields,
469469
joinQuery: false,
470+
tableName,
470471
})
471472

472473
return result

test/database/config.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,29 @@ export default buildConfigWithDefaults({
604604
},
605605
],
606606
},
607+
{
608+
slug: 'aliases',
609+
fields: [
610+
{
611+
name: 'thisIsALongFieldNameThatCanCauseAPostgresErrorEvenThoughWeSetAShorterDBName',
612+
dbName: 'shortname',
613+
type: 'array',
614+
fields: [
615+
{
616+
name: 'nestedArray',
617+
type: 'array',
618+
dbName: 'short_nested_1',
619+
fields: [
620+
{
621+
type: 'text',
622+
name: 'text',
623+
},
624+
],
625+
},
626+
],
627+
},
628+
],
629+
},
607630
],
608631
globals: [
609632
{

test/database/int.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
killTransaction,
2222
QueryError,
2323
} from 'payload'
24+
import { assert } from 'ts-essentials'
2425
import { fileURLToPath } from 'url'
2526

2627
import type { Global2 } from './payload-types.js'
@@ -783,6 +784,28 @@ describe('database', () => {
783784
expect(doc.blocks[0].text).toStrictEqual('hello')
784785
expect(doc.blocks[0].localizedText).toStrictEqual('goodbye')
785786
})
787+
788+
it('arrays should work with both long field names and dbName', async () => {
789+
const { id } = await payload.create({
790+
collection: 'aliases',
791+
data: {
792+
thisIsALongFieldNameThatCanCauseAPostgresErrorEvenThoughWeSetAShorterDBName: [
793+
{
794+
nestedArray: [{ text: 'some-text' }],
795+
},
796+
],
797+
},
798+
})
799+
const res = await payload.findByID({ collection: 'aliases', id })
800+
expect(
801+
res.thisIsALongFieldNameThatCanCauseAPostgresErrorEvenThoughWeSetAShorterDBName,
802+
).toHaveLength(1)
803+
const item =
804+
res.thisIsALongFieldNameThatCanCauseAPostgresErrorEvenThoughWeSetAShorterDBName?.[0]
805+
assert(item)
806+
expect(item.nestedArray).toHaveLength(1)
807+
expect(item.nestedArray?.[0]?.text).toBe('some-text')
808+
})
786809
})
787810

788811
describe('transactions', () => {

0 commit comments

Comments
 (0)