Update DBStatement for SQLite #9
I had to split DBStatement for SQLite into two branches: for PHP 7 and for PHP 8, otherwise it does not allow inheriting the PDOStatement class.
This commit is contained in:
parent
481489f505
commit
0d443ff683
6 changed files with 166 additions and 85 deletions
|
@ -56,21 +56,27 @@ class DB extends PDO
|
|||
|
||||
public function __construct(string $dsn, string $username = null, string $password = null, array $options = [], string $prefix = '')
|
||||
{
|
||||
$type = \strstr($dsn, ':', true);
|
||||
$type = \strstr($dsn, ':', true);
|
||||
$typeU = \ucfirst($type);
|
||||
|
||||
if (
|
||||
! $type
|
||||
|| ! \in_array($type, PDO::getAvailableDrivers(), true)
|
||||
|| ! \is_file(__DIR__ . '/DB/' . \ucfirst($type) . '.php')
|
||||
|| ! \is_file(__DIR__ . "/DB/{$typeU}.php")
|
||||
) {
|
||||
throw new PDOException("Driver isn't found for '$type'");
|
||||
}
|
||||
|
||||
$statement = DBStatement::class;
|
||||
$statement = $typeU . 'Statement' . (\PHP_MAJOR_VERSION < 8 ? '7' : '');
|
||||
|
||||
if (\is_file(__DIR__ . "/DB/{$typeU}.php")) {
|
||||
$statement = 'ForkBB\\Core\\DB\\' . $statement;
|
||||
} else {
|
||||
$statement = DBStatement::class;
|
||||
}
|
||||
|
||||
if ('sqlite' === $type) {
|
||||
$dsn = \str_replace('!PATH!', \realpath(__DIR__ . '/../config/db') . '/', $dsn);
|
||||
$statement = 'ForkBB\\Core\\DB\\' . \ucfirst($type) . 'Statement';
|
||||
}
|
||||
|
||||
$this->dbType = $type;
|
||||
|
|
88
app/Core/DB/AbstractSqliteStatement.php
Normal file
88
app/Core/DB/AbstractSqliteStatement.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of the ForkBB <https://github.com/forkbb>.
|
||||
*
|
||||
* @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
|
||||
* @license The MIT License (MIT)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ForkBB\Core\DB;
|
||||
|
||||
use ForkBB\Core\DB\AbstractStatement;
|
||||
use PDO;
|
||||
|
||||
abstract class AbstractSqliteStatement extends AbstractStatement
|
||||
{
|
||||
/**
|
||||
* https://github.com/php/php-src/blob/master/ext/pdo_sqlite/sqlite_statement.c
|
||||
*
|
||||
* SQLite:
|
||||
* native_type:
|
||||
* null - для значения NULL, а не типа столбца
|
||||
* integer - это INTEGER, NUMERIC(?), BOOLEAN // BOOLEAN тут как-то не к месту, его бы в отдельный тип
|
||||
* string - это TEXT
|
||||
* double - это REAL, NUMERIC(?) // NUMERIC может быть и double, и integer
|
||||
* sqlite:decl_type:
|
||||
* INTEGER
|
||||
* TEXT
|
||||
* REAL
|
||||
* NUMERIC
|
||||
* BOOLEAN
|
||||
* ... (это те типы, которые прописаны в CREATE TABLE и полученные после перекодировки из {driver}::bTypeRepl)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $nativeTypeRepl = [
|
||||
'integer' => self::INTEGER,
|
||||
'double' => self::FLOAT,
|
||||
];
|
||||
|
||||
public function getColumnsType(): array
|
||||
{
|
||||
if (isset($this->columnsType)) {
|
||||
return $this->columnsType;
|
||||
}
|
||||
|
||||
$this->columnsType = [];
|
||||
|
||||
$count = $this->columnCount();
|
||||
$i = 0;
|
||||
// $dbType = $this->db->getType();
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$meta = $this->getColumnMeta($i);
|
||||
$type = null;
|
||||
// $declType = $meta[$dbType . ':decl_type'] ?? null;
|
||||
$declType = $meta['sqlite:decl_type'] ?? null;
|
||||
|
||||
if (null === $declType) {
|
||||
$type = $this->nativeTypeRepl[$meta['native_type']] ?? null;
|
||||
} elseif (\preg_match('%INT%i', $declType)) {
|
||||
$type = self::INTEGER;
|
||||
} elseif (\preg_match('%BOOL%i', $declType)) {
|
||||
$type = self::BOOLEAN;
|
||||
// } elseif (\preg_match('%REAL|FLOA|DOUB|NUMERIC|DECIMAL%i', $declType)) {
|
||||
// $type = self::FLOAT;
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
$this->columnsType[$i] = $type;
|
||||
|
||||
if (isset($meta['name'])) { // ????? проверка на тип содержимого? только строки, не числа?
|
||||
$this->columnsType[$meta['name']] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->columnsType;
|
||||
}
|
||||
|
||||
protected function convToBoolean(/* mixed */ $value): bool
|
||||
{
|
||||
return (bool) $value;
|
||||
}
|
||||
}
|
|
@ -15,15 +15,9 @@ use PDO;
|
|||
use PDOStatement;
|
||||
use PDOException;
|
||||
use RuntimeException;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
abstract class AbstractStatement extends DBStatement
|
||||
{
|
||||
const BOOLEAN = 'b';
|
||||
const FLOAT = 'f';
|
||||
const INTEGER = 'i';
|
||||
const STRING = 's';
|
||||
|
||||
/**
|
||||
* Типы столбцов полученные через getColumnMeta()
|
||||
* @var array
|
||||
|
@ -33,8 +27,7 @@ abstract class AbstractStatement extends DBStatement
|
|||
abstract public function getColumnsType(): array;
|
||||
abstract protected function convToBoolean(/* mixed */ $value): bool;
|
||||
|
||||
#[ReturnTypeWillChange]
|
||||
public function fetch(/* int */ $mode = 0 /* PDO::FETCH_DEFAULT */, /* int */ $cursorOrientation = PDO::FETCH_ORI_NEXT, /* int */ $cursorOffset = 0) /* : mixed */
|
||||
protected function dbFetch(int $mode, int $cursorOrientation, int $cursorOffset) /* : mixed */
|
||||
{
|
||||
$data = parent::fetch($mode, $cursorOrientation, $cursorOffset);
|
||||
|
||||
|
@ -70,4 +63,9 @@ abstract class AbstractStatement extends DBStatement
|
|||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function dbFetchAll(int $mode = 0 /* PDO::FETCH_DEFAULT */, /* mixed */ ...$args): array
|
||||
{
|
||||
return parent::fetchAll($mode, ...$args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,82 +10,21 @@ declare(strict_types=1);
|
|||
|
||||
namespace ForkBB\Core\DB;
|
||||
|
||||
use ForkBB\Core\DB\AbstractStatement;
|
||||
use ForkBB\Core\DB\AbstractSqliteStatement;
|
||||
use PDO;
|
||||
use PDOStatement;
|
||||
use PDOException;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
class SqliteStatement extends AbstractStatement
|
||||
/**
|
||||
* For PHP 8
|
||||
*/
|
||||
class SqliteStatement extends AbstractSqliteStatement
|
||||
{
|
||||
/**
|
||||
* https://github.com/php/php-src/blob/master/ext/pdo_sqlite/sqlite_statement.c
|
||||
*
|
||||
* SQLite:
|
||||
* native_type:
|
||||
* null - для значения NULL, а не типа столбца
|
||||
* integer - это INTEGER, NUMERIC(?), BOOLEAN // BOOLEAN тут как-то не к месту, его бы в отдельный тип
|
||||
* string - это TEXT
|
||||
* double - это REAL, NUMERIC(?) // NUMERIC может быть и double, и integer
|
||||
* sqlite:decl_type:
|
||||
* INTEGER
|
||||
* TEXT
|
||||
* REAL
|
||||
* NUMERIC
|
||||
* BOOLEAN
|
||||
* ... (это те типы, которые прописаны в CREATE TABLE и полученные после перекодировки из {driver}::bTypeRepl)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $nativeTypeRepl = [
|
||||
'integer' => self::INTEGER,
|
||||
'double' => self::FLOAT,
|
||||
];
|
||||
|
||||
public function getColumnsType(): array
|
||||
public function fetch(int $mode = PDO::FETCH_DEFAULT, int $cursorOrientation = PDO::FETCH_ORI_NEXT, int $cursorOffset = 0): mixed
|
||||
{
|
||||
if (isset($this->columnsType)) {
|
||||
return $this->columnsType;
|
||||
}
|
||||
|
||||
$this->columnsType = [];
|
||||
|
||||
$count = $this->columnCount();
|
||||
$i = 0;
|
||||
// $dbType = $this->db->getType();
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$meta = $this->getColumnMeta($i);
|
||||
$type = null;
|
||||
// $declType = $meta[$dbType . ':decl_type'] ?? null;
|
||||
$declType = $meta['sqlite:decl_type'] ?? null;
|
||||
|
||||
if (null === $declType) {
|
||||
$type = $this->nativeTypeRepl[$meta['native_type']] ?? null;
|
||||
} elseif (\preg_match('%INT%i', $declType)) {
|
||||
$type = self::INTEGER;
|
||||
} elseif (\preg_match('%BOOL%i', $declType)) {
|
||||
$type = self::BOOLEAN;
|
||||
// } elseif (\preg_match('%REAL|FLOA|DOUB|NUMERIC|DECIMAL%i', $declType)) {
|
||||
// $type = self::FLOAT;
|
||||
}
|
||||
|
||||
if ($type) {
|
||||
$this->columnsType[$i] = $type;
|
||||
|
||||
if (isset($meta['name'])) { // ????? проверка на тип содержимого? только строки, не числа?
|
||||
$this->columnsType[$meta['name']] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->columnsType;
|
||||
return $this->dbFetch($mode, $cursorOrientation, $cursorOffset);
|
||||
}
|
||||
|
||||
protected function convToBoolean(/* mixed */ $value): bool
|
||||
public function fetchAll(int $mode = PDO::FETCH_DEFAULT, ...$args): array
|
||||
{
|
||||
return (bool) $value;
|
||||
return $this->dbFetchAll($mode, ...$args);
|
||||
}
|
||||
}
|
||||
|
|
45
app/Core/DB/SqliteStatement7.php
Normal file
45
app/Core/DB/SqliteStatement7.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is part of the ForkBB <https://github.com/forkbb>.
|
||||
*
|
||||
* @copyright (c) Visman <mio.visman@yandex.ru, https://github.com/MioVisman>
|
||||
* @license The MIT License (MIT)
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ForkBB\Core\DB;
|
||||
|
||||
use ForkBB\Core\DB\AbstractSqliteStatement;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* For PHP 7
|
||||
*/
|
||||
class SqliteStatement7 extends AbstractSqliteStatement
|
||||
{
|
||||
public function fetch($mode = null, $orientation = null, $offset = null)
|
||||
{
|
||||
$mode = $mode ?? 0;
|
||||
$orientation = $orientation ?? PDO::FETCH_ORI_NEXT;
|
||||
$offset = $offset ?? 0;
|
||||
|
||||
return $this->dbFetch($mode, $orientation, $offset);
|
||||
}
|
||||
|
||||
public function fetchAll($mode = null, $fetch_argument = null, $ctor_args = null)
|
||||
{
|
||||
$mode = $mode ?? 0;
|
||||
$args = [];
|
||||
|
||||
if (isset($fetch_argument)) {
|
||||
$args[] = $fetch_argument;
|
||||
|
||||
if (isset($ctor_args)) {
|
||||
$args[] = $ctor_args;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dbFetchAll($mode, ...$args);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,11 @@ use PDOException;
|
|||
|
||||
class DBStatement extends PDOStatement
|
||||
{
|
||||
const BOOLEAN = 'b';
|
||||
const FLOAT = 'f';
|
||||
const INTEGER = 'i';
|
||||
const STRING = 's';
|
||||
|
||||
/**
|
||||
* Префикс для таблиц базы
|
||||
* @var PDO
|
||||
|
@ -33,13 +38,13 @@ class DBStatement extends PDOStatement
|
|||
* @var array
|
||||
*/
|
||||
protected $types = [
|
||||
's' => PDO::PARAM_STR,
|
||||
'i' => PDO::PARAM_INT,
|
||||
'b' => PDO::PARAM_BOOL,
|
||||
'f' => PDO::PARAM_STR,
|
||||
'i' => PDO::PARAM_INT,
|
||||
's' => PDO::PARAM_STR,
|
||||
'a' => PDO::PARAM_STR,
|
||||
'as' => PDO::PARAM_STR,
|
||||
'ai' => PDO::PARAM_INT,
|
||||
'as' => PDO::PARAM_STR,
|
||||
];
|
||||
|
||||
protected function __construct(PDO $db)
|
||||
|
|
Loading…
Add table
Reference in a new issue