From cae38dae95f9a726b8795010d436b1140c5e36db Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 28 Apr 2025 04:43:01 +0400 Subject: [PATCH] auto-migration des canaux --- php/src/db/CapacitorStorage.php | 40 ++++++++++++++++++++++++++++- php/src/db/_private/_generic.php | 11 +++++--- php/src/db/mysql/MysqlStorage.php | 24 ++++++++--------- php/src/db/pgsql/PgsqlStorage.php | 34 ++++++++++++------------ php/src/db/sqlite/SqliteStorage.php | 24 ++++++++--------- 5 files changed, 86 insertions(+), 47 deletions(-) diff --git a/php/src/db/CapacitorStorage.php b/php/src/db/CapacitorStorage.php index 66acb17..01412d4 100644 --- a/php/src/db/CapacitorStorage.php +++ b/php/src/db/CapacitorStorage.php @@ -166,6 +166,41 @@ $sql; EOT; } + abstract protected function tableExists(string $tableName): bool; + + const METADATA_TABLE = "_metadata"; + const METADATA_COLS = [ + "name" => "varchar not null primary key", + "value" => "varchar", + ]; + + protected function _prepareMetadata(): void { + if (!$this->tableExists(self::METADATA_TABLE)) { + $db = $this->db(); + $db->exec([ + "drop table", + "table" => self::CHANNELS_TABLE, + ]); + $db->exec([ + "drop table", + "table" => _migration::MIGRATION_TABLE + ]); + $db->exec([ + "create table", + "table" => self::METADATA_TABLE, + "cols" => self::METADATA_COLS, + ]); + $db->exec([ + "insert", + "into" => self::METADATA_TABLE, + "values" => [ + "name" => "version", + "value" => "1", + ], + ]); + } + } + abstract function _getMigration(CapacitorChannel $channel): _migration; const CHANNELS_TABLE = "_channels"; @@ -204,6 +239,7 @@ EOT; protected function _create(CapacitorChannel $channel): void { $channel->ensureSetup(); if (!$channel->isCreated()) { + $this->_prepareMetadata(); $this->_getMigration($channel)->migrate($this->db()); $this->_afterCreate($channel); $channel->setCreated(); @@ -211,7 +247,9 @@ EOT; } /** tester si le canal spécifié existe */ - abstract function _exists(CapacitorChannel $channel): bool; + function _exists(CapacitorChannel $channel): bool { + return $this->tableExists($channel->getTableName()); + } function exists(?string $channel): bool { return $this->_exists($this->getChannel($channel)); diff --git a/php/src/db/_private/_generic.php b/php/src/db/_private/_generic.php index a2ec549..dea829c 100644 --- a/php/src/db/_private/_generic.php +++ b/php/src/db/_private/_generic.php @@ -2,6 +2,7 @@ namespace nulib\db\_private; use nulib\cl; +use nulib\str; use nulib\ValueException; class _generic extends _common { @@ -13,9 +14,13 @@ class _generic extends _common { } static function parse(array $query, ?array &$bindings=null): string { - if (!cl::is_list($query)) { - throw new ValueException("Seuls les tableaux séquentiels sont supportés"); + $sql = ""; + foreach ($query as $value) { + if ($sql && !str::ends_with(" ", $sql) && !str::starts_with(" ", $value)) { + $sql .= " "; + } + $sql .= $value; } - return self::merge_seq($query); + return $sql; } } diff --git a/php/src/db/mysql/MysqlStorage.php b/php/src/db/mysql/MysqlStorage.php index 9f23ec4..de4e3ff 100644 --- a/php/src/db/mysql/MysqlStorage.php +++ b/php/src/db/mysql/MysqlStorage.php @@ -23,6 +23,18 @@ class MysqlStorage extends CapacitorStorage { "id_" => "integer primary key auto_increment", ]; + protected function tableExists(string $tableName): bool { + $db = $this->db; + $found = $db->get([ + "select table_name from information_schema.tables", + "where" => [ + "table_schema" => $db->getDbname(), + "table_name" => $tableName, + ], + ]); + return $found !== null; + } + function _getMigration(CapacitorChannel $channel): _mysqlMigration { return new _mysqlMigration(cl::merge([ $this->_createSql($channel), @@ -46,18 +58,6 @@ class MysqlStorage extends CapacitorStorage { ]); } - function _exists(CapacitorChannel $channel): bool { - $mysql = $this->db; - $tableName = $mysql->get([ - "select table_name from information_schema.tables", - "where" => [ - "table_schema" => $mysql->getDbname(), - "table_name" => $channel->getTableName(), - ], - ]); - return $tableName !== null; - } - function close(): void { $this->db->close(); } diff --git a/php/src/db/pgsql/PgsqlStorage.php b/php/src/db/pgsql/PgsqlStorage.php index d9ec58a..0dc93b7 100644 --- a/php/src/db/pgsql/PgsqlStorage.php +++ b/php/src/db/pgsql/PgsqlStorage.php @@ -24,6 +24,23 @@ class PgsqlStorage extends CapacitorStorage { "id_" => "serial primary key", ]; + protected function tableExists(string $tableName): bool { + if (($index = strpos($tableName, ".")) !== false) { + $schemaName = substr($tableName, 0, $index); + $tableName = substr($tableName, $index + 1); + } else { + $schemaName = "public"; + } + $found = $this->db->get([ + "select tablename from pg_tables", + "where" => [ + "schemaname" => $schemaName, + "tablename" => $tableName, + ], + ]); + return $found !== null; + } + function _getMigration(CapacitorChannel $channel): _pgsqlMigration { return new _pgsqlMigration(cl::merge([ $this->_createSql($channel), @@ -41,23 +58,6 @@ class PgsqlStorage extends CapacitorStorage { ]); } - function _exists(CapacitorChannel $channel): bool { - $tableName = $channel->getTableName(); - if (($index = strpos($tableName, ".")) !== false) { - $schemaName = substr($tableName, 0, $index); - $tableName = substr($tableName, $index + 1); - } else { - $schemaName = "public"; - } - return null !== $this->db->get([ - "select tablename from pg_tables", - "where" => [ - "schemaname" => $schemaName, - "tablename" => $tableName, - ], - ]); - } - function close(): void { $this->db->close(); } diff --git a/php/src/db/sqlite/SqliteStorage.php b/php/src/db/sqlite/SqliteStorage.php index 9850406..f031a56 100644 --- a/php/src/db/sqlite/SqliteStorage.php +++ b/php/src/db/sqlite/SqliteStorage.php @@ -23,6 +23,16 @@ class SqliteStorage extends CapacitorStorage { "id_" => "integer primary key autoincrement", ]; + protected function tableExists(string $tableName): bool { + $found = $this->db->get([ + # depuis la version 3.33.0 le nom officiel de la table est sqlite_schema, + # mais le nom sqlite_master est toujours valable pour le moment + "select name from sqlite_master ", + "where" => ["name" => $tableName], + ]); + return $found !== null; + } + function _getMigration(CapacitorChannel $channel): _sqliteMigration { return new _sqliteMigration(cl::merge([ $this->_createSql($channel), @@ -34,16 +44,6 @@ class SqliteStorage extends CapacitorStorage { return self::format_sql($channel, $query->getSql()); } - function tableExists(string $tableName): bool { - $name = $this->db->get([ - # depuis la version 3.33.0 le nom officiel de la table est sqlite_schema, - # mais le nom sqlite_master est toujours valable pour le moment - "select name from sqlite_master ", - "where" => ["name" => $tableName], - ]); - return $name !== null; - } - function channelExists(string $name): bool { return null !== $this->db->get([ "select name", @@ -72,10 +72,6 @@ class SqliteStorage extends CapacitorStorage { } } - function _exists(CapacitorChannel $channel): bool { - return $this->tableExists($channel->getTableName()); - } - function close(): void { $this->db->close(); }