From 7cba0e638589e16a31e571dc9d22a860a557d22b Mon Sep 17 00:00:00 2001 From: Luiz Barni Date: Fri, 3 Jan 2025 19:22:44 -0300 Subject: [PATCH 1/2] made it compatible with its dependencies --- src/MysqlConnection.php | 71 +++++++++++++++++++++-------------------- src/MysqlDriver.php | 31 ++++++++++-------- src/MysqlException.php | 5 +-- src/MysqlResult.php | 15 +++++---- src/MysqlStatement.php | 33 +++++++++++-------- 5 files changed, 85 insertions(+), 70 deletions(-) diff --git a/src/MysqlConnection.php b/src/MysqlConnection.php index 48d38ed..bac33e4 100644 --- a/src/MysqlConnection.php +++ b/src/MysqlConnection.php @@ -2,32 +2,41 @@ namespace Amp\Mysql\DBAL; -use Amp\Mysql\Connection as SqlConnection; -use Amp\Mysql\Result as SqlResult; +use Amp\Mysql\MysqlConnection as AmphpMysqlConnection; +use Amp\Mysql\MysqlResult as AmphpMysqlResult; +use Closure; +use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\Driver\Result; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\ParameterType; -use function Amp\await; -use function Amp\Pipeline\discard; +use Error; +use Throwable; +use function Amp\Future\await; -class MysqlConnection implements ServerInfoAwareConnection +class MysqlConnection implements Connection { - private SqlConnection $connection; - private \Closure $resultListener; - private mixed $lastInsertId; + private AmphpMysqlConnection $connection; - public function __construct(SqlConnection $connection) + private Closure $resultListener; + + private int|string|null $lastInsertId = null; + + public function __construct(AmphpMysqlConnection $connection) { $this->connection = $connection; - $this->resultListener = fn(SqlResult $result) => $this->lastInsertId = $result->getLastInsertId(); + $this->resultListener = fn(AmphpMysqlResult $result) => $this->lastInsertId = $result->getLastInsertId(); + } + + public function getNativeConnection(): AmphpMysqlConnection + { + return $this->connection; } public function prepare(string $sql): Statement { try { return new MysqlStatement($this->connection->prepare($sql), $this->resultListener); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw MysqlException::new($e); } } @@ -39,14 +48,14 @@ public function query(string $sql): Result ($this->resultListener)($result); return new MysqlResult($result); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw MysqlException::new($e); } } - public function quote($value, $type = ParameterType::STRING) + public function quote($value, $type = ParameterType::STRING): string { - throw new \Error("Not implemented, use prepared statements"); + throw new Error('Not implemented, use prepared statements'); } public function exec(string $sql): int @@ -56,51 +65,45 @@ public function exec(string $sql): int ($this->resultListener)($result); return $result->getRowCount(); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw MysqlException::new($e); } } - public function lastInsertId($name = null) + public function lastInsertId($name = null): int|string { return $this->lastInsertId; } - public function beginTransaction(): bool + public function beginTransaction(): void { try { - await(discard($this->connection->query("START TRANSACTION"))); - - return true; - } catch (\Throwable $e) { + await($this->connection->query('START TRANSACTION')); + } catch (Throwable $e) { throw MysqlException::new($e); } } - public function commit(): bool + public function commit(): void { try { - await(discard($this->connection->query("COMMIT"))); - - return true; - } catch (\Throwable $e) { + await($this->connection->query('COMMIT')); + } catch (Throwable $e) { throw MysqlException::new($e); } } - public function rollBack(): bool + public function rollBack(): void { try { - await(discard($this->connection->query("ROLLBACK"))); - - return true; - } catch (\Throwable $e) { + await($this->connection->query('ROLLBACK')); + } catch (Throwable $e) { throw MysqlException::new($e); } } public function getServerVersion(): string { - return $this->query("SELECT @@version")->fetchOne(); + return $this->query('SELECT @@version')->fetchOne(); } -} \ No newline at end of file +} diff --git a/src/MysqlDriver.php b/src/MysqlDriver.php index 1ad2901..d48846c 100644 --- a/src/MysqlDriver.php +++ b/src/MysqlDriver.php @@ -2,31 +2,36 @@ namespace Amp\Mysql\DBAL; -use Amp\Mysql\CancellableConnector; -use Amp\Mysql\ConnectionConfig; -use Amp\Socket\StaticConnector; +use Amp\Mysql\MysqlConfig; +use Amp\Mysql\SocketMysqlConnector; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\Connection; -use function Amp\Socket\connector; +use Throwable; +use function Amp\Mysql\mysqlConnector; final class MysqlDriver extends Driver\AbstractMySQLDriver { public function connect(array $params): Connection { - $config = new ConnectionConfig($params['host'] ?? 'localhost', - $params['port'] ?? ConnectionConfig::DEFAULT_PORT, - $params['user'] ?? '', $params['password'] ?? '', $params['dbname'] ?? null, null, - $params['charset'] ?? ConnectionConfig::DEFAULT_CHARSET); + $config = new MysqlConfig( + $params['host'] ?? 'localhost', + $params['port'] ?? MysqlConfig::DEFAULT_PORT, + $params['user'] ?? '', + $params['password'] ?? '', + $params['dbname'] ?? null, + null, + $params['charset'] ?? MysqlConfig::DEFAULT_CHARSET + ); - $connector = connector(); + $connector = mysqlConnector(); if (isset($params['unix_socket'])) { - $connector = new StaticConnector('unix:' . $params['unix_socket'], $connector); + $connector = new SocketMysqlConnector(); } try { - return new MysqlConnection((new CancellableConnector($connector))->connect($config)); - } catch (\Throwable $e) { + return new MysqlConnection($connector->connect($config)); + } catch (Throwable $e) { throw MysqlException::new($e); } } -} \ No newline at end of file +} diff --git a/src/MysqlException.php b/src/MysqlException.php index 7259ef5..9cd7f70 100644 --- a/src/MysqlException.php +++ b/src/MysqlException.php @@ -3,11 +3,12 @@ namespace Amp\Mysql\DBAL; use Doctrine\DBAL\Driver\AbstractException; +use Throwable; final class MysqlException extends AbstractException { - public static function new(\Throwable $exception): self + public static function new(Throwable $exception): self { return new self($exception->getMessage(), null, $exception->getCode(), $exception); } -} \ No newline at end of file +} diff --git a/src/MysqlResult.php b/src/MysqlResult.php index 320c85b..3473491 100644 --- a/src/MysqlResult.php +++ b/src/MysqlResult.php @@ -2,9 +2,11 @@ namespace Amp\Mysql\DBAL; -use Amp\Mysql\Result as SqlResult; +use Amp\Mysql\MysqlResult as SqlResult; use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\Result; +use function array_values; +use function count; class MysqlResult implements Result { @@ -22,16 +24,16 @@ public function fetchNumeric(): array|false return false; } - return \array_values($row); + return array_values($row); } public function fetchAssociative(): array|false { /** @noinspection ProperNullCoalescingOperatorUsageInspection */ - return $this->result->continue() ?? false; + return $this->result->fetchRow() ?? false; } - public function fetchOne() + public function fetchOne(): mixed { return FetchUtils::fetchOne($this); } @@ -58,11 +60,10 @@ public function rowCount(): int public function columnCount(): int { - return \count($this->result->getFields()); + return count($this->result->getColumnDefinitions()); } public function free(): void { - $this->result->dispose(); } -} \ No newline at end of file +} diff --git a/src/MysqlStatement.php b/src/MysqlStatement.php index b0d9d1e..01aab01 100644 --- a/src/MysqlStatement.php +++ b/src/MysqlStatement.php @@ -2,36 +2,41 @@ namespace Amp\Mysql\DBAL; -use Amp\Mysql\Statement as SqlStatement; +use Amp\Mysql\MysqlStatement as SqlStatement; +use Closure; use Doctrine\DBAL\Driver\Exception; use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\ParameterType; +use Throwable; +use function is_int; class MysqlStatement implements Statement { private const PARAM_TYPES = [ - ParameterType::NULL => null, - ParameterType::INTEGER => null, - ParameterType::STRING => null, - ParameterType::ASCII => null, - ParameterType::BINARY => null, - ParameterType::LARGE_OBJECT => null, - ParameterType::BOOLEAN => null, + ParameterType::NULL => true, + ParameterType::INTEGER => true, + ParameterType::STRING => true, + ParameterType::ASCII => true, + ParameterType::BINARY => true, + ParameterType::LARGE_OBJECT => true, + ParameterType::BOOLEAN => true, ]; private SqlStatement $statement; - private \Closure $resultListener; + + private Closure $resultListener; private array $values = []; + private array $types = []; public function __construct(SqlStatement $statement, callable $resultListener) { $this->statement = $statement; - $this->resultListener = $resultListener instanceof \Closure + $this->resultListener = $resultListener instanceof Closure ? $resultListener - : \Closure::fromCallable($resultListener); + : $resultListener(...); } public function bindValue($param, $value, $type = ParameterType::STRING): bool @@ -40,7 +45,7 @@ public function bindValue($param, $value, $type = ParameterType::STRING): bool throw Exception\UnknownParameterType::new($type); } - $key = \is_int($param) ? $param - 1 : $param; + $key = is_int($param) ? $param - 1 : $param; $this->values[$key] = $this->convertValue($value, $type); @@ -81,7 +86,7 @@ public function execute($params = null): Result ($this->resultListener)($result); return new MysqlResult($result); - } catch (\Throwable $e) { + } catch (Throwable $e) { throw MysqlException::new($e); } } @@ -96,4 +101,4 @@ private function convertValue($value, int $type): null|bool|int|string default => throw Exception\UnknownParameterType::new($type), }; } -} \ No newline at end of file +} From 2332366c8fab27975408b625858ee6e65f0eb03b Mon Sep 17 00:00:00 2001 From: Luiz Barni Date: Mon, 6 Jan 2025 10:53:32 -0300 Subject: [PATCH 2/2] fixed null value conversion previously null values were being incorrectly casted to empty strings --- src/MysqlStatement.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/MysqlStatement.php b/src/MysqlStatement.php index 01aab01..0c53f75 100644 --- a/src/MysqlStatement.php +++ b/src/MysqlStatement.php @@ -93,6 +93,11 @@ public function execute($params = null): Result private function convertValue($value, int $type): null|bool|int|string { + // we don't want to convert or cast null values + if ($value === null) { + // Doctrine needs to receive the null value as-is + return null; + } return match ($type) { ParameterType::NULL => null, ParameterType::INTEGER => (int) $value,