# 404-solution/4.3.3/includes/database/DatabaseTransactionExecutor.php

404 Solution, version 4.3.3. 95 lines.

- Page: https://pluginprobe.com/plugins/404-solution/4.3.3/code/includes/database/DatabaseTransactionExecutor.php
- Raw: https://pluginprobe.com/plugins/404-solution/4.3.3/raw/includes/database/DatabaseTransactionExecutor.php
- Modified: 2026-07-14T10:28:14+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/404-solution/4.3.3/code/includes/database/DatabaseTransactionExecutor.php#L10-L20`.

```php
<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Executes SQL statements inside a transaction with deadlock-aware retry.
 *
 * Transaction lifecycle is separate from the single-query pipeline: it owns
 * BEGIN/COMMIT/ROLLBACK bookkeeping, infrastructure-error classification for
 * statement failures, and retry delay for deadlock or lock-wait timeouts.
 */
class ABJ_404_Solution_DatabaseTransactionExecutor {

    /** @var ABJ_404_Solution_DatabaseCore */
    private $core;

    /** @var ABJ_404_Solution_Logging */
    private $logger;

    /**
     * @param ABJ_404_Solution_DatabaseCore $core
     * @param ABJ_404_Solution_Logging $logger
     */
    public function __construct(ABJ_404_Solution_DatabaseCore $core, $logger) {
        $this->core = $core;
        $this->logger = $logger;
    }

    /**
     * @param array<int, string> $statementArray
     * @return void
     */
    public function executeAsTransaction(array $statementArray): void {
        global $wpdb;
        $maxAttempts = 3;
        $lastException = null;
        $lastError = '';

        for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
            $allIsWell = true;
            $lastError = '';
            $lastException = null;
            try {
                // DAO-bypass-approved: transaction boundary must run on the active wpdb connection before grouped statements execute.
                $wpdb->query('START TRANSACTION');
                foreach ($statementArray as $statement) {
                    // DAO-bypass-approved: transaction executor must preserve same-connection transaction state and last_error per statement.
                    $wpdb->query($statement);
                    // Null-safe read (matches DataAccess.php/StatsRepository.php/NGramFilter.php):
                    // a partial test double or a future custom wpdb drop-in that omits
                    // last_error must not raise an "undefined property" notice here.
                    $statementError = trim((string)($wpdb->last_error ?? ''));
                    if ($statementError !== '') {
                        $allIsWell = false;
                        $lastError = $statementError;
                        if (!$this->core->errorClassifier()->classifyAndHandleInfrastructureError($lastError)) {
                            $this->logger->errorMessage("Error executing SQL transaction: " . $lastError);
                            $this->logger->errorMessage("SQL causing the transaction error: " . $statement);
                        }
                        break;
                    }
                }
            } catch (Throwable $ex) {
                $allIsWell = false;
                $lastException = $ex;
                $lastError = $ex->getMessage();
            }

            if ($allIsWell && $lastException == null) {
                // DAO-bypass-approved: transaction boundary must commit the active wpdb connection.
                $wpdb->query('commit');
                return;
            }

            // DAO-bypass-approved: transaction boundary must roll back the active wpdb connection after any grouped statement failure.
            $wpdb->query('rollback');
            $retryable = $this->core->errorClassifier()->taxonomy()->connectivity()->isDeadlockOrLockTimeoutError($lastError);
            if (!$retryable || $attempt >= $maxAttempts) {
                break;
            }
            $sleepMicros = 100000 + random_int(0, 200000);
            usleep($sleepMicros);
        }

        if ($lastException != null) {
            throw $lastException;
        }
        if ($lastError !== '') {
            throw new Exception($lastError); // allow-raw-error: behavior preserved from pre-extraction DatabaseCore::executeAsTransaction
        }
    }
}

```
