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

@@ -220,6 +220,37 @@ export const getTableColumnFromPath = ({
let result: TableColumn
const blockConstraints = []
const blockSelectFields = {}
let blockJoin: BuildQueryJoinAliases[0]
if (isFieldLocalized && adapter.payload.config.localization) {
const conditions = [
eq(
(aliasTable || adapter.tables[tableName]).id,
adapter.tables[newTableName]._parentID,
),
]
if (locale !== 'all') {
conditions.push(eq(adapter.tables[newTableName]._locale, locale))
}
blockJoin = {
condition: and(...conditions),
table: adapter.tables[newTableName],
}
} else {
blockJoin = {
condition: eq(
(aliasTable || adapter.tables[tableName]).id,
adapter.tables[newTableName]._parentID,
),
table: adapter.tables[newTableName],
}
}
// Create a new reference for nested joins
const newJoins = [...joins]
try {
result = getTableColumnFromPath({
adapter,
@@ -227,7 +258,7 @@ export const getTableColumnFromPath = ({
constraintPath,
constraints: blockConstraints,
fields: block.flattenedFields,
joins,
joins: newJoins,
locale,
parentIsLocalized: parentIsLocalized || field.localized,
pathSegments: pathSegments.slice(1),
@@ -246,30 +277,14 @@ export const getTableColumnFromPath = ({
blockTableColumn = result
constraints = constraints.concat(blockConstraints)
selectFields = { ...selectFields, ...blockSelectFields }
if (isFieldLocalized && adapter.payload.config.localization) {
const conditions = [
eq(
(aliasTable || adapter.tables[tableName]).id,
adapter.tables[newTableName]._parentID,
),
]
if (locale !== 'all') {
conditions.push(eq(adapter.tables[newTableName]._locale, locale))
const previousLength = joins.length
joins.push(blockJoin)
// Append new joins AFTER the block join to prevent errors with missing FROM clause.
if (newJoins.length > previousLength) {
for (let i = previousLength; i < newJoins.length; i++) {
joins.push(newJoins[i])
}
joins.push({
condition: and(...conditions),
table: adapter.tables[newTableName],
})
} else {
joins.push({
condition: eq(
(aliasTable || adapter.tables[tableName]).id,
adapter.tables[newTableName]._parentID,
),
table: adapter.tables[newTableName],
})
}
return true
})