Browse Source

Support PHP 8.1

dbtest
J. King 11 months ago
parent
commit
b5579d6e43
  1. 2
      arsse.php
  2. 3
      composer.json
  3. 2
      lib/Db/MySQL/Driver.php
  4. 3
      lib/Db/MySQL/PDODriver.php
  5. 2
      lib/Db/PostgreSQL/Driver.php
  6. 2
      lib/Db/PostgreSQL/Statement.php
  7. 5
      lib/Db/Result.php
  8. 3
      lib/Db/SQLite3/PDODriver.php
  9. 4
      tests/bootstrap.php
  10. 54
      tests/lib/DatabaseDrivers/MySQL.php
  11. 60
      tests/lib/DatabaseDrivers/MySQLCommon.php
  12. 15
      tests/lib/DatabaseDrivers/MySQLPDO.php
  13. 59
      tests/lib/DatabaseDrivers/PostgreSQL.php
  14. 69
      tests/lib/DatabaseDrivers/PostgreSQLCommon.php
  15. 14
      tests/lib/DatabaseDrivers/PostgreSQLPDO.php
  16. 61
      tests/lib/DatabaseDrivers/SQLite3.php
  17. 70
      tests/lib/DatabaseDrivers/SQLite3Common.php
  18. 19
      tests/lib/DatabaseDrivers/SQLite3PDO.php

2
arsse.php

