fix(drizzle): ignore empty in/not_in operands instead of passing them to typed columns - #17839
Open
creativoma wants to merge 1 commit into
Open
fix(drizzle): ignore empty in/not_in operands instead of passing them to typed columns#17839creativoma wants to merge 1 commit into
creativoma wants to merge 1 commit into
Conversation
… to typed columns `in`/`not_in` operands were only coerced when the value arrived as a comma-delineated string. An indexed query string is parsed into an array instead, so the coercion was skipped and an operand that cannot be cast to the column's type reached the driver as-is. Payload's own relationship field sends `?where[id][not_in][0]=` when nothing is selected yet, which bound an empty string to the id column and failed with `invalid input syntax for type integer: ""` (or `for type uuid: ""`). An operand that cannot be cast to the column type can never match a row, so dropping it leaves the result set unchanged; drizzle compiles an empty `in` to `false` and an empty `not in` to `true`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
sanitizeQueryValueonly coercedin/not_in/alloperands when the incoming value was a comma-delineated string. When the same value arrives as an array — which is what an indexed query string produces — the coercion was skipped entirely, so an operand that cannot be cast to the column's type reached the driver as-is.This moves the existing numeric coercion below the array normalisation so it applies in both cases, drops operands that are not numbers, and adds the equivalent for
uuidid columns.Why?
Payload's own relationship field asks for its options with the already-selected ids excluded, and it still sends the parameter when nothing is selected yet:
qsparses that intonot_in: ['']. Because the value is an array, no coercion ran, and the empty string was bound straight to the id column:The endpoint 500s and the field spins on "Loading…" with nothing surfaced to the user. On a
uuidadapter the same query fails withinvalid input syntax for type uuid: "". Every collection is affected, not only the one where we hit it.Where it actually shows up is an install whose
userstable is empty while the data to select already exists — thecreate-first-userscreen — because that is when nothing is selected yet. Local development rarely reproduces it, since those databases already have users.Related issues:
where[...][id][not_equals]=. It was closed by removing the empty parameter at that one call site rather than in the adapter, which is why this variant still reproduces.NaNsibling of the same problem. Not addressed in general here, but'5,,6'no longer produces[5, NaN, 6].How?
The coercion moved below the
Array.isArraynormalisation and gained a filter:Dropping the operand is semantics-preserving rather than lenient: a value that cannot be cast to the column's type can never equal any row, so removing it leaves the result set identical for both operators. Filtering down to an empty list stays correct as well — drizzle compiles
inArray(col, [])tofalse(matches nothing) andnotInArray(col, [])totrue(excludes nothing), which is exactly what anin/not_inof nothing means.isUUIDis only true when the column really is aPgUUID, so the uuid filter cannot narrow a plain text id column.Tests
packages/drizzle/src/queries/sanitizeQueryValue.spec.ts— new unit spec covering both id types, including that valid operands are left untouched.test/database/int.spec.ts— one integration test underdescribe('id type'), tagged{ db: 'drizzle' }. It asserts the semantics rather than just the absence of a throw:not_in: ['']excludes nothing,in: ['']matches nothing.Without this change that integration test fails with the driver error above:
invalid input syntax for type integer: ""onpostgres, andinvalid input syntax for type uuid: ""onpostgres-uuid.Verified locally:
test:unit,test:types,build:core, and thedatabaseint suite onpostgres,postgres-uuidandsqlite.This targets
main(v4). The3.xbranch carries the identical block, so the fix applies there unchanged if you would like a backport.