mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
Handle connection errors
This commit is contained in:
parent
e92bda5373
commit
4670dfc849
7 changed files with 112 additions and 14 deletions
|
@ -35,7 +35,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
||||||
$port = Arsse::$conf->dbMySQLPost ?? 3306;
|
$port = Arsse::$conf->dbMySQLPost ?? 3306;
|
||||||
$db = Arsse::$conf->dbMySQLDb ?? "arsse";
|
$db = Arsse::$conf->dbMySQLDb ?? "arsse";
|
||||||
// make the connection
|
// make the connection
|
||||||
$this->makeConnection($user, $pass, $db, $host, $port, $socket);
|
$this->makeConnection($db, $user, $pass, $host, $port, $socket);
|
||||||
// set session variables
|
// set session variables
|
||||||
foreach (static::makeSetupQueries() as $q) {
|
foreach (static::makeSetupQueries() as $q) {
|
||||||
$this->exec($q);
|
$this->exec($q);
|
||||||
|
@ -157,15 +157,12 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function makeConnection(string $db, string $user, string $password, string $host, int $port, string $socket) {
|
protected function makeConnection(string $db, string $user, string $password, string $host, int $port, string $socket) {
|
||||||
try {
|
$this->db = @new \mysqli($host, $user, $password, $db, $port, $socket);
|
||||||
$this->db = new \mysqli($host, $user, $password, $db, $port, $socket);
|
if ($this->db->connect_errno) {
|
||||||
if ($this->db->connect_errno) {
|
list($excClass, $excMsg, $excData) = $this->buildConnectionException($this->db->connect_errno, $this->db->connect_error);
|
||||||
echo $this->db->connect_errno.": ".$this->db->connect_error;
|
throw new $excClass($excMsg, $excData);
|
||||||
}
|
|
||||||
$this->db->set_charset("utf8mb4");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
|
$this->db->set_charset("utf8mb4");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exec(string $query): bool {
|
public function exec(string $query): bool {
|
||||||
|
|
|
@ -23,4 +23,35 @@ trait ExceptionBuilder {
|
||||||
return [Exception::class, 'engineErrorGeneral', $msg];
|
return [Exception::class, 'engineErrorGeneral', $msg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function buildConnectionException($code, string $msg): array {
|
||||||
|
switch ($code) {
|
||||||
|
case 1045:
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
case 1043:
|
||||||
|
case 1044:
|
||||||
|
case 1046:
|
||||||
|
case 1049:
|
||||||
|
case 2001:
|
||||||
|
case 2002:
|
||||||
|
case 2003:
|
||||||
|
case 2004:
|
||||||
|
case 2005:
|
||||||
|
case 2007:
|
||||||
|
case 2009:
|
||||||
|
case 2010:
|
||||||
|
case 2011:
|
||||||
|
case 2012:
|
||||||
|
case 2015:
|
||||||
|
case 2016:
|
||||||
|
case 2017:
|
||||||
|
case 2018:
|
||||||
|
case 2026:
|
||||||
|
case 2028:
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
return [Exception::class, 'connectionFailure', ['engine' => "MySQL", 'message' => $msg]];
|
||||||
|
default:
|
||||||
|
return [Exception::class, 'engineErrorGeneral', $msg]; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,17 @@ class PDODriver extends Driver {
|
||||||
"socket=$socket",
|
"socket=$socket",
|
||||||
"port=$port",
|
"port=$port",
|
||||||
]);
|
]);
|
||||||
$this->db = new \PDO($dsn, $user, $password, [
|
try {
|
||||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
$this->db = new \PDO($dsn, $user, $password, [
|
||||||
]);
|
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||||
|
]);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
$msg = $e->getMessage();
|
||||||
|
$code = (int) substr($msg, 17, 4);
|
||||||
|
$msg = substr($msg, 23);
|
||||||
|
list($excClass, $excMsg, $excData) = $this->buildConnectionException($code, $msg);
|
||||||
|
throw new $excClass($excMsg, $excData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
|
|
|
@ -31,7 +31,7 @@ class PDODriver extends Driver {
|
||||||
if ($e->getCode() == 7) {
|
if ($e->getCode() == 7) {
|
||||||
switch (substr($e->getMessage(), 9, 5)) {
|
switch (substr($e->getMessage(), 9, 5)) {
|
||||||
case "08006":
|
case "08006":
|
||||||
throw new Exception("connectionFailure", ["PostgreSQL", substr($e->getMessage(), 28)]);
|
throw new Exception("connectionFailure", ['engine' => "PostgreSQL", 'message' => substr($e->getMessage(), 28)]);
|
||||||
default:
|
default:
|
||||||
throw $e; // @codeCoverageIgnore
|
throw $e; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ return [
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUnusable' => 'Insufficient permissions to open database file "{0}" for reading or writing',
|
'Exception.JKingWeb/Arsse/Db/Exception.fileUnusable' => 'Insufficient permissions to open database file "{0}" for reading or writing',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.fileUncreatable' => 'Insufficient permissions to create new database file "{0}"',
|
'Exception.JKingWeb/Arsse/Db/Exception.fileUncreatable' => 'Insufficient permissions to create new database file "{0}"',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database',
|
'Exception.JKingWeb/Arsse/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.connectionFailure' => 'Could not connect to {0} database: {1}',
|
'Exception.JKingWeb/Arsse/Db/Exception.connectionFailure' => 'Could not connect to {engine} database: {message}',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid',
|
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented',
|
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented',
|
||||||
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
|
'Exception.JKingWeb/Arsse/Db/Exception.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
|
||||||
|
|
31
tests/cases/Db/MySQL/TestCreation.php
Normal file
31
tests/cases/Db/MySQL/TestCreation.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/** @license MIT
|
||||||
|
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||||
|
* See LICENSE and AUTHORS files for details */
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\Arsse\TestCase\Db\MySQL;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
use JKingWeb\Arsse\Db\MySQL\Driver as Driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group slow
|
||||||
|
* @covers \JKingWeb\Arsse\Db\MySQL\Driver<extended>
|
||||||
|
* @covers \JKingWeb\Arsse\Db\MySQL\ExceptionBuilder */
|
||||||
|
class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
public function setUp() {
|
||||||
|
if (!Driver::requirementsMet()) {
|
||||||
|
$this->markTestSkipped("MySQL extension not loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailToConnect() {
|
||||||
|
// for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do
|
||||||
|
self::setConf([
|
||||||
|
'dbMySQLPass' => (string) rand(),
|
||||||
|
]);
|
||||||
|
$this->assertException("connectionFailure", "Db");
|
||||||
|
new Driver;
|
||||||
|
}
|
||||||
|
}
|
31
tests/cases/Db/MySQLPDO/TestCreation.php
Normal file
31
tests/cases/Db/MySQLPDO/TestCreation.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/** @license MIT
|
||||||
|
* Copyright 2017 J. King, Dustin Wilson et al.
|
||||||
|
* See LICENSE and AUTHORS files for details */
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\Arsse\TestCase\Db\MySQLPDO;
|
||||||
|
|
||||||
|
use JKingWeb\Arsse\Arsse;
|
||||||
|
use JKingWeb\Arsse\Db\MySQL\PDODriver as Driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group slow
|
||||||
|
* @covers \JKingWeb\Arsse\Db\MySQL\PDODriver<extended>
|
||||||
|
* @covers \JKingWeb\Arsse\Db\MySQL\ExceptionBuilder */
|
||||||
|
class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest {
|
||||||
|
public function setUp() {
|
||||||
|
if (!Driver::requirementsMet()) {
|
||||||
|
$this->markTestSkipped("PDO-MySQL extension not loaded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFailToConnect() {
|
||||||
|
// for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do
|
||||||
|
self::setConf([
|
||||||
|
'dbMySQLPass' => (string) rand(),
|
||||||
|
]);
|
||||||
|
$this->assertException("connectionFailure", "Db");
|
||||||
|
new Driver;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue