Skip to content

Commit

Permalink
fix(db-postgres): querying on array within a relationship field (#8153)
Browse files Browse the repository at this point in the history
## Description

Fixes #6037
2.0 port of #8152

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

<!-- Please delete options that are not relevant. -->

- [x] Bug fix (non-breaking change which fixes an issue)
## Checklist:

- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] Existing test suite passes locally with my changes
  • Loading branch information
r1tsuu authored Sep 10, 2024
1 parent cfb5658 commit 170ea5b
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 45 deletions.
9 changes: 4 additions & 5 deletions packages/db-postgres/src/queries/getTableColumnFromPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,12 @@ export const getTableColumnFromPath = ({
`${tableName}_${tableNameSuffix}${toSnakeCase(field.name)}`,
)

const arrayParentTable = aliasTable || adapter.tables[tableName]

constraintPath = `${constraintPath}${field.name}.%.`
if (locale && field.localized && adapter.payload.config.localization) {
joins[newTableName] = and(
eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID),
eq(arrayParentTable.id, adapter.tables[newTableName]._parentID),
eq(adapter.tables[newTableName]._locale, locale),
)
if (locale !== 'all') {
Expand All @@ -312,10 +314,7 @@ export const getTableColumnFromPath = ({
})
}
} else {
joins[newTableName] = eq(
adapter.tables[tableName].id,
adapter.tables[newTableName]._parentID,
)
joins[newTableName] = eq(arrayParentTable.id, adapter.tables[newTableName]._parentID)
}
return getTableColumnFromPath({
adapter,
Expand Down
25 changes: 25 additions & 0 deletions test/relationships/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,31 @@ export default buildConfigWithDefaults({
},
],
},
{
slug: 'pages',
fields: [
{
type: 'array',
name: 'menu',
fields: [
{
name: 'label',
type: 'text',
},
],
},
],
},
{
slug: 'rels-to-pages',
fields: [
{
name: 'page',
type: 'relationship',
relationTo: 'pages',
},
],
},
],
onInit: async (payload) => {
await payload.create({
Expand Down
31 changes: 31 additions & 0 deletions test/relationships/int.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,37 @@ describe('Relationships', () => {
expect(query.docs).toHaveLength(1)
expect(query.docs[0].id).toStrictEqual(firstLevelID)
})

it('should allow querying within array nesting', async () => {
const page = await payload.create({
collection: 'pages',
data: {
menu: [
{
label: 'hello',
},
],
},
})

const rel = await payload.create({ collection: 'rels-to-pages', data: { page: page.id } })

const resEquals = await payload.find({
collection: 'rels-to-pages',
where: { 'page.menu.label': { equals: 'hello' } },
})

expect(resEquals.totalDocs).toBe(1)
expect(resEquals.docs[0].id).toBe(rel.id)

const resIn = await payload.find({
collection: 'rels-to-pages',
where: { 'page.menu.label': { in: ['hello'] } },
})

expect(resIn.totalDocs).toBe(1)
expect(resIn.docs[0].id).toBe(rel.id)
})
})

describe('Nested Querying Separate Collections', () => {
Expand Down
233 changes: 193 additions & 40 deletions test/relationships/payload-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* tslint:disable */
/* eslint-disable */
/**
* This file was automatically generated by Payload.
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
Expand All @@ -8,103 +9,255 @@
export interface Config {
collections: {
posts: Post
relation: Relation
postsLocalized: PostsLocalized
relation: Relation
'strict-access': StrictAccess
'chained-relation': ChainedRelation
'custom-id-relation': CustomIdRelation
'custom-id-number-relation': CustomIdNumberRelation
chained: Chained
'custom-id': CustomId
'custom-id-number': CustomIdNumber
screenings: Screening
movies: Movie
directors: Director
movieReviews: MovieReview
'polymorphic-relationships': PolymorphicRelationship
tree: Tree
pages: Page
'rels-to-pages': RelsToPage
users: User
'payload-preferences': PayloadPreference
'payload-migrations': PayloadMigration
}
globals: {}
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "posts".
*/
export interface Post {
id: string
title?: string
description?: string
number?: number
relationField?: string | Relation
defaultAccessRelation?: string | StrictAccess
chainedRelation?: string | ChainedRelation
maxDepthRelation?: string | Relation
customIdRelation?: string | CustomIdRelation
customIdNumberRelation?: number | CustomIdNumberRelation
filteredRelation?: string | Relation
updatedAt: string
createdAt: string
}
export interface PostsLocalized {
id: string
title?: string | null
description?: string | null
number?: number | null
relationField?: (string | null) | Relation
defaultAccessRelation?: (string | null) | StrictAccess
chainedRelation?: (string | null) | Chained
maxDepthRelation?: (string | null) | Relation
customIdRelation?: (string | null) | CustomId
customIdNumberRelation?: (number | null) | CustomIdNumber
filteredRelation?: (string | null) | Relation
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "relation".
*/
export interface Relation {
id: string
name?: string
name?: string | null
disableRelation: boolean
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "strict-access".
*/
export interface StrictAccess {
id: string
name?: string
name?: string | null
disableRelation: boolean
updatedAt: string
createdAt: string
}
export interface ChainedRelation {
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "chained".
*/
export interface Chained {
id: string
name?: string
relation?: string | ChainedRelation
name?: string | null
relation?: (string | null) | Chained
updatedAt: string
createdAt: string
}
export interface CustomIdRelation {
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "custom-id".
*/
export interface CustomId {
id: string
name?: string
name?: string | null
updatedAt: string
createdAt: string
}
export interface CustomIdNumberRelation {
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "custom-id-number".
*/
export interface CustomIdNumber {
id: number
name?: string
name?: string | null
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "postsLocalized".
*/
export interface PostsLocalized {
id: string
title?: string | null
relationField?: (string | null) | Relation
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "screenings".
*/
export interface Screening {
id: string
name?: string
movie?: string | Movie
name?: string | null
movie?: (string | null) | Movie
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "movies".
*/
export interface Movie {
id: string
name?: string
director?: string | Director
name?: string | null
director?: (string | null) | Director
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "directors".
*/
export interface Director {
id: string
name?: string
movies?: Array<string | Movie>
name?: string | null
movies?: (string | Movie)[] | null
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "movieReviews".
*/
export interface MovieReview {
id: string
movieReviewer: string | User
likes?: (string | User)[] | null
visibility: 'followers' | 'public'
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users".
*/
export interface User {
id: string
updatedAt: string
createdAt: string
email?: string
resetPasswordToken?: string
resetPasswordExpiration?: string
loginAttempts?: number
lockUntil?: string
password?: string
email: string
resetPasswordToken?: string | null
resetPasswordExpiration?: string | null
salt?: string | null
hash?: string | null
loginAttempts?: number | null
lockUntil?: string | null
password: string | null
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "polymorphic-relationships".
*/
export interface PolymorphicRelationship {
id: string
polymorphic?: {
relationTo: 'movies'
value: string | Movie
} | null
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "tree".
*/
export interface Tree {
id: string
text?: string | null
parent?: (string | null) | Tree
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "pages".
*/
export interface Page {
id: string
menu?:
| {
label?: string | null
id?: string | null
}[]
| null
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "rels-to-pages".
*/
export interface RelsToPage {
id: string
page?: (string | null) | Page
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: string
user: {
relationTo: 'users'
value: string | User
}
key?: string | null
value?:
| {
[k: string]: unknown
}
| unknown[]
| string
| number
| boolean
| null
updatedAt: string
createdAt: string
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: string
name?: string | null
batch?: number | null
updatedAt: string
createdAt: string
}

declare module 'payload' {
export interface GeneratedTypes extends Config {}
}

0 comments on commit 170ea5b

Please sign in to comment.