From cdb8832048c23e8c1cd56ac0fcb1fca7b18d073d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 5 Sep 2024 03:45:58 +0200 Subject: [PATCH] decorators WIP --- src/Bridges/DatabaseTracy/ConnectionPanel.php | 19 ++-- .../Accessory/ExceptionHandlingConnection.php | 98 +++++++++++++++++++ .../Accessory/ExceptionHandlingResult.php | 54 ++++++++++ .../Drivers/Accessory/LazyConnection.php | 71 ++++---------- .../Drivers/Accessory/LoggingConnection.php | 86 ++++++++++++++++ .../Accessory/ReconnectingConnection.php | 79 +++++++++++++++ src/Database/Drivers/Decorator/Connection.php | 87 ++++++++++++++++ .../Drivers/Decorator/ConnectionDecorator.php | 22 +++++ src/Database/Drivers/Decorator/Result.php | 69 +++++++++++++ .../Drivers/Decorator/ResultDecorator.php | 22 +++++ src/Database/Drivers/PDO/Connection.php | 57 +++-------- src/Database/Drivers/PDO/Driver.php | 29 ++++-- src/Database/Drivers/PDO/MySQL/Driver.php | 2 +- src/Database/Drivers/PDO/PgSQL/Driver.php | 4 +- src/Database/Drivers/PDO/Result.php | 28 ++---- src/Database/Drivers/PDO/SQLSrv/Driver.php | 4 +- src/Database/Drivers/PDO/SQLite/Driver.php | 4 +- src/Database/Explorer.php | 97 +++++++----------- src/Database/Result.php | 7 -- .../Explorer/Explorer.cache.observer.phpt | 8 +- tests/Database/Explorer/Explorer.cache.phpt | 4 +- 21 files changed, 639 insertions(+), 212 deletions(-) create mode 100644 src/Database/Drivers/Accessory/ExceptionHandlingConnection.php create mode 100644 src/Database/Drivers/Accessory/ExceptionHandlingResult.php create mode 100644 src/Database/Drivers/Accessory/LoggingConnection.php create mode 100644 src/Database/Drivers/Accessory/ReconnectingConnection.php create mode 100644 src/Database/Drivers/Decorator/Connection.php create mode 100644 src/Database/Drivers/Decorator/ConnectionDecorator.php create mode 100644 src/Database/Drivers/Decorator/Result.php create mode 100644 src/Database/Drivers/Decorator/ResultDecorator.php diff --git a/src/Bridges/DatabaseTracy/ConnectionPanel.php b/src/Bridges/DatabaseTracy/ConnectionPanel.php index ba6abdcc8..d8d49dc03 100644 --- a/src/Bridges/DatabaseTracy/ConnectionPanel.php +++ b/src/Bridges/DatabaseTracy/ConnectionPanel.php @@ -10,10 +10,12 @@ namespace Nette\Bridges\DatabaseTracy; use Nette; +use Nette\Database\Drivers; use Nette\Database\DriverException; use Nette\Database\Explorer; use Nette\Database\Helpers; use Nette\Database\Result; +use Nette\Database\SqlLiteral; use Tracy; @@ -64,13 +66,14 @@ public function __construct(Explorer $explorer, Tracy\BlueScreen $blueScreen) } - private function logQuery(Explorer $connection, $result): void + private function logQuery(Explorer $connection, mixed $result, SqlLiteral $query, ?float $time): void { if ($this->disabled) { return; } $this->count++; + $this->totalTime += $time; $source = null; $trace = $result instanceof DriverException @@ -89,13 +92,13 @@ private function logQuery(Explorer $connection, $result): void } } - if ($result instanceof Result) { - $this->totalTime += $result->getTime(); - if ($this->count < $this->maxQueries) { - $this->events[] = [$connection, $result->getQuery(), $source, $result->getTime(), $result->getRowCount(), null]; - } - } elseif ($result instanceof DriverException && $this->count < $this->maxQueries) { - $this->events[] = [$connection, $result->getQuery(), $source, null, null, $result->getMessage()]; + if ($this->count >= $this->maxQueries) { + // nothing + } elseif ($result instanceof DriverException) { + $this->events[] = [$connection, $query, $source, null, null, $result->getMessage()]; + } else { + $rowCount = $result instanceof Drivers\Result ? $result->getRowCount() : $result; + $this->events[] = [$connection, $query, $source, $time, $rowCount, null]; } } diff --git a/src/Database/Drivers/Accessory/ExceptionHandlingConnection.php b/src/Database/Drivers/Accessory/ExceptionHandlingConnection.php new file mode 100644 index 000000000..a30670b3b --- /dev/null +++ b/src/Database/Drivers/Accessory/ExceptionHandlingConnection.php @@ -0,0 +1,98 @@ +innerConnection->query($sql, $params), + $this->translator, + ); + } catch (\Throwable $e) { + throw ($this->translator)($e, new SqlLiteral($sql), $params); + } + } + + + public function execute(string $sql): int + { + try { + return $this->innerConnection->execute($sql); + } catch (\Throwable $e) { + throw ($this->translator)($e, new SqlLiteral($sql)); + } + } + + + public function beginTransaction(): void + { + try { + $this->innerConnection->beginTransaction(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function commit(): void + { + try { + $this->innerConnection->commit(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function rollBack(): void + { + try { + $this->innerConnection->rollBack(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function getInsertId(?string $sequence = null): int|string + { + try { + return $this->innerConnection->getInsertId($sequence); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function getServerVersion(): string + { + try { + return $this->innerConnection->getServerVersion(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } +} diff --git a/src/Database/Drivers/Accessory/ExceptionHandlingResult.php b/src/Database/Drivers/Accessory/ExceptionHandlingResult.php new file mode 100644 index 000000000..23f532ac6 --- /dev/null +++ b/src/Database/Drivers/Accessory/ExceptionHandlingResult.php @@ -0,0 +1,54 @@ +innerResult->fetch(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function fetchList(): ?array + { + try { + return $this->innerResult->fetchList(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } + + + public function getColumnsInfo(): array + { + try { + return $this->innerResult->getColumnsInfo(); + } catch (\Throwable $e) { + throw ($this->translator)($e); + } + } +} diff --git a/src/Database/Drivers/Accessory/LazyConnection.php b/src/Database/Drivers/Accessory/LazyConnection.php index 2755def89..d140bb235 100644 --- a/src/Database/Drivers/Accessory/LazyConnection.php +++ b/src/Database/Drivers/Accessory/LazyConnection.php @@ -10,72 +10,35 @@ namespace Nette\Database\Drivers\Accessory; use Nette\Database\Drivers; +use Nette\Database\Drivers\Decorator; -final class LazyConnection implements Drivers\Connection +final class LazyConnection extends Decorator\Connection { public function __construct( - private \Closure $callback, + /** @var \Closure(self): void */ + private \Closure $factory, ) { + unset($this->innerConnection); } - private function getConnection(): Drivers\Connection + public function setInnerConnection(?Drivers\Connection $connection): static { - return ($this->callback)(); + if ($connection) { + $this->innerConnection = $connection; + } else { + unset($this->innerConnection); + } + return $this; } - public function query(string $sql, array $params = []): Drivers\Result + public function __get(string $name): mixed { - return $this->getConnection()->query($sql, $params); - } - - - public function execute(string $sql): int - { - return $this->getConnection()->execute($sql); - } - - - public function getNativeConnection(): mixed - { - return $this->getConnection()->getNativeConnection(); - } - - - public function beginTransaction(): void - { - $this->getConnection()->beginTransaction(); - } - - - public function commit(): void - { - $this->getConnection()->commit(); - } - - - public function rollBack(): void - { - $this->getConnection()->rollBack(); - } - - - public function getInsertId(?string $sequence = null): int|string - { - return $this->getConnection()->getInsertId($sequence); - } - - - public function quote(string $string): string - { - return $this->getConnection()->quote($string); - } - - - public function getServerVersion(): string - { - return $this->getConnection()->getServerVersion(); + if ($name === 'innerConnection') { + ($this->factory)($this); + return $this->innerConnection ?? null; + } } } diff --git a/src/Database/Drivers/Accessory/LoggingConnection.php b/src/Database/Drivers/Accessory/LoggingConnection.php new file mode 100644 index 000000000..5113beafd --- /dev/null +++ b/src/Database/Drivers/Accessory/LoggingConnection.php @@ -0,0 +1,86 @@ +logOperation( + fn() => $this->innerConnection->query($sql, $params), + new SqlLiteral($sql, $params), + ); + } + + + public function execute(string $sql): int + { + return $this->logOperation( + fn() => $this->innerConnection->execute($sql), + new SqlLiteral($sql), + ); + } + + + public function beginTransaction(): void + { + $this->logOperation( + fn() => $this->innerConnection->beginTransaction(), + new SqlLiteral('BEGIN TRANSACTION'), + ); + } + + + public function commit(): void + { + $this->logOperation( + fn() => $this->innerConnection->commit(), + new SqlLiteral('COMMIT'), + ); + } + + + public function rollBack(): void + { + $this->logOperation( + fn() => $this->innerConnection->rollBack(), + new SqlLiteral('ROLLBACK'), + ); + } + + + private function logOperation(callable $operation, SqlLiteral $query): mixed + { + $time = microtime(true); + try { + $result = $operation(); + } catch (\Throwable $e) { + ($this->logger)($e, $query, null); + throw $e; + } + + $time = microtime(true) - $time; + ($this->logger)($result, $query, $time); + return $result; + } +} diff --git a/src/Database/Drivers/Accessory/ReconnectingConnection.php b/src/Database/Drivers/Accessory/ReconnectingConnection.php new file mode 100644 index 000000000..6743731ca --- /dev/null +++ b/src/Database/Drivers/Accessory/ReconnectingConnection.php @@ -0,0 +1,79 @@ +tryOperation( + fn() => $this->innerConnection->query($sql, $params), + ); + } + + + public function execute(string $sql): int + { + return $this->tryOperation( + fn() => $this->innerConnection->execute($sql), + ); + } + + + public function beginTransaction(): void + { + $this->tryOperation( + fn() => $this->innerConnection->beginTransaction(), + ); + } + + + public function commit(): void + { + $this->tryOperation( + fn() => $this->innerConnection->commit(), + ); + } + + + public function rollBack(): void + { + $this->tryOperation( + fn() => $this->innerConnection->rollBack(), + ); + } + + + private function tryOperation(callable $operation): mixed + { + $attempts = 0; + while (true) { + try { + return $operation(); + } catch (ConnectionLostException $e) { + if (++$attempts > $this->maxRetries) { + throw $e; + } + $this->innerConnection->connect(); // TODO + } + } + } +} diff --git a/src/Database/Drivers/Decorator/Connection.php b/src/Database/Drivers/Decorator/Connection.php new file mode 100644 index 000000000..b06dec440 --- /dev/null +++ b/src/Database/Drivers/Decorator/Connection.php @@ -0,0 +1,87 @@ + + */ +abstract class Connection implements ConnectionDecorator +{ + public function __construct( + /** @var T */ + protected Drivers\Connection $innerConnection, + ) { + } + + + /** @return T */ + public function getInnerConnection(): Drivers\Connection + { + return $this->innerConnection; + } + + + public function query(string $sql, array $params = []): Drivers\Result + { + return $this->innerConnection->query($sql, $params); + } + + + public function execute(string $sql): int + { + return $this->innerConnection->execute($sql); + } + + + public function getNativeConnection(): mixed + { + return $this->innerConnection->getNativeConnection(); + } + + + public function beginTransaction(): void + { + $this->innerConnection->beginTransaction(); + } + + + public function commit(): void + { + $this->innerConnection->commit(); + } + + + public function rollBack(): void + { + $this->innerConnection->rollBack(); + } + + + public function getInsertId(?string $sequence = null): int|string + { + return $this->innerConnection->getInsertId($sequence); + } + + + public function quote(string $string): string + { + return $this->innerConnection->quote($string); + } + + + public function getServerVersion(): string + { + return $this->innerConnection->getServerVersion(); + } +} diff --git a/src/Database/Drivers/Decorator/ConnectionDecorator.php b/src/Database/Drivers/Decorator/ConnectionDecorator.php new file mode 100644 index 000000000..2fd1bc596 --- /dev/null +++ b/src/Database/Drivers/Decorator/ConnectionDecorator.php @@ -0,0 +1,22 @@ + + */ +abstract class Result implements ResultDecorator +{ + public function __construct( + /** @var T */ + protected Drivers\Result $innerResult, + ) { + } + + + /** @return T */ + public function getInnerResult(): Drivers\Result + { + return $this->innerResult; + } + + + public function fetch(): ?array + { + return $this->innerResult->fetch(); + } + + + public function fetchList(): ?array + { + return $this->innerResult->fetchList(); + } + + + public function getColumnCount(): int + { + return $this->innerResult->getColumnCount(); + } + + + public function getRowCount(): int + { + return $this->innerResult->getRowCount(); + } + + + public function getColumnsInfo(): array + { + return $this->innerResult->getColumnsInfo(); + } + + + public function free(): void + { + $this->innerResult->free(); + } +} diff --git a/src/Database/Drivers/Decorator/ResultDecorator.php b/src/Database/Drivers/Decorator/ResultDecorator.php new file mode 100644 index 000000000..fba79fe53 --- /dev/null +++ b/src/Database/Drivers/Decorator/ResultDecorator.php @@ -0,0 +1,22 @@ + PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT, 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL]; - - try { - $statement = $this->pdo->prepare($sql); - foreach ($params as $key => $value) { - $statement->bindValue(is_int($key) ? $key + 1 : $key, $value, $types[gettype($value)] ?? PDO::PARAM_STR); - } - $statement->execute(); - return new ($this->resultClass)($statement, $this); - - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e, new SqlLiteral($sql, $params))); + $statement = $this->pdo->prepare($sql); + foreach ($params as $key => $value) { + $statement->bindValue(is_int($key) ? $key + 1 : $key, $value, $types[gettype($value)] ?? PDO::PARAM_STR); } + $statement->execute(); + return new ($this->resultClass)($statement, $this); } public function execute(string $sql): int { - try { - return $this->pdo->exec($sql); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e, new SqlLiteral($sql))); - } + return $this->pdo->exec($sql); } public function beginTransaction(): void { - try { - $this->pdo->beginTransaction(); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); - } + $this->pdo->beginTransaction(); } public function commit(): void { - try { - $this->pdo->commit(); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); - } + $this->pdo->commit(); } public function rollBack(): void { - try { - $this->pdo->rollBack(); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); - } + $this->pdo->rollBack(); } public function getInsertId(?string $sequence = null): int|string { - try { - $id = $this->pdo->lastInsertId($sequence); - if ($id === '0' || $id === '' || $id === false) { - throw new DriverException('Cannot retrieve last generated ID.'); - } - $int = (int) $id; - return $id === (string) $int ? $int : $id; - - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); + $id = $this->pdo->lastInsertId($sequence); + if ($id === '0' || $id === '' || $id === false) { + throw new DriverException('Cannot retrieve last generated ID.'); } + $int = (int) $id; + return $id === (string) $int ? $int : $id; } diff --git a/src/Database/Drivers/PDO/Driver.php b/src/Database/Drivers/PDO/Driver.php index 21b2f1139..cdd958988 100644 --- a/src/Database/Drivers/PDO/Driver.php +++ b/src/Database/Drivers/PDO/Driver.php @@ -9,8 +9,10 @@ namespace Nette\Database\Drivers\PDO; +use Nette\Database\ConnectionException; use Nette\Database\DriverException; use Nette\Database\Drivers; +use Nette\Database\Drivers\Accessory\ExceptionHandlingConnection; use Nette\Database\SqlLiteral; use PDOException; @@ -30,19 +32,34 @@ public function __construct( } - public function connect(): Connection + /** @return ExceptionHandlingConnection */ + public function connect(): Drivers\Connection + { + return new ExceptionHandlingConnection($this->createConnection(), $this->translateException(...)); + } + + + protected function createConnection(): Connection { try { - $pdo = new \PDO($this->dsn, $this->username, $this->password, $this->options); + return new Connection(new \PDO($this->dsn, $this->username, $this->password, $this->options)); } catch (PDOException $e) { - throw new DriverException(...self::exceptionArgs($e)); + throw ConnectionException::from($this->translateException($e)); // TODO } - return new Connection($pdo); } - public static function exceptionArgs(PDOException $e, ?SqlLiteral $query = null): array + private function translateException(\Throwable $e, ?SqlLiteral $query = null): \Throwable { - return [$e->getMessage(), $e->errorInfo[0] ?? null, $e->errorInfo[1] ?? 0, $query, $e]; + if ($e instanceof PDOException) { + $e = new DriverException($e->getMessage(), $e->errorInfo[0] ?? null, $e->errorInfo[1] ?? 0, $query, $e); + } + if ( + $e instanceof DriverException + && ($class = $this->createEngine(new Drivers\Accessory\LazyConnection(fn() => null))->classifyException($e)) + ) { + $e = $class::from($e); + } + return $e; } } diff --git a/src/Database/Drivers/PDO/MySQL/Driver.php b/src/Database/Drivers/PDO/MySQL/Driver.php index c6e5ccb6f..c8d06b63b 100644 --- a/src/Database/Drivers/PDO/MySQL/Driver.php +++ b/src/Database/Drivers/PDO/MySQL/Driver.php @@ -33,7 +33,7 @@ public function __construct( } - public function connect(): Drivers\PDO\Connection + public function connect(): Drivers\Connection { $connection = parent::connect(); if ($this->charset) { diff --git a/src/Database/Drivers/PDO/PgSQL/Driver.php b/src/Database/Drivers/PDO/PgSQL/Driver.php index 289707b15..8712e7c89 100644 --- a/src/Database/Drivers/PDO/PgSQL/Driver.php +++ b/src/Database/Drivers/PDO/PgSQL/Driver.php @@ -18,9 +18,9 @@ */ class Driver extends Drivers\PDO\Driver { - public function connect(): Drivers\PDO\Connection + protected function createConnection(): Drivers\PDO\Connection { - $connection = parent::connect(); + $connection = parent::createConnection(); $connection->resultClass = Result::class; return $connection; } diff --git a/src/Database/Drivers/PDO/Result.php b/src/Database/Drivers/PDO/Result.php index f17b88cef..f62a885ea 100644 --- a/src/Database/Drivers/PDO/Result.php +++ b/src/Database/Drivers/PDO/Result.php @@ -11,7 +11,6 @@ use Nette\Database\DriverException; use Nette\Database\Drivers; -use PDOException; class Result implements Drivers\Result @@ -43,37 +42,24 @@ public function fetch(): ?array public function fetchList(): ?array { - try { - $row = $this->result->fetch(\PDO::FETCH_NUM); - if (!$row) { - $this->free(); - return null; - } - return $row; - - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); + $row = $this->result->fetch(\PDO::FETCH_NUM); + if (!$row) { + $this->free(); + return null; } + return $row; } public function getColumnCount(): int { - try { - return $this->result->columnCount(); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); - } + return $this->result->columnCount(); } public function getRowCount(): int { - try { - return $this->result->rowCount(); - } catch (PDOException $e) { - throw new DriverException(...Driver::exceptionArgs($e)); - } + return $this->result->rowCount(); } diff --git a/src/Database/Drivers/PDO/SQLSrv/Driver.php b/src/Database/Drivers/PDO/SQLSrv/Driver.php index 46909e970..5a51b3ffd 100644 --- a/src/Database/Drivers/PDO/SQLSrv/Driver.php +++ b/src/Database/Drivers/PDO/SQLSrv/Driver.php @@ -20,9 +20,9 @@ */ class Driver extends Drivers\PDO\Driver { - public function connect(): Drivers\PDO\Connection + protected function createConnection(): Drivers\PDO\Connection { - $connection = parent::connect(); + $connection = parent::createConnection(); $connection->metaTypeKey = 'sqlsrv:decl_type'; return $connection; } diff --git a/src/Database/Drivers/PDO/SQLite/Driver.php b/src/Database/Drivers/PDO/SQLite/Driver.php index f73619b0c..02271945d 100644 --- a/src/Database/Drivers/PDO/SQLite/Driver.php +++ b/src/Database/Drivers/PDO/SQLite/Driver.php @@ -29,9 +29,9 @@ public function __construct( } - public function connect(): Drivers\PDO\Connection + protected function createConnection(): Drivers\PDO\Connection { - $connection = parent::connect(); + $connection = parent::createConnection(); $connection->metaTypeKey = 'sqlite:decl_type'; return $connection; } diff --git a/src/Database/Explorer.php b/src/Database/Explorer.php index e500345ea..7b44418ad 100644 --- a/src/Database/Explorer.php +++ b/src/Database/Explorer.php @@ -37,7 +37,7 @@ class Explorer /** @var array Occurs after query is executed */ public array $onQuery = []; private Drivers\Driver $driver; - private ?Drivers\Connection $connection = null; + private Drivers\Connection $connection; private Drivers\Engine $engine; private SqlPreprocessor $preprocessor; private TypeConverter $typeConverter; @@ -110,35 +110,45 @@ public function __construct( $this->driver = $driver; $this->typeConverter = new TypeConverter; } + + $this->connection = new Drivers\Accessory\LazyConnection($this->createConnection(...)); + $this->engine = $this->driver->createEngine($this->connection); } - public function connect(): void + private function createConnection(Drivers\Accessory\LazyConnection $lazy): void { - if ($this->connection) { - return; - } - - try { - $this->connection = $this->driver->connect(); - } catch (DriverException $e) { - throw ConnectionException::from($e); - } + $connection = $this->driver->connect(); + $connection = new Drivers\Accessory\LoggingConnection( + $connection, + fn(mixed $result, SqlLiteral $query, ?float $time) => Arrays::invoke($this->onQuery, $this, $result, $query, $time), + ); + $lazy->setInnerConnection($connection); Arrays::invoke($this->onConnect, $this); } - public function reconnect(): void + public function connect(): void + { + $this->connection->getNativeConnection(); + } + + + public function reconnect(): void // REMOVE { $this->disconnect(); $this->connect(); } - public function disconnect(): void + public function disconnect(): void // REMOVE { - $this->connection = null; + if (!$this->connection instanceof Drivers\Accessory\LazyConnection) { + throw new \LogicException('Cannot disconnect non-lazy connection.'); + } + $this->connection->setInnerConnection(null); + $this->transactionDepth = 0; } @@ -153,13 +163,12 @@ public function getDsn(): string public function getPdo(): \PDO { trigger_error(__METHOD__ . '() is deprecated, use getConnection()->getNativeConnection()', E_USER_DEPRECATED); - return $this->getConnection()->getNativeConnection(); + return $this->connection->getNativeConnection(); } public function getConnection(): Drivers\Connection { - $this->connect(); return $this->connection; } @@ -168,25 +177,25 @@ public function getConnection(): Drivers\Connection public function getSupplementalDriver(): Drivers\Connection { trigger_error(__METHOD__ . '() is deprecated, use getConnection()', E_USER_DEPRECATED); - return $this->getConnection(); + return $this->connection; } public function getDatabaseEngine(): Drivers\Engine { - return $this->engine ??= $this->driver->createEngine(new Drivers\Accessory\LazyConnection($this->getConnection(...))); + return $this->engine; } public function getServerVersion(): string { - return $this->getConnection()->getServerVersion(); + return $this->connection->getServerVersion(); } public function getReflection(): Reflection { - return new Reflection($this->getDatabaseEngine()); + return new Reflection($this->engine); } @@ -205,17 +214,13 @@ public function setRowNormalizer(?callable $normalizer): static public function getInsertId(?string $sequence = null): int|string { - try { - return $this->getConnection()->getInsertId($sequence); - } catch (DriverException $e) { - throw $this->convertException($e); - } + return $this->connection->getInsertId($sequence); } public function quote(string $string): string { - return $this->getConnection()->quote($string); + return $this->connection->quote($string); } @@ -225,7 +230,7 @@ public function beginTransaction(): void throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback'); } - $this->logOperation($this->getConnection()->beginTransaction(...), new SqlLiteral('BEGIN TRANSACTION')); + $this->connection->beginTransaction(); } @@ -235,7 +240,7 @@ public function commit(): void throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback'); } - $this->logOperation($this->getConnection()->commit(...), new SqlLiteral('COMMIT')); + $this->connection->commit(); } @@ -245,7 +250,7 @@ public function rollBack(): void throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback'); } - $this->logOperation($this->getConnection()->rollBack(...), new SqlLiteral('ROLLBACK')); + $this->connection->rollBack(); } @@ -283,10 +288,8 @@ public function transaction(callable $callback): mixed public function query(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): Result { [$sql, $params] = $this->preprocess($sql, ...$params); - return $this->logOperation( - fn() => $this->connection->query($sql, $params), - $this->lastQuery = new SqlLiteral($sql, $params), - ); + $this->lastQuery = new SqlLiteral($sql, $params); + return new Result($this, $this->lastQuery, $this->connection->query($sql, $params)); } @@ -304,7 +307,6 @@ public function queryArgs(string $sql, array $params): Result */ public function preprocess(string $sql, ...$params): array { - $this->connect(); $this->preprocessor ??= new SqlPreprocessor($this); return $params ? $this->preprocessor->process(func_get_args()) @@ -312,24 +314,6 @@ public function preprocess(string $sql, ...$params): array } - private function logOperation(\Closure $callback, SqlLiteral $query): Result - { - try { - $time = microtime(true); - $result = $callback(); - $time = microtime(true) - $time; - } catch (DriverException $e) { - $e = $this->convertException($e); - Arrays::invoke($this->onQuery, $this, $e); - throw $e; - } - - $result = new Result($this, $query, $result, $time); - Arrays::invoke($this->onQuery, $this, $result); - return $result; - } - - public function getLastQuery(): ?SqlLiteral { return $this->lastQuery; @@ -344,13 +328,6 @@ public function getLastQueryString(): ?string } - private function convertException(DriverException $e): DriverException - { - $class = $this->getDatabaseEngine()->classifyException($e); - return $class ? $class::from($e) : $e; - } - - /********************* shortcuts ****************d*g**/ @@ -476,7 +453,7 @@ public function getConventions(): Conventions /** @internal */ public function getStructure(): Structure { - return $this->structure ??= new Structure($this->getDatabaseEngine(), $this->getCache()); + return $this->structure ??= new Structure($this->engine, $this->getCache()); } } diff --git a/src/Database/Result.php b/src/Database/Result.php index bc5b23414..580850d8e 100644 --- a/src/Database/Result.php +++ b/src/Database/Result.php @@ -29,7 +29,6 @@ public function __construct( private readonly Explorer $explorer, private readonly SqlLiteral $query, private readonly ?Drivers\Result $result, - private float $time, ) { } @@ -74,12 +73,6 @@ public function getRowCount(): ?int } - public function getTime(): float - { - return $this->time; - } - - /********************* misc tools ****************d*g**/ diff --git a/tests/Database/Explorer/Explorer.cache.observer.phpt b/tests/Database/Explorer/Explorer.cache.observer.phpt index 931a926a8..5ca0defd8 100644 --- a/tests/Database/Explorer/Explorer.cache.observer.phpt +++ b/tests/Database/Explorer/Explorer.cache.observer.phpt @@ -7,7 +7,7 @@ declare(strict_types=1); -use Nette\Database\Result; +use Nette\Database\Drivers; use Tester\Assert; require __DIR__ . '/../../bootstrap.php'; @@ -26,10 +26,10 @@ $cache->shouldReceive('save')->with(Mockery::any(), ['id' => true, 'author_id' = $explorer->setCache($cache); $queries = 0; -$explorer->onQuery[] = function ($explorer, $result) use (&$queries) { +$explorer->onQuery[] = function ($explorer, $result, $query) use (&$queries) { if ( - $result instanceof Result - && !preg_match('#SHOW|CONSTRAINT_NAME|pg_catalog|sys\.|SET|PRAGMA|FROM sqlite_#i', $result->getQuery()->getSql()) + $result instanceof Drivers\Result + && !preg_match('#SHOW|CONSTRAINT_NAME|pg_catalog|sys\.|SET|PRAGMA|FROM sqlite_#i', $query->getSql()) ) { $queries++; } diff --git a/tests/Database/Explorer/Explorer.cache.phpt b/tests/Database/Explorer/Explorer.cache.phpt index 9ec981e47..f5817670b 100644 --- a/tests/Database/Explorer/Explorer.cache.phpt +++ b/tests/Database/Explorer/Explorer.cache.phpt @@ -197,8 +197,8 @@ test('Test saving the union of needed cols, the second call is not subset', func test('Test multiple use of same selection', function () use ($explorer) { $sql = []; - $explorer->onQuery[] = function ($_, $result) use (&$sql) { - $sql[] = $result->getQueryString(); + $explorer->onQuery[] = function ($_, $result, $query) use (&$sql) { + $sql[] = $query->getSql(); }; for ($i = 0; $i < 3; ++$i) {