From d499de1e0f8035d28280ed59b8e54f65e83a30de Mon Sep 17 00:00:00 2001 From: Sasha <64744993+r1tsuu@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:42:05 +0200 Subject: [PATCH] fix(db-postgres): joins with versions and hasMany relationship (#9370) Fixes errors when having joins with versions +drafts on `hasMany: true` relationships. Removes `joinQuery` overhead if we don't need it for the current operation. Right now, in all adapters we support joins only for `find`, `findOne`, and `queryDrafts`. Fixes https://github.com/payloadcms/payload/issues/9369 --- packages/drizzle/src/deleteMany.ts | 1 + packages/drizzle/src/deleteOne.ts | 12 ++------ packages/drizzle/src/deleteVersions.ts | 1 + packages/drizzle/src/find/traverseFields.ts | 2 +- packages/drizzle/src/findVersions.ts | 1 + packages/drizzle/src/updateVersion.ts | 1 + packages/drizzle/src/upsertRow/index.ts | 2 ++ test/joins/collections/CategoriesVersions.ts | 6 ++++ test/joins/collections/Versions.ts | 6 ++++ test/joins/int.spec.ts | 31 +++++++++++++++++++- test/joins/payload-types.ts | 8 +++++ 11 files changed, 60 insertions(+), 11 deletions(-) diff --git a/packages/drizzle/src/deleteMany.ts b/packages/drizzle/src/deleteMany.ts index 7d0637fe34..55c878a082 100644 --- a/packages/drizzle/src/deleteMany.ts +++ b/packages/drizzle/src/deleteMany.ts @@ -19,6 +19,7 @@ export const deleteMany: DeleteMany = async function deleteMany( const result = await findMany({ adapter: this, fields: collectionConfig.fields, + joins: false, limit: 0, locale: req.locale, page: 1, diff --git a/packages/drizzle/src/deleteOne.ts b/packages/drizzle/src/deleteOne.ts index ca9e330441..1c3f726a05 100644 --- a/packages/drizzle/src/deleteOne.ts +++ b/packages/drizzle/src/deleteOne.ts @@ -12,13 +12,7 @@ import { transform } from './transform/read/index.js' export const deleteOne: DeleteOne = async function deleteOne( this: DrizzleAdapter, - { - collection: collectionSlug, - joins: joinQuery, - req = {} as PayloadRequest, - select, - where: whereArg, - }, + { collection: collectionSlug, req = {} as PayloadRequest, select, where: whereArg }, ) { const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config @@ -54,7 +48,7 @@ export const deleteOne: DeleteOne = async function deleteOne( adapter: this, depth: 0, fields: collection.fields, - joinQuery, + joinQuery: false, select, tableName, }) @@ -69,7 +63,7 @@ export const deleteOne: DeleteOne = async function deleteOne( config: this.payload.config, data: docToDelete, fields: collection.fields, - joinQuery, + joinQuery: false, }) await this.deleteWhere({ diff --git a/packages/drizzle/src/deleteVersions.ts b/packages/drizzle/src/deleteVersions.ts index 4f1df9f2d8..5bbcc02df1 100644 --- a/packages/drizzle/src/deleteVersions.ts +++ b/packages/drizzle/src/deleteVersions.ts @@ -24,6 +24,7 @@ export const deleteVersions: DeleteVersions = async function deleteVersion( const { docs } = await findMany({ adapter: this, fields, + joins: false, limit: 0, locale, page: 1, diff --git a/packages/drizzle/src/find/traverseFields.ts b/packages/drizzle/src/find/traverseFields.ts index 152a0510fb..10e6b0feb8 100644 --- a/packages/drizzle/src/find/traverseFields.ts +++ b/packages/drizzle/src/find/traverseFields.ts @@ -330,7 +330,6 @@ export const traverseFields = ({ } case 'group': - case 'tab': { const fieldSelect = select?.[field.name] @@ -364,6 +363,7 @@ export const traverseFields = ({ break } + case 'join': { // when `joinsQuery` is false, do not join if (joinQuery === false) { diff --git a/packages/drizzle/src/findVersions.ts b/packages/drizzle/src/findVersions.ts index 3c86547342..93b1807bca 100644 --- a/packages/drizzle/src/findVersions.ts +++ b/packages/drizzle/src/findVersions.ts @@ -34,6 +34,7 @@ export const findVersions: FindVersions = async function findVersions( return findMany({ adapter: this, fields, + joins: false, limit, locale, page, diff --git a/packages/drizzle/src/updateVersion.ts b/packages/drizzle/src/updateVersion.ts index 935623bce9..fbba1197b8 100644 --- a/packages/drizzle/src/updateVersion.ts +++ b/packages/drizzle/src/updateVersion.ts @@ -49,6 +49,7 @@ export async function updateVersion( data: versionData, db, fields, + joinQuery: false, operation: 'update', req, select, diff --git a/packages/drizzle/src/upsertRow/index.ts b/packages/drizzle/src/upsertRow/index.ts index fa09fecc2f..ec9f20e3d1 100644 --- a/packages/drizzle/src/upsertRow/index.ts +++ b/packages/drizzle/src/upsertRow/index.ts @@ -411,6 +411,8 @@ export const upsertRow = async | TypeWithID>( // RETRIEVE NEWLY UPDATED ROW // ////////////////////////////////// + joinQuery = operation === 'create' ? false : joinQuery + const findManyArgs = buildFindManyArgs({ adapter, depth: 0, diff --git a/test/joins/collections/CategoriesVersions.ts b/test/joins/collections/CategoriesVersions.ts index 521cd2b92b..74a150aee7 100644 --- a/test/joins/collections/CategoriesVersions.ts +++ b/test/joins/collections/CategoriesVersions.ts @@ -13,6 +13,12 @@ export const CategoriesVersions: CollectionConfig = { collection: versionsSlug, on: 'categoryVersion', }, + { + name: 'relatedVersionsMany', + type: 'join', + collection: versionsSlug, + on: 'categoryVersions', + }, ], versions: { drafts: true, diff --git a/test/joins/collections/Versions.ts b/test/joins/collections/Versions.ts index 5c1f2d7848..a15a963d3c 100644 --- a/test/joins/collections/Versions.ts +++ b/test/joins/collections/Versions.ts @@ -15,6 +15,12 @@ export const Versions: CollectionConfig = { relationTo: 'categories-versions', type: 'relationship', }, + { + name: 'categoryVersions', + relationTo: 'categories-versions', + type: 'relationship', + hasMany: true, + }, ], versions: { drafts: true, diff --git a/test/joins/int.spec.ts b/test/joins/int.spec.ts index fcf0f40355..33ea1cf737 100644 --- a/test/joins/int.spec.ts +++ b/test/joins/int.spec.ts @@ -480,7 +480,20 @@ describe('Joins Field', () => { expect(res.docs[0].relatedVersions.docs[0].id).toBe(version.id) }) - it('should populate joins when versions on both sides draft true payload.db.queryDrafts', async () => { + it('should populate joins with hasMany relationships when versions on both sides draft false', async () => { + const category = await payload.create({ collection: 'categories-versions', data: {} }) + + const version = await payload.create({ + collection: 'versions', + data: { categoryVersions: [category.id] }, + }) + + const res = await payload.find({ collection: 'categories-versions', draft: false }) + + expect(res.docs[0].relatedVersionsMany.docs[0].id).toBe(version.id) + }) + + it('should populate joins with hasMany relationships when versions on both sides draft true payload.db.queryDrafts', async () => { const category = await payload.create({ collection: 'categories-versions', data: {} }) const version = await payload.create({ @@ -495,6 +508,22 @@ describe('Joins Field', () => { expect(res.docs[0].relatedVersions.docs[0].id).toBe(version.id) }) + + it('should populate joins when versions on both sides draft true payload.db.queryDrafts', async () => { + const category = await payload.create({ collection: 'categories-versions', data: {} }) + + const version = await payload.create({ + collection: 'versions', + data: { categoryVersions: [category.id] }, + }) + + const res = await payload.find({ + collection: 'categories-versions', + draft: true, + }) + + expect(res.docs[0].relatedVersionsMany.docs[0].id).toBe(version.id) + }) }) describe('REST', () => { diff --git a/test/joins/payload-types.ts b/test/joins/payload-types.ts index 7218bad040..9fb1389045 100644 --- a/test/joins/payload-types.ts +++ b/test/joins/payload-types.ts @@ -41,6 +41,7 @@ export interface Config { }; 'categories-versions': { relatedVersions: 'versions'; + relatedVersionsMany: 'versions'; }; 'localized-categories': { relatedPosts: 'localized-posts'; @@ -197,6 +198,7 @@ export interface Version { id: string; category?: (string | null) | Category; categoryVersion?: (string | null) | CategoriesVersion; + categoryVersions?: (string | CategoriesVersion)[] | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -211,6 +213,10 @@ export interface CategoriesVersion { docs?: (string | Version)[] | null; hasNextPage?: boolean | null; } | null; + relatedVersionsMany?: { + docs?: (string | Version)[] | null; + hasNextPage?: boolean | null; + } | null; updatedAt: string; createdAt: string; _status?: ('draft' | 'published') | null; @@ -442,6 +448,7 @@ export interface UploadsSelect { export interface VersionsSelect { category?: T; categoryVersion?: T; + categoryVersions?: T; updatedAt?: T; createdAt?: T; _status?: T; @@ -452,6 +459,7 @@ export interface VersionsSelect { */ export interface CategoriesVersionsSelect { relatedVersions?: T; + relatedVersionsMany?: T; updatedAt?: T; createdAt?: T; _status?: T;