Code Coverage |
||||||||||||||||
Lines |
Branches |
Paths |
Functions and Methods |
Classes and Traits |
||||||||||||
| Total | |
100.00% |
124 / 124 |
|
98.10% |
103 / 105 |
|
44.19% |
38 / 86 |
|
91.67% |
22 / 24 |
CRAP | |
0.00% |
0 / 1 |
| Query | |
100.00% |
124 / 124 |
|
98.10% |
103 / 105 |
|
44.19% |
38 / 86 |
|
100.00% |
24 / 24 |
561.01 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| __toString | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| one | |
100.00% |
9 / 9 |
|
100.00% |
7 / 7 |
|
25.00% |
1 / 4 |
|
100.00% |
1 / 1 |
6.80 | |||
| first | |
100.00% |
5 / 5 |
|
100.00% |
6 / 6 |
|
0.00% |
0 / 4 |
|
100.00% |
1 / 1 |
2 | |||
| fetch | |
100.00% |
4 / 4 |
|
100.00% |
4 / 4 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| all | |
100.00% |
10 / 10 |
|
100.00% |
9 / 9 |
|
0.00% |
0 / 8 |
|
100.00% |
1 / 1 |
3 | |||
| lazy | |
100.00% |
8 / 8 |
|
88.89% |
8 / 9 |
|
0.00% |
0 / 6 |
|
100.00% |
1 / 1 |
3 | |||
| terminalOptions | |
100.00% |
8 / 8 |
|
92.31% |
12 / 13 |
|
15.00% |
3 / 20 |
|
100.00% |
1 / 1 |
20.35 | |||
| executeFresh | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| executeForFetch | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| executeStatement | |
100.00% |
5 / 5 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| fail | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| hydrateRecord | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| hydrator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| run | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| len | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
0.00% |
0 / 2 |
|
100.00% |
1 / 1 |
1 | |||
| interpolate | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| prepare | |
100.00% |
7 / 7 |
|
100.00% |
6 / 6 |
|
50.00% |
2 / 4 |
|
100.00% |
1 / 1 |
4.12 | |||
| useCurrentConnection | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| bindArgs | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| bindValue | |
100.00% |
25 / 25 |
|
100.00% |
17 / 17 |
|
53.85% |
7 / 13 |
|
100.00% |
1 / 1 |
14.29 | |||
| fetchArrayRecord | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| fetchAllRecords | |
100.00% |
4 / 4 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| nullIfNot | |
100.00% |
3 / 3 |
|
100.00% |
3 / 3 |
|
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Celema\Quma; |
| 6 | |
| 7 | use Celema\Quma\Exception\UnexpectedResultCount; |
| 8 | use Celema\Quma\Hydration\Hydrator; |
| 9 | use Closure; |
| 10 | use Generator; |
| 11 | use InvalidArgumentException; |
| 12 | use JsonException; |
| 13 | use PDO; |
| 14 | use PDOException; |
| 15 | use PDOStatement; |
| 16 | |
| 17 | /** @api */ |
| 18 | class Query |
| 19 | { |
| 20 | // Matches multi line single and double quotes and handles \' \" escapes |
| 21 | public const string PATTERN_STRING = '/([\'"])(?:\\\1|[\s\S])*?\1/'; |
| 22 | |
| 23 | // PostgreSQL blocks delimited with $$ |
| 24 | public const string PATTERN_BLOCK = '/(\$\$)[\s\S]*?\1/'; |
| 25 | |
| 26 | // Multi line comments /* */ |
| 27 | public const string PATTERN_COMMENT_MULTI = '/\/\*([\s\S]*?)\*\//'; |
| 28 | |
| 29 | // Single line comments -- |
| 30 | public const string PATTERN_COMMENT_SINGLE = '/--.*$/m'; |
| 31 | |
| 32 | protected PDOStatement $stmt; |
| 33 | protected bool $executed = false; |
| 34 | protected ?Hydrator $hydrator = null; |
| 35 | |
| 36 | /** The connection the statement was prepared on. */ |
| 37 | private PDO $pdo; |
| 38 | |
| 39 | public function __construct( |
| 40 | protected Database $db, |
| 41 | protected string $query, |
| 42 | protected Args $args, |
| 43 | protected ?string $sourcePath = null, |
| 44 | ) { |
| 45 | $this->prepare($this->db->getConn()); |
| 46 | |
| 47 | if ($this->db->debug) { |
| 48 | Debug::query($this->db, $this->query, $this->args, $this->sourcePath); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | public function __toString(): string |
| 53 | { |
| 54 | return $this->interpolate(); |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * @template T of object |
| 59 | * |
| 60 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 61 | * @return ($map is null ? array<array-key, mixed> : T) |
| 62 | */ |
| 63 | public function one(string|Closure|null $map = null, ?int $fetchMode = null): array|object |
| 64 | { |
| 65 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 66 | $this->executeFresh(); |
| 67 | |
| 68 | try { |
| 69 | $record = $this->fetchArrayRecord($fetchMode); |
| 70 | |
| 71 | if ($record === null) { |
| 72 | throw UnexpectedResultCount::none(); |
| 73 | } |
| 74 | |
| 75 | if ($this->fetchArrayRecord($fetchMode) !== null) { |
| 76 | throw UnexpectedResultCount::multiple(); |
| 77 | } |
| 78 | |
| 79 | return $this->hydrateRecord($record, $map); |
| 80 | } finally { |
| 81 | $this->stmt->closeCursor(); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /** |
| 86 | * @template T of object |
| 87 | * |
| 88 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 89 | * @return ($map is null ? array<array-key, mixed>|null : T|null) |
| 90 | */ |
| 91 | public function first(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 92 | { |
| 93 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 94 | $this->executeFresh(); |
| 95 | |
| 96 | try { |
| 97 | $record = $this->fetchArrayRecord($fetchMode); |
| 98 | |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 100 | } finally { |
| 101 | $this->stmt->closeCursor(); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * @template T of object |
| 107 | * |
| 108 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 109 | * @return ($map is null ? array<array-key, mixed>|null : T|null) |
| 110 | */ |
| 111 | public function fetch(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 112 | { |
| 113 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 114 | $this->executeForFetch(); |
| 115 | |
| 116 | $record = $this->fetchArrayRecord($fetchMode); |
| 117 | |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * @template T of object |
| 123 | * |
| 124 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 125 | * @return ($map is null ? list<array<array-key, mixed>> : list<T>) |
| 126 | */ |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 136 | return $records; |
| 137 | } |
| 138 | |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 146 | } finally { |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /** |
| 152 | * @template T of object |
| 153 | * |
| 154 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 155 | * @return ($map is null |
| 156 | * ? Generator<int, array<array-key, mixed>, mixed, void> |
| 157 | * : Generator<int, T, mixed, void>) |
| 158 | */ |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 167 | yield $record; |
| 168 | |
| 169 | continue; |
| 170 | } |
| 171 | |
| 172 | yield $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 173 | } |
| 174 | } finally { |
| 175 | $this->stmt->closeCursor(); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 184 | throw new InvalidArgumentException('Hydration requires PDO::FETCH_ASSOC.'); |
| 185 | } |
| 186 | |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 190 | ); |
| 191 | } |
| 192 | |
| 193 | return $mode; |
| 194 | } |
| 195 | |
| 196 | private function executeFresh(): void |
| 197 | { |
| 198 | $this->executeStatement(); |
| 199 | $this->executed = false; |
| 200 | } |
| 201 | |
| 202 | private function executeForFetch(): void |
| 203 | { |
| 204 | if (!$this->executed) { |
| 205 | $this->executeStatement(); |
| 206 | $this->executed = true; |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | private function executeStatement(): bool |
| 211 | { |
| 212 | $this->useCurrentConnection(); |
| 213 | |
| 214 | try { |
| 215 | $this->stmt->closeCursor(); |
| 216 | |
| 217 | return $this->stmt->execute(); |
| 218 | } catch (PDOException $e) { |
| 219 | $this->fail($this->pdo, $e); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | /** |
| 224 | * Lets the database verify the connection before it is reused, as the |
| 225 | * failure may mean that the connection was lost. The failed operation |
| 226 | * itself is never retried. |
| 227 | */ |
| 228 | private function fail(PDO $pdo, PDOException $e): never |
| 229 | { |
| 230 | $this->db->markSuspect($pdo); |
| 231 | |
| 232 | throw $e; |
| 233 | } |
| 234 | |
| 235 | /** |
| 236 | * @template T of object |
| 237 | * |
| 238 | * @param array<array-key, mixed> $record |
| 239 | * @param class-string<T>|Closure(array<string, mixed>):class-string<T>|null $map |
| 240 | * @return ($map is null ? array<array-key, mixed> : T) |
| 241 | */ |
| 242 | private function hydrateRecord(array $record, string|Closure|null $map): array|object |
| 243 | { |
| 244 | if ($map === null) { |
| 245 | return $record; |
| 246 | } |
| 247 | |
| 248 | return $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 249 | } |
| 250 | |
| 251 | private function hydrator(): Hydrator |
| 252 | { |
| 253 | return $this->hydrator ??= Hydrator::default(); |
| 254 | } |
| 255 | |
| 256 | public function run(): bool |
| 257 | { |
| 258 | $this->executed = false; |
| 259 | |
| 260 | return $this->executeStatement(); |
| 261 | } |
| 262 | |
| 263 | public function len(): int |
| 264 | { |
| 265 | $this->executeFresh(); |
| 266 | |
| 267 | try { |
| 268 | return $this->stmt->rowCount(); |
| 269 | } finally { |
| 270 | $this->stmt->closeCursor(); |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | /** |
| 275 | * For debugging purposes only. |
| 276 | * |
| 277 | * Replaces any parameter placeholders in a query with the |
| 278 | * value of that parameter and returns the query as string. |
| 279 | * |
| 280 | * Covers most of the cases but is not perfect. |
| 281 | */ |
| 282 | public function interpolate(): string |
| 283 | { |
| 284 | return Debug::interpolate($this->query, $this->args); |
| 285 | } |
| 286 | |
| 287 | private function prepare(PDO $pdo): void |
| 288 | { |
| 289 | try { |
| 290 | $stmt = $pdo->prepare($this->query); |
| 291 | } catch (PDOException $e) { |
| 292 | $this->fail($pdo, $e); |
| 293 | } |
| 294 | |
| 295 | // Only a prepared statement switches the query to the connection; |
| 296 | // otherwise its next execution would not prepare it again. |
| 297 | $this->pdo = $pdo; |
| 298 | $this->stmt = $stmt; |
| 299 | |
| 300 | if ($this->args->count() > 0) { |
| 301 | $this->bindArgs($this->args->get(), $this->args->type()); |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | /** |
| 306 | * Before an execution, prepares the statement again if the database |
| 307 | * replaced its connection since, for example after the maximum age. The |
| 308 | * statement would otherwise still run on the old connection, outside a |
| 309 | * transaction begun on the new one. |
| 310 | */ |
| 311 | private function useCurrentConnection(): void |
| 312 | { |
| 313 | $pdo = $this->db->getConn(); |
| 314 | |
| 315 | if ($pdo !== $this->pdo) { |
| 316 | $this->prepare($pdo); |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | /** @param array<array-key, mixed> $args */ |
| 321 | protected function bindArgs(array $args, ArgType $argType): void |
| 322 | { |
| 323 | array_walk( |
| 324 | $args, |
| 325 | function (mixed $value, int|string $index) use ($argType): void { |
| 326 | if ($argType === ArgType::Named) { |
| 327 | $arg = ':' . $index; |
| 328 | } else { |
| 329 | $arg = (int) $index + 1; // question mark placeholders are 1-indexed |
| 330 | } |
| 331 | |
| 332 | $this->bindValue($arg, $value); |
| 333 | }, |
| 334 | ); |
| 335 | } |
| 336 | |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 341 | $this->stmt->bindValue($arg, $value, PDO::PARAM_BOOL); |
| 342 | |
| 343 | break; |
| 344 | |
| 345 | case 'integer': |
| 346 | $this->stmt->bindValue($arg, $value, PDO::PARAM_INT); |
| 347 | |
| 348 | break; |
| 349 | |
| 350 | case 'string': |
| 351 | $this->stmt->bindValue($arg, $value, PDO::PARAM_STR); |
| 352 | |
| 353 | break; |
| 354 | |
| 355 | case 'NULL': |
| 356 | $this->stmt->bindValue($arg, $value, PDO::PARAM_NULL); |
| 357 | |
| 358 | break; |
| 359 | |
| 360 | case 'array': |
| 361 | try { |
| 362 | $json = json_encode($value, JSON_THROW_ON_ERROR); |
| 363 | } catch (JsonException $e) { |
| 364 | throw new InvalidArgumentException( |
| 365 | 'Array parameters must be JSON-encodable.', |
| 366 | previous: $e, |
| 367 | ); |
| 368 | } |
| 369 | |
| 370 | $this->stmt->bindValue($arg, $json, PDO::PARAM_STR); |
| 371 | |
| 372 | break; |
| 373 | |
| 374 | default: |
| 375 | throw new InvalidArgumentException( |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | /** @return array<array-key, mixed>|null */ |
| 382 | protected function fetchArrayRecord(int $fetchMode): ?array |
| 383 | { |
| 384 | try { |
| 385 | return $this->nullIfNot($this->stmt->fetch($fetchMode)); |
| 386 | } catch (PDOException $e) { |
| 387 | $this->fail($this->pdo, $e); |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | /** @return list<array<array-key, mixed>> */ |
| 392 | private function fetchAllRecords(int $fetchMode): array |
| 393 | { |
| 394 | try { |
| 395 | /** |
| 396 | * @mago-expect lint:inline-variable-return Psalm makes this necessary |
| 397 | * @var list<array<array-key, mixed>> $records |
| 398 | */ |
| 399 | $records = $this->stmt->fetchAll($fetchMode); |
| 400 | |
| 401 | return $records; |
| 402 | } catch (PDOException $e) { |
| 403 | $this->fail($this->pdo, $e); |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | /** @return array<array-key, mixed>|null */ |
| 408 | protected function nullIfNot(mixed $value): ?array |
| 409 | { |
| 410 | if (is_array($value)) { |
| 411 | return $value; |
| 412 | } |
| 413 | |
| 414 | return null; |
| 415 | } |
| 416 | } |
Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not
necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once.
Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement
always has an else as part of its logical flow even if you didn't write one.
| 40 | protected Database $db, |
| 41 | protected string $query, |
| 42 | protected Args $args, |
| 43 | protected ?string $sourcePath = null, |
| 44 | ) { |
| 45 | $this->prepare($this->db->getConn()); |
| 46 | |
| 47 | if ($this->db->debug) { |
| 48 | Debug::query($this->db, $this->query, $this->args, $this->sourcePath); |
| 49 | } |
| 50 | } |
| 50 | } |
| 40 | protected Database $db, |
| 41 | protected string $query, |
| 42 | protected Args $args, |
| 43 | protected ?string $sourcePath = null, |
| 44 | ) { |
| 45 | $this->prepare($this->db->getConn()); |
| 46 | |
| 47 | if ($this->db->debug) { |
| 50 | } |
| 54 | return $this->interpolate(); |
| 55 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 136 | return $records; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 136 | return $records; |
| 136 | return $records; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 321 | protected function bindArgs(array $args, ArgType $argType): void |
| 322 | { |
| 323 | array_walk( |
| 324 | $args, |
| 325 | function (mixed $value, int|string $index) use ($argType): void { |
| 326 | if ($argType === ArgType::Named) { |
| 327 | $arg = ':' . $index; |
| 328 | } else { |
| 329 | $arg = (int) $index + 1; // question mark placeholders are 1-indexed |
| 330 | } |
| 331 | |
| 332 | $this->bindValue($arg, $value); |
| 333 | }, |
| 334 | ); |
| 335 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 341 | $this->stmt->bindValue($arg, $value, PDO::PARAM_BOOL); |
| 342 | |
| 343 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 346 | $this->stmt->bindValue($arg, $value, PDO::PARAM_INT); |
| 347 | |
| 348 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 351 | $this->stmt->bindValue($arg, $value, PDO::PARAM_STR); |
| 352 | |
| 353 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 356 | $this->stmt->bindValue($arg, $value, PDO::PARAM_NULL); |
| 357 | |
| 358 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 361 | try { |
| 362 | $json = json_encode($value, JSON_THROW_ON_ERROR); |
| 370 | $this->stmt->bindValue($arg, $json, PDO::PARAM_STR); |
| 371 | |
| 372 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 375 | throw new InvalidArgumentException( |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 345 | case 'integer': |
| 350 | case 'string': |
| 355 | case 'NULL': |
| 360 | case 'array': |
| 360 | case 'array': |
| 375 | throw new InvalidArgumentException( |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 345 | case 'integer': |
| 350 | case 'string': |
| 355 | case 'NULL': |
| 360 | case 'array': |
| 361 | try { |
| 362 | $json = json_encode($value, JSON_THROW_ON_ERROR); |
| 370 | $this->stmt->bindValue($arg, $json, PDO::PARAM_STR); |
| 371 | |
| 372 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 345 | case 'integer': |
| 350 | case 'string': |
| 355 | case 'NULL': |
| 356 | $this->stmt->bindValue($arg, $value, PDO::PARAM_NULL); |
| 357 | |
| 358 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 345 | case 'integer': |
| 350 | case 'string': |
| 351 | $this->stmt->bindValue($arg, $value, PDO::PARAM_STR); |
| 352 | |
| 353 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 345 | case 'integer': |
| 346 | $this->stmt->bindValue($arg, $value, PDO::PARAM_INT); |
| 347 | |
| 348 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 337 | protected function bindValue(string|int $arg, mixed $value): void |
| 338 | { |
| 339 | switch (gettype($value)) { |
| 340 | case 'boolean': |
| 341 | $this->stmt->bindValue($arg, $value, PDO::PARAM_BOOL); |
| 342 | |
| 343 | break; |
| 376 | 'Only the types bool, int, string, null and array are supported', |
| 377 | ); |
| 378 | } |
| 379 | } |
| 363 | } catch (JsonException $e) { |
| 364 | throw new InvalidArgumentException( |
| 365 | 'Array parameters must be JSON-encodable.', |
| 204 | if (!$this->executed) { |
| 205 | $this->executeStatement(); |
| 206 | $this->executed = true; |
| 207 | } |
| 208 | } |
| 208 | } |
| 204 | if (!$this->executed) { |
| 208 | } |
| 198 | $this->executeStatement(); |
| 199 | $this->executed = false; |
| 200 | } |
| 212 | $this->useCurrentConnection(); |
| 213 | |
| 214 | try { |
| 215 | $this->stmt->closeCursor(); |
| 216 | |
| 217 | return $this->stmt->execute(); |
| 218 | } catch (PDOException $e) { |
| 219 | $this->fail($this->pdo, $e); |
| 220 | } |
| 221 | } |
| 228 | private function fail(PDO $pdo, PDOException $e): never |
| 229 | { |
| 230 | $this->db->markSuspect($pdo); |
| 231 | |
| 232 | throw $e; |
| 233 | } |
| 111 | public function fetch(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 112 | { |
| 113 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 114 | $this->executeForFetch(); |
| 115 | |
| 116 | $record = $this->fetchArrayRecord($fetchMode); |
| 117 | |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 119 | } |
| 111 | public function fetch(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 112 | { |
| 113 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 114 | $this->executeForFetch(); |
| 115 | |
| 116 | $record = $this->fetchArrayRecord($fetchMode); |
| 117 | |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 118 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 119 | } |
| 392 | private function fetchAllRecords(int $fetchMode): array |
| 393 | { |
| 394 | try { |
| 395 | /** |
| 396 | * @mago-expect lint:inline-variable-return Psalm makes this necessary |
| 397 | * @var list<array<array-key, mixed>> $records |
| 398 | */ |
| 399 | $records = $this->stmt->fetchAll($fetchMode); |
| 400 | |
| 401 | return $records; |
| 402 | } catch (PDOException $e) { |
| 403 | $this->fail($this->pdo, $e); |
| 404 | } |
| 405 | } |
| 382 | protected function fetchArrayRecord(int $fetchMode): ?array |
| 383 | { |
| 384 | try { |
| 385 | return $this->nullIfNot($this->stmt->fetch($fetchMode)); |
| 386 | } catch (PDOException $e) { |
| 387 | $this->fail($this->pdo, $e); |
| 388 | } |
| 389 | } |
| 91 | public function first(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 92 | { |
| 93 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 94 | $this->executeFresh(); |
| 95 | |
| 96 | try { |
| 97 | $record = $this->fetchArrayRecord($fetchMode); |
| 98 | |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 101 | $this->stmt->closeCursor(); |
| 102 | } |
| 103 | } |
| 91 | public function first(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 92 | { |
| 93 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 94 | $this->executeFresh(); |
| 95 | |
| 96 | try { |
| 97 | $record = $this->fetchArrayRecord($fetchMode); |
| 98 | |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 91 | public function first(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 92 | { |
| 93 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 94 | $this->executeFresh(); |
| 95 | |
| 96 | try { |
| 97 | $record = $this->fetchArrayRecord($fetchMode); |
| 98 | |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 101 | $this->stmt->closeCursor(); |
| 102 | } |
| 103 | } |
| 91 | public function first(string|Closure|null $map = null, ?int $fetchMode = null): array|object|null |
| 92 | { |
| 93 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 94 | $this->executeFresh(); |
| 95 | |
| 96 | try { |
| 97 | $record = $this->fetchArrayRecord($fetchMode); |
| 98 | |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 99 | return $record === null ? null : $this->hydrateRecord($record, $map); |
| 242 | private function hydrateRecord(array $record, string|Closure|null $map): array|object |
| 243 | { |
| 244 | if ($map === null) { |
| 245 | return $record; |
| 242 | private function hydrateRecord(array $record, string|Closure|null $map): array|object |
| 243 | { |
| 244 | if ($map === null) { |
| 248 | return $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 249 | } |
| 253 | return $this->hydrator ??= Hydrator::default(); |
| 254 | } |
| 284 | return Debug::interpolate($this->query, $this->args); |
| 285 | } |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 175 | $this->stmt->closeCursor(); |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 174 | } finally { |
| 177 | } |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 167 | yield $record; |
| 168 | |
| 169 | continue; |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 175 | $this->stmt->closeCursor(); |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 167 | yield $record; |
| 168 | |
| 169 | continue; |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 174 | } finally { |
| 177 | } |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 167 | yield $record; |
| 168 | |
| 169 | continue; |
| 170 | } |
| 171 | |
| 172 | yield $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 175 | $this->stmt->closeCursor(); |
| 159 | public function lazy(string|Closure|null $map = null, ?int $fetchMode = null): Generator |
| 160 | { |
| 161 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 162 | $this->executeFresh(); |
| 163 | |
| 164 | try { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 166 | if ($map === null) { |
| 167 | yield $record; |
| 168 | |
| 169 | continue; |
| 170 | } |
| 171 | |
| 172 | yield $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 165 | while (($record = $this->fetchArrayRecord($fetchMode)) !== null) { |
| 174 | } finally { |
| 174 | } finally { |
| 177 | } |
| 265 | $this->executeFresh(); |
| 266 | |
| 267 | try { |
| 268 | return $this->stmt->rowCount(); |
| 270 | $this->stmt->closeCursor(); |
| 271 | } |
| 272 | } |
| 265 | $this->executeFresh(); |
| 266 | |
| 267 | try { |
| 268 | return $this->stmt->rowCount(); |
| 268 | return $this->stmt->rowCount(); |
| 408 | protected function nullIfNot(mixed $value): ?array |
| 409 | { |
| 410 | if (is_array($value)) { |
| 411 | return $value; |
| 408 | protected function nullIfNot(mixed $value): ?array |
| 409 | { |
| 410 | if (is_array($value)) { |
| 414 | return null; |
| 415 | } |
| 63 | public function one(string|Closure|null $map = null, ?int $fetchMode = null): array|object |
| 64 | { |
| 65 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 66 | $this->executeFresh(); |
| 67 | |
| 68 | try { |
| 69 | $record = $this->fetchArrayRecord($fetchMode); |
| 70 | |
| 71 | if ($record === null) { |
| 72 | throw UnexpectedResultCount::none(); |
| 63 | public function one(string|Closure|null $map = null, ?int $fetchMode = null): array|object |
| 64 | { |
| 65 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 66 | $this->executeFresh(); |
| 67 | |
| 68 | try { |
| 69 | $record = $this->fetchArrayRecord($fetchMode); |
| 70 | |
| 71 | if ($record === null) { |
| 75 | if ($this->fetchArrayRecord($fetchMode) !== null) { |
| 76 | throw UnexpectedResultCount::multiple(); |
| 63 | public function one(string|Closure|null $map = null, ?int $fetchMode = null): array|object |
| 64 | { |
| 65 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 66 | $this->executeFresh(); |
| 67 | |
| 68 | try { |
| 69 | $record = $this->fetchArrayRecord($fetchMode); |
| 70 | |
| 71 | if ($record === null) { |
| 75 | if ($this->fetchArrayRecord($fetchMode) !== null) { |
| 79 | return $this->hydrateRecord($record, $map); |
| 81 | $this->stmt->closeCursor(); |
| 82 | } |
| 83 | } |
| 63 | public function one(string|Closure|null $map = null, ?int $fetchMode = null): array|object |
| 64 | { |
| 65 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 66 | $this->executeFresh(); |
| 67 | |
| 68 | try { |
| 69 | $record = $this->fetchArrayRecord($fetchMode); |
| 70 | |
| 71 | if ($record === null) { |
| 75 | if ($this->fetchArrayRecord($fetchMode) !== null) { |
| 79 | return $this->hydrateRecord($record, $map); |
| 79 | return $this->hydrateRecord($record, $map); |
| 287 | private function prepare(PDO $pdo): void |
| 288 | { |
| 289 | try { |
| 290 | $stmt = $pdo->prepare($this->query); |
| 297 | $this->pdo = $pdo; |
| 298 | $this->stmt = $stmt; |
| 299 | |
| 300 | if ($this->args->count() > 0) { |
| 301 | $this->bindArgs($this->args->get(), $this->args->type()); |
| 302 | } |
| 303 | } |
| 303 | } |
| 287 | private function prepare(PDO $pdo): void |
| 288 | { |
| 289 | try { |
| 290 | $stmt = $pdo->prepare($this->query); |
| 297 | $this->pdo = $pdo; |
| 298 | $this->stmt = $stmt; |
| 299 | |
| 300 | if ($this->args->count() > 0) { |
| 303 | } |
| 291 | } catch (PDOException $e) { |
| 292 | $this->fail($pdo, $e); |
| 293 | } |
| 294 | |
| 295 | // Only a prepared statement switches the query to the connection; |
| 296 | // otherwise its next execution would not prepare it again. |
| 297 | $this->pdo = $pdo; |
| 297 | $this->pdo = $pdo; |
| 298 | $this->stmt = $stmt; |
| 299 | |
| 300 | if ($this->args->count() > 0) { |
| 301 | $this->bindArgs($this->args->get(), $this->args->type()); |
| 302 | } |
| 303 | } |
| 303 | } |
| 291 | } catch (PDOException $e) { |
| 292 | $this->fail($pdo, $e); |
| 293 | } |
| 294 | |
| 295 | // Only a prepared statement switches the query to the connection; |
| 296 | // otherwise its next execution would not prepare it again. |
| 297 | $this->pdo = $pdo; |
| 297 | $this->pdo = $pdo; |
| 298 | $this->stmt = $stmt; |
| 299 | |
| 300 | if ($this->args->count() > 0) { |
| 303 | } |
| 258 | $this->executed = false; |
| 259 | |
| 260 | return $this->executeStatement(); |
| 261 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 184 | throw new InvalidArgumentException('Hydration requires PDO::FETCH_ASSOC.'); |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 184 | throw new InvalidArgumentException('Hydration requires PDO::FETCH_ASSOC.'); |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 184 | throw new InvalidArgumentException('Hydration requires PDO::FETCH_ASSOC.'); |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 184 | throw new InvalidArgumentException('Hydration requires PDO::FETCH_ASSOC.'); |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 188 | throw new InvalidArgumentException( |
| 189 | 'Unsupported fetch mode. Use PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, or PDO::FETCH_NAMED.', |
| 179 | private function terminalOptions(string|Closure|null $map, ?int $fetchMode): int |
| 180 | { |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 181 | $mode = $fetchMode ?? ($map === null ? $this->db->getFetchMode() : PDO::FETCH_ASSOC); |
| 182 | |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 183 | if ($map !== null && $mode !== PDO::FETCH_ASSOC) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 187 | if (!in_array($mode, [PDO::FETCH_ASSOC, PDO::FETCH_NUM, PDO::FETCH_BOTH, PDO::FETCH_NAMED], true)) { |
| 193 | return $mode; |
| 194 | } |
| 313 | $pdo = $this->db->getConn(); |
| 314 | |
| 315 | if ($pdo !== $this->pdo) { |
| 316 | $this->prepare($pdo); |
| 317 | } |
| 318 | } |
| 318 | } |
| 313 | $pdo = $this->db->getConn(); |
| 314 | |
| 315 | if ($pdo !== $this->pdo) { |
| 318 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 136 | return $records; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 136 | return $records; |
| 136 | return $records; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 147 | $this->stmt->closeCursor(); |
| 148 | } |
| 149 | } |
| 127 | public function all(string|Closure|null $map = null, ?int $fetchMode = null): array |
| 128 | { |
| 129 | $fetchMode = $this->terminalOptions($map, $fetchMode); |
| 130 | $this->executeFresh(); |
| 131 | |
| 132 | try { |
| 133 | $records = $this->fetchAllRecords($fetchMode); |
| 134 | |
| 135 | if ($map === null) { |
| 139 | $result = []; |
| 140 | |
| 141 | foreach ($records as $record) { |
| 141 | foreach ($records as $record) { |
| 142 | $result[] = $this->hydrator()->hydrate($record, $map, $this->sourcePath); |
| 143 | } |
| 144 | |
| 145 | return $result; |
| 145 | return $result; |
| 325 | function (mixed $value, int|string $index) use ($argType): void { |
| 326 | if ($argType === ArgType::Named) { |
| 326 | if ($argType === ArgType::Named) { |
| 327 | $arg = ':' . $index; |
| 332 | $this->bindValue($arg, $value); |
| 333 | }, |
| 325 | function (mixed $value, int|string $index) use ($argType): void { |
| 326 | if ($argType === ArgType::Named) { |
| 329 | $arg = (int) $index + 1; // question mark placeholders are 1-indexed |
| 330 | } |
| 331 | |
| 332 | $this->bindValue($arg, $value); |
| 332 | $this->bindValue($arg, $value); |
| 333 | }, |