classZtdPdoStatement
final class ZtdPdoStatement
extends PDOStatement
@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.
$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() // => falseMethods§
public function __construct(
PDOStatement $statement,
Session $session,
?RewritePlan $plan,
?PreparedQuery $preparedExecution = null,
private int $defaultFetchMode = PDO::FETCH_BOTH,
)Wrap a driver statement with the session state that governs its execution.
Parameters
$statement | PDOStatement | |
$session | Session | |
$plan | ?RewritePlan | |
$preparedExecution | ?PreparedQuery | |
$defaultFetchMode | int |
Calls 3
- class-const
PDO::FETCH_BOTH()line 55 - new StatementExecution line 57
- new BufferedRow line 58
public function bindValue(int|string $param, mixed $value, int $type = PDO::PARAM_STR): bool@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
$param | int|string | |
$value | mixed | |
$type | int |
Returns
bool Whether the value was boundThrows
ZtdPdoException When PDO cannot bind a value of that type$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() // => 7Test cases 1
Calls 4
- class-const
PDO::PARAM_STR()line 81 - method-call StatementExecution::bindings() line 83
- method-call
PDOStatement::bindValue()line 83 - method-call StatementExecution::native() line 84
public function bindParam(
int|string $param,
mixed &$var,
int $type = PDO::PARAM_STR,
int $maxLength = 0,
mixed $driverOptions = null,
): bool@visibility public.{@inheritDoc}
The variable is remembered by reference, so that what the caller changes between executions is what the next execution sends.
Parameters
$param | int|string | |
$var | mixed | |
$type | int | |
$maxLength | int | |
$driverOptions | mixed |
Returns
bool Whether the variable was boundThrows
ZtdPdoException When PDO cannot bind a value of that type$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() // => 9Calls 3
- class-const
PDO::PARAM_STR()line 109 - method-call StatementExecution::bindParameter() line 111
- method-call
PDOStatement::bindParam()line 112
public function bindColumn(
int|string $column,
mixed &$var,
int $type = PDO::PARAM_STR,
int $maxLength = 0,
mixed $driverOptions = null,
): bool@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
$column | int|string | |
$var | mixed | |
$type | int | |
$maxLength | int | |
$driverOptions | mixed |
Returns
bool Whether the column was bound$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 // => 7Test cases 1
Calls 2
- class-const
PDO::PARAM_STR()line 136 - method-call StatementExecution::native() line 140
public function execute(array<int|string, mixed>|null $params = null): bool@visibility public.Execute the statement, applying ZTD simulation as needed.
Parameters
$params | array<int|string, mixed>|null | Parameters to run it with, or null for those already bound |
Returns
bool Whether the statement ranThrows
ZtdPdoException When ZTD cannot carry the statement out$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
ZtdPdoStatementTest::testBindColumnFillsTheVariableTheColumnIsReadIntocallsZtdPdoStatementTest::testErrorCodeAnswersWhatTheDriverSaysWentWrongLastcallsZtdPdoStatementTest::testErrorInfoAnswersWhatTheDriverSaysAboutTheLastFailurecallsZtdPdoStatementTest::testExecuteDelegatesWhenNoPlancallsZtdPdoStatementTest::testExecuteDelegatesWhenNoPostProcessingNeededcallsZtdPdoStatementTest::testExecuteReturnsFalseWhenShouldExecuteIsFalsecallsZtdPdoStatementTest::testExecuteWithoutPostProcessingRunsNativeStatementOncecallsZtdPdoStatementTest::testExecuteWrapsSimulationFailureAsAdapterExceptioncallsZtdPdoStatementTest::testGetAttributeReadsTheAttributeOffTheStatementItWrapscallsZtdPdoStatementTest::testGetColumnMetaAnswersWhatTheDriverSaysAboutAColumncallsZtdPdoStatementTest::testGetIteratorWalksTheDriversOwnCursorWhereNothingWasBufferedcallsZtdPdoStatementTest::testNextRowsetMovesTheStatementOnToTheDriversNextResultcallsZtdPdoStatementTest::testPassthroughFetchAllForwardsColumnAndCallbackArgumentscallsZtdPdoStatementTest::testPassthroughFetchAllPreservesKeyPairKeyscallsZtdPdoStatementTest::testSetAttributeSetsTheAttributeOnTheStatementItWrapscalls
Calls 1
- method-call StatementExecution::execute() line 161
public function fetch(
int $mode = PDO::FETCH_DEFAULT,
int $cursorOrientation = PDO::FETCH_ORI_NEXT,
int $cursorOffset = 0,
): mixed@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
$mode | int | |
$cursorOrientation | int | |
$cursorOffset | int |
Returns
mixed The next row as that mode reads it, or false where there is none$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() // => falseTest cases 1
Calls 6
- class-const
PDO::FETCH_DEFAULT()line 185 - class-const
PDO::FETCH_ORI_NEXT()line 185 - method-call StatementExecution::result() line 187
- method-call BufferedRow::resolveMode() line 189
- method-call BufferedRow::fetch() line 190
- method-call StatementExecution::native() line 192
public function fetchAll(
int $mode = PDO::FETCH_DEFAULT,
mixed ...$args,
): array<array-key, mixed>@visibility public.{@inheritDoc}
Parameters
$mode | int | |
$args | mixed | The rest of what the fetch mode reads |
Returns
array<array-key, mixed> Every remaining row, as that mode reads them$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
- class-const
PDO::FETCH_DEFAULT()line 208 - method-call StatementExecution::result() line 210
- method-call BufferedRow::resolveMode() line 212
- method-call BufferedRow::all() line 213
- method-call StatementExecution::native() line 215
public function fetchColumn(int $column = 0): mixed@visibility public.{@inheritDoc}
Parameters
$column | int |
Returns
mixed The column's value in the next row, or false where there is none$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->fetchColumn() // => 7
$statement->fetchColumn() // => falseCalls 3
- method-call StatementExecution::result() line 232
- method-call BufferedRow::column() line 234
- method-call StatementExecution::native() line 236
public function fetchObject<T of object>(
class-string<T>|null $class = 'stdClass',
array<mixed> $constructorArgs = [],
): ($class is null ? stdClass : T)|false@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
$class | class-string<T>|null | Class to build, or null for stdClass |
$constructorArgs | array<mixed> | Arguments to build it with |
Returns
($class is null ? stdClass : T)|false The object, or false where there is no rowThrows
ReflectionException When the class will not let a property be written$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() // => falseTest cases 1
Calls 3
- method-call StatementExecution::result() line 264
- method-call BufferedRow::object() line 266
- method-call StatementExecution::native() line 268
public function rowCount(): int@visibility public.{@inheritDoc}
Returns
int Rows the statement answered or affected$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() // => 1Test cases 1
Calls 2
- method-call StatementExecution::result() line 287
- method-call StatementExecution::native() line 291
public function closeCursor(): bool@visibility public.{@inheritDoc}
Returns
bool Whether the cursor was closed$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->closeCursor() // => trueTest cases 1
Calls 1
- method-call StatementExecution::native() line 307
public function setFetchMode(int $mode, mixed ...$args): bool@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
$mode | int | |
$args | mixed | The rest of what that mode reads |
Returns
bool Whether the mode was set$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
- method-call StatementExecution::bindings() line 332
- method-call
PDOStatement::setFetchMode()line 332 - method-call StatementExecution::native() line 333
public function errorCode(): string@visibility public.{@inheritDoc}
Returns
string The driver's code for what went wrong last, or an empty string where nothing did$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
- method-call StatementExecution::native() line 349
public function errorInfo(): array{0: string|null, 1: int|null, 2: string|null}@visibility public.{@inheritDoc}
Returns
array{0: string|null, 1: int|null, 2: string|null}$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->errorInfo()[0] // => '00000'Calls 1
- method-call StatementExecution::native() line 366
public function getAttribute(int $name): mixed@visibility public.{@inheritDoc}
Parameters
$name | int |
Returns
mixed What the driver has that attribute set to$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->getAttribute(\PDO::ATTR_CURSOR) // throws \PDOExceptionCalls 1
- method-call StatementExecution::native() line 382
public function setAttribute(int $attribute, mixed $value): bool@visibility public.{@inheritDoc}
Parameters
$attribute | int | |
$value | mixed |
Returns
bool Whether the attribute was set$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 // => falseCalls 1
- method-call StatementExecution::native() line 399
public function columnCount(): int@visibility public.{@inheritDoc}
Returns
int Columns in the result the statement answered$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->columnCount() // => 1Test cases 1
Calls 1
- method-call StatementExecution::native() line 415
public function getColumnMeta(int $column): array|false@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
$column | int |
Returns
array|false$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->getColumnMeta(0)['name'] // => 'id'Calls 1
- method-call StatementExecution::native() line 432
public function nextRowset(): bool@visibility public.{@inheritDoc}
Returns
bool Whether there was another result to move to$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->nextRowset() // throws \PDOExceptionCalls 1
- method-call StatementExecution::native() line 448
public function debugDumpParams(): bool|null@visibility public.{@inheritDoc}
Returns
bool|null Always true, because the dump is written rather than answered$pdo = \ZtdQuery\Adapter\Pdo\ZtdPdo::fromPdo(new \PDO('sqlite::memory:'));
$statement = $pdo->query('SELECT 7 AS id');
$statement->debugDumpParams() // => trueCalls 1
- method-call StatementExecution::native() line 465
public function getIterator(): Iterator<mixed, mixed>@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$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
- method-call StatementExecution::result() line 487
- new
ArrayIteratorline 488 - method-call ZtdPdoStatement::fetchAll() line 488
- method-call StatementExecution::native() line 491
Private surface 4§
Implementation details, listed for orientation only.
private StatementExecution $executionprivate BufferedRow $bufferedRowprivate ?int $fetchMode = nullprivate int $defaultFetchMode = PDO::FETCH_BOTHTest cases 49§
Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.
Dedicated tests 41
ZtdPdoStatementTest::testBindColumnFillsTheVariableTheColumnIsReadIntocallsZtdPdoStatementTest::testBindParamSurvivesPreparedStatementRecompilationcallsZtdPdoStatementTest::testBindValueDelegatesToInnercallsZtdPdoStatementTest::testBindValueSurvivesPreparedStatementRecompilationcallsZtdPdoStatementTest::testBufferedColumnFetchAllReturnsEveryRowcallsZtdPdoStatementTest::testBufferedColumnFetchDefaultsToTheFirstColumnAndThenExhaustscallsZtdPdoStatementTest::testBufferedObjectHydrationUsesDeclaredPropertiescallsZtdPdoStatementTest::testCloseCursorDelegatesToInnercallsZtdPdoStatementTest::testColumnCountDelegatesToInnercallsZtdPdoStatementTest::testDebugDumpParamsWritesTheDumpRatherThanAnsweringItcallsZtdPdoStatementTest::testErrorCodeAnswersNothingWhereTheDriverSaysNothingcallsZtdPdoStatementTest::testErrorCodeAnswersWhatTheDriverSaysWentWrongLastcallsZtdPdoStatementTest::testErrorInfoAnswersWhatTheDriverSaysAboutTheLastFailurecallsZtdPdoStatementTest::testExecuteAndPostProcessLetsZtdReadWhatTheStatementAnsweredcallsZtdPdoStatementTest::testExecuteDelegatesWhenNoPlancallsZtdPdoStatementTest::testExecuteDelegatesWhenNoPostProcessingNeededcallsZtdPdoStatementTest::testExecuteReturnsFalseWhenShouldExecuteIsFalsecallsZtdPdoStatementTest::testExecuteWithoutPostProcessingRunsNativeStatementOncecallsZtdPdoStatementTest::testExecuteWrapsSimulationFailureAsAdapterExceptioncallsZtdPdoStatementTest::testFetchAllAnswersEveryBufferedRowAndNotJustTheFirstcallsZtdPdoStatementTest::testFetchAllAnswersEveryBufferedRowInTheModeItIsAskedcallsZtdPdoStatementTest::testFetchAllAnswersFalseForAColumnTheBufferedRowDoesNotHoldcallsZtdPdoStatementTest::testFetchAllAnswersOneColumnWhereOnlyOneIsAskedcallsZtdPdoStatementTest::testFetchAnswersFalseOnceTheBufferedRowsRunOutcallsZtdPdoStatementTest::testFetchAnswersOneBufferedRowAtATimecallsZtdPdoStatementTest::testFetchColumnAnswersTheColumnAskedForInTheBufferedRowcallsZtdPdoStatementTest::testFetchObjectAnswersFalseWhereThereIsNoBufferedRowLeftcallsZtdPdoStatementTest::testFetchObjectBuildsAnObjectOutOfTheBufferedRowcallsZtdPdoStatementTest::testFetchObjectDelegatesWithoutABufferedResultcallsZtdPdoStatementTest::testGetAttributeReadsTheAttributeOffTheStatementItWrapscallsZtdPdoStatementTest::testGetColumnMetaAnswersWhatTheDriverSaysAboutAColumncallsZtdPdoStatementTest::testGetIteratorWalksTheDriversOwnCursorWhereNothingWasBufferedcallsZtdPdoStatementTest::testGetIteratorWalksTheRowsZtdBufferedcallsZtdPdoStatementTest::testNextRowsetMovesTheStatementOnToTheDriversNextResultcallsZtdPdoStatementTest::testPassthroughFetchAllForwardsColumnAndCallbackArgumentscallsZtdPdoStatementTest::testPassthroughFetchAllForwardsConstructorArgumentscallsZtdPdoStatementTest::testPassthroughFetchAllPreservesKeyPairKeyscallsZtdPdoStatementTest::testRowCountDelegatesToInnerWhenNoResultcallsZtdPdoStatementTest::testSetAttributeSetsTheAttributeOnTheStatementItWrapscallsZtdPdoStatementTest::testSetFetchModeIsRememberedAcrossARepreparecallsZtdPdoStatementTest::testSimulatedWritesWithoutReturningHaveNoFetchableRowscalls