Skip to content

fix(drizzle): preserve both top-level and/or clauses in where queries - #17495

Open
Osamaali313 wants to merge 1 commit into
payloadcms:mainfrom
Osamaali313:fix-drizzle-and-or-clause-drop
Open

fix(drizzle): preserve both top-level and/or clauses in where queries#17495
Osamaali313 wants to merge 1 commit into
payloadcms:mainfrom
Osamaali313:fix-drizzle-and-or-clause-drop

Conversation

@Osamaali313

Copy link
Copy Markdown

What?

In the SQL adapters (@payloadcms/drizzle), a where query that has both a top-level and key and a top-level or key silently drops one of them. Only the clause that happens to be iterated last is applied.

GET /api/posts?where[or][0][status][equals]=published
              &where[or][1][status][equals]=featured
              &where[and][0][views][greater_than]=100
  • Expected: (status = 'published' OR status = 'featured') AND views > 100
  • Actual: views > 100 only — the entire OR (status …) restriction is dropped (reverse the key order and the AND clause is dropped instead), so the query returns rows that should have been filtered out.

Why?

In packages/drizzle/src/queries/parseParams.ts, each top-level and/or key did a bare assignment:

if (builtConditions.length > 0) {
  result = conditionOperator(...builtConditions) // overwrites any previous and/or
}

Field-path constraints accumulate into constraints[] and are ANDed at the end, but the two array-keys overwrite the single result, so the first is lost. The MongoDB adapter (packages/db-mongodb/src/queries/parseParams.ts) stores them under separate $and / $or keys and keeps both — so the same valid query returns different result sets on Postgres/SQLite vs MongoDB.

How?

AND the built groups together instead of overwriting:

const builtCondition = conditionOperator(...builtConditions)
result = result ? and(result, builtCondition) : builtCondition

Single-and and single-or queries produce byte-identical output; only the both-keys case changes (from dropping a clause to keeping both). Nested forms (and: [{ or: [...] }]) were already fine.

Verified with a standalone repro of the loop + end-combine (sibling or+and now keeps both; single-key output unchanged). I did not add an integration test because the where-query suite (test/database/int.spec.ts) runs against live DB adapters and I couldn't run it locally — happy to add one there if you'd like.

Fixes #

parseParams assigned `result` directly for each top-level `and`/`or` key, so
a where object containing both an `and` and an `or` key at the same level kept
only whichever was iterated last, silently dropping the other clause. AND the
built groups together instead (matching how field-path constraints already
combine, and how the MongoDB adapter preserves both keys). Single `and` /
single `or` queries produce identical output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant