Skip to content

Write inside SAVEPOINT attempts nested BEGIN IMMEDIATE #495

Description

@chubes4

Summary

A translated write executed after a MySQL-compatible SAVEPOINT is active attempts to open the adapter's wrapper transaction with BEGIN IMMEDIATE. SQLite rejects that with cannot start a transaction within a transaction, so wpdb->update() returns false even though the savepoint itself was accepted.

Exact behavior

The failing sequence is:

SAVEPOINT datamachine_transaction_1;
UPDATE wp_datamachine_jobs
SET status = 'processing', engine_data = '...'
WHERE job_id = 1 AND status = 'pending';

The update result observed immediately at the caller boundary is:

{
  "return": false,
  "return_type": "boolean",
  "rows_affected": 0,
  "last_error_has_nested_transaction": true
}

The adapter trace for the UPDATE contains only:

Executing: BEGIN IMMEDIATE | (no parameters)
SQLSTATE[HY000]: General error: 1 cannot start a transaction within a transaction

The translated UPDATE itself is therefore never executed.

Root behavior

WP_PDO_MySQL_On_SQLite::query() wraps translated writes in its own transaction. A preceding SQL SAVEPOINT has already opened an SQLite transaction, but that state is not preventing the write wrapper from issuing BEGIN IMMEDIATE. This may be because the transaction was opened through SQL rather than PDO::beginTransaction(), so PDO transaction state alone cannot identify it.

Reproduction evidence

This was reproduced through the exact deterministic Extra-Chill/data-machine#2578 agent bundle pinned from chubes4/wp-site-generator revision b2669b1e59681e58997f2bf6bacfd18eb8bf230d, with deterministic OpenAI and GitHub doubles and no live external mutation.

  • WordPress: 6.9.2
  • PHP: 8.3.32
  • WP Codebox CLI/runtime packages: 0.21.0
  • Playground CLI: 3.1.46
  • retained runtime: runtime-mt6bqbcc-dfymmz
  • retained artifact bundle: artifact-bundle-sha256-38b3a05a217740e7b6801de40989b68ad518c5fa789c97c5a683ea9ae0df5161
  • artifact path: /mnt/extrachill-workspace/tmp/opencode/verify-2578-after-3346-filesystem-trace-wp692/runtime-mt6bqbcc-dfymmz

The runtime proves the surrounding effect: one Action Scheduler action starts and completes, but the compare-and-swap update fails, the job remains pending, and the downstream deterministic handler runs zero times.

Expected

A write inside an active SQLite savepoint should execute under that transaction without attempting another top-level BEGIN IMMEDIATE. The adapter should preserve the write's real affected-row result and allow the caller to release or roll back its savepoint.

Refs Extra-Chill/data-machine#3348
Refs Extra-Chill/data-machine#2578

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions