From eee64327156f8858bae1f784534a0f635bcb93eb Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Thu, 19 Dec 2024 05:26:08 +0200 Subject: [PATCH] fix(db-postgres): query has many relationships nested in row fields (#9944) (#9944) ### What? Querying by nested to rows fields in has many relationships like this: ```ts const result = await payload.find({ collection: 'relationship-fields', where: { 'relationToRowMany.title': { equals: 'some-title' }, }, }) ``` Where the related collection: ```ts const RowFields: CollectionConfig = { slug: rowFieldsSlug, fields: [ { type: 'row', fields: [ { name: 'title', label: 'Title within a row', type: 'text', required: true, }, ], }, ], } ``` was broken ### Why? We migrated to use `flattenedFields`, but not in this specific case. This error would be caught earlier we used `noImplictAny` typescript rule. https://www.typescriptlang.org/tsconfig/#noImplicitAny which wouldn't allow us to create variable like this: ```ts let relationshipFields // relationshipFields is any here ``` Instead, we should write: ```ts let relationshipFields: FlattenedField[] ``` We should migrate to it and `strictNullChecks` as well. Fixes https://github.com/payloadcms/payload/issues/9534 --- .../src/queries/getTableColumnFromPath.ts | 4 +-- test/fields/collections/Relationship/index.ts | 11 +++++++ test/fields/int.spec.ts | 31 +++++++++++++++++++ test/fields/payload-types.ts | 4 +++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/packages/drizzle/src/queries/getTableColumnFromPath.ts b/packages/drizzle/src/queries/getTableColumnFromPath.ts index 676f5dd47e..edcede204a 100644 --- a/packages/drizzle/src/queries/getTableColumnFromPath.ts +++ b/packages/drizzle/src/queries/getTableColumnFromPath.ts @@ -358,7 +358,7 @@ export const getTableColumnFromPath = ({ const newCollectionPath = pathSegments.slice(1).join('.') if (Array.isArray(field.relationTo) || field.hasMany) { - let relationshipFields + let relationshipFields: FlattenedField[] const relationTableName = `${rootTableName}${adapter.relationshipsSuffix}` const { newAliasTable: aliasRelationshipTable, @@ -405,7 +405,7 @@ export const getTableColumnFromPath = ({ newTableName = adapter.tableNameMap.get(toSnakeCase(relationshipConfig.slug)) // parent to relationship join table - relationshipFields = relationshipConfig.fields + relationshipFields = relationshipConfig.flattenedFields ;({ newAliasTable } = getTableAlias({ adapter, tableName: newTableName })) joins.push({ diff --git a/test/fields/collections/Relationship/index.ts b/test/fields/collections/Relationship/index.ts index 8db4b1559b..ee2ee915fa 100644 --- a/test/fields/collections/Relationship/index.ts +++ b/test/fields/collections/Relationship/index.ts @@ -115,6 +115,17 @@ const RelationshipFields: CollectionConfig = { minRows: 2, type: 'relationship', }, + { + name: 'relationToRow', + relationTo: 'row-fields', + type: 'relationship', + }, + { + name: 'relationToRowMany', + relationTo: 'row-fields', + type: 'relationship', + hasMany: true, + }, ], slug: relationshipFieldsSlug, } diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts index b2fedd3656..8aaa086bf8 100644 --- a/test/fields/int.spec.ts +++ b/test/fields/int.spec.ts @@ -453,6 +453,37 @@ describe('Fields', () => { expect(result.docs).toHaveLength(1) expect(result.docs[0]).toMatchObject(relationshipInArray) }) + + it('should query text in row after relationship', async () => { + const row = await payload.create({ + collection: 'row-fields', + data: { title: 'some-title', id: 'custom-row-id' }, + }) + const textDoc = await payload.create({ + collection: 'text-fields', + data: { text: 'asd' }, + }) + + const rel = await payload.create({ + collection: 'relationship-fields', + data: { + relationship: { relationTo: 'text-fields', value: textDoc }, + relationToRow: row.id, + relationToRowMany: [row.id], + }, + }) + + const result = await payload.find({ + collection: 'relationship-fields', + where: { + 'relationToRow.title': { equals: 'some-title' }, + 'relationToRowMany.title': { equals: 'some-title' }, + }, + }) + + expect(result.docs[0].id).toBe(rel.id) + expect(result.totalDocs).toBe(1) + }) }) describe('timestamps', () => { diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index e169f7f34d..352cc72fc0 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -1335,6 +1335,8 @@ export interface RelationshipField { value: string | TextField; }[] | null; + relationToRow?: (string | null) | RowField; + relationToRowMany?: (string | RowField)[] | null; updatedAt: string; createdAt: string; } @@ -2970,6 +2972,8 @@ export interface RelationshipFieldsSelect { id?: T; }; relationshipWithMinRows?: T; + relationToRow?: T; + relationToRowMany?: T; updatedAt?: T; createdAt?: T; }