From 8cbdf25372115f78f0eae192bead8062642f0121 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 16 Jul 2025 17:25:19 +0400 Subject: [PATCH 1/6] modifs.mineures sans commentaires --- php/src/app/args.php | 123 ++++++++++++++++++++++++++++++++++++- php/tests/app/argsTest.php | 45 ++++++++++++++ 2 files changed, 167 insertions(+), 1 deletion(-) diff --git a/php/src/app/args.php b/php/src/app/args.php index 90e24c7..3804bbc 100644 --- a/php/src/app/args.php +++ b/php/src/app/args.php @@ -2,6 +2,8 @@ namespace nulib\app; use nulib\A; +use nulib\cl; +use nulib\cv; use nulib\str; class args { @@ -10,7 +12,10 @@ class args { * - ["myArg" => $value] devient ["--my-arg", "$value"] * - ["myOpt" => true] devient ["--my-opt"] * - ["myOpt" => false] est omis - * - les autres valeurs sont prises telles quelles + * - les autres valeurs sont transformées en chaines puis ajoutée + * + * ainsi, ["myOpt" => "value", "myArg", "myBool" => true] + * devient ["--my-opt", "value", "myArg", "--my-bool"] */ static function from_array(?array $array): array { $args = []; @@ -36,4 +41,120 @@ class args { } return $args; } + + private static function tint(string $value): int { + return intval($value); + } + + private static function tbool(string $value): bool { + return boolval($value); + } + + private static function tarray(string $value): ?array { + if ($value === "") return null; + $tmparray = explode(",", $value); + $array = null; + foreach ($tmparray as $tmpvalue) { + [$tmpkey, $tmpvalue] = str::split_pair($tmpvalue); + if ($tmpvalue === null) cv::swap($tmpkey, $tmpvalue); + if ($tmpkey === null) { + $array[] = $tmpvalue; + } else { + if (str::del_suffix($tmpkey, ":int")) { + $tmpvalue = self::tint($tmpvalue); + } elseif (str::del_suffix($tmpkey, ":bool")) { + $tmpvalue = self::tbool($tmpvalue); + } + $array[$tmpkey] = $tmpvalue; + } + } + return $array; + } + + /** + * convertir une liste d'arguments de façon qu'ils soient utilisables pour un + * appel de méthode. les arguments peuvent être de la forme: + * - "name=value" + * qui est stocké dans le tableau $query ["name" => "value"] + * - "+arg" + * qui est stocké dans le tableau $query ["arg" => true] + * - "-arg" ou "~arg" + * qui est stocké dans le tableau $query ["arg" => false] + * - "array:sval,key:aval,..." + * qui devient l'argument ["sval", "key" => "aval", ...] + * - "int:value" + * qui devient l'argument intval("value") + * - "bool:value" + * qui devient l'argument boolval("value") + * - "value" + * qui devient l'argument "value" + * + * à la fin, la liste des arguments est retournée [$arguments...] + * si le tableau $query est renseigné, il est en premier dans la liste des + * arguments e.g [$query, $arguments...] + */ + static function build_method_args(?array $args): ?array { + $query = null; + $margs = []; + $args ??= []; + foreach ($args as $arg) { + [$name, $value] = str::split_pair($arg, "="); + if ($value === null) { + if (str::del_prefix($name, "+")) { + $value = true; + } elseif (str::del_prefix($name, "-") || str::del_prefix($name, "~")) { + $value = false; + } elseif (str::del_prefix($name, "int:")) { + $margs[] = self::tint($name); + continue; + } elseif (str::del_prefix($name, "bool:")) { + $margs[] = self::tbool($name); + continue; + } elseif (str::del_prefix($name, "array:")) { + if (str::del_prefix($name, "int:")) { + $map = [self::class, "tint"]; + } elseif (str::del_prefix($name, "bool:")) { + $map = [self::class, "tbool"]; + } else { + $map = null; + } + $value = self::tarray($name); + if ($map !== null) $value = array_map($map, $value); + $margs[] = $value; + continue; + } else { + $margs[] = $name; + continue; + } + } + if (str::del_suffix($name, ":int")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tint"], self::tarray($value)); + } else { + $value = self::tint($value); + } + } elseif (str::del_suffix($name, ":bool")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tbool"], self::tarray($value)); + } else { + $value = self::tbool($value); + } + } elseif (str::del_suffix($name, ":array")) { + $value = self::tarray($value); + if (str::del_suffix($name, ":int")) { + $value = array_map([self::class, "tint"], $value); + } elseif (str::del_suffix($name, ":bool")) { + $value = array_map([self::class, "tbool"], $value); + } + } + if (cl::has($query, $name)) { + A::ensure_array($query[$name]); + $query[$name][] = $value; + } else { + $query[$name] = $value; + } + } + if ($query !== null) array_unshift($margs, $query); + return $margs; + } } diff --git a/php/tests/app/argsTest.php b/php/tests/app/argsTest.php index 90252d9..f4f5619 100644 --- a/php/tests/app/argsTest.php +++ b/php/tests/app/argsTest.php @@ -23,4 +23,49 @@ class argsTest extends TestCase { self::assertSame(["x", "1", "2", "3", "y"], args::from_array(["x", [1, 2, 3], "y"])); } + + function testBuild_method_args() { + self::assertSame([], args::build_method_args(null)); + self::assertSame([], args::build_method_args([])); + + self::assertSame(["a"], args::build_method_args(["a"])); + self::assertSame(["a", "b"], args::build_method_args(["a", "b"])); + + self::assertSame([0], args::build_method_args(["int:0"])); + self::assertSame([42], args::build_method_args(["int:42"])); + # pour le moment, pas de tint + self::assertSame([0], args::build_method_args(["int:"])); + self::assertSame([0], args::build_method_args(["int:truc"])); + + self::assertSame([false], args::build_method_args(["bool:0"])); + self::assertSame([true], args::build_method_args(["bool:42"])); + self::assertSame([false], args::build_method_args(["bool:"])); + self::assertSame([true], args::build_method_args(["bool:truc"])); + # pour le moment, pas de tbool + self::assertSame([true], args::build_method_args(["bool:false"])); + self::assertSame([true], args::build_method_args(["bool:true"])); + + self::assertSame([["a", "b"]], args::build_method_args(["array:a,b"])); + self::assertSame([["x" => "a", "y" => "b"]], args::build_method_args(["array:x:a,y:b"])); + # pour le moment, pas de tint + self::assertSame([[0, 42, 0, 0]], args::build_method_args(["array:int:0,42,,truc"])); + self::assertSame([["x" => 0, "y" => 42]], args::build_method_args(["array:int:x:0,y:42"])); + # pour le moment, pas de tbool + self::assertSame([[false, true, false, true, true, true]], args::build_method_args(["array:bool:0,42,,truc,false,true"])); + self::assertSame([["x" => false, "y" => true]], args::build_method_args(["array:bool:x:0,y:42"])); + + self::assertSame([["a" => true]], args::build_method_args(["+a"])); + self::assertSame([["a" => false]], args::build_method_args(["-a"])); + self::assertSame([["a" => false]], args::build_method_args(["~a"])); + self::assertSame([["x" => "a"]], args::build_method_args(["x=a"])); + self::assertSame([["x" => 0]], args::build_method_args(["x:int=0"])); + self::assertSame([["x" => 42]], args::build_method_args(["x:int=42"])); + self::assertSame([["x" => false]], args::build_method_args(["x:bool=0"])); + self::assertSame([["x" => true]], args::build_method_args(["x:bool=42"])); + self::assertSame([["x" => ["a", "b"]]], args::build_method_args(["x:array=a,b"])); + self::assertSame([["x" => [0, 42]]], args::build_method_args(["x:array:int=0,42"])); + self::assertSame([["x" => [0, 42]]], args::build_method_args(["x:int:array=0,42"])); + + self::assertSame([["x" => "a", "y" => "b"], "a", "b"], args::build_method_args(["x=a", "a", "y=b", "b"])); + } } From 4a9eecbda89c4df3a85e00f325e8eb97fb9b1dd5 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 16 Jul 2025 17:54:26 +0400 Subject: [PATCH 2/6] modifs.mineures sans commentaires --- php/src/app/args.php | 86 ++++++++++++++++++++++++++++++++++++++ php/tests/app/argsTest.php | 23 ++++++++++ 2 files changed, 109 insertions(+) diff --git a/php/src/app/args.php b/php/src/app/args.php index 3804bbc..db56ce1 100644 --- a/php/src/app/args.php +++ b/php/src/app/args.php @@ -4,6 +4,7 @@ namespace nulib\app; use nulib\A; use nulib\cl; use nulib\cv; +use nulib\file; use nulib\str; class args { @@ -71,17 +72,102 @@ class args { return $array; } + /** + * convertir une liste d'arguments en tableau qui est utilisable comme un + * filtre de base de données ou des données d'une requête REST. les arguments + * peuvent être de la forme: + * - "name=value" + * qui devient dans le tableau ["name" => "value"] + * - "+arg" ou "arg" + * qui devient dans le tableau ["arg" => true] + * - "-arg" ou "~arg" + * qui est stocké dans le tableau $query ["arg" => false] + * + * si $allow_file == true, les formes d'arguments suivantes sont reconnues + * aussi: + * - "name=@file" (1 argument) OU + * "name=@" "file" (2 arguments) + * qui deviennent ["name" => new FileReader(file)] + */ + static function build_query(?array $args, bool $allow_file=true): ?array { + $query = null; + $args ??= []; + $keys = array_keys($args); + $index = 0; + $count = count($keys); + while ($index < $count) { + $arg = $args[$keys[$index++]]; + [$name, $value] = str::split_pair($arg, "="); + $checkType = true; + if ($value === null) { + if (str::del_prefix($name, "+")) { + $value = true; + } elseif (str::del_prefix($name, "-") || str::del_prefix($name, "~")) { + $value = false; + } else { + $value = true; + } + } elseif ($allow_file) { + if ($value === "@") { + $value = $args[$keys[$index++]]; + $value = file::reader($value); + $checkType = false; + } elseif (substr($value, 0, 1) === "@") { + $value = substr($value, 1); + $value = file::reader($value); + $checkType = false; + } + } + if ($checkType) { + if (str::del_suffix($name, ":int")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tint"], self::tarray($value)); + } else { + $value = self::tint($value); + } + } elseif (str::del_suffix($name, ":bool")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tbool"], self::tarray($value)); + } else { + $value = self::tbool($value); + } + } elseif (str::del_suffix($name, ":array")) { + $value = self::tarray($value); + if (str::del_suffix($name, ":int")) { + $value = array_map([self::class, "tint"], $value); + } elseif (str::del_suffix($name, ":bool")) { + $value = array_map([self::class, "tbool"], $value); + } + } + } + if (cl::has($query, $name)) { + A::ensure_array($query[$name]); + $query[$name][] = $value; + } else { + $query[$name] = $value; + } + } + return $query; + } + /** * convertir une liste d'arguments de façon qu'ils soient utilisables pour un * appel de méthode. les arguments peuvent être de la forme: * - "name=value" * qui est stocké dans le tableau $query ["name" => "value"] + * il est possible de forcer le type de la valeur avec l'un des suffixes + * :int, :bool ou :array, e.g + * un entier: "name:int=42" + * un tableau de chaines: "name:array=a,b,c" + * un tableau d'entiers: "name:array:int=1,2,3" * - "+arg" * qui est stocké dans le tableau $query ["arg" => true] * - "-arg" ou "~arg" * qui est stocké dans le tableau $query ["arg" => false] * - "array:sval,key:aval,..." * qui devient l'argument ["sval", "key" => "aval", ...] + * il est possible de forcer le types des éléments avec le préfixe int: ou + * bool: e.g "array:int:1,2,3" * - "int:value" * qui devient l'argument intval("value") * - "bool:value" diff --git a/php/tests/app/argsTest.php b/php/tests/app/argsTest.php index f4f5619..c0a894c 100644 --- a/php/tests/app/argsTest.php +++ b/php/tests/app/argsTest.php @@ -24,6 +24,27 @@ class argsTest extends TestCase { self::assertSame(["x", "1", "2", "3", "y"], args::from_array(["x", [1, 2, 3], "y"])); } + function testBuild_query() { + self::assertSame(null, args::build_query(null)); + self::assertSame(null, args::build_query([])); + + self::assertSame(["a" => true], args::build_query(["a"])); + self::assertSame(["a" => true], args::build_query(["+a"])); + self::assertSame(["a" => false], args::build_query(["-a"])); + self::assertSame(["a" => false], args::build_query(["~a"])); + self::assertSame(["x" => "a"], args::build_query(["x=a"])); + self::assertSame(["x" => 0], args::build_query(["x:int=0"])); + self::assertSame(["x" => 42], args::build_query(["x:int=42"])); + self::assertSame(["x" => false], args::build_query(["x:bool=0"])); + self::assertSame(["x" => true], args::build_query(["x:bool=42"])); + self::assertSame(["x" => ["a", "b"]], args::build_query(["x:array=a,b"])); + self::assertSame(["x" => [0, 42]], args::build_query(["x:array:int=0,42"])); + self::assertSame(["x" => [0, 42]], args::build_query(["x:int:array=0,42"])); + + self::assertSame(["x" => "a", "y" => "b"], args::build_query(["x=a", "y=b"])); + self::assertSame(["x" => ["a", "b"]], args::build_query(["x=a", "x=b"])); + } + function testBuild_method_args() { self::assertSame([], args::build_method_args(null)); self::assertSame([], args::build_method_args([])); @@ -67,5 +88,7 @@ class argsTest extends TestCase { self::assertSame([["x" => [0, 42]]], args::build_method_args(["x:int:array=0,42"])); self::assertSame([["x" => "a", "y" => "b"], "a", "b"], args::build_method_args(["x=a", "a", "y=b", "b"])); + + self::assertSame([["x" => ["a", "b"]]], args::build_method_args(["x=a", "x=b"])); } } From 52736d8af03e9a37cd369ee308bfb09ec10fb8e4 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 17 Jul 2025 12:04:16 +0400 Subject: [PATCH 3/6] maj TODO --- TODO.md | 12 +++++++++++- php/src/TODO.md | 5 +++++ php/src/app/TODO.md | 2 ++ php/src/output/TODO.md | 8 +++++++- 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 php/src/TODO.md diff --git a/TODO.md b/TODO.md index 5ea289c..30b20cf 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,6 @@ -# nulib +# nulib/bash +* [nulib/bash](bash/TODO.md) * runners * [ ] rnlphp -- lancer un programme php avec la bonne version (+docker le cas échéant) * [ ] utilisable en shebang @@ -12,4 +13,13 @@ * [ ] rnlsh -- lancer un shell avec les librairies bash / lancer un script * MYTRUEDIR, MYTRUENAME, MYTRUESELF -- résoudre les liens symboliques +# nulib/php + +* [nulib](php/src/TODO.md) +* [nulib\app](php/src/app/TODO.md) +* [nulib\db](php/src/db/TODO.md) +* [nulib\os](php/src/os/TODO.md) +* [nulib\output](php/src/output/TODO.md) +* [nulib\php\time](php/src/php/time/TODO.md) + -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/php/src/TODO.md b/php/src/TODO.md new file mode 100644 index 0000000..1af900c --- /dev/null +++ b/php/src/TODO.md @@ -0,0 +1,5 @@ +# nulib + +* [ ] support de UserException pour ExceptionShadow: distinguer userMessage et techMessage + +-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/php/src/app/TODO.md b/php/src/app/TODO.md index 142c37e..bec0657 100644 --- a/php/src/app/TODO.md +++ b/php/src/app/TODO.md @@ -3,5 +3,7 @@ * [ ] ajouter des méthodes normalisées `app::get_cachedir()` et `app::get_cachefile($name)` avec la valeur par défaut `cachedir = $vardir/cache` +* [ ] `app::action()` et `app::step()` appellent automatiquement + `app::_dispatch_signals()` -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/php/src/output/TODO.md b/php/src/output/TODO.md index e10fe8d..fc100bf 100644 --- a/php/src/output/TODO.md +++ b/php/src/output/TODO.md @@ -1,4 +1,4 @@ -# TOOD +# nulib\output * dans msg::action($m, function() {}), *bloquer* la marque pour empêcher d'aller plus bas que prévu. comme ça s'il y a plusieurs success ou failure dans la @@ -32,4 +32,10 @@ pour l'UI peut-être rajouter `ui` (ou `web`?) en plus de say, log, debuglog? --> ou renommer `say` en `console`, et `ui` en `say` +* [ ] ajouter une option `Application::MSG_SIGNALS` qui fait que + * les méthodes `msg::eXXX()` appellent automatiquement `app::_dispatch_signals()` +* [ ] ajouter une option `Application::MSG_ACTIONS` qui fait que + * `msg::section()` et/ou `msg::title()` appellent automatiquement `app::action()` + * `msg::estep()` appelle automatiquement `app::step()` + -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file From 4208412189f18c27cf13cd7dc24ec150dde03e59 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sun, 20 Jul 2025 17:10:05 +0400 Subject: [PATCH 4/6] modifs.mineures sans commentaires --- composer.lock | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index d7a5d80..eb7f2b1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4569957a35f86d8a4964d01c7358935c", + "content-hash": "71744d15224f445d1aeefe16ec7d1099", "packages": [ { "name": "symfony/deprecation-contracts", @@ -301,16 +301,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", "shasum": "" }, "require": { @@ -349,7 +349,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" }, "funding": [ { @@ -357,7 +357,7 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-07-05T12:25:42+00:00" }, { "name": "nikic/php-parser", @@ -2027,6 +2027,8 @@ "php": "^7.4" }, "platform-dev": { + "ext-mbstring": "*", + "ext-iconv": "*", "ext-posix": "*", "ext-pcntl": "*", "ext-curl": "*", From 7587572f2c6f664915c5131454eaf6b3234a0e2e Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 11 Aug 2025 12:23:43 +0400 Subject: [PATCH 5/6] modifs.mineures sans commentaires --- TODO.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TODO.md b/TODO.md index 30b20cf..8eea214 100644 --- a/TODO.md +++ b/TODO.md @@ -22,4 +22,8 @@ * [nulib\output](php/src/output/TODO.md) * [nulib\php\time](php/src/php/time/TODO.md) +vrac: +* PID dans les logs +* build --ci + -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file From 368de874b425911eb36ac17c3265f36cfe87e34e Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 20 Aug 2025 10:37:32 +0400 Subject: [PATCH 6/6] corriger ensure pour utiliser query --- php/src/db/pdo/Pdo.php | 35 ++++++++++++++++++++++++----------- php/src/db/pgsql/Pgsql.php | 36 +++++++++++++++++++++++++----------- php/src/db/sqlite/Sqlite.php | 36 +++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 33 deletions(-) diff --git a/php/src/db/pdo/Pdo.php b/php/src/db/pdo/Pdo.php index fc324dc..10da1c6 100644 --- a/php/src/db/pdo/Pdo.php +++ b/php/src/db/pdo/Pdo.php @@ -134,17 +134,6 @@ class Pdo implements IDatabase { return $this; } - const SQL_CHECK_LIVE = "select 1"; - - function ensure(): self { - try { - $this->_exec(static::SQL_CHECK_LIVE); - } catch (\PDOException $e) { - $this->open(true); - } - return $this; - } - function close(): void { $this->db = null; } @@ -159,6 +148,30 @@ class Pdo implements IDatabase { return $this->db()->exec($query); } + /** @return array|null */ + function _query(string $query) { + $db = $this->db(); + /** @var \PDOStatement $stmt */ + $stmt = $db->query($query); + if ($stmt === false) return null; + try { + return $stmt->fetchAll(\PDO::FETCH_ASSOC); + } finally { + $stmt->closeCursor(); + } + } + + const SQL_CHECK_LIVE = "select 1"; + + function ensure(): self { + try { + $this->_query(static::SQL_CHECK_LIVE); + } catch (\PDOException $e) { + $this->open(true); + } + return $this; + } + function exec($query, ?array $params=null) { $db = $this->db(); $query = new _pdoQuery($query, $params); diff --git a/php/src/db/pgsql/Pgsql.php b/php/src/db/pgsql/Pgsql.php index deeebac..ca9b7e9 100644 --- a/php/src/db/pgsql/Pgsql.php +++ b/php/src/db/pgsql/Pgsql.php @@ -173,17 +173,6 @@ class Pgsql implements IDatabase { return $this; } - const SQL_CHECK_LIVE = "select 1"; - - function ensure(): self { - try { - $this->_exec(static::SQL_CHECK_LIVE); - } catch (\PDOException $e) { - $this->open(true); - } - return $this; - } - function close(): self { if ($this->db !== null) { pg_close($this->db); @@ -204,6 +193,31 @@ class Pgsql implements IDatabase { return true; } + function _query(string $query): ?array { + $result = pg_query($this->db(), $query); + if ($result === false) return null; + try { + $rows = []; + while (($row = pg_fetch_assoc($result)) !== false) { + $rows[] = $row; + } + return $rows; + } finally { + pg_free_result($result); + } + } + + const SQL_CHECK_LIVE = "select 1"; + + function ensure(): self { + try { + $this->_query(static::SQL_CHECK_LIVE); + } catch (\PDOException $e) { + $this->open(true); + } + return $this; + } + function getLastSerial() { $db = $this->db(); $result = @pg_query($db, "select lastval()"); diff --git a/php/src/db/sqlite/Sqlite.php b/php/src/db/sqlite/Sqlite.php index ece4379..1d52f2c 100644 --- a/php/src/db/sqlite/Sqlite.php +++ b/php/src/db/sqlite/Sqlite.php @@ -167,17 +167,6 @@ class Sqlite implements IDatabase { return $this; } - const SQL_CHECK_LIVE = "select 1"; - - function ensure(): self { - try { - $this->_exec(static::SQL_CHECK_LIVE); - } catch (\PDOException $e) { - $this->open(true); - } - return $this; - } - function close(): void { if ($this->db !== null) { $this->db->close(); @@ -203,6 +192,31 @@ class Sqlite implements IDatabase { return $this->db()->exec($query); } + function _query(string $query): ?array { + $result = $this->db()->query($query); + if ($result === false) return null; + try { + $rows = []; + while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) { + $rows[] = $row; + } + return $rows; + } finally { + $result->finalize(); + } + } + + const SQL_CHECK_LIVE = "select 1"; + + function ensure(): self { + try { + $this->_query(static::SQL_CHECK_LIVE); + } catch (\PDOException $e) { + $this->open(true); + } + return $this; + } + function exec($query, ?array $params=null) { $db = $this->db(); $query = new _sqliteQuery($query, $params);