From 0ef47e93dbc0a7b7a6e1b5c4e665858756527053 Mon Sep 17 00:00:00 2001 From: Yurun Date: Wed, 27 Mar 2024 18:43:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20MySQL=20=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E7=A6=BB=E7=BA=BF=E7=9A=84=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=A0=81=E7=B4=A2=E5=BC=95=20(#686)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 修复 MySQL 检查是否离线的错误码索引 * 修复 * 重构为 sqlState+驱动特定错误的方式判断是否为掉线 * 去除不必要注释 * 清理代码 --- .../pgsql/src/Db/Contract/IPgsqlDb.php | 2 +- .../pgsql/src/Db/Drivers/Swoole/Driver.php | 4 ++ .../pgsql/src/Db/Drivers/SwooleNew/Driver.php | 4 ++ .../src/Db/Drivers/SwooleNew/Statement.php | 4 ++ src/Components/pgsql/src/Db/PgsqlBase.php | 7 ++- .../swoole/src/Db/Driver/Swoole/Driver.php | 14 +++--- .../swoole/src/Db/Driver/Swoole/Statement.php | 4 +- src/Db/Drivers/TPdoDriver.php | 44 ++++++++++++------- src/Db/Drivers/TPdoStatement.php | 11 ++--- src/Db/Interfaces/IDb.php | 2 +- src/Db/Mysql/Contract/IMysqlDb.php | 2 +- src/Db/Mysql/Drivers/MysqlBase.php | 5 ++- src/Db/Mysql/Drivers/Mysqli/Driver.php | 16 +++---- src/Db/Mysql/Drivers/Mysqli/Statement.php | 2 +- src/Db/SqlState.php | 29 ++++++++++++ 15 files changed, 102 insertions(+), 48 deletions(-) create mode 100644 src/Db/SqlState.php diff --git a/src/Components/pgsql/src/Db/Contract/IPgsqlDb.php b/src/Components/pgsql/src/Db/Contract/IPgsqlDb.php index 7dee87753d..dfce32a33e 100644 --- a/src/Components/pgsql/src/Db/Contract/IPgsqlDb.php +++ b/src/Components/pgsql/src/Db/Contract/IPgsqlDb.php @@ -13,5 +13,5 @@ interface IPgsqlDb extends IDb * * @param string|null $code */ - public function checkCodeIsOffline($code): bool; + public function checkCodeIsOffline(string $sqlState, $code = null): bool; } diff --git a/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php b/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php index 047fe04ffd..31d381e32b 100644 --- a/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php +++ b/src/Components/pgsql/src/Db/Drivers/Swoole/Driver.php @@ -268,6 +268,10 @@ public function errorCode() { return $this->instance->resultDiag['sqlstate'] ?? null; } + elseif (null !== $this->instance->error) + { + return '08006'; // connection_failure + } else { return ''; diff --git a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php index 6cef27777a..64ca1de785 100644 --- a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php +++ b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Driver.php @@ -261,6 +261,10 @@ public function errorCode() { return $this->instance->resultDiag['sqlstate'] ?? null; } + elseif (null !== $this->instance->error) + { + return '08006'; // connection_failure + } else { return ''; diff --git a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Statement.php b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Statement.php index 054ae2d34d..2124bf9961 100644 --- a/src/Components/pgsql/src/Db/Drivers/SwooleNew/Statement.php +++ b/src/Components/pgsql/src/Db/Drivers/SwooleNew/Statement.php @@ -132,6 +132,10 @@ public function errorCode() { return $this->stmt->resultDiag['sqlstate'] ?? null; } + elseif (null !== $this->stmt->error) + { + return '08006'; // connection_failure + } else { return ''; diff --git a/src/Components/pgsql/src/Db/PgsqlBase.php b/src/Components/pgsql/src/Db/PgsqlBase.php index fcad30603c..575467c699 100644 --- a/src/Components/pgsql/src/Db/PgsqlBase.php +++ b/src/Components/pgsql/src/Db/PgsqlBase.php @@ -6,6 +6,7 @@ use Imi\Db\Drivers\Base; use Imi\Db\Query\Interfaces\IQuery; +use Imi\Db\SqlState; use Imi\Pgsql\Db\Contract\IPgsqlDb; use Imi\Pgsql\Db\Query\PgsqlQuery; @@ -29,11 +30,9 @@ public function getDbType(): string /** * {@inheritDoc} - * - * @see http://www.postgres.cn/docs/13/errcodes-appendix.html */ - public function checkCodeIsOffline($code): bool + public function checkCodeIsOffline(string $sqlState, $code = null): bool { - return null === $code || '57P01' === $code; + return SqlState::checkCodeIsOffline($sqlState); } } diff --git a/src/Components/swoole/src/Db/Driver/Swoole/Driver.php b/src/Components/swoole/src/Db/Driver/Swoole/Driver.php index b0767d3056..dcd9a90460 100644 --- a/src/Components/swoole/src/Db/Driver/Swoole/Driver.php +++ b/src/Components/swoole/src/Db/Driver/Swoole/Driver.php @@ -94,7 +94,7 @@ public function ping(): bool { return true; } - if ($this->checkCodeIsOffline($instance->errno)) + if ($this->checkCodeIsOffline('HY000', $instance->errno)) { $this->close(); } @@ -170,7 +170,7 @@ public function beginTransaction(): bool { if (!$this->inTransaction() && !$this->instance->begin()) { - if ($this->checkCodeIsOffline($this->instance->errno)) + if ($this->checkCodeIsOffline('HY000', $this->instance->errno)) { $this->close(); } @@ -190,7 +190,7 @@ public function commit(): bool { if (!$this->instance->commit()) { - if ($this->checkCodeIsOffline($this->instance->errno)) + if ($this->checkCodeIsOffline('HY000', $this->instance->errno)) { $this->close(); } @@ -219,7 +219,7 @@ public function rollBack(?int $levels = null): bool { $this->getTransaction()->rollBack($levels); } - elseif ($this->checkCodeIsOffline($this->instance->errno)) + elseif ($this->checkCodeIsOffline('HY000', $this->instance->errno)) { $this->close(); } @@ -297,7 +297,7 @@ public function exec(string $sql): int $this->lastStmt = null; $this->lastSql = $sql; $instance = $this->instance; - if (false === $instance->query($sql) && $this->checkCodeIsOffline($this->instance->errno)) + if (false === $instance->query($sql) && $this->checkCodeIsOffline('HY000', $this->instance->errno)) { $this->close(); @@ -372,7 +372,7 @@ public function prepare(string $sql, array $driverOptions = []): IMysqlStatement { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) + if ($this->checkCodeIsOffline('HY000', $errorCode)) { $this->close(); } @@ -400,7 +400,7 @@ public function query(string $sql): IMysqlStatement { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) + if ($this->checkCodeIsOffline('HY000', $errorCode)) { $this->close(); } diff --git a/src/Components/swoole/src/Db/Driver/Swoole/Statement.php b/src/Components/swoole/src/Db/Driver/Swoole/Statement.php index 4396f99840..349774a0a1 100644 --- a/src/Components/swoole/src/Db/Driver/Swoole/Statement.php +++ b/src/Components/swoole/src/Db/Driver/Swoole/Statement.php @@ -159,7 +159,7 @@ public function execute(array $inputParameters = null): bool $dbInstance = $db->getInstance(); $errorCode = $dbInstance->errorCode(); $errorInfo = $dbInstance->errorInfo(); - if ($db->checkCodeIsOffline($errorCode)) + if ($db->checkCodeIsOffline('HY000', $errorCode)) { $db->close(); } @@ -221,7 +221,7 @@ public function execute(array $inputParameters = null): bool { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->db->checkCodeIsOffline($errorCode)) + if ($this->db->checkCodeIsOffline('HY000', $errorCode)) { $this->db->close(); } diff --git a/src/Db/Drivers/TPdoDriver.php b/src/Db/Drivers/TPdoDriver.php index 10812e386a..2c1d1553e7 100644 --- a/src/Db/Drivers/TPdoDriver.php +++ b/src/Db/Drivers/TPdoDriver.php @@ -86,15 +86,16 @@ public function ping(): bool { return true; } - // @phpstan-ignore-next-line - if ($this->checkCodeIsOffline($instance->errorCode())) + $errorInfo = $instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -149,12 +150,13 @@ public function getInstance(): ?\PDO */ public function beginTransaction(): bool { + $instance = $this->instance; try { - if (!$this->inTransaction() && !$this->instance->beginTransaction()) + if (!$this->inTransaction() && !$instance->beginTransaction()) { - // @phpstan-ignore-next-line - if ($this->checkCodeIsOffline($this->instance->errorCode())) + $errorInfo = $instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -166,7 +168,8 @@ public function beginTransaction(): bool } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -185,8 +188,8 @@ public function commit(): bool { if (!$this->instance->commit()) { - // @phpstan-ignore-next-line - if ($this->checkCodeIsOffline($this->instance->errorCode())) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -196,7 +199,8 @@ public function commit(): bool } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -219,7 +223,8 @@ public function rollBack(?int $levels = null): bool } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -236,9 +241,13 @@ public function rollBack(?int $levels = null): bool $this->getTransaction()->rollBack($levels); } // @phpstan-ignore-next-line - elseif ($this->checkCodeIsOffline($this->instance->errorCode())) + else { - $this->close(); + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) + { + $this->close(); + } } return $result; @@ -328,7 +337,8 @@ public function exec(string $sql): int } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -405,7 +415,8 @@ public function prepare(string $sql, array $driverOptions = []): IStatement } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } @@ -439,7 +450,8 @@ public function query(string $sql): IStatement } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $this->instance->errorInfo(); + if ($this->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->close(); } diff --git a/src/Db/Drivers/TPdoStatement.php b/src/Db/Drivers/TPdoStatement.php index 7e7de8fe5e..330ce745b0 100644 --- a/src/Db/Drivers/TPdoStatement.php +++ b/src/Db/Drivers/TPdoStatement.php @@ -125,9 +125,9 @@ public function getSql(): string */ public function execute(array $inputParameters = null): bool { + $statement = $this->statement; try { - $statement = $this->statement; $statement->closeCursor(); if ($inputParameters) { @@ -147,18 +147,19 @@ public function execute(array $inputParameters = null): bool if (!$result) { $errorCode = $this->errorCode(); - $errorInfo = $this->errorInfo(); - if ($this->db->checkCodeIsOffline($errorCode)) + $errorInfo = $statement->errorInfo(); + if ($this->db->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->db->close(); } - throw new DbException('SQL query error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $this->getSql() . \PHP_EOL); + throw new DbException('SQL query error [' . $errorCode . '] ' . $errorInfo[2] . \PHP_EOL . 'sql: ' . $this->getSql() . \PHP_EOL); } $this->updateLastInsertId(); } catch (\PDOException $e) { - if (isset($e->errorInfo[0]) && $this->db->checkCodeIsOffline($e->errorInfo[0])) + $errorInfo = $statement->errorInfo(); + if ($this->db->checkCodeIsOffline($errorInfo[0], $errorInfo[1])) { $this->db->close(); } diff --git a/src/Db/Interfaces/IDb.php b/src/Db/Interfaces/IDb.php index da8338dce5..bb2df73127 100644 --- a/src/Db/Interfaces/IDb.php +++ b/src/Db/Interfaces/IDb.php @@ -152,5 +152,5 @@ public function getOption(): array; * * @param mixed $code */ - public function checkCodeIsOffline($code): bool; + public function checkCodeIsOffline(string $sqlState, $code = null): bool; } diff --git a/src/Db/Mysql/Contract/IMysqlDb.php b/src/Db/Mysql/Contract/IMysqlDb.php index caa939bb4c..975f815f08 100644 --- a/src/Db/Mysql/Contract/IMysqlDb.php +++ b/src/Db/Mysql/Contract/IMysqlDb.php @@ -13,5 +13,5 @@ interface IMysqlDb extends IDb * * @param int $code */ - public function checkCodeIsOffline($code): bool; + public function checkCodeIsOffline(string $sqlState, $code = null): bool; } diff --git a/src/Db/Mysql/Drivers/MysqlBase.php b/src/Db/Mysql/Drivers/MysqlBase.php index 0d0d20a923..af3ff4d426 100644 --- a/src/Db/Mysql/Drivers/MysqlBase.php +++ b/src/Db/Mysql/Drivers/MysqlBase.php @@ -8,6 +8,7 @@ use Imi\Db\Mysql\Contract\IMysqlDb; use Imi\Db\Mysql\Query\MysqlQuery; use Imi\Db\Query\Interfaces\IQuery; +use Imi\Db\SqlState; abstract class MysqlBase extends Base implements IMysqlDb { @@ -32,7 +33,7 @@ public function getDbType(): string * * @see https://github.com/mysql/mysql-server/blob/HEAD/include/errmsg.h */ - public function checkCodeIsOffline($code): bool + public function checkCodeIsOffline(string $sqlState, $code = null): bool { return \in_array($code, [ 2001, // CR_SOCKET_CREATE_ERROR @@ -45,6 +46,6 @@ public function checkCodeIsOffline($code): bool 2012, // CR_SERVER_HANDSHAKE_ERR 2013, // CR_SERVER_LOST 2026, // CR_SSL_CONNECTION_ERROR - ]); + ]) || SqlState::checkCodeIsOffline($sqlState); } } diff --git a/src/Db/Mysql/Drivers/Mysqli/Driver.php b/src/Db/Mysql/Drivers/Mysqli/Driver.php index 45dbacf692..ba6160ffd7 100644 --- a/src/Db/Mysql/Drivers/Mysqli/Driver.php +++ b/src/Db/Mysql/Drivers/Mysqli/Driver.php @@ -97,7 +97,7 @@ public function ping(): bool { return true; } - if ($this->checkCodeIsOffline($instance->errno)) + if ($this->checkCodeIsOffline($instance->sqlstate, $instance->errno)) { $this->close(); } @@ -156,7 +156,7 @@ public function beginTransaction(): bool { if (!$this->inTransaction() && !$this->instance->begin_transaction()) { - if ($this->checkCodeIsOffline($this->instance->errno)) + if ($this->checkCodeIsOffline($this->instance->sqlstate, $this->instance->errno)) { $this->close(); } @@ -176,7 +176,7 @@ public function commit(): bool { if (!$this->instance->commit()) { - if ($this->checkCodeIsOffline($this->instance->errno)) + if ($this->checkCodeIsOffline($this->instance->sqlstate, $this->instance->errno)) { $this->close(); } @@ -205,7 +205,7 @@ public function rollBack(?int $levels = null): bool { $this->getTransaction()->rollBack($levels); } - elseif ($this->checkCodeIsOffline($this->instance->errno)) + elseif ($this->checkCodeIsOffline($this->instance->sqlstate, $this->instance->errno)) { $this->close(); } @@ -275,7 +275,7 @@ public function exec(string $sql): int $this->lastSql = $sql; $instance = $this->instance; $this->lastStmt = null; - if (false === $instance->query($sql) && $this->checkCodeIsOffline($this->instance->errno)) + if (false === $instance->query($sql) && $this->checkCodeIsOffline($instance->sqlstate, $this->instance->errno)) { $this->close(); @@ -297,7 +297,7 @@ public function batchExec(string $sql): array { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) + if ($this->checkCodeIsOffline($instance->sqlstate, $errorCode)) { $this->close(); } @@ -379,7 +379,7 @@ public function prepare(string $sql, array $driverOptions = []): IMysqlStatement { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) + if ($this->checkCodeIsOffline($this->instance->sqlstate, $errorCode)) { $this->close(); } @@ -408,7 +408,7 @@ public function query(string $sql): IMysqlStatement { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->checkCodeIsOffline($errorCode)) + if ($this->checkCodeIsOffline($this->instance->sqlstate, $errorCode)) { $this->close(); } diff --git a/src/Db/Mysql/Drivers/Mysqli/Statement.php b/src/Db/Mysql/Drivers/Mysqli/Statement.php index 14985a132a..d21855f0fd 100644 --- a/src/Db/Mysql/Drivers/Mysqli/Statement.php +++ b/src/Db/Mysql/Drivers/Mysqli/Statement.php @@ -183,7 +183,7 @@ public function execute(array $inputParameters = null): bool { $errorCode = $this->errorCode(); $errorInfo = $this->errorInfo(); - if ($this->db->checkCodeIsOffline($errorCode)) + if ($this->db->checkCodeIsOffline($statement->sqlstate, $errorCode)) { $this->db->close(); } diff --git a/src/Db/SqlState.php b/src/Db/SqlState.php new file mode 100644 index 0000000000..76e2fe84e7 --- /dev/null +++ b/src/Db/SqlState.php @@ -0,0 +1,29 @@ +