fix(db-postgres): querying other collections via relationships inside blocks (#11255)

### What?
Previously, in postgres query like:
```ts
const result = await payload.find({
  collection: 'blocks',
  where: { 'blocks.director.name': { equals: 'Test Director' } },
})
```
where `blocks` is a blocks field, `director` is a relationship field and
`name` is a text field inside `directors`, failed with:

![image](https://github.com/user-attachments/assets/f4b62b69-bd17-4ef0-9f0c-08057e9f2d57)

### Why?
The generated query before was a bit wrong.
Before:
```sql
select distinct
  "blocks"."id",
  "blocks"."created_at",
  "blocks"."created_at"
from
  "blocks"
  left join "directors" "a5ad426a_eda4_4067_af7e_5b294d7f0968" on "a5ad426a_eda4_4067_af7e_5b294d7f0968"."id" = "blocks_blocks_some"."director_id"
   left join "blocks_blocks_some" on "blocks"."id" = "blocks_blocks_some"."_parent_id"
where
  "a5ad426a_eda4_4067_af7e_5b294d7f0968"."name" = 'Test Director'
order by
  "blocks"."created_at" desc
limit
	10
```
Notice `left join directors` _before_ join of `blocks_blocks_some`.
`blocks_blocks_some` doesn't exist yet, this PR changes so now we
generate
```sql
select distinct
  "blocks"."id",
  "blocks"."created_at",
  "blocks"."created_at"
from
  "blocks"
  left join "blocks_blocks_some" on "blocks"."id" = "blocks_blocks_some"."_parent_id"
  left join "directors" "a5ad426a_eda4_4067_af7e_5b294d7f0968" on "a5ad426a_eda4_4067_af7e_5b294d7f0968"."id" = "blocks_blocks_some"."director_id"
where
  "a5ad426a_eda4_4067_af7e_5b294d7f0968"."name" = 'Test Director'
order by
  "blocks"."created_at" desc
limit
	10
```
This commit is contained in:
Sasha
2025-02-18 21:51:17 +02:00
committed by GitHub
parent 06debf5e14
commit 88548fcbe6
4 changed files with 131 additions and 23 deletions

View File

@@ -460,6 +460,27 @@ export default buildConfigWithDefaults({
},
],
},
{
slug: 'blocks',
fields: [
{
type: 'blocks',
name: 'blocks',
blocks: [
{
slug: 'some',
fields: [
{
type: 'relationship',
relationTo: 'directors',
name: 'director',
},
],
},
],
},
],
},
],
onInit: async (payload) => {
await payload.create({

View File

@@ -1130,6 +1130,36 @@ describe('Relationships', () => {
})
})
it('should allow querying within block nesting', async () => {
const director = await payload.create({
collection: 'directors',
data: { name: 'Test Director' },
})
const director_false = await payload.create({
collection: 'directors',
data: { name: 'False Director' },
})
const doc = await payload.create({
collection: 'blocks',
data: { blocks: [{ blockType: 'some', director: director.id }] },
})
await payload.create({
collection: 'blocks',
data: { blocks: [{ blockType: 'some', director: director_false.id }] },
})
const result = await payload.find({
collection: 'blocks',
where: { 'blocks.director.name': { equals: 'Test Director' } },
})
expect(result.totalDocs).toBe(1)
expect(result.docs[0]!.id).toBe(doc.id)
})
describe('Nested Querying Separate Collections', () => {
let director: Director

View File

@@ -86,6 +86,7 @@ export interface Config {
'deep-nested': DeepNested;
relations: Relation1;
items: Item;
blocks: Block;
users: User;
'payload-locked-documents': PayloadLockedDocument;
'payload-preferences': PayloadPreference;
@@ -117,6 +118,7 @@ export interface Config {
'deep-nested': DeepNestedSelect<false> | DeepNestedSelect<true>;
relations: RelationsSelect<false> | RelationsSelect<true>;
items: ItemsSelect<false> | ItemsSelect<true>;
blocks: BlocksSelect<false> | BlocksSelect<true>;
users: UsersSelect<false> | UsersSelect<true>;
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
@@ -464,6 +466,23 @@ export interface Item {
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blocks".
*/
export interface Block {
id: string;
blocks?:
| {
director?: (string | null) | Director;
id?: string | null;
blockName?: string | null;
blockType: 'some';
}[]
| null;
updatedAt: string;
createdAt: string;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "payload-locked-documents".
@@ -551,6 +570,10 @@ export interface PayloadLockedDocument {
relationTo: 'items';
value: string | Item;
} | null)
| ({
relationTo: 'blocks';
value: string | Block;
} | null)
| ({
relationTo: 'users';
value: string | User;
@@ -840,6 +863,25 @@ export interface ItemsSelect<T extends boolean = true> {
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "blocks_select".
*/
export interface BlocksSelect<T extends boolean = true> {
blocks?:
| T
| {
some?:
| T
| {
director?: T;
id?: T;
blockName?: T;
};
};
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "users_select".