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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -34,6 +34,7 @@ export const findVersions: FindVersions = async function findVersions(
|
||||
return findMany({
|
||||
adapter: this,
|
||||
fields,
|
||||
joins: false,
|
||||
limit,
|
||||
locale,
|
||||
page,
|
||||
|
||||
@@ -49,6 +49,7 @@ export async function updateVersion<T extends TypeWithID>(
|
||||
data: versionData,
|
||||
db,
|
||||
fields,
|
||||
joinQuery: false,
|
||||
operation: 'update',
|
||||
req,
|
||||
select,
|
||||
|
||||
@@ -411,6 +411,8 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
// RETRIEVE NEWLY UPDATED ROW
|
||||
// //////////////////////////////////
|
||||
|
||||
joinQuery = operation === 'create' ? false : joinQuery
|
||||
|
||||
const findManyArgs = buildFindManyArgs({
|
||||
adapter,
|
||||
depth: 0,
|
||||
|
||||
@@ -13,6 +13,12 @@ export const CategoriesVersions: CollectionConfig = {
|
||||
collection: versionsSlug,
|
||||
on: 'categoryVersion',
|
||||
},
|
||||
{
|
||||
name: 'relatedVersionsMany',
|
||||
type: 'join',
|
||||
collection: versionsSlug,
|
||||
on: 'categoryVersions',
|
||||
},
|
||||
],
|
||||
versions: {
|
||||
drafts: true,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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<T extends boolean = true> {
|
||||
export interface VersionsSelect<T extends boolean = true> {
|
||||
category?: T;
|
||||
categoryVersion?: T;
|
||||
categoryVersions?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
_status?: T;
|
||||
@@ -452,6 +459,7 @@ export interface VersionsSelect<T extends boolean = true> {
|
||||
*/
|
||||
export interface CategoriesVersionsSelect<T extends boolean = true> {
|
||||
relatedVersions?: T;
|
||||
relatedVersionsMany?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
_status?: T;
|
||||
|
||||
Reference in New Issue
Block a user