modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2024-06-14 09:32:59 +04:00
parent ee80fad847
commit f431ce248a
9 changed files with 195 additions and 125 deletions

View File

@ -15,10 +15,15 @@ use nur\sery\file\Stream;
use nur\yaml; use nur\yaml;
Application::run(new class extends Application { Application::run(new class extends Application {
const ACTION_QUERY = 0, ACTION_SQL = 1;
const ARGS = [ const ARGS = [
"merge" => parent::ARGS, "merge" => parent::ARGS,
"purpose" => "gestion d'un capacitor mysql", "purpose" => "gestion d'un capacitor mysql",
"usage" => "-d DBCONN -c CHANNEL key=value...", "usage" => [
"-d DBCONN -c CHANNEL [--query] key=value...",
"-d DBCONN -c CHANNEL --sql-create",
],
["-d", "--dbconn", "args" => 1, ["-d", "--dbconn", "args" => 1,
"help" => "nom de la connexion à la base de données", "help" => "nom de la connexion à la base de données",
], ],
@ -28,6 +33,12 @@ Application::run(new class extends Application {
["-c", "--channel-class", "args" => 1, ["-c", "--channel-class", "args" => 1,
"help" => "nom de la classe dérivée de CapacitorChannel", "help" => "nom de la classe dérivée de CapacitorChannel",
], ],
["--query", "name" => "action", "value" => self::ACTION_QUERY,
"help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut",
],
["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
"help" => "afficher la requête pour créer la table",
],
]; ];
protected ?string $dbconn = null; protected ?string $dbconn = null;
@ -36,6 +47,8 @@ Application::run(new class extends Application {
protected ?string $channelClass = null; protected ?string $channelClass = null;
protected int $action = self::ACTION_QUERY;
protected ?array $args = null; protected ?array $args = null;
protected static function isa_cond(string $arg, ?array &$ms=null): bool { protected static function isa_cond(string $arg, ?array &$ms=null): bool {
@ -66,42 +79,49 @@ Application::run(new class extends Application {
$storage = new MysqlStorage($dbconn); $storage = new MysqlStorage($dbconn);
$capacitor = new Capacitor($storage, $channel); $capacitor = new Capacitor($storage, $channel);
$args = $this->args; switch ($this->action) {
if (!$args) { case self::ACTION_QUERY:
# lister les id $args = $this->args;
$out = new Stream(STDOUT); if (!$args) {
$primaryKeys = $storage->getPrimaryKeys($channel); # lister les id
$rows = $storage->db()->all([ $out = new Stream(STDOUT);
"select", $primaryKeys = $storage->getPrimaryKeys($channel);
"cols" => $primaryKeys, $rows = $storage->db()->all([
"from" => $channel->getTableName(), "select",
]); "cols" => $primaryKeys,
$out->fputcsv($primaryKeys); "from" => $channel->getTableName(),
foreach ($rows as $row) { ]);
$rowIds = $storage->getRowIds($channel, $row); $out->fputcsv($primaryKeys);
$out->fputcsv($rowIds); foreach ($rows as $row) {
} $rowIds = $storage->getRowIds($channel, $row);
} else { $out->fputcsv($rowIds);
# afficher les lignes correspondantes }
if (count($args) == 1 && !self::isa_cond($args[0])) {
$filter = $args[0];
} else { } else {
$filter = []; # afficher les lignes correspondantes
$ms = null; if (count($args) == 1 && !self::isa_cond($args[0])) {
foreach ($args as $arg) { $filter = $args[0];
if (self::isa_cond($arg, $ms)) { } else {
$filter[$ms[1]] = [$ms[2], $ms[3]]; $filter = [];
} else { $ms = null;
$filter[$arg] = ["not null"]; foreach ($args as $arg) {
if (self::isa_cond($arg, $ms)) {
$filter[$ms[1]] = [$ms[2], $ms[3]];
} else {
$filter[$arg] = ["not null"];
}
} }
} }
$first = true;
$capacitor->each($filter, function ($item, $row) use (&$first) {
if ($first) $first = false;
else echo "---\n";
yaml::dump($row);
});
} }
$first = true; break;
$capacitor->each($filter, function ($item, $row) use (&$first) { case self::ACTION_SQL:
if ($first) $first = false; echo $capacitor->getCreateSql()."\n";
else echo "---\n"; break;
yaml::dump($row);
});
} }
} }
}); });

View File

@ -13,10 +13,15 @@ use nur\sery\file\Stream;
use nur\yaml; use nur\yaml;
Application::run(new class extends Application { Application::run(new class extends Application {
const ACTION_QUERY = 0, ACTION_SQL = 1;
const ARGS = [ const ARGS = [
"merge" => parent::ARGS, "merge" => parent::ARGS,
"purpose" => "gestion d'un capacitor sqlite", "purpose" => "gestion d'un capacitor sqlite",
"usage" => "-f DBFILE -c CHANNEL key=value...", "usage" => [
"-f DBFILE -c CHANNEL [--query] key=value...",
"-f DBFILE -c CHANNEL --sql-create",
],
["-f", "--dbfile", "args" => 1, ["-f", "--dbfile", "args" => 1,
"help" => "chemin vers la base de données", "help" => "chemin vers la base de données",
], ],
@ -26,6 +31,12 @@ Application::run(new class extends Application {
["-c", "--channel-class", "args" => 1, ["-c", "--channel-class", "args" => 1,
"help" => "nom de la classe dérivée de CapacitorChannel", "help" => "nom de la classe dérivée de CapacitorChannel",
], ],
["--query", "name" => "action", "value" => self::ACTION_QUERY,
"help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut",
],
["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
"help" => "afficher la requête pour créer la table",
],
]; ];
protected ?string $dbfile = null; protected ?string $dbfile = null;
@ -34,6 +45,8 @@ Application::run(new class extends Application {
protected ?string $channelClass = null; protected ?string $channelClass = null;
protected int $action = self::ACTION_QUERY;
protected ?array $args = null; protected ?array $args = null;
protected static function isa_cond(string $arg, ?array &$ms=null): bool { protected static function isa_cond(string $arg, ?array &$ms=null): bool {
@ -62,42 +75,49 @@ Application::run(new class extends Application {
$storage = new SqliteStorage($dbfile); $storage = new SqliteStorage($dbfile);
$capacitor = new Capacitor($storage, $channel); $capacitor = new Capacitor($storage, $channel);
$args = $this->args; switch ($this->action) {
if (!$args) { case self::ACTION_QUERY:
# lister les id $args = $this->args;
$out = new Stream(STDOUT); if (!$args) {
$primaryKeys = $storage->getPrimaryKeys($channel); # lister les id
$rows = $storage->db()->all([ $out = new Stream(STDOUT);
"select", $primaryKeys = $storage->getPrimaryKeys($channel);
"cols" => $primaryKeys, $rows = $storage->db()->all([
"from" => $channel->getTableName(), "select",
]); "cols" => $primaryKeys,
$out->fputcsv($primaryKeys); "from" => $channel->getTableName(),
foreach ($rows as $row) { ]);
$rowIds = $storage->getRowIds($channel, $row); $out->fputcsv($primaryKeys);
$out->fputcsv($rowIds); foreach ($rows as $row) {
} $rowIds = $storage->getRowIds($channel, $row);
} else { $out->fputcsv($rowIds);
# afficher les lignes correspondantes }
if (count($args) == 1 && !self::isa_cond($args[0])) {
$filter = $args[0];
} else { } else {
$filter = []; # afficher les lignes correspondantes
$ms = null; if (count($args) == 1 && !self::isa_cond($args[0])) {
foreach ($args as $arg) { $filter = $args[0];
if (self::isa_cond($arg, $ms)) { } else {
$filter[$ms[1]] = [$ms[2], $ms[3]]; $filter = [];
} else { $ms = null;
$filter[$arg] = ["not null"]; foreach ($args as $arg) {
if (self::isa_cond($arg, $ms)) {
$filter[$ms[1]] = [$ms[2], $ms[3]];
} else {
$filter[$arg] = ["not null"];
}
} }
} }
$first = true;
$capacitor->each($filter, function ($item, $row) use (&$first) {
if ($first) $first = false;
else echo "---\n";
yaml::dump($row);
});
} }
$first = true; break;
$capacitor->each($filter, function ($item, $row) use (&$first) { case self::ACTION_SQL:
if ($first) $first = false; echo $capacitor->getCreateSql()."\n";
else echo "---\n"; break;
yaml::dump($row);
});
} }
} }
}); });

View File

@ -34,6 +34,10 @@ class Capacitor {
return $this->getChannel()->getTableName(); return $this->getChannel()->getTableName();
} }
function getCreateSql(): string {
return $this->storage->_getCreateSql($this->channel);
}
function exists(): bool { function exists(): bool {
return $this->storage->_exists($this->channel); return $this->storage->_exists($this->channel);
} }
@ -42,8 +46,8 @@ class Capacitor {
$this->storage->_ensureExists($this->channel); $this->storage->_ensureExists($this->channel);
} }
function reset(bool $ensureExists=false): void { function reset(bool $recreate=false): void {
$this->storage->_reset($this->channel, $ensureExists); $this->storage->_reset($this->channel, $recreate);
} }
function charge($item, $func=null, ?array $args=null): int { function charge($item, $func=null, ?array $args=null): int {

View File

@ -27,6 +27,7 @@ class CapacitorChannel {
$this->name = self::verifix_name($name ?? static::NAME); $this->name = self::verifix_name($name ?? static::NAME);
$this->tableName = static::TABLE_NAME ?? ($this->name."_channel"); $this->tableName = static::TABLE_NAME ?? ($this->name."_channel");
$this->eachCommitThreshold = $eachCommitThreshold ?? static::EACH_COMMIT_THRESHOLD; $this->eachCommitThreshold = $eachCommitThreshold ?? static::EACH_COMMIT_THRESHOLD;
$this->setup = false;
$this->created = false; $this->created = false;
$columnDefinitions = cl::withn(static::COLUMN_DEFINITIONS); $columnDefinitions = cl::withn(static::COLUMN_DEFINITIONS);
$primaryKeys = cl::withn(static::PRIMARY_KEYS); $primaryKeys = cl::withn(static::PRIMARY_KEYS);
@ -73,6 +74,21 @@ class CapacitorChannel {
return $this->eachCommitThreshold; return $this->eachCommitThreshold;
} }
/**
* initialiser ce channel avant sa première utilisation.
*/
protected function setup(): void {
}
protected $setup;
function ensureSetup() {
if (!$this->setup) {
$this->setup();
$this->setup = true;
}
}
protected $created; protected $created;
function isCreated(): bool { function isCreated(): bool {

View File

@ -113,6 +113,39 @@ abstract class CapacitorStorage {
else return $rowIds; else return $rowIds;
} }
protected function _createSql(CapacitorChannel $channel): array {
$cols = $this->ColumnDefinitions($channel);
return [
"create table if not exists",
"table" => $channel->getTableName(),
"cols" => $cols,
];
}
protected static function format_sql(CapacitorChannel $channel, string $sql): string {
$class = get_class($channel);
return <<<EOT
-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
-- autogénéré à partir de $class
$sql;
EOT;
}
abstract function _getCreateSql(CapacitorChannel $channel): string;
/** obtenir la requête SQL utilisée pour créer la table */
function getCreateSql(?string $channel): string {
return $this->_getCreateSql($this->getChannel($channel));
}
protected function _create(CapacitorChannel $channel): void {
$channel->ensureSetup();
if (!$channel->isCreated()) {
$this->db->exec($this->_createSql($channel));
$channel->setCreated();
}
}
abstract function _exists(CapacitorChannel $channel): bool; abstract function _exists(CapacitorChannel $channel): bool;
/** tester si le canal spécifié existe */ /** tester si le canal spécifié existe */
@ -120,18 +153,27 @@ abstract class CapacitorStorage {
return $this->_exists($this->getChannel($channel)); return $this->_exists($this->getChannel($channel));
} }
abstract function _ensureExists(CapacitorChannel $channel): void; function _ensureExists(CapacitorChannel $channel): void {
$this->_create($channel);
}
/** s'assurer que le canal spécifié existe */ /** s'assurer que le canal spécifié existe */
function ensureExists(?string $channel): void { function ensureExists(?string $channel): void {
$this->_ensureExists($this->getChannel($channel)); $this->_ensureExists($this->getChannel($channel));
} }
abstract function _reset(CapacitorChannel $channel, bool $ensureExists=false): void; function _reset(CapacitorChannel $channel, bool $recreate=false): void {
$this->db->exec([
"drop table if exists",
$channel->getTableName(),
]);
$channel->setCreated(false);
if ($recreate) $this->_ensureExists($channel);
}
/** supprimer le canal spécifié */ /** supprimer le canal spécifié */
function reset(?string $channel, bool $ensureExists=false): void { function reset(?string $channel, bool $recreate=false): void {
$this->_reset($this->getChannel($channel), $ensureExists); $this->_reset($this->getChannel($channel), $recreate);
} }
function _charge(CapacitorChannel $channel, $item, $func, ?array $args): int { function _charge(CapacitorChannel $channel, $item, $func, ?array $args): int {
@ -228,6 +270,7 @@ abstract class CapacitorStorage {
} }
function _discharge(CapacitorChannel $channel, bool $reset=true): iterable { function _discharge(CapacitorChannel $channel, bool $reset=true): iterable {
$this->_create($channel);
$rows = $this->db()->all([ $rows = $this->db()->all([
"select item__", "select item__",
"from" => $channel->getTableName(), "from" => $channel->getTableName(),
@ -253,6 +296,7 @@ abstract class CapacitorStorage {
} }
function _count(CapacitorChannel $channel, $filter): int { function _count(CapacitorChannel $channel, $filter): int {
$this->_create($channel);
$this->verifixFilter($channel, $filter); $this->verifixFilter($channel, $filter);
return $this->db()->get([ return $this->db()->get([
"select count(*)", "select count(*)",
@ -268,6 +312,7 @@ abstract class CapacitorStorage {
function _one(CapacitorChannel $channel, $filter): ?array { function _one(CapacitorChannel $channel, $filter): ?array {
if ($filter === null) throw ValueException::null("filter"); if ($filter === null) throw ValueException::null("filter");
$this->_create($channel);
$this->verifixFilter($channel, $filter); $this->verifixFilter($channel, $filter);
$row = $this->db()->one([ $row = $this->db()->one([
"select", "select",
@ -287,6 +332,7 @@ abstract class CapacitorStorage {
} }
function _all(CapacitorChannel $channel, $filter): iterable { function _all(CapacitorChannel $channel, $filter): iterable {
$this->_create($channel);
$this->verifixFilter($channel, $filter); $this->verifixFilter($channel, $filter);
$rows = $this->db()->all([ $rows = $this->db()->all([
"select", "select",
@ -308,6 +354,7 @@ abstract class CapacitorStorage {
} }
function _each(CapacitorChannel $channel, $filter, $func, ?array $args): int { function _each(CapacitorChannel $channel, $filter, $func, ?array $args): int {
$this->_create($channel);
if ($func === null) $func = "->onEach"; if ($func === null) $func = "->onEach";
func::ensure_func($func, $channel, $args); func::ensure_func($func, $channel, $args);
$onEach = func::_prepare($func); $onEach = func::_prepare($func);
@ -367,6 +414,7 @@ abstract class CapacitorStorage {
} }
function _delete(CapacitorChannel $channel, $filter, $func, ?array $args): int { function _delete(CapacitorChannel $channel, $filter, $func, ?array $args): int {
$this->_create($channel);
if ($func === null) $func = "->onDelete"; if ($func === null) $func = "->onDelete";
func::ensure_func($func, $channel, $args); func::ensure_func($func, $channel, $args);
$onEach = func::_prepare($func); $onEach = func::_prepare($func);

View File

@ -28,7 +28,7 @@ trait Tcreate {
$definition = "$col $definition"; $definition = "$col $definition";
} }
}; unset($definition); }; unset($definition);
$sql[] = "(".implode(", ", $cols).")"; $sql[] = "(\n ".implode("\n, ", $cols).")";
## suffixe ## suffixe
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix; if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;

View File

@ -242,9 +242,17 @@ abstract class _base {
/** @var string */ /** @var string */
protected $sql; protected $sql;
function getSql(): string {
return $this->sql;
}
/** @var ?array */ /** @var ?array */
protected $bindings; protected $bindings;
function getBindings(): ?array {
return $this->bindings;
}
/** @var ?array */ /** @var ?array */
protected $meta; protected $meta;
} }

View File

@ -1,11 +1,8 @@
<?php <?php
namespace nur\sery\db\mysql; namespace nur\sery\db\mysql;
use nur\sery\cl;
use nur\sery\db\CapacitorChannel; use nur\sery\db\CapacitorChannel;
use nur\sery\db\CapacitorStorage; use nur\sery\db\CapacitorStorage;
use nur\sery\php\func;
use nur\sery\ValueException;
/** /**
* Class MysqlStorage * Class MysqlStorage
@ -26,16 +23,9 @@ class MysqlStorage extends CapacitorStorage {
"id_" => "integer primary key auto_increment", "id_" => "integer primary key auto_increment",
]; ];
protected function _create(CapacitorChannel $channel): void { function _getCreateSql(CapacitorChannel $channel): string {
if (!$channel->isCreated()) { $query = new _query_base($this->_createSql($channel));
$cols = $this->ColumnDefinitions($channel); return self::format_sql($channel, $query->getSql());
$this->db->exec([
"create table if not exists",
"table" => $channel->getTableName(),
"cols" => $cols,
]);
$channel->setCreated();
}
} }
function _exists(CapacitorChannel $channel): bool { function _exists(CapacitorChannel $channel): bool {
@ -50,19 +40,6 @@ class MysqlStorage extends CapacitorStorage {
return $tableName !== null; return $tableName !== null;
} }
function _ensureExists(CapacitorChannel $channel): void {
$this->_create($channel);
}
function _reset(CapacitorChannel $channel, bool $ensureExists=false): void {
$this->db->exec([
"drop table if exists",
$channel->getTableName(),
]);
$channel->setCreated(false);
if ($ensureExists) $this->_ensureExists($channel);
}
function close(): void { function close(): void {
$this->db->close(); $this->db->close();
} }

View File

@ -1,11 +1,8 @@
<?php <?php
namespace nur\sery\db\sqlite; namespace nur\sery\db\sqlite;
use nur\sery\cl;
use nur\sery\db\CapacitorChannel; use nur\sery\db\CapacitorChannel;
use nur\sery\db\CapacitorStorage; use nur\sery\db\CapacitorStorage;
use nur\sery\php\func;
use nur\sery\ValueException;
/** /**
* Class SqliteStorage * Class SqliteStorage
@ -26,16 +23,9 @@ class SqliteStorage extends CapacitorStorage {
"id_" => "integer primary key autoincrement", "id_" => "integer primary key autoincrement",
]; ];
protected function _create(CapacitorChannel $channel): void { function _getCreateSql(CapacitorChannel $channel): string {
if (!$channel->isCreated()) { $query = new _query_base($this->_createSql($channel));
$cols = $this->ColumnDefinitions($channel); return self::format_sql($channel, $query->getSql());
$this->db->exec([
"create table if not exists",
"table" => $channel->getTableName(),
"cols" => $cols,
]);
$channel->setCreated();
}
} }
function _exists(CapacitorChannel $channel): bool { function _exists(CapacitorChannel $channel): bool {
@ -48,19 +38,6 @@ class SqliteStorage extends CapacitorStorage {
return $tableName !== null; return $tableName !== null;
} }
function _ensureExists(CapacitorChannel $channel): void {
$this->_create($channel);
}
function _reset(CapacitorChannel $channel, bool $ensureExists=false): void {
$this->db->exec([
"drop table if exists",
$channel->getTableName(),
]);
$channel->setCreated(false);
if ($ensureExists) $this->_ensureExists($channel);
}
function close(): void { function close(): void {
$this->db->close(); $this->db->close();
} }