Skip to content

UpdateColumns can reuse cached update plans across column filters #15

@akshithg

Description

@akshithg

Summary

DbMap.UpdateColumns can reuse an update plan generated by an earlier Update
or UpdateColumns call with a different ColumnFilter. The filter is part of
the caller's intended write set, so a filtered update can still generate SQL and
bind values for columns rejected by the current filter.

Affected area

Tested on main at c0288adf3b533244dd2bf2fca08ca4418b25d281.

Affected paths:

  • DbMap.Update
  • DbMap.UpdateColumns
  • TableMap.bindUpdate

Reproduction

A focused regression uses a database/sql capture driver. First call Update
for a row with PublicNote, Admin, and Balance. Then call UpdateColumns
with a filter that only accepts PublicNote.

Expected second query:

update "security_rows" set "PublicNote"=? where "ID"=?;

Actual second query:

update "security_rows" set "PublicNote"=?, "Admin"=?, "Balance"=? where "ID"=?;

The second call also binds values for Admin and Balance.

Impact

Consumer code that treats UpdateColumns as an allowed-column boundary can
unintentionally write protected fields after another path has primed the
table's cached update plan.

Root cause

TableMap.bindUpdate caches one updatePlan per table through plan.once.Do.
The cached plan is keyed by the table, not by the supplied ColumnFilter, so
the first call's filter controls later calls.

Suggested fix

Keep cached update plans for unfiltered updates, but build filtered update plans
per call, or key filtered plans by an explicit stable filter identity.

Add regression coverage for full-to-filtered and filtered-to-filtered update
sequences.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions