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; protected ?array $migration;
function getMigration(): ?array { function getMigration(?string $prefix=null): ?array {
return $this->migration; 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; protected ?array $primaryKeys;

View File

@ -122,7 +122,7 @@ abstract class CapacitorStorage {
} }
protected function getMigration(CapacitorChannel $channel): ?array { 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 */ /** sérialiser les valeurs qui doivent l'être dans $row */

View File

@ -2,6 +2,12 @@
namespace nulib\db; namespace nulib\db;
interface IDatabase extends ITransactor { 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 */ /** obtenir la requête SQL correspondant à $query */
function getSql($query, ?array $params=null): string; function getSql($query, ?array $params=null): string;

View File

@ -4,6 +4,8 @@ namespace nulib\db\mysql;
use nulib\db\pdo\Pdo; use nulib\db\pdo\Pdo;
class Mysql extends Pdo { class Mysql extends Pdo {
const PREFIX = "mysql";
function getDbname(): ?string { function getDbname(): ?string {
$url = $this->dbconn["name"] ?? null; $url = $this->dbconn["name"] ?? null;
if ($url !== null && preg_match('/^mysql(?::|.*;)dbname=([^;]+)/i', $url, $ms)) { 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 { function _getMigration(CapacitorChannel $channel): _mysqlMigration {
$migrations = cl::merge([ $migrations = cl::merge([
"0init" => [$this->_createSql($channel)], "0init" => [$this->_createSql($channel)],
], $channel->getMigration()); ], $channel->getMigration($this->db->getPrefix()));
return new _mysqlMigration($migrations, $channel->getName()); return new _mysqlMigration($migrations, $channel->getName());
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,6 @@ class Date extends DateTime {
} }
function format($format=self::DEFAULT_FORMAT): string { 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); 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 DMY_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))?$/';
const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/'; const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/';
const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/'; 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\MyChannel;
use nulib\db\sqlite\impl\MyChannelV2; use nulib\db\sqlite\impl\MyChannelV2;
use nulib\db\sqlite\impl\MyChannelV3; use nulib\db\sqlite\impl\MyChannelV3;
use nulib\db\sqlite\impl\MyIndexChannel;
use nulib\output\msg; use nulib\output\msg;
use nulib\output\std\StdMessenger; use nulib\output\std\StdMessenger;
use nulib\php\time\DateTime; use nulib\php\time\DateTime;
@ -69,6 +70,42 @@ alter table my add column date_mod datetime;
-- infos -- infos
alter table my add column age integer; 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; EOT;
self::assertSame($expected, $sql); 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,
]);
}
}