diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e04222e..4ae81fad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Enh #342: Add JSON overlaps condition builder (@Tigrov) - Enh #344: Update `bit` type according to main PR yiisoft/db#860 (@Tigrov) - Enh #347: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov) +- Bug #349: Restore connection if closed by connection timeout (@Tigrov) ## 1.2.0 March 21, 2024 diff --git a/src/Command.php b/src/Command.php index b8d0de6c..594c4bb5 100644 --- a/src/Command.php +++ b/src/Command.php @@ -5,6 +5,9 @@ namespace Yiisoft\Db\Mysql; use Yiisoft\Db\Driver\Pdo\AbstractPdoCommand; +use Yiisoft\Db\Exception\IntegrityException; + +use function str_starts_with; /** * Implements a database command that can be executed with a PDO (PHP Data Object) database connection for MySQL, @@ -40,6 +43,22 @@ public function insertWithReturningPks(string $table, array $columns): bool|arra return $result; } + protected function queryInternal(int $queryMode): mixed + { + try { + return parent::queryInternal($queryMode); + } catch (IntegrityException $e) { + if (str_starts_with($e->getMessage(), 'SQLSTATE[HY000]: General error: 2006 ')) { + $this->db->close(); + $this->cancel(); + + return parent::queryInternal($queryMode); + } + + throw $e; + } + } + public function showDatabases(): array { $sql = <<assertTrue(true); + + $db->close(); } /** @@ -119,5 +121,23 @@ static function (ConnectionInterface $db) { )->queryScalar(); $this->assertSame('1', $profilesCount, 'profile should be inserted in transaction shortcut'); + + $db->close(); + } + + /** @link https://github.com/yiisoft/db-mysql/issues/348 */ + public function testRestartConnectionOnTimeout(): void + { + $db = $this->getConnection(); + + $db->createCommand('SET SESSION wait_timeout = 1')->execute(); + + sleep(1); + + $result = $db->createCommand("SELECT '1'")->queryScalar(); + + $this->assertSame('1', $result); + + $db->close(); } }