modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2024-06-05 14:03:42 +04:00
parent 1c57fcf041
commit 243bae60d6
5 changed files with 80 additions and 54 deletions

View File

@ -88,7 +88,7 @@ class CapacitorChannel {
* *
* la clé primaire "id_" a pour définition "integer primary key autoincrement". * la clé primaire "id_" a pour définition "integer primary key autoincrement".
* elle peut être redéfinie, et dans ce cas la valeur à utiliser doit être * elle peut être redéfinie, et dans ce cas la valeur à utiliser doit être
* retournée par {@link getKeyValues()} * retournée par {@link getItemValues()}
* *
* la colonne "item__" contient la valeur sérialisée de l'élément chargé. bien * la colonne "item__" contient la valeur sérialisée de l'élément chargé. bien
* que ce soit possible techniquement, cette colonne n'a pas à être redéfinie * que ce soit possible techniquement, cette colonne n'a pas à être redéfinie
@ -112,10 +112,11 @@ class CapacitorChannel {
* calculer les valeurs des colonnes supplémentaires à insérer pour le * calculer les valeurs des colonnes supplémentaires à insérer pour le
* chargement de $item * chargement de $item
* *
* Cette méthode est utilisée par {@link Capacitor::charge()}. Si une valeur * Cette méthode est utilisée par {@link Capacitor::charge()}. Si la clé
* "id_" est retourné, la ligne correspondate existante est mise à jour * primaire est retournée (il s'agit généralement de "id_"), la ligne
* correspondate est mise à jour si elle existe.
*/ */
function getKeyValues($item): ?array { function getItemValues($item): ?array {
return null; return null;
} }
@ -123,30 +124,47 @@ class CapacitorChannel {
* Avant d'utiliser un id pour rechercher dans la base de donnée, corriger sa * Avant d'utiliser un id pour rechercher dans la base de donnée, corriger sa
* valeur le cas échéant. * valeur le cas échéant.
* *
* Cette fonction assume que l'unique clé primaire est id_. Elle n'est pas * Cette fonction assume que l'unique clé primaire est "id_". Elle n'est pas
* utilisée si une clé primaire multiple est définie. * utilisée si une clé primaire multiple est définie.
*/ */
function verifixId(string &$id): void { function verifixId(string &$id): void {
} }
/** /**
* méthode appelée lors du chargement d'un élément avec * méthode appelée lors du chargement avec {@link Capacitor::charge()} pour
* {@link Capacitor::charge()} * créer un nouvel élément
* *
* @param mixed $item l'élément à charger * @param mixed $item l'élément à charger
* @param array $updates les valeurs calculées par {@link getKeyValues()} * @param array $updates les valeurs calculées par {@link getItemValues()}
* @param ?array $row la ligne à mettre à jour. vaut null s'il faut insérer
* une nouvelle ligne
* @return ?array le cas échéant, un tableau non null à merger dans $updates * @return ?array le cas échéant, un tableau non null à merger dans $updates
* et utilisé pour provisionner la ligne nouvellement créée, ou mettre à jour * et utilisé pour provisionner la ligne nouvellement créée
* la ligne existante
* *
* Si $item est modifié dans cette méthode, il est possible de le retourner * Si $item est modifié dans cette méthode, il est possible de le retourner
* avec la clé "item" pour mettre à jour la ligne correspondante. * avec la clé "item" pour mettre à jour la ligne correspondante.
* La colonne "id_" ne peut pas être modifiée: si "id_" est retourné, il est
* ignoré
*/ */
function onCharge($item, array $updates, ?array $row): ?array { function onCreate($item, array $updates, ?array $row): ?array {
return null;
}
/**
* méthode appelée lors du chargement avec {@link Capacitor::charge()} pour
* mettre à jour un élément existant
*
* @param mixed $item l'élément à charger
* @param array $updates les valeurs calculées par {@link getItemValues()}
* Si l'élément a été modifié par rapport au dernier chargement, ce tableau
* contient une clé "modified_" avec la date de modification.
* @param array $row la ligne à mettre à jour.
* @return ?array le cas échéant, un tableau non null à merger dans $updates
* et utilisé pour mettre à jour la ligne existante
*
* Si $item est modifié dans cette méthode, il est possible de le retourner
* avec la clé "item" pour mettre à jour la ligne correspondante.
*
* La clé primaire (il s'agit généralement de "id_") ne peut pas être
* modifiée. si elle est retournée, elle est ignorée
*/
function onUpdate($item, array $updates, ?array $row): ?array {
return null; return null;
} }

View File

@ -137,7 +137,7 @@ abstract class CapacitorStorage {
* charger une valeur dans le canal * charger une valeur dans le canal
* *
* Si $func!==null, après avoir calculé les valeurs des clés supplémentaires * Si $func!==null, après avoir calculé les valeurs des clés supplémentaires
* avec {@link CapacitorChannel::getKeyValues()}, la fonction est appelée avec * avec {@link CapacitorChannel::getItemValues()}, la fonction est appelée avec
* la signature ($item, $keyValues, $row, ...$args) * la signature ($item, $keyValues, $row, ...$args)
* Si la fonction retourne un tableau, il est utilisé pour modifier les valeurs * Si la fonction retourne un tableau, il est utilisé pour modifier les valeurs
* insérées/mises à jour * insérées/mises à jour

View File

@ -67,7 +67,7 @@ class MysqlStorage extends CapacitorStorage {
$row = cl::merge([ $row = cl::merge([
"item__" => $item__, "item__" => $item__,
"sum_" => $sum_, "sum_" => $sum_,
], $this->unserialize($channel, $channel->getKeyValues($item))); ], $this->unserialize($channel, $channel->getItemValues($item)));
$prow = null; $prow = null;
$rowIds = $this->getRowIds($channel, $row, $primaryKeys); $rowIds = $this->getRowIds($channel, $row, $primaryKeys);
if ($rowIds !== null) { if ($rowIds !== null) {
@ -84,6 +84,7 @@ class MysqlStorage extends CapacitorStorage {
"where" => $rowIds, "where" => $rowIds,
]); ]);
} }
$insert = null; $insert = null;
if ($prow === null) { if ($prow === null) {
# création # création
@ -92,21 +93,26 @@ class MysqlStorage extends CapacitorStorage {
"modified_" => $now, "modified_" => $now,
]); ]);
$insert = true; $insert = true;
} elseif ($sum_ !== $prow["sum_"]) { if ($func === null) $func = "->onCreate";
func::ensure_func($func, $channel, $args);
$values = $this->unserialize($channel, $row);
$args = [$item, $values, ...$args];
} else {
# modification # modification
$row = cl::merge($row, [ $row = cl::merge($row, [
"modified_" => $now, "modified_" => $now,
]); ]);
$insert = false; if ($sum_ !== $prow["sum_"]) $insert = false;
if ($func === null) $func = "->onUpdate";
func::ensure_func($func, $channel, $args);
$values = $this->unserialize($channel, $row);
$pvalues = $this->unserialize($channel, $prow);
$args = [$item, $values, $pvalues, ...$args];
} }
if ($func === null) $func = [$channel, "onCharge"]; $updates = func::call($func, ...$args);
$onCharge = func::_prepare($func);
$args ??= [];
$values = $this->unserialize($channel, $row);
$pvalues = $this->unserialize($channel, $prow);
$updates = func::_call($onCharge, [$item, $values, $pvalues, ...$args]);
if (is_array($updates)) { if (is_array($updates)) {
if ($insert === null) $insert = false;
$updates = $this->serialize($channel, $updates); $updates = $this->serialize($channel, $updates);
if (array_key_exists("item__", $updates)) { if (array_key_exists("item__", $updates)) {
# si item a été mis à jour, il faut mettre à jour sum_ # si item a été mis à jour, il faut mettre à jour sum_

View File

@ -64,7 +64,7 @@ class SqliteStorage extends CapacitorStorage {
$row = cl::merge([ $row = cl::merge([
"item__" => $item__, "item__" => $item__,
"sum_" => $sum_, "sum_" => $sum_,
], $this->unserialize($channel, $channel->getKeyValues($item))); ], $this->unserialize($channel, $channel->getItemValues($item)));
$prow = null; $prow = null;
$rowIds = $this->getRowIds($channel, $row, $primaryKeys); $rowIds = $this->getRowIds($channel, $row, $primaryKeys);
if ($rowIds !== null) { if ($rowIds !== null) {
@ -81,6 +81,7 @@ class SqliteStorage extends CapacitorStorage {
"where" => $rowIds, "where" => $rowIds,
]); ]);
} }
$insert = null; $insert = null;
if ($prow === null) { if ($prow === null) {
# création # création
@ -89,21 +90,26 @@ class SqliteStorage extends CapacitorStorage {
"modified_" => $now, "modified_" => $now,
]); ]);
$insert = true; $insert = true;
} elseif ($sum_ !== $prow["sum_"]) { if ($func === null) $func = "->onCreate";
func::ensure_func($func, $channel, $args);
$values = $this->unserialize($channel, $row);
$args = [$item, $values, ...$args];
} else {
# modification # modification
$row = cl::merge($row, [ $row = cl::merge($row, [
"modified_" => $now, "modified_" => $now,
]); ]);
$insert = false; if ($sum_ !== $prow["sum_"]) $insert = false;
if ($func === null) $func = "->onUpdate";
func::ensure_func($func, $channel, $args);
$values = $this->unserialize($channel, $row);
$pvalues = $this->unserialize($channel, $prow);
$args = [$item, $values, $pvalues, ...$args];
} }
if ($func === null) $func = [$channel, "onCharge"]; $updates = func::call($func, ...$args);
$onCharge = func::_prepare($func);
$args ??= [];
$values = $this->unserialize($channel, $row);
$pvalues = $this->unserialize($channel, $prow);
$updates = func::_call($onCharge, [$item, $values, $pvalues, ...$args]);
if (is_array($updates)) { if (is_array($updates)) {
if ($insert === null) $insert = false;
$updates = $this->serialize($channel, $updates); $updates = $this->serialize($channel, $updates);
if (array_key_exists("item__", $updates)) { if (array_key_exists("item__", $updates)) {
# si item a été mis à jour, il faut mettre à jour sum_ # si item a été mis à jour, il faut mettre à jour sum_

View File

@ -2,6 +2,7 @@
namespace nur\sery\db\sqlite; namespace nur\sery\db\sqlite;
use nulib\tests\TestCase; use nulib\tests\TestCase;
use nur\sery\cl;
use nur\sery\db\Capacitor; use nur\sery\db\Capacitor;
use nur\sery\db\CapacitorChannel; use nur\sery\db\CapacitorChannel;
@ -11,7 +12,7 @@ class SqliteStorageTest extends TestCase {
$storage->charge($channel, "first"); $storage->charge($channel, "first");
$storage->charge($channel, "second"); $storage->charge($channel, "second");
$storage->charge($channel, "third"); $storage->charge($channel, "third");
$items = iterator_to_array($storage->discharge($channel, false)); $items = cl::all($storage->discharge($channel, false));
self::assertSame(["first", "second", "third"], $items); self::assertSame(["first", "second", "third"], $items);
} }
@ -32,10 +33,9 @@ class SqliteStorageTest extends TestCase {
$storage = new SqliteStorage(__DIR__.'/capacitor.db'); $storage = new SqliteStorage(__DIR__.'/capacitor.db');
$storage->addChannel(new class extends CapacitorChannel { $storage->addChannel(new class extends CapacitorChannel {
const NAME = "arrays"; const NAME = "arrays";
function getColumnDefinitions(): ?array { const COLUMN_DEFINITIONS = ["id" => "integer"];
return ["id" => "integer"];
} function getItemValues($item): ?array {
function getKeyValues($item): ?array {
return ["id" => $item["id"] ?? null]; return ["id" => $item["id"] ?? null];
} }
}); });
@ -49,14 +49,12 @@ class SqliteStorageTest extends TestCase {
$storage = new SqliteStorage(__DIR__.'/capacitor.db'); $storage = new SqliteStorage(__DIR__.'/capacitor.db');
$capacitor = new Capacitor($storage, new class extends CapacitorChannel { $capacitor = new Capacitor($storage, new class extends CapacitorChannel {
const NAME = "each"; const NAME = "each";
const COLUMN_DEFINITIONS = [
"age" => "integer",
"done" => "integer default 0",
];
function getColumnDefinitions(): ?array { function getItemValues($item): ?array {
return [
"age" => "integer",
"done" => "integer default 0",
];
}
function getKeyValues($item): ?array {
return [ return [
"age" => $item["age"], "age" => $item["age"],
]; ];
@ -79,7 +77,7 @@ class SqliteStorageTest extends TestCase {
}; };
$capacitor->each(["age" => [">", 10]], $setDone, ["++"]); $capacitor->each(["age" => [">", 10]], $setDone, ["++"]);
$capacitor->each(["done" => 0], $setDone, null); $capacitor->each(["done" => 0], $setDone, null);
Txx(iterator_to_array($capacitor->discharge(null, false))); Txx(cl::all($capacitor->discharge(null, false)));
$capacitor->close(); $capacitor->close();
self::assertTrue(true); self::assertTrue(true);
@ -89,14 +87,12 @@ class SqliteStorageTest extends TestCase {
$storage = new SqliteStorage(__DIR__.'/capacitor.db'); $storage = new SqliteStorage(__DIR__.'/capacitor.db');
$capacitor = new Capacitor($storage, new class extends CapacitorChannel { $capacitor = new Capacitor($storage, new class extends CapacitorChannel {
const NAME = "pk"; const NAME = "pk";
const COLUMN_DEFINITIONS = [
"id_" => "varchar primary key",
"done" => "integer default 0",
];
function getColumnDefinitions(): ?array { function getItemValues($item): ?array {
return [
"id_" => "varchar primary key",
"done" => "integer default 0",
];
}
function getKeyValues($item): ?array {
return [ return [
"id_" => $item["numero"], "id_" => $item["numero"],
]; ];