Skip to content

fix(bigtable): validate DirectRow and table match in MutationsBatcher.mutate - #18874

Merged
mutianf merged 2 commits into
mainfrom
fix-batcher-row-validation
Oct 30, 2026
Merged

mutianf merged 2 commits into
mainfrom
fix-batcher-row-validation

Conversation

@mutianf

@mutianf mutianf commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Validate that rows passed to MutationsBatcher.mutate(row) (and by extension MutationsBatcher.mutate_rows(rows)) are instances of DirectRow and are not bound to a different table, matching the existing validation in Table.mutate_rows().

Problem

When MutationsBatcher was refactored to wrap self.table._table_impl.mutations_batcher(...) directly (#18200) instead of delegating to self.table.mutate_rows(...), two row-validation checks from Table.mutate_rows() were dropped:

  1. DirectRow type check (TypeError): Passing a ConditionalRow to batcher.mutate(cond_row) called cond_row._get_mutations() with the default state=None, which returns self._false_pb_mutations and unconditionally sends false-branch mutations via MutateRows without evaluating the row filter predicate. Passing an AppendRow raised a raw AttributeError: 'AppendRow' object has no attribute '_get_mutations' instead of TypeError.
  2. Table match check (TableMismatchError): Passing a DirectRow bound to another table silently sent its mutations to batcher.table instead of raising TableMismatchError.

Solution

  • Validate isinstance(row, DirectRow) in MutationsBatcher.mutate(), raising TypeError("Bulk processing can not be applied for conditional or append mutations.") if not.
  • Validate row.table is None or row.table.name == self.table.name in MutationsBatcher.mutate(), raising TableMismatchError if the row belongs to a different table.
  • Document :raises: (TypeError and TableMismatchError) on MutationsBatcher.mutate() and MutationsBatcher.mutate_rows().

Test Plan

  • Added unit tests in packages/google-cloud-bigtable/tests/unit/v2_client/test_batcher.py:
    • test_mutations_batcher_mutate_w_bound_table_row
    • test_mutations_batcher_mutate_wrong_row_type (ConditionalRow and AppendRow across mutate and mutate_rows, verifying no mutations are queued)
    • test_mutations_batcher_mutate_table_mismatch (cross-table DirectRow across mutate and mutate_rows)

@mutianf
mutianf requested a review from a team as a code owner October 27, 2026 21:37

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces validation checks in MutationsBatcher.mutate to ensure that only DirectRow instances are processed and that the row's table matches the batcher's table. Corresponding unit tests have been added to verify these validations. The review feedback suggests using f-strings instead of % formatting for better readability and correcting a typo ('can not' to 'cannot') in the error message.

@mutianf
mutianf force-pushed the fix-batcher-row-validation branch from 6f5cff0 to be1f1fd Compare October 28, 2026 19:30
@daniel-sanche daniel-sanche added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Oct 29, 2026
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Oct 29, 2026
@mutianf
mutianf force-pushed the fix-batcher-row-validation branch from be1f1fd to de7e4e4 Compare October 30, 2026 02:41
@mutianf
mutianf enabled auto-merge (squash) October 30, 2026 02:41
@mutianf
mutianf merged commit 8aa6d4d into main Oct 30, 2026
57 checks passed
@mutianf
mutianf deleted the fix-batcher-row-validation branch October 30, 2026 03:19
daniel-sanche pushed a commit that referenced this pull request Oct 30, 2026
….mutate (#18874)

## Summary

Validate that rows passed to `MutationsBatcher.mutate(row)` (and by
extension `MutationsBatcher.mutate_rows(rows)`) are instances of
`DirectRow` and are not bound to a different table, matching the
existing validation in `Table.mutate_rows()`.

### Problem
When `MutationsBatcher` was refactored to wrap
`self.table._table_impl.mutations_batcher(...)` directly (#18200)
instead of delegating to `self.table.mutate_rows(...)`, two
row-validation checks from `Table.mutate_rows()` were dropped:
1. **`DirectRow` type check (`TypeError`)**: Passing a `ConditionalRow`
to `batcher.mutate(cond_row)` called `cond_row._get_mutations()` with
the default `state=None`, which returns `self._false_pb_mutations` and
unconditionally sends false-branch mutations via `MutateRows` without
evaluating the row filter predicate. Passing an `AppendRow` raised a raw
`AttributeError: 'AppendRow' object has no attribute '_get_mutations'`
instead of `TypeError`.
2. **Table match check (`TableMismatchError`)**: Passing a `DirectRow`
bound to another table silently sent its mutations to `batcher.table`
instead of raising `TableMismatchError`.

### Solution
- Validate `isinstance(row, DirectRow)` in `MutationsBatcher.mutate()`,
raising `TypeError("Bulk processing can not be applied for conditional
or append mutations.")` if not.
- Validate `row.table is None or row.table.name == self.table.name` in
`MutationsBatcher.mutate()`, raising `TableMismatchError` if the row
belongs to a different table.
- Document `:raises:` (`TypeError` and `TableMismatchError`) on
`MutationsBatcher.mutate()` and `MutationsBatcher.mutate_rows()`.

## Test Plan
- Added unit tests in
`packages/google-cloud-bigtable/tests/unit/v2_client/test_batcher.py`:
  - `test_mutations_batcher_mutate_w_bound_table_row`
- `test_mutations_batcher_mutate_wrong_row_type` (`ConditionalRow` and
`AppendRow` across `mutate` and `mutate_rows`, verifying no mutations
are queued)
- `test_mutations_batcher_mutate_table_mismatch` (cross-table
`DirectRow` across `mutate` and `mutate_rows`)
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