@ -13,7 +13,7 @@ require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";
ignore_user_abort(true);
ini_set("memory_limit", "-1");
ini_set("max_execution_time", "0");
// FIXME: This is required by a dependency of Picofeed
// FIXME: This is required because various dependencies have yet to adjust to PHP 8.1
error_reporting(\E_ALL & ~\E_DEPRECATED);
if (\PHP_SAPI === "cli") {

3
composer.json

@ -40,6 +40,9 @@
"config": {
"platform": {
"php": "7.1.33"
},
"allow-plugins": {
"bamarni/composer-bin-plugin": true
}
},
"scripts": {

2
lib/Db/MySQL/Driver.php

@ -163,6 +163,8 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
}
protected function makeConnection(string $db, string $user, string $password, string $host, int $port, string $socket): void {
$drv = new \mysqli_driver;
$drv->report_mode = \MYSQLI_REPORT_OFF;
$this->db = mysqli_init();
$this->db->options(\MYSQLI_SET_CHARSET_NAME, "utf8mb4");
$this->db->options(\MYSQLI_OPT_INT_AND_FLOAT_NATIVE, false);

3
lib/Db/MySQL/PDODriver.php

@ -28,7 +28,8 @@ class PDODriver extends Driver {
]);
try {
$this->db = new \PDO($dsn, $user, $password, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
} catch (\PDOException $e) {
$msg = $e->getMessage();

2
lib/Db/PostgreSQL/Driver.php

@ -211,7 +211,7 @@ class Driver extends \JKingWeb\Arsse\Db\AbstractDriver {
public function query(string $query): \JKingWeb\Arsse\Db\Result {
$r = $this->dispatchQuery($query);
if (is_resource($r)) {
if (is_resource($r) || $r instanceof \PgSql\Result) { //class since PHP 8.1
return new Result($this->db, $r);
} else {
[$excClass, $excMsg, $excData] = $r;

2
lib/Db/PostgreSQL/Statement.php

@ -35,7 +35,7 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
$this->bindValues($values);
$r = $this->dispatchQuery($this->qMunged, $this->in);
$this->in = [];
if (is_resource($r)) {
if (is_resource($r) || $r instanceof \PgSql\Result) { //class since PHP 8.1
return new Result($this->db, $r);
} else {
[$excClass, $excMsg, $excData] = $r;

5
lib/Db/Result.php

@ -7,10 +7,15 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\Db;
interface Result extends \Iterator {
#[\ReturnTypeWillChange]
public function current();
#[\ReturnTypeWillChange]
public function key();
#[\ReturnTypeWillChange]
public function next();
#[\ReturnTypeWillChange]
public function rewind();
#[\ReturnTypeWillChange]
public function valid();
public function getRow();

3
lib/Db/SQLite3/PDODriver.php

@ -18,7 +18,8 @@ class PDODriver extends AbstractPDODriver {
protected function makeConnection(string $file, string $key): void {
$this->db = new \PDO("sqlite:".$file, "", "", [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
}

4
tests/bootstrap.php

@ -12,9 +12,7 @@ const DOCROOT = BASE."tests".DIRECTORY_SEPARATOR."docroot".DIRECTORY_SEPARATOR;
ini_set("memory_limit", "-1");
ini_set("zend.assertions", "1");
ini_set("assert.exception", "true");
// FIXME: Workaround for a bug in PCRE2 10.37
ini_set("pcre.jit", "0");
// FIXME: This is required by a dependency of Picofeed
// FIXME: This is required because various dependencies have yet to adjust to PHP 8.1
error_reporting(\E_ALL & ~\E_DEPRECATED);
require_once BASE."vendor".DIRECTORY_SEPARATOR."autoload.php";

54
tests/lib/DatabaseDrivers/MySQL.php

@ -7,9 +7,10 @@ declare(strict_types=1);
namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait MySQL {
use MySQLCommon;
protected static $implementation = "MySQL";
protected static $backend = "MySQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\MySQL\Result::class;
@ -21,6 +22,8 @@ trait MySQL {
if (!class_exists("mysqli")) {
return null;
}
$drv = new \mysqli_driver;
$drv->report_mode = \MYSQLI_REPORT_OFF;
$d = mysqli_init();
$d->options(\MYSQLI_OPT_INT_AND_FLOAT_NATIVE, false);
$d->options(\MYSQLI_SET_CHARSET_NAME, "utf8mb4");
@ -34,53 +37,4 @@ trait MySQL {
}
return $d;
}
public static function dbTableList($db): array {
$listTables = "SELECT table_name as name from information_schema.tables where table_schema = database() and table_name like 'arsse_%'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
} elseif ($db instanceof \PDO) {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$tables = $db->query($listTables)->fetch_all(\MYSQLI_ASSOC);
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'");
} else {
$db->query("TRUNCATE TABLE $table");
}
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
$db->query("DROP TABLE IF EXISTS $table");
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
}

60
tests/lib/DatabaseDrivers/MySQLCommon.php

@ -0,0 +1,60 @@
<?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\Test\DatabaseDrivers;
use JKingWeb\Arsse\Db\Driver;
trait MySQLCommon {
public static function dbTableList($db): array {
$listTables = "SELECT table_name as name from information_schema.tables where table_schema = database() and table_name like 'arsse_%'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
} elseif ($db instanceof \PDO) {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$tables = $db->query($listTables)->fetch_all(\MYSQLI_ASSOC);
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->query("DELETE FROM $table where `key` <> 'schema_version'");
} else {
$db->query("TRUNCATE TABLE $table");
}
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->query("UNLOCK TABLES; ROLLBACK");
} catch (\Throwable $e) {
}
$db->query("SET FOREIGN_KEY_CHECKS=0");
foreach (self::dbTableList($db) as $table) {
$db->query("DROP TABLE IF EXISTS $table");
}
foreach ($afterStatements as $st) {
$db->query($st);
}
$db->query("SET FOREIGN_KEY_CHECKS=1");
}
}

15
tests/lib/DatabaseDrivers/MySQLPDO.php

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait MySQLPDO {
use MySQLCommon;
protected static $implementation = "PDO MySQL";
protected static $backend = "MySQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PDOResult::class;
@ -31,6 +33,7 @@ trait MySQLPDO {
$dsn = "mysql:".implode(";", $dsn);
$d = new \PDO($dsn, Arsse::$conf->dbMySQLUser, Arsse::$conf->dbMySQLPass, [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
\PDO::MYSQL_ATTR_MULTI_STATEMENTS => false,
]);
foreach (\JKingWeb\Arsse\Db\MySQL\PDODriver::makeSetupQueries() as $q) {
@ -41,16 +44,4 @@ trait MySQLPDO {
return;
}
}
public static function dbTableList($db): array {
return MySQL::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
MySQL::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
MySQL::dbRaze($db, $afterStatements);
}
}

59
tests/lib/DatabaseDrivers/PostgreSQL.php

@ -10,6 +10,8 @@ use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait PostgreSQL {
use PostgreSQLCommon;
protected static $implementation = "PostgreSQL";
protected static $backend = "PostgreSQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PostgreSQL\Result::class;
@ -28,61 +30,4 @@ trait PostgreSQL {
return;
}
}
public static function dbExec($db, $q): void {
if ($db instanceof Driver) {
$db->exec($q);
} elseif ($db instanceof \PDO) {
$db->exec($q);
} else {
pg_query($db, $q);
}
}
public static function dbTableList($db): array {
$listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()";
if ($db instanceof Driver) {
return $db->query($listObjects)->getAll();
} elseif ($db instanceof \PDO) {
return $db->query($listObjects)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$r = @pg_query($db, $listObjects);
$out = $r ? pg_fetch_all($r) : false;
return $out ? $out : [];
}
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
if ($obj['type'] !== "TABLE") {
continue;
} elseif ($obj['name'] === "arsse_meta") {
self::dbExec($db, "DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
self::dbExec($db, "TRUNCATE TABLE {$obj['name']} restart identity cascade");
}
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
self::dbExec($db, "DROP {$obj['type']} IF EXISTS {$obj['name']} cascade");
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
}

69
tests/lib/DatabaseDrivers/PostgreSQLCommon.php

@ -0,0 +1,69 @@
<?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\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait PostgreSQLCommon {
public static function dbExec($db, $q): void {
if ($db instanceof Driver) {
$db->exec($q);
} elseif ($db instanceof \PDO) {
$db->exec($q);
} else {
pg_query($db, $q);
}
}
public static function dbTableList($db): array {
$listObjects = "SELECT table_name as name, 'TABLE' as type from information_schema.tables where table_schema = current_schema() and table_name like 'arsse_%' union SELECT collation_name as name, 'COLLATION' as type from information_schema.collations where collation_schema = current_schema()";
if ($db instanceof Driver) {
return $db->query($listObjects)->getAll();
} elseif ($db instanceof \PDO) {
return $db->query($listObjects)->fetchAll(\PDO::FETCH_ASSOC);
} else {
$r = @pg_query($db, $listObjects);
$out = $r ? pg_fetch_all($r) : false;
return $out ? $out : [];
}
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
if ($obj['type'] !== "TABLE") {
continue;
} elseif ($obj['name'] === "arsse_meta") {
self::dbExec($db, "DELETE FROM {$obj['name']} where key <> 'schema_version'");
} else {
self::dbExec($db, "TRUNCATE TABLE {$obj['name']} restart identity cascade");
}
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
@self::dbExec($db, "ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $obj) {
self::dbExec($db, "DROP {$obj['type']} IF EXISTS {$obj['name']} cascade");
}
foreach ($afterStatements as $st) {
self::dbExec($db, $st);
}
}
}

14
tests/lib/DatabaseDrivers/PostgreSQLPDO.php

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait PostgreSQLPDO {
use PostgreSQLCommon;
protected static $implementation = "PDO PostgreSQL";
protected static $backend = "PostgreSQL";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PostgreSQL\PDOResult::class;
@ -28,16 +30,4 @@ trait PostgreSQLPDO {
}
return $d;
}
public static function dbTableList($db): array {
return PostgreSQL::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
PostgreSQL::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
PostgreSQL::dbRaze($db, $afterStatements);
}
}

61
tests/lib/DatabaseDrivers/SQLite3.php

@ -10,6 +10,8 @@ use JKingWeb\Arsse\Arsse;
use JKingWeb\Arsse\Db\Driver;
trait SQLite3 {
use SQLite3Common;
protected static $implementation = "SQLite 3";
protected static $backend = "SQLite 3";
protected static $dbResultClass = \JKingWeb\Arsse\Db\SQLite3\Result::class;
@ -26,63 +28,4 @@ trait SQLite3 {
$d->enableExceptions(true);
return $d;
}
public static function dbTableList($db): array {
$listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse^_%' escape '^'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} elseif ($db instanceof \PDO) {
retry:
try {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
goto retry;
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} else {
$tables = [];
$result = $db->query($listTables);
while ($r = $result->fetchArray(\SQLITE3_ASSOC)) {
$tables[] = $r['name'];
}
$result->finalize();
}
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
$db->exec("PRAGMA foreign_keys=0");
foreach (self::dbTableList($db) as $table) {
$db->exec("DROP TABLE IF EXISTS $table");
}
$db->exec("PRAGMA user_version=0");
$db->exec("PRAGMA foreign_keys=1");
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
}

70
tests/lib/DatabaseDrivers/SQLite3Common.php

@ -0,0 +1,70 @@
<?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\Test\DatabaseDrivers;
use JKingWeb\Arsse\Db\Driver;
trait SQLite3Common {
public static function dbTableList($db): array {
$listTables = "SELECT name from sqlite_master where type = 'table' and name like 'arsse^_%' escape '^'";
if ($db instanceof Driver) {
$tables = $db->query($listTables)->getAll();
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} elseif ($db instanceof \PDO) {
retry:
try {
$tables = $db->query($listTables)->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
goto retry;
}
$tables = sizeof($tables) ? array_column($tables, "name") : [];
} else {
$tables = [];
$result = $db->query($listTables);
while ($r = $result->fetchArray(\SQLITE3_ASSOC)) {
$tables[] = $r['name'];
}
$result->finalize();
}
return $tables;
}
public static function dbTruncate($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
foreach (self::dbTableList($db) as $table) {
if ($table === "arsse_meta") {
$db->exec("DELETE FROM $table where key <> 'schema_version'");
} else {
$db->exec("DELETE FROM $table");
}
}
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
public static function dbRaze($db, array $afterStatements = []): void {
// rollback any pending transaction
try {
$db->exec("ROLLBACK");
} catch (\Throwable $e) {
}
$db->exec("PRAGMA foreign_keys=0");
foreach (self::dbTableList($db) as $table) {
$db->exec("DROP TABLE IF EXISTS $table");
}
$db->exec("PRAGMA user_version=0");
$db->exec("PRAGMA foreign_keys=1");
foreach ($afterStatements as $st) {
$db->exec($st);
}
}
}

19
tests/lib/DatabaseDrivers/SQLite3PDO.php

@ -9,6 +9,8 @@ namespace JKingWeb\Arsse\Test\DatabaseDrivers;
use JKingWeb\Arsse\Arsse;
trait SQLite3PDO {
use SQLite3Common;
protected static $implementation = "PDO SQLite 3";
protected static $backend = "SQLite 3";
protected static $dbResultClass = \JKingWeb\Arsse\Db\PDOResult::class;
@ -18,23 +20,14 @@ trait SQLite3PDO {
public static function dbInterface() {
try {
$d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
$d = new \PDO("sqlite:".Arsse::$conf->dbSQLite3File, "", "", [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_STRINGIFY_FETCHES => true,
]);
$d->exec("PRAGMA busy_timeout=0");
return $d;
} catch (\Throwable $e) {
return;
}
}
public static function dbTableList($db): array {
return SQLite3::dbTableList($db);
}
public static function dbTruncate($db, array $afterStatements = []): void {
SQLite3::dbTruncate($db, $afterStatements);
}
public static function dbRaze($db, array $afterStatements = []): void {
SQLite3::dbRaze($db, $afterStatements);
}
}

Loading…
Cancel
Save