début d'implémentation capacitor
This commit is contained in:
parent
52700ee53b
commit
a3ae6847d4
|
@ -11,6 +11,25 @@ use SQLite3Stmt;
|
|||
* Class Sqlite: frontend vers une base de données sqlite3
|
||||
*/
|
||||
class Sqlite {
|
||||
static function with($sqlite, ?array $params=null): self {
|
||||
if ($sqlite instanceof static) {
|
||||
return $sqlite;
|
||||
} elseif ($sqlite instanceof self) {
|
||||
# recréer avec les mêmes paramètres
|
||||
return new static(null, cl::merge([
|
||||
"file" => $sqlite->file,
|
||||
"flags" => $sqlite->flags,
|
||||
"encryption_key" => $sqlite->encryptionKey,
|
||||
"config" => $sqlite->config,
|
||||
"migrate" => $sqlite->migration,
|
||||
], $params));
|
||||
} elseif (is_array($sqlite)) {
|
||||
return new static(null, cl::merge($sqlite, $params));
|
||||
} else {
|
||||
return new static($sqlite, $params);
|
||||
}
|
||||
}
|
||||
|
||||
static function config_enableExceptions(self $sqlite) {
|
||||
$sqlite->db->enableExceptions(true);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
namespace nur\sery\db\sqlite;
|
||||
|
||||
use nur\sery\cl;
|
||||
use nur\sery\php\func;
|
||||
|
||||
/**
|
||||
* Class SqliteCapacitor: objet permettant d'accumuler des données pour les
|
||||
* réutiliser plus tard
|
||||
*/
|
||||
class SqliteCapacitor {
|
||||
function __construct($sqlite) {
|
||||
$this->sqlite = Sqlite::with($sqlite);
|
||||
}
|
||||
|
||||
/** @var Sqlite */
|
||||
protected $sqlite;
|
||||
|
||||
protected function getTableName(?string $channel): string {
|
||||
return ($channel ?? "default")."_channel";
|
||||
}
|
||||
|
||||
/** tester si le canal spécifié existe */
|
||||
function exists(?string $channel=null): bool {
|
||||
|
||||
}
|
||||
|
||||
/** supprimer le canal spécifié */
|
||||
function reset(?string $channel=null) {
|
||||
$tableName = $this->getTableName($channel);
|
||||
$this->sqlite->exec("drop table if exists $tableName");
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
protected $created;
|
||||
|
||||
protected function getKeyDefinitions(?string $channel): ?array {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getKeyValues($item, ?string $channel): ?array {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function create(?string $channel): void {
|
||||
if ($this->created[$channel] ?? false) return;
|
||||
$columns = cl::merge([
|
||||
"_id" => "integer primary key autoincrement",
|
||||
"_item" => "text",
|
||||
], $this->getKeyDefinitions($channel));
|
||||
#XXXvvv migrer vers la syntaxe tableau de create
|
||||
$index = 0;
|
||||
foreach ($columns as $column => &$definition) {
|
||||
if ($column === $index) {
|
||||
$index++;
|
||||
} else {
|
||||
$definition = "$column $definition";
|
||||
}
|
||||
}; unset($definition);
|
||||
$query = implode("", [
|
||||
"create table if not exists ",
|
||||
$this->getTableName($channel),
|
||||
" (",
|
||||
implode(", ", $columns),
|
||||
")",
|
||||
]);
|
||||
#XXX^^^ migrer vers la syntaxe tableau de create
|
||||
$this->sqlite->exec($query);
|
||||
$this->created[$channel] = true;
|
||||
}
|
||||
|
||||
function charge($item, ?string $channel=null) {
|
||||
$this->create($channel);
|
||||
$values = cl::merge([
|
||||
"_item" => serialize($item),
|
||||
], $this->getKeyValues($item, $channel));
|
||||
$this->sqlite->exec([
|
||||
"insert",
|
||||
"into" => $this->getTableName($channel),
|
||||
"values" => $values,
|
||||
]);
|
||||
}
|
||||
|
||||
/** décharger les données du canal spécifié */
|
||||
function discharge(?string $channel=null, bool $reset=true): iterable {
|
||||
$rows = $this->sqlite->all([
|
||||
"select _item",
|
||||
"from" => $this->getTableName($channel),
|
||||
]);
|
||||
foreach ($rows as $row) {
|
||||
$item = unserialize($row['_item']);
|
||||
yield $item;
|
||||
}
|
||||
if ($reset) $this->reset($channel);
|
||||
}
|
||||
|
||||
/** appeler une fonction pour chaque élément du canal spécifié */
|
||||
function each(callable $func, ?string $channel=null): void {
|
||||
$context = func::_prepare($func);
|
||||
foreach ($this->discharge($channel, false) as $item) {
|
||||
func::_call($context, [$item]);
|
||||
}
|
||||
}
|
||||
|
||||
/** obtenir l'élément identifié par les clés spécifiées sur le canal spécifié */
|
||||
function get(?array $keys, ?string $channel=null) {
|
||||
|
||||
}
|
||||
|
||||
function close(): void {
|
||||
$this->sqlite->close();
|
||||
}
|
||||
|
||||
function sqlite__exec(string $query): bool {
|
||||
return $this->sqlite->_exec($query);
|
||||
}
|
||||
|
||||
function sqlite_exec($query, ?array $params=null): bool {
|
||||
return $this->sqlite->exec($query, $params);
|
||||
}
|
||||
|
||||
function sqlite__get(string $query, bool $entireRow=false) {
|
||||
return $this->sqlite->_get($query, $entireRow);
|
||||
}
|
||||
|
||||
function sqlite_get($query, ?array $params=null, bool $entireRow=false) {
|
||||
return $this->sqlite->get($query, $params, $entireRow);
|
||||
}
|
||||
|
||||
function sqlite_one($query, ?array $params=null): ?array {
|
||||
return $this->sqlite->one($query, $params);
|
||||
}
|
||||
|
||||
function sqlite_all($query, ?array $params=null): iterable {
|
||||
return $this->sqlite->all($query, $params);
|
||||
}
|
||||
}
|
|
@ -5,8 +5,13 @@ use nur\sery\php\func;
|
|||
|
||||
class _migration {
|
||||
static function with($migrations): self {
|
||||
if ($migrations instanceof static) return $migrations;
|
||||
return new static($migrations);
|
||||
if ($migrations instanceof static) {
|
||||
return $migrations;
|
||||
} elseif ($migrations instanceof self) {
|
||||
return new static($migrations->migrations);
|
||||
} else {
|
||||
return new static($migrations);
|
||||
}
|
||||
}
|
||||
|
||||
const MIGRATE = null;
|
||||
|
|
|
@ -60,7 +60,7 @@ class _query {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected static function parse_conds(?array $conds, ?array &$sql, ?array &$params): void {
|
||||
static function parse_conds(?array $conds, ?array &$sql, ?array &$params): void {
|
||||
if (!$conds) return;
|
||||
$sep = null;
|
||||
$index = 0;
|
||||
|
@ -126,7 +126,7 @@ class _query {
|
|||
}
|
||||
}
|
||||
|
||||
protected static function parse_set_values(?array $values, ?array &$sql, ?array &$params): void {
|
||||
static function parse_set_values(?array $values, ?array &$sql, ?array &$params): void {
|
||||
if (!$values) return;
|
||||
$index = 0;
|
||||
$parts = [];
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/capacitor.db
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
namespace nur\sery\db\sqlite;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SqliteCapacitorTest extends TestCase {
|
||||
function _testChargeStrings(SqliteCapacitor $capacitor, ?string $channel) {
|
||||
$capacitor->reset($channel);
|
||||
$capacitor->charge("first", $channel);
|
||||
$capacitor->charge("second", $channel);
|
||||
$capacitor->charge("third", $channel);
|
||||
$items = iterator_to_array($capacitor->discharge($channel, false));
|
||||
self::assertSame(["first", "second", "third"], $items);
|
||||
}
|
||||
function _testChargeArrays(SqliteCapacitor $capacitor, ?string $channel) {
|
||||
$capacitor->reset($channel);
|
||||
$capacitor->charge(["id" => 10, "name" => "first"], $channel);
|
||||
$capacitor->charge(["name" => "second", "id" => 20], $channel);
|
||||
$capacitor->charge(["name" => "third", "id" => "30"], $channel);
|
||||
}
|
||||
|
||||
function testChargeStrings() {
|
||||
$capacitor = new SqliteCapacitor(__DIR__.'/capacitor.db');
|
||||
$this->_testChargeStrings($capacitor, null);
|
||||
$capacitor->close();
|
||||
}
|
||||
|
||||
function testChargeArrays() {
|
||||
$capacitor = new class(__DIR__.'/capacitor.db') extends SqliteCapacitor {
|
||||
protected function getKeyDefinitions(?string $channel): ?array {
|
||||
if ($channel === "arrays") {
|
||||
return ["id" => "integer"];
|
||||
}
|
||||
return parent::getKeyDefinitions($channel);
|
||||
}
|
||||
protected function getKeyValues($item, ?string $channel): ?array {
|
||||
if ($channel === "arrays") {
|
||||
return ["id" => $item["id"] ?? null];
|
||||
}
|
||||
return parent::getKeyValues($item, $channel);
|
||||
}
|
||||
};
|
||||
|
||||
$this->_testChargeStrings($capacitor, "strings");
|
||||
$this->_testChargeArrays($capacitor, "arrays");
|
||||
$capacitor->close();
|
||||
}
|
||||
}
|
|
@ -41,6 +41,12 @@ class SqliteTest extends TestCase {
|
|||
self::assertException(SqliteException::class, [$sqlite, "exec"], ["prout"]);
|
||||
}
|
||||
|
||||
protected function assertInserted(Sqlite $sqlite, array $row, array $query): void {
|
||||
$sqlite->exec($query);
|
||||
self::assertSame($row, $sqlite->one("select * from mapping where i = :i", [
|
||||
"i" => $query["values"]["i"],
|
||||
]));
|
||||
}
|
||||
function testInsert() {
|
||||
$sqlite = new Sqlite(":memory:", [
|
||||
"migrate" => "create table mapping (i integer, s varchar)",
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace nur\sery\db\sqlite;
|
|||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class _QueryTest extends TestCase {
|
||||
class _queryTest extends TestCase {
|
||||
function testParseConds(): void {
|
||||
$sql = $params = null;
|
||||
_query::parse_conds(null, $sql, $params);
|
Loading…
Reference in New Issue