final class ZtdPdoStatement
    extends PDOStatement
Public API: explicitly declared with @visibility public.

PDOStatement wrapper that applies ZTD rewrite/simulation on execute().

Uses delegation pattern: extends PDOStatement for type compatibility, but delegates all operations to an inner PDOStatement instance.

Fetch a row through the PDO statement interfacedoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $pdo->exec("INSERT INTO users VALUES (1, 'Alice')");
    $statement = $pdo->query('SELECT id, name FROM users');
    $statement->fetch(\PDO::FETCH_ASSOC) // => ['id' => 1, 'name' => 'Alice']
    $statement->fetch() // => false

Methods§

public function __construct(
    PDOStatement $statement,
    Session $session,
    ?RewritePlan $plan,
    ?PreparedQuery $preparedExecution = null,
    private int $defaultFetchMode = PDO::FETCH_BOTH,
)
Restricted visibility: declared "@visibility ZtdQuery\Adapter\Pdo". Code outside that scope must not name this declaration.

Wrap a driver statement with the session state that governs its execution.

Parameters

$statementPDOStatement
$sessionSession
$plan?RewritePlan
$preparedExecution?PreparedQuery
$defaultFetchModeint
Calls 3
public function bindValue(int|string $param, mixed $value, int $type = PDO::PARAM_STR): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

The binding is remembered as well as made, because ZTD prepares the statement again on each execute() and a statement prepared again has nothing bound to it.

Parameters

$paramint|string
$valuemixed
$typeint

Returns

bool Whether the value was bound

Throws

ZtdPdoException When PDO cannot bind a value of that type
Retain typed values when the query is prepared againdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->prepare('SELECT :id AS id');
    $statement->bindValue(':id', 7, \PDO::PARAM_INT) // => true
    $statement->execute() // => true
    $statement->fetchColumn() // => 7
Test cases 1
Calls 4
public function bindParam(
    int|string $param,
    mixed &$var,
    int $type = PDO::PARAM_STR,
    int $maxLength = 0,
    mixed $driverOptions = null,
): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

The variable is remembered by reference, so that what the caller changes between executions is what the next execution sends.

Parameters

$paramint|string
$varmixed
$typeint
$maxLengthint
$driverOptionsmixed

Returns

bool Whether the variable was bound

Throws

ZtdPdoException When PDO cannot bind a value of that type
Read the current variable at each executiondoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->prepare('SELECT ? AS id');
    $params = (object) ['id' => 7];
    $statement->bindParam(1, $params->id, \PDO::PARAM_INT);
    $statement->execute();
    $statement->fetchColumn() // => 7
    $params->id = 9;
    $statement->execute();
    $statement->fetchColumn() // => 9
Calls 3
public function bindColumn(
    int|string $column,
    mixed &$var,
    int $type = PDO::PARAM_STR,
    int $maxLength = 0,
    mixed $driverOptions = null,
): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

A column is bound on the statement the driver prepared, which is the one that fills the variable when a row is read from it.

Parameters

$columnint|string
$varmixed
$typeint
$maxLengthint
$driverOptionsmixed

Returns

bool Whether the column was bound
Bind a column on an executed statementdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $row = (object) ['id' => null];
    $statement->bindColumn('id', $row->id, \PDO::PARAM_INT) // => true
    $statement->fetch(\PDO::FETCH_BOUND);
    $row->id // => 7
Test cases 1
Calls 2
public function execute(array<int|string, mixed>|null $params = null): bool
Public API: explicitly declared with @visibility public.

Execute the statement, applying ZTD simulation as needed.

Parameters

$paramsarray<int|string, mixed>|nullParameters to run it with, or null for those already bound

Returns

bool Whether the statement ran

Throws

ZtdPdoException When ZTD cannot carry the statement out
Execute parameters against current shadow statedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->prepare('SELECT ? AS name');
    $statement->execute(['Ada']) // => true
    $statement->fetchColumn() // => 'Ada'
Test cases 15
Calls 1
public function fetch(
    int $mode = PDO::FETCH_DEFAULT,
    int $cursorOrientation = PDO::FETCH_ORI_NEXT,
    int $cursorOffset = 0,
): mixed
Public API: explicitly declared with @visibility public.

{@inheritDoc}

A row ZTD buffered is shaped here for the mode it is read in; a row the driver holds is read off the driver, which shapes it itself.

Parameters

$modeint
$cursorOrientationint
$cursorOffsetint

Returns

mixed The next row as that mode reads it, or false where there is none
Fetch an associative rowdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->fetch(\PDO::FETCH_ASSOC) // => ['id' => 7]
    $statement->fetch() // => false
Test cases 1
Calls 6
public function fetchAll(
    int $mode = PDO::FETCH_DEFAULT,
    mixed ...$args,
): array<array-key, mixed>
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$modeint
$argsmixedThe rest of what the fetch mode reads

Returns

array<array-key, mixed> Every remaining row, as that mode reads them
Fetch one column from every rowdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id UNION ALL SELECT 9 AS id');
    $statement->fetchAll(\PDO::FETCH_COLUMN) // => [7, 9]
Test cases 2
Called from 1
Calls 5
public function fetchColumn(int $column = 0): mixed
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$columnint

Returns

mixed The column's value in the next row, or false where there is none
Read a single valuedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->fetchColumn() // => 7
    $statement->fetchColumn() // => false
Calls 3
public function fetchObject<T of object>(
    class-string<T>|null $class = 'stdClass',
    array<mixed> $constructorArgs = [],
): ($class is null ? stdClass : T)|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

A row ZTD buffered never reached the driver, so nothing hydrated an object from it; the object is built here and its properties written from the row, which is what the driver would have done.

Parameters

$classclass-string<T>|nullClass to build, or null for stdClass
$constructorArgsarray<mixed>Arguments to build it with

Returns

($class is null ? stdClass : T)|false The object, or false where there is no row

Throws

ReflectionException When the class will not let a property be written
Hydrate an anonymous row objectdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $row = $statement->fetchObject();
    $row->id // => 7
    $statement->fetchObject() // => false
Test cases 1
Calls 3
public function rowCount(): int
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

int Rows the statement answered or affected
Count affected shadow rowsdoctest
$native = new \PDO('sqlite::memory:');
    $native->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)');
    $pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo($native);
    $statement = $pdo->prepare('INSERT INTO users VALUES (?, ?)');
    $statement->execute([1, 'Ada']);
    $statement->rowCount() // => 1
Test cases 1
Calls 2
public function closeCursor(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool Whether the cursor was closed
Release a native cursordoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->closeCursor() // => true
Test cases 1
Calls 1
public function setFetchMode(int $mode, mixed ...$args): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

The mode is remembered as well as set, because ZTD prepares the statement again on each execute() and a statement prepared again is back on the connection's own mode.

Parameters

$modeint
$argsmixedThe rest of what that mode reads

Returns

bool Whether the mode was set
Choose the shape of subsequent rowsdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->setFetchMode(\PDO::FETCH_NUM) // => true
    $statement->fetch() // => [7]
Calls 3
public function errorCode(): string
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

string The driver's code for what went wrong last, or an empty string where nothing did
Read statement SQLSTATEdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->errorCode() // => '00000'
Test cases 2
Calls 1
public function errorInfo(): array{0: string|null, 1: int|null, 2: string|null}
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

array{0: string|null, 1: int|null, 2: string|null}
Read statement error detailsdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->errorInfo()[0] // => '00000'
Test cases 1
Calls 1
public function getAttribute(int $name): mixed
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$nameint

Returns

mixed What the driver has that attribute set to
Handle an unsupported SQLite statement attributedoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->getAttribute(\PDO::ATTR_CURSOR) // throws \PDOException
Test cases 1
Calls 1
public function setAttribute(int $attribute, mixed $value): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Parameters

$attributeint
$valuemixed

Returns

bool Whether the attribute was set
Handle a driver that does not support statement attributesdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    try { $supported = $statement->setAttribute(\PDO::ATTR_CURSOR, \PDO::CURSOR_FWDONLY); } catch (\PDOException) { $supported = false; }
    $supported // => false
Test cases 1
Calls 1
public function columnCount(): int
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

int Columns in the result the statement answered
Inspect result widthdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->columnCount() // => 1
Test cases 1
Calls 1
public function getColumnMeta(int $column): array|false
Public API: explicitly declared with @visibility public.

{@inheritDoc}

The metadata is the driver's own; a statement ZTD simulated has none, because nothing the driver prepared answered its columns.

Parameters

$columnint

Returns

array|false
Read a projected column labeldoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->getColumnMeta(0)['name'] // => 'id'
Test cases 1
Calls 1
public function nextRowset(): bool
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool Whether there was another result to move to
Handle SQLite without multiple rowsetsdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->nextRowset() // throws \PDOException
Test cases 1
Calls 1
public function debugDumpParams(): bool|null
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Returns

bool|null Always true, because the dump is written rather than answered
Print the native statement diagnosticsdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->debugDumpParams() // => true
Test cases 1
Calls 1
public function getIterator(): Iterator<mixed, mixed>
Public API: explicitly declared with @visibility public.

{@inheritDoc}

Rows ZTD buffered are walked from what it buffered; anything else is walked off the driver's own cursor.

Returns

Iterator<mixed, mixed> Every remaining row
Iterate remaining rowsdoctest
$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
    $statement = $pdo->query('SELECT 7 AS id');
    $statement->setFetchMode(\PDO::FETCH_ASSOC);
    iterator_to_array($statement->getIterator()) // => [['id' => 7]]
Test cases 1
Calls 4

Private surface 4§

Implementation details, listed for orientation only.

private StatementExecution $execution
private BufferedRow $bufferedRow
private ?int $fetchMode = null
private int $defaultFetchMode = PDO::FETCH_BOTH

Test cases 49§

Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.

Dedicated tests 41
Other tests reaching this symbol 8

Relations§

Instantiated in 1