Fix ON CONFLICT placeholder numbering when inserting multiple rows - #6
Merged
Merged
Conversation
CreateManyOperation numbered the placeholders after ON CONFLICT incorrectly.
For example, the added spec generated:
INSERT INTO users ("email", "name") VALUES ($1, $2), ($3, $4) ON CONFLICT (email) DO UPDATE SET name = $3
which is incorrect and fails with "bind message supplies 5 parameters, but prepared statement requires 4".
Fixed version:
INSERT INTO users ("email", "name") VALUES ($1, $2), ($3, $4) ON CONFLICT (email) DO UPDATE SET name = $5
mloughran
added a commit
to concentric-health/interro
that referenced
this pull request
Aug 26, 2026
A conflict handler was told where to start numbering: each INSERT counted the placeholders its VALUES lists had emitted, appended the handler's values to the args array itself, and passed the total as `start_at`. For a multi-row insert that count was rows × columns, which is what jgaskins#6 fixed. The handler now appends its own values to the shared args array as it renders, so its placeholder numbers are simply the positions they land at, and nobody has to know how many came before. That deletes `start_at`, both create operations' computation of it, and the `Action#params` hook that only existed so they could collect those values ahead of rendering. This was the last placeholder numbering done independently of the args array: every write path, like every read path before it, now builds SQL and args in one pass.
mloughran
added a commit
to concentric-health/interro
that referenced
this pull request
Aug 26, 2026
A conflict handler was told where to start numbering: each INSERT counted the placeholders its VALUES lists had emitted, appended the handler's values to the args array itself, and passed the total as `start_at`. For a multi-row insert that count was rows × columns, which is what jgaskins#6 fixed. The handler now appends its own values to the shared args array as it renders, so its placeholder numbers are simply the positions they land at, and nobody has to know how many came before. That deletes `start_at`, both create operations' computation of it, and the `Action#params` hook that only existed so they could collect those values ahead of rendering. This was the last placeholder numbering done independently of the args array: every write path, like every read path before it, now builds SQL and args in one pass.
mloughran
added a commit
to concentric-health/interro
that referenced
this pull request
Sep 21, 2026
A conflict handler was told where to start numbering: each INSERT counted the placeholders its VALUES lists had emitted, appended the handler's values to the args array itself, and passed the total as `start_at`. For a multi-row insert that count was rows × columns, which is what jgaskins#6 fixed. The handler now appends its own values to the shared args array as it renders, so its placeholder numbers are simply the positions they land at, and nobody has to know how many came before. That deletes `start_at`, both create operations' computation of it, and the `Action#params` hook that only existed so they could collect those values ahead of rendering. This was the last placeholder numbering done independently of the args array: every write path, like every read path before it, now builds SQL and args in one pass.
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.
CreateManyOperationnumbered the placeholders afterON CONFLICTincorrectly.For example, the added spec generated:
which is incorrect and fails with "bind message supplies 5 parameters, but prepared statement requires 4".
Fixed version: