Browse Source

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.
Visman 3 years ago
parent
commit
0d443ff683

+ 10 - 4
app/Core/DB.php

@@ -56,21 +56,27 @@ class DB extends PDO
 
 
     public function __construct(string $dsn, string $username = null, string $password = null, array $options = [], string $prefix = '')
     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 (
         if (
             ! $type
             ! $type
             || ! \in_array($type, PDO::getAvailableDrivers(), true)
             || ! \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'");
             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) {
         if ('sqlite' === $type) {
             $dsn = \str_replace('!PATH!', \realpath(__DIR__ . '/../config/db') . '/', $dsn);
             $dsn = \str_replace('!PATH!', \realpath(__DIR__ . '/../config/db') . '/', $dsn);
-            $statement = 'ForkBB\\Core\\DB\\' . \ucfirst($type) . 'Statement';
         }
         }
 
 
         $this->dbType   = $type;
         $this->dbType   = $type;

+ 88 - 0
app/Core/DB/AbstractSqliteStatement.php

@@ -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;
+    }
+}

+ 6 - 8
app/Core/DB/AbstractStatement.php

@@ -15,15 +15,9 @@ use PDO;
 use PDOStatement;
 use PDOStatement;
 use PDOException;
 use PDOException;
 use RuntimeException;
 use RuntimeException;
-use ReturnTypeWillChange;
 
 
 abstract class AbstractStatement extends DBStatement
 abstract class AbstractStatement extends DBStatement
 {
 {
-    const BOOLEAN = 'b';
-    const FLOAT   = 'f';
-    const INTEGER = 'i';
-    const STRING  = 's';
-
     /**
     /**
      * Типы столбцов полученные через getColumnMeta()
      * Типы столбцов полученные через getColumnMeta()
      * @var array
      * @var array
@@ -33,8 +27,7 @@ abstract class AbstractStatement extends DBStatement
     abstract public function getColumnsType(): array;
     abstract public function getColumnsType(): array;
     abstract protected function convToBoolean(/* mixed */ $value): bool;
     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);
         $data = parent::fetch($mode, $cursorOrientation, $cursorOffset);
 
 
@@ -70,4 +63,9 @@ abstract class AbstractStatement extends DBStatement
 
 
         return $data;
         return $data;
     }
     }
+
+    protected function dbFetchAll(int $mode = 0 /* PDO::FETCH_DEFAULT */, /* mixed */ ...$args): array
+    {
+        return parent::fetchAll($mode, ...$args);
+    }
 }
 }

+ 9 - 70
app/Core/DB/SqliteStatement.php

@@ -10,82 +10,21 @@ declare(strict_types=1);
 
 
 namespace ForkBB\Core\DB;
 namespace ForkBB\Core\DB;
 
 
-use ForkBB\Core\DB\AbstractStatement;
+use ForkBB\Core\DB\AbstractSqliteStatement;
 use PDO;
 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 - 0
app/Core/DB/SqliteStatement7.php

@@ -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);
+    }
+}

+ 8 - 3
app/Core/DBStatement.php

@@ -16,6 +16,11 @@ use PDOException;
 
 
 class DBStatement extends PDOStatement
 class DBStatement extends PDOStatement
 {
 {
+    const BOOLEAN = 'b';
+    const FLOAT   = 'f';
+    const INTEGER = 'i';
+    const STRING  = 's';
+
     /**
     /**
      * Префикс для таблиц базы
      * Префикс для таблиц базы
      * @var PDO
      * @var PDO
@@ -33,13 +38,13 @@ class DBStatement extends PDOStatement
      * @var array
      * @var array
      */
      */
     protected $types = [
     protected $types = [
-        's'  => PDO::PARAM_STR,
-        'i'  => PDO::PARAM_INT,
         'b'  => PDO::PARAM_BOOL,
         'b'  => PDO::PARAM_BOOL,
         'f'  => PDO::PARAM_STR,
         'f'  => PDO::PARAM_STR,
+        'i'  => PDO::PARAM_INT,
+        's'  => PDO::PARAM_STR,
         'a'  => PDO::PARAM_STR,
         'a'  => PDO::PARAM_STR,
-        'as' => PDO::PARAM_STR,
         'ai' => PDO::PARAM_INT,
         'ai' => PDO::PARAM_INT,
+        'as' => PDO::PARAM_STR,
     ];
     ];
 
 
     protected function __construct(PDO $db)
     protected function __construct(PDO $db)