diff --git a/.idea/php-test-framework.xml b/.idea/php-test-framework.xml new file mode 100644 index 0000000..c092999 --- /dev/null +++ b/.idea/php-test-framework.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nur_bin/sqlite-storage.php b/nur_bin/sqlite-storage.php index f73c5ce..7b6d24f 100755 --- a/nur_bin/sqlite-storage.php +++ b/nur_bin/sqlite-storage.php @@ -19,12 +19,15 @@ Application::run(new class extends Application { "merge" => parent::ARGS, "purpose" => "gestion d'un capacitor sqlite", "usage" => [ - "-f DBFILE -c CHANNEL [--query] key=value...", - "-f DBFILE -c CHANNEL --sql-create", + "-f DBFILE -n CHANNEL [--query] key=value...", + "-f DBFILE -n CHANNEL --sql-create", ], ["-f", "--dbfile", "args" => 1, "help" => "chemin vers la base de données", ], + ["-n", "--name", "args" => 1, + "help" => "nom du canal de données. table-name et channel-class sont chargés depuis la base de données", + ], ["-t", "--table-name", "args" => 1, "help" => "nom de la table porteuse du canal de données", ], @@ -41,6 +44,8 @@ Application::run(new class extends Application { protected ?string $dbfile = null; + protected ?string $name = null; + protected ?string $tableName = null; protected ?string $channelClass = null; @@ -57,12 +62,25 @@ Application::run(new class extends Application { $dbfile = $this->dbfile; if ($dbfile === null) self::die("Vous devez spécifier la base de données"); if (!file_exists($dbfile)) self::die("$dbfile: fichier introuvable"); + $storage = new SqliteStorage($dbfile); - if ($this->channelClass !== null) { - $channelClass = str_replace("/", "\\", $this->channelClass); + $name = $this->name; + $channelClass = $this->channelClass; + $tableName = $this->tableName; + if ($name !== null) { + $row = $storage->db()->one([ + "select from _channels", + "where" => ["name" => $name], + ]); + if ($row === null) self::die("$name: nom de canal de données introuvable"); + if ($row["class"] !== "class@anonymous") $channelClass = $row["class"]; + else $tableName = $row["table_name"]; + } + if ($channelClass !== null) { + $channelClass = str_replace("/", "\\", $channelClass); $channel = new $channelClass; - } elseif ($this->tableName !== null) { - $channel = new class($this->tableName) extends CapacitorChannel { + } elseif ($tableName !== null) { + $channel = new class($tableName) extends CapacitorChannel { function __construct(?string $name=null) { parent::__construct($name); $this->tableName = $name; @@ -71,8 +89,6 @@ Application::run(new class extends Application { } else { self::die("Vous devez spécifier le canal de données"); } - - $storage = new SqliteStorage($dbfile); $capacitor = new Capacitor($storage, $channel); switch ($this->action) { diff --git a/src/db/CapacitorChannel.php b/src/db/CapacitorChannel.php index a3d6297..e2a1c88 100644 --- a/src/db/CapacitorChannel.php +++ b/src/db/CapacitorChannel.php @@ -27,7 +27,7 @@ class CapacitorChannel { if ($name !== null) { $name = strtolower($name); if ($tableName === null) { - $tableName = str_replace("-", "_", $tableName) . "_channel"; + $tableName = str_replace("-", "_", $name) . "_channel"; } } else { $name = static::class; diff --git a/src/db/CapacitorStorage.php b/src/db/CapacitorStorage.php index 46cde2e..7e1dca4 100644 --- a/src/db/CapacitorStorage.php +++ b/src/db/CapacitorStorage.php @@ -154,10 +154,14 @@ EOT; return $this->_getCreateSql($this->getChannel($channel)); } + protected function _afterCreate(CapacitorChannel $channel): void { + } + protected function _create(CapacitorChannel $channel): void { $channel->ensureSetup(); if (!$channel->isCreated()) { $this->db->exec($this->_createSql($channel)); + $this->_afterCreate($channel); $channel->setCreated(); } } @@ -178,8 +182,12 @@ EOT; $this->_ensureExists($this->getChannel($channel)); } + protected function _beforeReset(CapacitorChannel $channel): void { + } + /** supprimer le canal spécifié */ function _reset(CapacitorChannel $channel, bool $recreate=false): void { + $this->_beforeReset($channel); $this->db->exec([ "drop table if exists", $channel->getTableName(), diff --git a/src/db/_private/Tinsert.php b/src/db/_private/Tinsert.php index edb9a22..2f46767 100644 --- a/src/db/_private/Tinsert.php +++ b/src/db/_private/Tinsert.php @@ -22,8 +22,8 @@ trait Tinsert { if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix; ## insert - self::consume('insert\s*', $tmpsql); - $sql[] = "insert"; + self::consume('(insert(?:\s+or\s+(?:ignore|replace))?)\s*', $tmpsql, $ms); + $sql[] = $ms[1]; ## into self::consume('into\s*', $tmpsql); diff --git a/src/db/sqlite/SqliteStorage.php b/src/db/sqlite/SqliteStorage.php index daa8839..92f77fc 100644 --- a/src/db/sqlite/SqliteStorage.php +++ b/src/db/sqlite/SqliteStorage.php @@ -28,6 +28,39 @@ class SqliteStorage extends CapacitorStorage { return self::format_sql($channel, $query->getSql()); } + protected function _afterCreate(CapacitorChannel $channel): void { + $db = $this->db; + $db->exec([ + "create table if not exists", + "table" => "_channels", + "cols" => [ + "name" => "varchar primary key", + "table_name" => "varchar", + "class" => "varchar", + ], + ]); + $db->exec([ + "insert", + "into" => "_channels", + "values" => [ + "name" => $channel->getName(), + "table_name" => $channel->getTableName(), + "class" => get_class($channel), + ], + "suffix" => "on conflict do nothing", + ]); + } + + protected function _beforeReset(CapacitorChannel $channel): void { + $this->db->exec([ + "delete", + "from" => "_channels", + "where" => [ + "name" => $channel->getName(), + ], + ]); + } + function _exists(CapacitorChannel $channel): bool { $tableName = $this->db->get([ "select name from sqlite_schema",