Let a null carry no type so postgres infers it #148
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "pg-null-type"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
wire: let a null carry no type so postgres infers it
Val::NullboundNone::<i64>, so sqlx declared that parameterint8in the Parse message. Postgres caches the prepared statement with those
types, so the first row to leave a column null fixed it as
int8forevery later execution — and the next row that supplied text sent four
bytes where eight were declared:
A null now binds a
Voidthat produces OID zero, which leaves the typeunspecified and lets Postgres infer it from the target column. The first
prepare then reads the type off the schema rather than off whichever row
happened to arrive first.
Sqlite is untouched: it declares no parameter types, so its null binding
was never able to poison a column.
The binding is as old as the adapter. What changed is that 0.10 writes
the manifest as rows, so
@field.serial— null for most fields, text fora scoped serial — puts the poisoning sequence directly in the boot path.
Two tests pin both halves:
scopedcovers bootstrap with a serial field,sparecovers an ordinary model whose optional field is absent in thefirst row and present in the second. Both failed before this.
release: advance keel to 0.10.1
The pg null binding fix, with its changelog in en and zh. Nothing is asked
of a caller: the public surface is unchanged and the estate format stays
at eleven.
`Val::Null` bound `None::<i64>`, so sqlx declared that parameter `int8` in the Parse message. Postgres caches the prepared statement with those types, so the first row to leave a column null fixed it as `int8` for every later execution — and the next row that supplied text sent four bytes where eight were declared: INSERT INTO "@unit_@field" (...) VALUES ($1..$14) ERROR: insufficient data left in message CONTEXT: unnamed portal parameter $6 A null now binds a `Void` that produces OID zero, which leaves the type unspecified and lets Postgres infer it from the target column. The first prepare then reads the type off the schema rather than off whichever row happened to arrive first. Sqlite is untouched: it declares no parameter types, so its null binding was never able to poison a column. The binding is as old as the adapter. What changed is that 0.10 writes the manifest as rows, so `@field.serial` — null for most fields, text for a scoped serial — puts the poisoning sequence directly in the boot path. Two tests pin both halves: `scoped` covers bootstrap with a serial field, `spare` covers an ordinary model whose optional field is absent in the first row and present in the second. Both failed before this.