Skip to content

feat(rows): add Rows::wasApplied() for lightweight transactions - #149

Merged
CodeLieutenant merged 1 commit into
trunkfrom
feat/rows-was-applied
Aug 9, 2026
Merged

feat(rows): add Rows::wasApplied() for lightweight transactions#149
CodeLieutenant merged 1 commit into
trunkfrom
feat/rows-was-applied

Conversation

@CodeLieutenant

Copy link
Copy Markdown
Member

What

Adds Cassandra\Rows::wasApplied(): bool.

A conditional write returns an [applied] column instead of an empty result. Until now the only way to read it was:

if ($rows->first()['[applied]'] === false) { /* ... */ }

Now:

if (! $rows->wasApplied()) {
    $current = $rows->first();   // the conflicting values
}

Semantics

wasApplied() reads the [applied] column of the first row. A statement with no condition has no such column, and the method then returns true, so a caller can ask this of any result. This matches wasApplied() in the Java driver and was_applied in the Python driver.

false means the condition failed, not that the row is present:

Statement wasApplied() === false means
IF NOT EXISTS The row is already there
IF EXISTS The row is not there
IF col = ? The current value does not match

This is why the method is not named exists() — the meaning inverts with the condition, which the driver cannot see.

Implementation

The method reads the already-decoded row array, so it adds no cass_* call and no round trip. The [applied] column stays readable through first() and array access, so old code keeps working.

Also in this PR

Two stale statements in CLAUDE.md:

  • It said to commit *_arginfo.h. That file is gitignored (.gitignore: src/**/*_arginfo.h) and generated at build time by cmake/GenStubs.cmake.
  • It said to run gen_stub.php directly. Upstream gen_stub.php fails on declare(strict_types=1); with Unexpected node Stmt_Declare. The build calls tools/gen_stub/gen_arginfo.sh, which strips the declare first.

Tests

New tests/Feature/Results/LightweightTransactionTest.php, 7 cases:

  • IF NOT EXISTS that wins, and one that loses (checks the current values come back)
  • IF EXISTS against a missing row
  • A failed IF col = ?
  • A write with no condition
  • A SELECT
  • A result fetched through executeAsync()

All 13 tests in tests/Feature/Results pass against ScyllaDB, built with the DebugPHP8.4NTS preset.

A conditional write returns an `[applied]` column instead of an empty
result. Until now the only way to read it was `$rows->first()['[applied]']`,
which is easy to misspell and gives no help when the statement had no
condition.

`wasApplied()` reads the `[applied]` column of the first row. A statement
with no condition has no such column, and the method then returns `true`,
so a caller can ask this of any result. This matches `wasApplied()` in the
Java driver and `was_applied` in the Python driver.

The method reads the decoded row array, so it adds no driver call. The
`[applied]` column stays readable through `first()` and array access, and
old code keeps working.

Also correct two stale statements in CLAUDE.md:

- `*_arginfo.h` is gitignored and generated at build time by
  cmake/GenStubs.cmake. Do not commit it.
- Upstream `gen_stub.php` fails on `declare(strict_types=1);`. Use
  tools/gen_stub/gen_arginfo.sh instead.
@mergify

mergify Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@CodeLieutenant
CodeLieutenant merged commit cf286c0 into trunk Aug 9, 2026
34 of 35 checks passed
@CodeLieutenant
CodeLieutenant deleted the feat/rows-was-applied branch August 9, 2026 23:48
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.

1 participant