modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2024-06-29 10:32:57 +04:00
parent fb2ebc2aca
commit 9eec059cc1
4 changed files with 233 additions and 11 deletions

View File

@ -309,6 +309,7 @@ class CapacitorChannel {
function onEach($item, array $values): ?array {
return null;
}
const onEach = "->".[self::class, "onEach"][1];
/**
* méthode appelée lors du parcours des éléments avec
@ -321,4 +322,5 @@ class CapacitorChannel {
function onDelete($item, array $values): bool {
return true;
}
const onDelete = "->".[self::class, "onDelete"][1];
}

View File

@ -241,11 +241,15 @@ EOT;
$pvalues = null;
} else {
# modification
# intégrer autant que possible les valeurs de prow dans row, de façon que
# l'utilisateur puisse voir clairement ce qui a été modifié
if ($channel->_wasSumModified("item", $row, $prow)) {
$insert = false;
$row = cl::merge($row, [
$row = cl::merge($prow, $row, [
"modified_" => $now,
]);
} else {
$row = cl::merge($prow, $row);
}
$initFunc = [$channel, "onUpdate"];
$initArgs = $args;
@ -285,6 +289,7 @@ EOT;
$commited = false;
$db->beginTransaction();
}
$nbModified = 0;
try {
if ($insert) {
$id = $db->exec([
@ -296,19 +301,41 @@ EOT;
# mettre à jour avec l'id généré
$values[$primaryKeys[0]] = $id;
}
$nbModified = 1;
} else {
$db->exec([
"update",
"table" => $tableName,
"values" => $row,
"where" => $rowIds,
]);
# calculer ce qui a changé pour ne mettre à jour que le nécessaire
$updates = [];
foreach ($row as $col => $value) {
if (array_key_exists($col, $rowIds)) {
# ne jamais mettre à jour la clé primaire
continue;
}
$pvalue = $prow[$col] ?? null;
if ($value !== ($pvalue)) {
$updates[$col] = $value;
}
}
if (count($updates) == 1 && array_key_first($updates) == "modified_") {
# si l'unique modification porte sur la date de modification, alors
# la ligne n'est pas modifiée. ce cas se présente quand on altère la
# valeur de $item
$updates = null;
}
if ($updates) {
$db->exec([
"update",
"table" => $tableName,
"values" => $updates,
"where" => $rowIds,
]);
$nbModified = 1;
}
}
if ($manageTransactions) {
$db->commit();
$commited = true;
}
return 1;
return $nbModified;
} finally {
if ($manageTransactions && !$commited) $db->rollback();
}
@ -443,7 +470,7 @@ EOT;
*/
function _each(CapacitorChannel $channel, $filter, $func, ?array $args, ?int &$updated=null): int {
$this->_create($channel);
if ($func === null) $func = "->onEach";
if ($func === null) $func = CapacitorChannel::onEach;
func::ensure_func($func, $channel, $args);
$onEach = func::_prepare($func);
$db = $this->db();
@ -510,7 +537,7 @@ EOT;
*/
function _delete(CapacitorChannel $channel, $filter, $func, ?array $args): int {
$this->_create($channel);
if ($func === null) $func = "->onDelete";
if ($func === null) $func = CapacitorChannel::onDelete;
func::ensure_func($func, $channel, $args);
$onEach = func::_prepare($func);
$db = $this->db();

View File

@ -1 +1 @@
/capacitor.db
/capacitor.db*

View File

@ -148,4 +148,197 @@ class SqliteStorageTest extends TestCase {
$capacitor->close();
self::assertTrue(true);
}
function testEachValues() {
# tester que values contient bien toutes les valeurs de la ligne
$storage = new SqliteStorage(__DIR__.'/capacitor.db');
$capacitor = new Capacitor($storage, new class extends CapacitorChannel {
const NAME = "each_values";
const COLUMN_DEFINITIONS = [
"name" => "varchar primary key",
"age" => "integer",
"done" => "integer default 0",
"notes" => "text",
];
function getItemValues($item): ?array {
return [
"name" => $item["name"],
"age" => $item["age"],
];
}
});
$capacitor->reset();
$capacitor->charge(["name" => "first", "age" => 5], function($item, ?array $values, ?array $pvalues) {
self::assertSame("first", $item["name"]);
self::assertSame(5, $item["age"]);
self::assertnotnull($values);
self::assertSame(["name", "age", "item", "item__sum_", "created_", "modified_"], array_keys($values));
self::assertSame([
"name" => "first",
"age" => 5,
"item" => $item,
], cl::select($values, ["name", "age", "item"]));
self::assertNull($pvalues);
});
$capacitor->charge(["name" => "first", "age" => 10], function($item, ?array $values, ?array $pvalues) {
self::assertSame("first", $item["name"]);
self::assertSame(10, $item["age"]);
self::assertnotnull($values);
self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values));
self::assertSame([
"name" => "first",
"age" => 10,
"done" => 0,
"notes" => null,
"item" => $item,
], cl::select($values, ["name", "age", "done", "notes", "item"]));
self::assertNotNull($pvalues);
self::assertSame([
"name" => "first",
"age" => 5,
"done" => 0,
"notes" => null,
"item" => ["name" => "first", "age" => 5],
], cl::select($pvalues, ["name", "age", "done", "notes", "item"]));
});
$capacitor->each(null, function($item, ?array $values) {
self::assertSame("first", $item["name"]);
self::assertSame(10, $item["age"]);
self::assertnotnull($values);
self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values));
self::assertSame([
"name" => "first",
"age" => 10,
"done" => 0,
"notes" => null,
"item" => $item,
], cl::select($values, ["name", "age", "done", "notes", "item"]));
return [
"done" => 1,
"notes" => "modified",
];
});
$capacitor->charge(["name" => "first", "age" => 10], function($item, ?array $values, ?array $pvalues) {
self::assertSame("first", $item["name"]);
self::assertSame(10, $item["age"]);
self::assertnotnull($values);
self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values));
self::assertSame([
"name" => "first",
"age" => 10,
"done" => 1,
"notes" => "modified",
"item" => $item,
], cl::select($values, ["name", "age", "done", "notes", "item"]));
self::assertNotNull($pvalues);
self::assertSame([
"name" => "first",
"age" => 10,
"done" => 1,
"notes" => "modified",
"item" => $item,
], cl::select($pvalues, ["name", "age", "done", "notes", "item"]));
});
$capacitor->charge(["name" => "first", "age" => 20], function($item, ?array $values, ?array $pvalues) {
self::assertSame("first", $item["name"]);
self::assertSame(20, $item["age"]);
self::assertnotnull($values);
self::assertSame(["name", "age", "done", "notes", "item", "item__sum_", "created_", "modified_"], array_keys($values));
self::assertSame([
"name" => "first",
"age" => 20,
"done" => 1,
"notes" => "modified",
"item" => $item,
], cl::select($values, ["name", "age", "done", "notes", "item"]));
self::assertNotNull($pvalues);
self::assertSame([
"name" => "first",
"age" => 10,
"done" => 1,
"notes" => "modified",
"item" => ["name" => "first", "age" => 10],
], cl::select($pvalues, ["name", "age", "done", "notes", "item"]));
});
}
function testSetItemNull() {
# tester le forçage de $îtem à null pour économiser la place
$storage = new SqliteStorage(__DIR__.'/capacitor.db');
$capacitor = new Capacitor($storage, new class extends CapacitorChannel {
const NAME = "set_item_null";
const COLUMN_DEFINITIONS = [
"name" => "varchar primary key",
"age" => "integer",
"done" => "integer default 0",
"notes" => "text",
];
function getItemValues($item): ?array {
return [
"name" => $item["name"],
"age" => $item["age"],
];
}
});
$capacitor->reset();
$nbModified = $capacitor->charge(["name" => "first", "age" => 5], function ($item, ?array $values, ?array $pvalues) {
self::assertSame([
"name" => "first", "age" => 5,
"item" => $item,
], cl::select($values, ["name", "age", "item"]));
return ["item" => null];
});
self::assertSame(1, $nbModified);
sleep(1);
# nb: on met des sleep() pour que la date de modification soit systématiquement différente
$nbModified = $capacitor->charge(["name" => "first", "age" => 10], function ($item, ?array $values, ?array $pvalues) {
self::assertSame([
"name" => "first", "age" => 10,
"item" => $item, "item__sum_" => "9181336dfca20c86313d6065d89aa2ad5070b0fc",
], cl::select($values, ["name", "age", "item", "item__sum_"]));
self::assertSame([
"name" => "first", "age" => 5,
"item" => null, "item__sum_" => null,
], cl::select($pvalues, ["name", "age", "item", "item__sum_"]));
return ["item" => null];
});
self::assertSame(1, $nbModified);
sleep(1);
# pas de modification ici
$nbModified = $capacitor->charge(["name" => "first", "age" => 10], function ($item, ?array $values, ?array $pvalues) {
self::assertSame([
"name" => "first", "age" => 10,
"item" => $item, "item__sum_" => "9181336dfca20c86313d6065d89aa2ad5070b0fc",
], cl::select($values, ["name", "age", "item", "item__sum_"]));
self::assertSame([
"name" => "first", "age" => 10,
"item" => null, "item__sum_" => null,
], cl::select($pvalues, ["name", "age", "item", "item__sum_"]));
return ["item" => null];
});
self::assertSame(0, $nbModified);
sleep(1);
$nbModified = $capacitor->charge(["name" => "first", "age" => 20], function ($item, ?array $values, ?array $pvalues) {
self::assertSame([
"name" => "first", "age" => 20,
"item" => $item, "item__sum_" => "001b91982b4e0883b75428c0eb28573a5dc5f7a5",
], cl::select($values, ["name", "age", "item", "item__sum_"]));
self::assertSame([
"name" => "first", "age" => 10,
"item" => null, "item__sum_" => null,
], cl::select($pvalues, ["name", "age", "item", "item__sum_"]));
return ["item" => null];
});
self::assertSame(1, $nbModified);
sleep(1);
}
}