support préfixe pour les migrations

This commit is contained in:
Jephté Clain 2025-06-24 10:38:10 +04:00
parent b71e879823
commit 4f17d19609
14 changed files with 119 additions and 7 deletions

View File

@ -214,8 +214,18 @@ class CapacitorChannel implements ITransactor {
protected ?array $migration;
function getMigration(): ?array {
return $this->migration;
function getMigration(?string $prefix=null): ?array {
if ($prefix === null || $this->migration === null) return $this->migration;
$migration = null;
str::add_suffix($prefix, ":");
foreach ($this->migration as $mkey => $mdef) {
if (str::starts_with($prefix, $mkey)) {
$migration[$mkey] = $mdef;
} elseif (strpos($mkey, ":") === false) {
$migration[$mkey] = $mdef;
}
}
return $migration;
}
protected ?array $primaryKeys;

View File

@ -122,7 +122,7 @@ abstract class CapacitorStorage {
}
protected function getMigration(CapacitorChannel $channel): ?array {
return $channel->getMigration();
return $channel->getMigration($this->db()->getPrefix());
}
/** sérialiser les valeurs qui doivent l'être dans $row */

View File

@ -2,6 +2,12 @@
namespace nulib\db;
interface IDatabase extends ITransactor {
/**
* retourner le type de la base de données (mysql, pgsql, sqlite, ...)
* ce préfixe peut servir à qualifier les migrations
*/
function getPrefix(): ?string;
/** obtenir la requête SQL correspondant à $query */
function getSql($query, ?array $params=null): string;

View File

@ -4,6 +4,8 @@ namespace nulib\db\mysql;
use nulib\db\pdo\Pdo;
class Mysql extends Pdo {
const PREFIX = "mysql";
function getDbname(): ?string {
$url = $this->dbconn["name"] ?? null;
if ($url !== null && preg_match('/^mysql(?::|.*;)dbname=([^;]+)/i', $url, $ms)) {

View File

@ -39,7 +39,7 @@ class MysqlStorage extends CapacitorStorage {
function _getMigration(CapacitorChannel $channel): _mysqlMigration {
$migrations = cl::merge([
"0init" => [$this->_createSql($channel)],
], $channel->getMigration());
], $channel->getMigration($this->db->getPrefix()));
return new _mysqlMigration($migrations, $channel->getName());
}

View File

@ -12,6 +12,12 @@ use nulib\ValueException;
class Pdo implements IDatabase {
use Tvalues;
const PREFIX = null;
function getPrefix(): ?string {
return static::PREFIX;
}
static function with($pdo, ?array $params=null): self {
if ($pdo instanceof static) {
return $pdo;

View File

@ -12,6 +12,12 @@ use nulib\ValueException;
class Pgsql implements IDatabase {
use Tvalues;
const PREFIX = "pgsql";
function getPrefix(): ?string {
return self::PREFIX;
}
static function with($pgsql, ?array $params=null): self {
if ($pgsql instanceof static) {
return $pgsql;

View File

@ -44,7 +44,7 @@ class PgsqlStorage extends CapacitorStorage {
function _getMigration(CapacitorChannel $channel): _pgsqlMigration {
$migrations = cl::merge([
"0init" => [$this->_createSql($channel)],
], $channel->getMigration());
], $channel->getMigration($this->db->getPrefix()));
return new _pgsqlMigration($migrations, $channel->getName());
}

View File

@ -19,6 +19,12 @@ use SQLite3Stmt;
class Sqlite implements IDatabase {
use Tvalues;
const PREFIX = "sqlite";
function getPrefix(): ?string {
return self::PREFIX;
}
static function with($sqlite, ?array $params=null): self {
if ($sqlite instanceof static) {
return $sqlite;

View File

@ -34,7 +34,7 @@ class SqliteStorage extends CapacitorStorage {
function _getMigration(CapacitorChannel $channel): _sqliteMigration {
$migrations = cl::merge([
"0init" => [$this->_createSql($channel)],
], $channel->getMigration());
], $channel->getMigration($this->db->getPrefix()));
return new _sqliteMigration($migrations, $channel->getName());
}

View File

@ -15,6 +15,6 @@ class Date extends DateTime {
}
function format($format=self::DEFAULT_FORMAT): string {
return \DateTime::format($format);
return parent::format($format);
}
}

View File

@ -30,6 +30,16 @@ class DateTime extends \DateTime {
else return new static($datetime);
}
static function withn($datetime): ?self {
if ($datetime === null) return null;
elseif ($datetime instanceof static) return $datetime;
else return new static($datetime);
}
static function ensure(&$datetime): void {
$datetime = static::withn($datetime);
}
const DMY_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))?$/';
const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/';
const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/';

View File

@ -5,6 +5,7 @@ use nulib\db\Capacitor;
use nulib\db\sqlite\impl\MyChannel;
use nulib\db\sqlite\impl\MyChannelV2;
use nulib\db\sqlite\impl\MyChannelV3;
use nulib\db\sqlite\impl\MyIndexChannel;
use nulib\output\msg;
use nulib\output\std\StdMessenger;
use nulib\php\time\DateTime;
@ -69,6 +70,42 @@ alter table my add column date_mod datetime;
-- infos
alter table my add column age integer;
EOT;
self::assertSame($expected, $sql);
}
function testMigrationIndex() {
$storage = new SqliteStorage(__DIR__.'/capacitor.db');
$data = [
["un", "premier", "first"],
["deux", "deuxieme", "second"],
];
new Capacitor($storage, $channel = new MyIndexChannel());
$channel->reset(true);
$channel->chargeAll($data);
$sql = $channel->getCapacitor()->getCreateSql();
$class = MyIndexChannel::class;
$expected = <<<EOT
-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
-- autogénéré à partir de $class
-- 0init
create table if not exists my_index (
name varchar not null primary key
, first varchar
, second varchar
, item__ mediumtext
, item__sum_ varchar(40)
, created_ datetime
, modified_ datetime
);
-- index
create index my_index_first on my_index(first);
create index my_index_second on my_index(second);
EOT;
self::assertSame($expected, $sql);
}

View File

@ -0,0 +1,29 @@
<?php
namespace nulib\db\sqlite\impl;
use nulib\cl;
use nulib\db\CapacitorChannel;
class MyIndexChannel extends CapacitorChannel {
const NAME = "my_index";
const TABLE_NAME = "my_index";
const COLUMN_DEFINITIONS = [
"name" => "varchar not null primary key",
"first" => "varchar",
"second" => "varchar",
];
const MIGRATION = [
"index" => [
"create index my_index_first on my_index(first)",
"create index my_index_second on my_index(second)",
],
];
function getItemValues($item): ?array {
return cl::select($item, [
"name" => 0,
"first" => 1,
"second" => 2,
]);
}
}