Skip to content

Add condition: and set_override: to BulkUpdate, expose #sql#5

Merged
senid231 merged 2 commits into
masterfrom
bulk-update-condition-and-set-override
Jul 23, 2026
Merged

Add condition: and set_override: to BulkUpdate, expose #sql#5
senid231 merged 2 commits into
masterfrom
bulk-update-condition-and-set-override

Conversation

@senid231

@senid231 senid231 commented Jul 23, 2026

Copy link
Copy Markdown
Member

condition: is a raw-SQL predicate ANDed onto the key match, so a payload is applied only to rows still in the state the caller expects. set_override: maps a column to a raw-SQL expression replacing its default col = v.col assignment; a key absent from attrs_list appends an assignment of its own, letting a column be written purely from SQL. Both fragments are interpolated verbatim and must qualify their column references with t. or v. — the two aliases expose the same column names, so an unqualified reference is ambiguous.

Validated before any SQL runs: a blank condition, a set_override naming an unknown or unique_by column, and a blank override expression all raise ArgumentError. Rows carrying only unique_by columns no longer raise when set_override supplies the assignments — the guard exists to prevent an empty SET clause, which overrides fill.

#sql is public so the generated statement can be inspected and asserted on. It is the same statement #call runs, so it validates the same inputs: validate! is the shared entry point of both, and statement assembly moved to a private build_sql that #call reaches without re-validating. #call still validates ahead of its empty-attrs_list short-circuit, so bad options raise even with nothing to update; #sql additionally rejects an empty attrs_list, which has no statement at all. Without this, #sql handed back ... AND () for a blank condition, emitted a set_override on an unknown or unique_by column verbatim, and raised NoMethodError on nil.keys for an empty payload.

unique_by is now coerced to Symbols. It was matched as-is against the payload's Symbol keys, so a String silently failed to exclude its column from the SET clause and escaped the guard against a set_override rewriting a match column.

Every behavioral context in the spec asserts the exact statement it runs as a separate example, and every context where .call raises asserts #sql raises the same error, so each scenario is covered from both ends; the file documents that convention.

`condition:` is a raw-SQL predicate ANDed onto the key match, so a payload is
applied only to rows still in the state the caller expects. `set_override:` maps
a column to a raw-SQL expression replacing its default `col = v.col` assignment;
a key absent from attrs_list appends an assignment of its own, letting a column
be written purely from SQL. Both fragments are interpolated verbatim and must
qualify their column references with `t.` or `v.` — the two aliases expose the
same column names, so an unqualified reference is ambiguous.

Validated before any SQL runs: a blank condition, a set_override naming an
unknown or unique_by column, and a blank override expression all raise
ArgumentError. Rows carrying only unique_by columns no longer raise when
set_override supplies the assignments — the guard exists to prevent an empty
SET clause, which overrides fill.

behavioral context in the spec asserts it as a separate example, so each
scenario is covered from both ends; the file documents that convention.
@senid231 senid231 self-assigned this Jul 23, 2026
@senid231
senid231 requested a review from Copilot July 23, 2026 08:58
@senid231
senid231 force-pushed the bulk-update-condition-and-set-override branch from 0a2af58 to 7048423 Compare July 23, 2026 09:00

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optimistic/conditional bulk updates to PgSqlCaller::BulkUpdate by allowing callers to (1) narrow eligible rows via an extra raw-SQL predicate and (2) override per-column SET assignments with raw SQL, plus exposing the generated statement via a new public #sql API.

Changes:

  • Add condition: (extra WHERE predicate) and set_override: (raw-SQL SET expressions) to BulkUpdate.call/initialize.
  • Expose BulkUpdate#sql publicly and expand specs to assert the generated SQL per scenario.
  • Update README + changelog to document the new options, raw-SQL caveats, and #sql.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.

File Description
lib/pg_sql_caller/bulk_update.rb Adds condition:/set_override: support, new where_clause, enhanced set_clause, and makes #sql public.
spec/pg_sql_caller/bulk_update_spec.rb Adds extensive SQL-shape assertions and new behavioral coverage for condition: and set_override:.
README.md Documents conditional updates, assignment overrides, and public access to generated SQL.
CHANGELOG.md Notes the new keywords and the new BulkUpdate#sql API.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/pg_sql_caller/bulk_update.rb
Comment thread lib/pg_sql_caller/bulk_update.rb Outdated
Comment thread lib/pg_sql_caller/bulk_update.rb Outdated
Comment thread spec/pg_sql_caller/bulk_update_spec.rb
Comment thread spec/pg_sql_caller/bulk_update_spec.rb
Comment thread spec/pg_sql_caller/bulk_update_spec.rb
Comment thread spec/pg_sql_caller/bulk_update_spec.rb
Comment thread CHANGELOG.md

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread lib/pg_sql_caller/bulk_update.rb Outdated
`#sql` became public in the previous commit but skipped every validation
`#call` runs: a blank `condition` yielded `... AND ()`, a `set_override`
naming an unknown or `unique_by` column was emitted verbatim, and an
empty
`attrs_list` raised NoMethodError on `nil.keys` instead of
ArgumentError.

Extract `validate!` as the shared entry point of `#call` and `#sql`, and
split statement assembly into a private `build_sql` so `#call` reaches
it
without re-validating. `#call` still validates before its
empty-attrs_list
short-circuit, so bad options raise even with nothing to update; `#sql`
additionally rejects an empty `attrs_list`, which has no statement at
all.

Coerce `unique_by` to Symbols: it was matched as-is against the
payload's
Symbol keys, so a String silently failed to exclude its column from the
SET
clause and escaped the guard against a `set_override` rewriting a match
column.

Every context where `.call` raises now asserts `#sql` raises the same
error.
@senid231
senid231 force-pushed the bulk-update-condition-and-set-override branch from c509228 to fbc77a7 Compare July 23, 2026 11:42
@senid231
senid231 merged commit c44ff61 into master Jul 23, 2026
10 checks passed
@senid231
senid231 deleted the bulk-update-condition-and-set-override branch July 23, 2026 11:43
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.

3 participants