modifs.mineures sans commentaires
This commit is contained in:
parent
d241ce6561
commit
2a46c12e08
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
|
/test_*
|
||||||
|
|
||||||
/.composer.lock.runphp
|
/.composer.lock.runphp
|
||||||
|
|
||||||
.~lock*#
|
.~lock*#
|
||||||
|
81
pgsql.php
81
pgsql.php
@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
require __DIR__.'/vendor/autoload.php';
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\db\Capacitor;
|
|
||||||
use nulib\db\CapacitorChannel;
|
|
||||||
use nulib\db\pgsql\Pgsql;
|
|
||||||
use nulib\db\pgsql\PgsqlStorage;
|
|
||||||
|
|
||||||
$pgsql = new Pgsql([
|
|
||||||
"host" => "pegase-dre.self",
|
|
||||||
"dbname" => "dre",
|
|
||||||
"user" => "root",
|
|
||||||
"password" => "admin",
|
|
||||||
#"user" => "reader",
|
|
||||||
#"password" => "reader",
|
|
||||||
]);
|
|
||||||
|
|
||||||
function e($sql) {
|
|
||||||
global $pgsql;
|
|
||||||
$v = $pgsql->exec($sql);
|
|
||||||
$v = var_export($v, true);
|
|
||||||
echo "'$sql' --> $v\n";
|
|
||||||
}
|
|
||||||
function g($sql) {
|
|
||||||
global $pgsql;
|
|
||||||
$v = $pgsql->get($sql);
|
|
||||||
$v = var_export($v, true);
|
|
||||||
echo "'$sql' --> $v\n";
|
|
||||||
}
|
|
||||||
function o($sql) {
|
|
||||||
global $pgsql;
|
|
||||||
$r = $pgsql->one($sql);
|
|
||||||
$r = var_export($r, true);
|
|
||||||
echo "'$sql' --> $r\n";
|
|
||||||
}
|
|
||||||
function a($sql) {
|
|
||||||
global $pgsql;
|
|
||||||
$rs = $pgsql->all($sql);
|
|
||||||
echo "'$sql'\n";
|
|
||||||
foreach ($rs as $r) {
|
|
||||||
$r = var_export($r, true);
|
|
||||||
echo " --> $r\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g("select age from personnes where id=1");
|
|
||||||
o("select name, age from personnes where id=2");
|
|
||||||
a("select id, name, age from personnes");
|
|
||||||
|
|
||||||
$n = rand();
|
|
||||||
$pgsql->exec([
|
|
||||||
"insert",
|
|
||||||
"into" => "personnes",
|
|
||||||
"values" => [
|
|
||||||
"name" => "prout$n",
|
|
||||||
"age" => $n,
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
|
|
||||||
class MyChannel extends CapacitorChannel {
|
|
||||||
const COLUMN_DEFINITIONS = [
|
|
||||||
"name" => "varchar",
|
|
||||||
"value" => "int",
|
|
||||||
];
|
|
||||||
|
|
||||||
function getItemValues($item): ?array {
|
|
||||||
return $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$storage = new PgsqlStorage($pgsql);
|
|
||||||
$channel = new MyChannel();
|
|
||||||
new Capacitor($storage, $channel);
|
|
||||||
|
|
||||||
$channel->charge([
|
|
||||||
"name" => "one",
|
|
||||||
"value" => rand(),
|
|
||||||
]);
|
|
||||||
foreach ($channel->all(null) as $row) {
|
|
||||||
var_export($row);
|
|
||||||
}
|
|
@ -120,10 +120,6 @@ class Capacitor implements ITransactor {
|
|||||||
if ($db->inTransaction()) $db->rollback();
|
if ($db->inTransaction()) $db->rollback();
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@ class CapacitorChannel {
|
|||||||
|
|
||||||
const PRIMARY_KEYS = null;
|
const PRIMARY_KEYS = null;
|
||||||
|
|
||||||
|
const MIGRATION = null;
|
||||||
|
|
||||||
const MANAGE_TRANSACTIONS = true;
|
const MANAGE_TRANSACTIONS = true;
|
||||||
|
|
||||||
const EACH_COMMIT_THRESHOLD = 100;
|
const EACH_COMMIT_THRESHOLD = 100;
|
||||||
@ -80,6 +82,7 @@ class CapacitorChannel {
|
|||||||
}
|
}
|
||||||
$this->columnDefinitions = $columnDefinitions;
|
$this->columnDefinitions = $columnDefinitions;
|
||||||
$this->primaryKeys = $primaryKeys;
|
$this->primaryKeys = $primaryKeys;
|
||||||
|
$this->migration = cl::withn(static::MIGRATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string $name;
|
protected string $name;
|
||||||
@ -192,6 +195,12 @@ class CapacitorChannel {
|
|||||||
return $this->columnDefinitions;
|
return $this->columnDefinitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ?array $migration;
|
||||||
|
|
||||||
|
function getMigration(): ?array {
|
||||||
|
return $this->migration;
|
||||||
|
}
|
||||||
|
|
||||||
protected ?array $primaryKeys;
|
protected ?array $primaryKeys;
|
||||||
|
|
||||||
function getPrimaryKeys(): ?array {
|
function getPrimaryKeys(): ?array {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace nulib\db;
|
namespace nulib\db;
|
||||||
|
|
||||||
use nulib\cl;
|
use nulib\cl;
|
||||||
|
use nulib\db\_private\_migration;
|
||||||
use nulib\db\cache\cache;
|
use nulib\db\cache\cache;
|
||||||
use nulib\php\func;
|
use nulib\php\func;
|
||||||
use nulib\ValueException;
|
use nulib\ValueException;
|
||||||
@ -75,6 +76,10 @@ abstract class CapacitorStorage {
|
|||||||
return cl::merge($definitions, $constraints);
|
return cl::merge($definitions, $constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getMigration(CapacitorChannel $channel): ?array {
|
||||||
|
return $channel->getMigration();
|
||||||
|
}
|
||||||
|
|
||||||
/** sérialiser les valeurs qui doivent l'être dans $values */
|
/** sérialiser les valeurs qui doivent l'être dans $values */
|
||||||
protected function serialize(CapacitorChannel $channel, ?array $values): ?array {
|
protected function serialize(CapacitorChannel $channel, ?array $values): ?array {
|
||||||
if ($values === null) return null;
|
if ($values === null) return null;
|
||||||
@ -137,11 +142,10 @@ abstract class CapacitorStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function _createSql(CapacitorChannel $channel): array {
|
protected function _createSql(CapacitorChannel $channel): array {
|
||||||
$cols = $this->ColumnDefinitions($channel);
|
|
||||||
return [
|
return [
|
||||||
"create table if not exists",
|
"create table if not exists",
|
||||||
"table" => $channel->getTableName(),
|
"table" => $channel->getTableName(),
|
||||||
"cols" => $cols,
|
"cols" => $this->ColumnDefinitions($channel),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,12 +160,7 @@ $sql;
|
|||||||
EOT;
|
EOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract function _getCreateSql(CapacitorChannel $channel): string;
|
abstract function _getMigration(CapacitorChannel $channel): _migration;
|
||||||
|
|
||||||
/** 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 _afterCreate(CapacitorChannel $channel): void {
|
protected function _afterCreate(CapacitorChannel $channel): void {
|
||||||
}
|
}
|
||||||
@ -169,7 +168,7 @@ EOT;
|
|||||||
protected function _create(CapacitorChannel $channel): void {
|
protected function _create(CapacitorChannel $channel): void {
|
||||||
$channel->ensureSetup();
|
$channel->ensureSetup();
|
||||||
if (!$channel->isCreated()) {
|
if (!$channel->isCreated()) {
|
||||||
$this->db()->exec($this->_createSql($channel));
|
$this->_getMigration($channel)->migrate($this->db());
|
||||||
$this->_afterCreate($channel);
|
$this->_afterCreate($channel);
|
||||||
$channel->setCreated();
|
$channel->setCreated();
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,22 @@ class _create extends _common {
|
|||||||
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
#XXX implémentation minimale
|
#XXX implémentation minimale
|
||||||
$sql = [self::merge_seq($query)];
|
$tmpsql = self::merge_seq($query);
|
||||||
|
self::consume('create(?:\s+table)?\b', $tmpsql);
|
||||||
|
$sql = ["create table"];
|
||||||
|
if ($tmpsql) $sql[] = $tmpsql;
|
||||||
|
|
||||||
## préfixe
|
## préfixe
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
$prefix = $query["prefix"] ?? null;
|
||||||
|
if ($prefix !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
## table
|
## table
|
||||||
$sql[] = $query["table"];
|
$table = $query["table"] ?? null;
|
||||||
|
if ($table !== null) $sql[] = $table;
|
||||||
|
|
||||||
## columns
|
## columns
|
||||||
$cols = $query["cols"];
|
$cols = $query["cols"] ?? null;
|
||||||
|
if ($cols !== null) {
|
||||||
$index = 0;
|
$index = 0;
|
||||||
foreach ($cols as $col => &$definition) {
|
foreach ($cols as $col => &$definition) {
|
||||||
if ($col === $index) {
|
if ($col === $index) {
|
||||||
@ -37,9 +43,11 @@ class _create extends _common {
|
|||||||
}
|
}
|
||||||
}; unset($definition);
|
}; unset($definition);
|
||||||
$sql[] = "(\n ".implode("\n, ", $cols)."\n)";
|
$sql[] = "(\n ".implode("\n, ", $cols)."\n)";
|
||||||
|
}
|
||||||
|
|
||||||
## suffixe
|
## suffixe
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
$suffix = $query["suffix"] ?? null;
|
||||||
|
if ($suffix !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
## fin de la requête
|
## fin de la requête
|
||||||
return implode(" ", $sql);
|
return implode(" ", $sql);
|
||||||
|
@ -17,13 +17,16 @@ class _delete extends _common {
|
|||||||
#XXX implémentation minimale
|
#XXX implémentation minimale
|
||||||
$tmpsql = self::merge_seq($query);
|
$tmpsql = self::merge_seq($query);
|
||||||
self::consume('delete(?:\s+from)?\b', $tmpsql);
|
self::consume('delete(?:\s+from)?\b', $tmpsql);
|
||||||
$sql = ["delete from", $tmpsql];
|
$sql = ["delete from"];
|
||||||
|
if ($tmpsql) $sql[] = $tmpsql;
|
||||||
|
|
||||||
## préfixe
|
## préfixe
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
$prefix = $query["prefix"] ?? null;
|
||||||
|
if ($prefix !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
## table
|
## table
|
||||||
$sql[] = $query["from"];
|
$from = $query["from"] ?? null;
|
||||||
|
if ($from !== null) $sql[] = $from;
|
||||||
|
|
||||||
## where
|
## where
|
||||||
$where = $query["where"] ?? null;
|
$where = $query["where"] ?? null;
|
||||||
@ -36,7 +39,8 @@ class _delete extends _common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
## suffixe
|
## suffixe
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
$suffix = $query["suffix"] ?? null;
|
||||||
|
if ($suffix !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
## fin de la requête
|
## fin de la requête
|
||||||
return implode(" ", $sql);
|
return implode(" ", $sql);
|
||||||
|
@ -9,7 +9,7 @@ class _generic extends _common {
|
|||||||
];
|
];
|
||||||
|
|
||||||
static function isa(string $sql): bool {
|
static function isa(string $sql): bool {
|
||||||
return preg_match('/^(?:drop\s+table)\b/i', $sql);
|
return preg_match('/^drop\s+table\b/i', $sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
45
php/src/db/_private/_migration.php
Normal file
45
php/src/db/_private/_migration.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
|
use nulib\db\IDatabase;
|
||||||
|
use nulib\php\func;
|
||||||
|
|
||||||
|
abstract class _migration {
|
||||||
|
const MIGRATION = null;
|
||||||
|
|
||||||
|
function __construct($migrations, string $channel="", ?IDatabase $db=null) {
|
||||||
|
$this->db = $db;
|
||||||
|
$this->channel = $channel;
|
||||||
|
if ($migrations === null) $migrations = static::MIGRATION;
|
||||||
|
if ($migrations === null) $migrations = [];
|
||||||
|
elseif (is_string($migrations)) $migrations = [$migrations];
|
||||||
|
elseif (is_callable($migrations)) $migrations = [$migrations];
|
||||||
|
elseif (!is_array($migrations)) $migrations = [strval($migrations)];
|
||||||
|
$this->migrations = $migrations;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ?IDatabase $db;
|
||||||
|
|
||||||
|
protected string $channel;
|
||||||
|
|
||||||
|
/** @var callable[]|string[] */
|
||||||
|
protected $migrations;
|
||||||
|
|
||||||
|
abstract function setup(): void;
|
||||||
|
abstract function beforeMigrate(string $key): bool;
|
||||||
|
abstract function afterMigrate(string $key): void;
|
||||||
|
|
||||||
|
function migrate(?IDatabase $db=null): void {
|
||||||
|
$db = ($this->db ??= $db);
|
||||||
|
$this->setup();
|
||||||
|
foreach ($this->migrations as $key => $migration) {
|
||||||
|
if (!$this->beforeMigrate($key)) continue;
|
||||||
|
if (is_string($migration) || !func::is_callable($migration)) {
|
||||||
|
$db->exec($migration);
|
||||||
|
} else {
|
||||||
|
func::with($migration)->bind($this, true)->invoke([$db, $key]);
|
||||||
|
}
|
||||||
|
$this->afterMigrate($key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,10 +21,12 @@ class _update extends _common {
|
|||||||
$sql = [self::merge_seq($query)];
|
$sql = [self::merge_seq($query)];
|
||||||
|
|
||||||
## préfixe
|
## préfixe
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
$prefix = $query["prefix"] ?? null;
|
||||||
|
if ($prefix !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
## table
|
## table
|
||||||
$sql[] = $query["table"];
|
$table = $query["table"] ?? null;
|
||||||
|
if ($table !== null) $sql[] = $table;
|
||||||
|
|
||||||
## set
|
## set
|
||||||
self::parse_set_values($query["values"], $setsql, $bindings);
|
self::parse_set_values($query["values"], $setsql, $bindings);
|
||||||
@ -42,7 +44,8 @@ class _update extends _common {
|
|||||||
}
|
}
|
||||||
|
|
||||||
## suffixe
|
## suffixe
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
$suffix = $query["suffix"] ?? null;
|
||||||
|
if ($suffix !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
## fin de la requête
|
## fin de la requête
|
||||||
return implode(" ", $sql);
|
return implode(" ", $sql);
|
||||||
|
@ -23,7 +23,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||||||
];
|
];
|
||||||
|
|
||||||
function _getCreateSql(CapacitorChannel $channel): string {
|
function _getCreateSql(CapacitorChannel $channel): string {
|
||||||
$query = new query($this->_createSql($channel));
|
$query = new _mysqlQuery($this->_createSql($channel));
|
||||||
return self::format_sql($channel, $query->getSql());
|
return self::format_sql($channel, $query->getSql());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
php/src/db/mysql/_mysqlQuery.php
Normal file
7
php/src/db/mysql/_mysqlQuery.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
namespace nulib\db\mysql;
|
||||||
|
|
||||||
|
use nulib\db\pdo\_pdoQuery;
|
||||||
|
|
||||||
|
class _mysqlQuery extends _pdoQuery {
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
class query extends \nulib\db\pdo\query {
|
|
||||||
}
|
|
@ -22,7 +22,7 @@ class Pdo implements IDatabase {
|
|||||||
"dbconn" => $pdo->dbconn,
|
"dbconn" => $pdo->dbconn,
|
||||||
"options" => $pdo->options,
|
"options" => $pdo->options,
|
||||||
"config" => $pdo->config,
|
"config" => $pdo->config,
|
||||||
"migrate" => $pdo->migration,
|
"migration" => $pdo->migration,
|
||||||
], $params));
|
], $params));
|
||||||
} else {
|
} else {
|
||||||
return new static($pdo, $params);
|
return new static($pdo, $params);
|
||||||
@ -50,7 +50,7 @@ class Pdo implements IDatabase {
|
|||||||
|
|
||||||
protected const CONFIG = null;
|
protected const CONFIG = null;
|
||||||
|
|
||||||
protected const MIGRATE = null;
|
protected const MIGRATION = null;
|
||||||
|
|
||||||
const dbconn_SCHEMA = [
|
const dbconn_SCHEMA = [
|
||||||
"name" => "string",
|
"name" => "string",
|
||||||
@ -63,7 +63,7 @@ class Pdo implements IDatabase {
|
|||||||
"options" => ["?array|callable"],
|
"options" => ["?array|callable"],
|
||||||
"replace_config" => ["?array|callable"],
|
"replace_config" => ["?array|callable"],
|
||||||
"config" => ["?array|callable"],
|
"config" => ["?array|callable"],
|
||||||
"migrate" => ["?array|string|callable"],
|
"migration" => ["?array|string|callable"],
|
||||||
"auto_open" => ["bool", true],
|
"auto_open" => ["bool", true],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class Pdo implements IDatabase {
|
|||||||
}
|
}
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
# migrations
|
# migrations
|
||||||
$this->migration = $params["migrate"] ?? static::MIGRATE;
|
$this->migration = $params["migration"] ?? static::MIGRATION;
|
||||||
#
|
#
|
||||||
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
||||||
if ($params["auto_open"] ?? $defaultAutoOpen) {
|
if ($params["auto_open"] ?? $defaultAutoOpen) {
|
||||||
@ -145,7 +145,7 @@ class Pdo implements IDatabase {
|
|||||||
|
|
||||||
function exec($query, ?array $params=null) {
|
function exec($query, ?array $params=null) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pdoQuery($query, $params);
|
||||||
if ($query->_use_stmt($db, $stmt, $sql)) {
|
if ($query->_use_stmt($db, $stmt, $sql)) {
|
||||||
if ($stmt->execute() === false) return false;
|
if ($stmt->execute() === false) return false;
|
||||||
if ($query->isInsert()) return $db->lastInsertId();
|
if ($query->isInsert()) return $db->lastInsertId();
|
||||||
@ -217,7 +217,7 @@ class Pdo implements IDatabase {
|
|||||||
|
|
||||||
function get($query, ?array $params=null, bool $entireRow=false) {
|
function get($query, ?array $params=null, bool $entireRow=false) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pdoQuery($query, $params);
|
||||||
$stmt = null;
|
$stmt = null;
|
||||||
try {
|
try {
|
||||||
/** @var \PDOStatement $stmt */
|
/** @var \PDOStatement $stmt */
|
||||||
@ -242,7 +242,7 @@ class Pdo implements IDatabase {
|
|||||||
|
|
||||||
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pdoQuery($query, $params);
|
||||||
$stmt = null;
|
$stmt = null;
|
||||||
try {
|
try {
|
||||||
/** @var \PDOStatement $stmt */
|
/** @var \PDOStatement $stmt */
|
||||||
|
@ -5,7 +5,7 @@ use nulib\db\_private\_base;
|
|||||||
use nulib\db\_private\Tbindings;
|
use nulib\db\_private\Tbindings;
|
||||||
use nulib\output\msg;
|
use nulib\output\msg;
|
||||||
|
|
||||||
class query extends _base {
|
class _pdoQuery extends _base {
|
||||||
use Tbindings;
|
use Tbindings;
|
||||||
|
|
||||||
const DEBUG_QUERIES = false;
|
const DEBUG_QUERIES = false;
|
@ -21,7 +21,7 @@ class Pgsql implements IDatabase {
|
|||||||
"dbconn" => $pgsql->dbconn,
|
"dbconn" => $pgsql->dbconn,
|
||||||
"options" => $pgsql->options,
|
"options" => $pgsql->options,
|
||||||
"config" => $pgsql->config,
|
"config" => $pgsql->config,
|
||||||
"migrate" => $pgsql->migration,
|
"migration" => $pgsql->migration,
|
||||||
], $params));
|
], $params));
|
||||||
} else {
|
} else {
|
||||||
return new static($pgsql, $params);
|
return new static($pgsql, $params);
|
||||||
@ -37,14 +37,14 @@ class Pgsql implements IDatabase {
|
|||||||
|
|
||||||
const CONFIG = null;
|
const CONFIG = null;
|
||||||
|
|
||||||
const MIGRATE = null;
|
const MIGRATION = null;
|
||||||
|
|
||||||
const params_SCHEMA = [
|
const params_SCHEMA = [
|
||||||
"dbconn" => ["array"],
|
"dbconn" => ["array"],
|
||||||
"options" => ["?array|callable"],
|
"options" => ["?array|callable"],
|
||||||
"replace_config" => ["?array|callable"],
|
"replace_config" => ["?array|callable"],
|
||||||
"config" => ["?array|callable"],
|
"config" => ["?array|callable"],
|
||||||
"migrate" => ["?array|string|callable"],
|
"migration" => ["?array|string|callable"],
|
||||||
"auto_open" => ["bool", true],
|
"auto_open" => ["bool", true],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ class Pgsql implements IDatabase {
|
|||||||
}
|
}
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
# migrations
|
# migrations
|
||||||
$this->migration = $params["migrate"] ?? static::MIGRATE;
|
$this->migration = $params["migration"] ?? static::MIGRATION;
|
||||||
#
|
#
|
||||||
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
||||||
if ($params["auto_open"] ?? $defaultAutoOpen) {
|
if ($params["auto_open"] ?? $defaultAutoOpen) {
|
||||||
@ -183,7 +183,7 @@ class Pgsql implements IDatabase {
|
|||||||
|
|
||||||
function exec($query, ?array $params=null) {
|
function exec($query, ?array $params=null) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pgsqlQuery($query, $params);
|
||||||
$result = $query->_exec($db);
|
$result = $query->_exec($db);
|
||||||
$serialSupport = $this->options["serial_support"] ?? true;
|
$serialSupport = $this->options["serial_support"] ?? true;
|
||||||
if ($serialSupport && $query->isInsert()) return $this->getLastSerial();
|
if ($serialSupport && $query->isInsert()) return $this->getLastSerial();
|
||||||
@ -261,7 +261,7 @@ class Pgsql implements IDatabase {
|
|||||||
|
|
||||||
function get($query, ?array $params=null, bool $entireRow=false) {
|
function get($query, ?array $params=null, bool $entireRow=false) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pgsqlQuery($query, $params);
|
||||||
$result = $query->_exec($db);
|
$result = $query->_exec($db);
|
||||||
$row = pg_fetch_assoc($result);
|
$row = pg_fetch_assoc($result);
|
||||||
pg_free_result($result);
|
pg_free_result($result);
|
||||||
@ -277,7 +277,7 @@ class Pgsql implements IDatabase {
|
|||||||
|
|
||||||
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _pgsqlQuery($query, $params);
|
||||||
$result = $query->_exec($db);
|
$result = $query->_exec($db);
|
||||||
$primaryKeys = cl::withn($primaryKeys);
|
$primaryKeys = cl::withn($primaryKeys);
|
||||||
while (($row = pg_fetch_assoc($result)) !== false) {
|
while (($row = pg_fetch_assoc($result)) !== false) {
|
||||||
|
@ -24,7 +24,7 @@ class PgsqlStorage extends CapacitorStorage {
|
|||||||
];
|
];
|
||||||
|
|
||||||
function _getCreateSql(CapacitorChannel $channel): string {
|
function _getCreateSql(CapacitorChannel $channel): string {
|
||||||
$query = new query($this->_createSql($channel));
|
$query = new _pgsqlQuery($this->_createSql($channel));
|
||||||
return self::format_sql($channel, $query->getSql());
|
return self::format_sql($channel, $query->getSql());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use nulib\db\_private\_base;
|
|||||||
use nulib\db\_private\Tbindings;
|
use nulib\db\_private\Tbindings;
|
||||||
use nulib\output\msg;
|
use nulib\output\msg;
|
||||||
|
|
||||||
class query extends _base {
|
class _pgsqlQuery extends _base {
|
||||||
use Tbindings;
|
use Tbindings;
|
||||||
|
|
||||||
const DEBUG_QUERIES = false;
|
const DEBUG_QUERIES = false;
|
@ -30,7 +30,7 @@ class Sqlite implements IDatabase {
|
|||||||
"encryption_key" => $sqlite->encryptionKey,
|
"encryption_key" => $sqlite->encryptionKey,
|
||||||
"allow_wal" => $sqlite->allowWal,
|
"allow_wal" => $sqlite->allowWal,
|
||||||
"config" => $sqlite->config,
|
"config" => $sqlite->config,
|
||||||
"migrate" => $sqlite->migration,
|
"migration" => $sqlite->migration,
|
||||||
], $params));
|
], $params));
|
||||||
} elseif (is_array($sqlite)) {
|
} elseif (is_array($sqlite)) {
|
||||||
return new static(null, cl::merge($sqlite, $params));
|
return new static(null, cl::merge($sqlite, $params));
|
||||||
@ -72,7 +72,7 @@ class Sqlite implements IDatabase {
|
|||||||
|
|
||||||
const CONFIG = null;
|
const CONFIG = null;
|
||||||
|
|
||||||
const MIGRATE = null;
|
const MIGRATION = null;
|
||||||
|
|
||||||
const params_SCHEMA = [
|
const params_SCHEMA = [
|
||||||
"file" => ["string", ""],
|
"file" => ["string", ""],
|
||||||
@ -81,7 +81,7 @@ class Sqlite implements IDatabase {
|
|||||||
"allow_wal" => ["?bool"],
|
"allow_wal" => ["?bool"],
|
||||||
"replace_config" => ["?array|callable"],
|
"replace_config" => ["?array|callable"],
|
||||||
"config" => ["?array|callable"],
|
"config" => ["?array|callable"],
|
||||||
"migrate" => ["?array|string|callable"],
|
"migration" => ["?array|string|callable"],
|
||||||
"auto_open" => ["bool", true],
|
"auto_open" => ["bool", true],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class Sqlite implements IDatabase {
|
|||||||
}
|
}
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
# migrations
|
# migrations
|
||||||
$this->migration = $params["migrate"] ?? static::MIGRATE;
|
$this->migration = $params["migration"] ?? static::MIGRATION;
|
||||||
#
|
#
|
||||||
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
|
||||||
$this->inTransaction = false;
|
$this->inTransaction = false;
|
||||||
@ -150,7 +150,7 @@ class Sqlite implements IDatabase {
|
|||||||
if ($this->db === null) {
|
if ($this->db === null) {
|
||||||
$this->db = new SQLite3($this->file, $this->flags, $this->encryptionKey);
|
$this->db = new SQLite3($this->file, $this->flags, $this->encryptionKey);
|
||||||
_config::with($this->config)->configure($this);
|
_config::with($this->config)->configure($this);
|
||||||
_migration::with($this->migration)->migrate($this);
|
_sqliteMigration::with($this->migration)->migrate($this);
|
||||||
$this->inTransaction = false;
|
$this->inTransaction = false;
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
@ -183,7 +183,7 @@ class Sqlite implements IDatabase {
|
|||||||
|
|
||||||
function exec($query, ?array $params=null) {
|
function exec($query, ?array $params=null) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _sqliteQuery($query, $params);
|
||||||
if ($query->_use_stmt($db, $stmt, $sql)) {
|
if ($query->_use_stmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
$result = $stmt->execute();
|
$result = $stmt->execute();
|
||||||
@ -270,7 +270,7 @@ class Sqlite implements IDatabase {
|
|||||||
|
|
||||||
function get($query, ?array $params=null, bool $entireRow=false) {
|
function get($query, ?array $params=null, bool $entireRow=false) {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _sqliteQuery($query, $params);
|
||||||
if ($query->_use_stmt($db, $stmt, $sql)) {
|
if ($query->_use_stmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
$result = $this->checkResult($stmt->execute());
|
$result = $this->checkResult($stmt->execute());
|
||||||
@ -315,7 +315,7 @@ class Sqlite implements IDatabase {
|
|||||||
|
|
||||||
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
function all($query, ?array $params=null, $primaryKeys=null): iterable {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new query($query, $params);
|
$query = new _sqliteQuery($query, $params);
|
||||||
if ($query->_use_stmt($db, $stmt, $sql)) {
|
if ($query->_use_stmt($db, $stmt, $sql)) {
|
||||||
$result = $this->checkResult($stmt->execute());
|
$result = $this->checkResult($stmt->execute());
|
||||||
return $this->_fetchResult($result, $stmt, $primaryKeys);
|
return $this->_fetchResult($result, $stmt, $primaryKeys);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\sqlite;
|
namespace nulib\db\sqlite;
|
||||||
|
|
||||||
|
use nulib\cl;
|
||||||
use nulib\db\CapacitorChannel;
|
use nulib\db\CapacitorChannel;
|
||||||
use nulib\db\CapacitorStorage;
|
use nulib\db\CapacitorStorage;
|
||||||
|
|
||||||
@ -22,8 +23,14 @@ class SqliteStorage extends CapacitorStorage {
|
|||||||
"id_" => "integer primary key autoincrement",
|
"id_" => "integer primary key autoincrement",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function _getMigration(CapacitorChannel $channel): _sqliteMigration {
|
||||||
|
return new _sqliteMigration(cl::merge([
|
||||||
|
$this->_createSql($channel),
|
||||||
|
], $channel->getMigration()), $channel->getName());
|
||||||
|
}
|
||||||
|
|
||||||
function _getCreateSql(CapacitorChannel $channel): string {
|
function _getCreateSql(CapacitorChannel $channel): string {
|
||||||
$query = new query($this->_createSql($channel));
|
$query = new _sqliteQuery($this->_createSql($channel));
|
||||||
return self::format_sql($channel, $query->getSql());
|
return self::format_sql($channel, $query->getSql());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +58,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||||||
# ne pas créer si la table existe déjà, pour éviter d'avoir besoin d'un
|
# ne pas créer si la table existe déjà, pour éviter d'avoir besoin d'un
|
||||||
# verrou en écriture
|
# verrou en écriture
|
||||||
$sqlite->exec([
|
$sqlite->exec([
|
||||||
"create table if not exists",
|
"create table if not exists _channels",
|
||||||
"table" => "_channels",
|
|
||||||
"cols" => [
|
"cols" => [
|
||||||
"name" => "varchar primary key",
|
"name" => "varchar primary key",
|
||||||
"table_name" => "varchar",
|
"table_name" => "varchar",
|
||||||
@ -64,8 +70,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||||||
# ne pas insérer si la ligne existe déjà, pour éviter d'avoir besoin d'un
|
# ne pas insérer si la ligne existe déjà, pour éviter d'avoir besoin d'un
|
||||||
# verrou en écriture
|
# verrou en écriture
|
||||||
$sqlite->exec([
|
$sqlite->exec([
|
||||||
"insert",
|
"insert into _channels",
|
||||||
"into" => "_channels",
|
|
||||||
"values" => [
|
"values" => [
|
||||||
"name" => $channel->getName(),
|
"name" => $channel->getName(),
|
||||||
"table_name" => $channel->getTableName(),
|
"table_name" => $channel->getTableName(),
|
||||||
@ -77,9 +82,15 @@ class SqliteStorage extends CapacitorStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected function _beforeReset(CapacitorChannel $channel): void {
|
protected function _beforeReset(CapacitorChannel $channel): void {
|
||||||
$this->sqlite->exec([
|
$sqlite = $this->sqlite;
|
||||||
"delete",
|
$sqlite->exec([
|
||||||
"from" => "_channels",
|
"delete from _migration",
|
||||||
|
"where" => [
|
||||||
|
"channel" => $channel->getName(),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$sqlite->exec([
|
||||||
|
"delete from _channels",
|
||||||
"where" => [
|
"where" => [
|
||||||
"name" => $channel->getName(),
|
"name" => $channel->getName(),
|
||||||
],
|
],
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\php\func;
|
|
||||||
|
|
||||||
class _migration {
|
|
||||||
static function with($migrations): self {
|
|
||||||
if ($migrations instanceof static) {
|
|
||||||
return $migrations;
|
|
||||||
} elseif ($migrations instanceof self) {
|
|
||||||
return new static($migrations->migrations);
|
|
||||||
} else {
|
|
||||||
return new static($migrations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const MIGRATE = null;
|
|
||||||
|
|
||||||
function __construct($migrations) {
|
|
||||||
if ($migrations === null) $migrations = static::MIGRATE;
|
|
||||||
if ($migrations === null) $migrations = [];
|
|
||||||
elseif (is_string($migrations)) $migrations = [$migrations];
|
|
||||||
elseif (is_callable($migrations)) $migrations = [$migrations];
|
|
||||||
elseif (!is_array($migrations)) $migrations = [strval($migrations)];
|
|
||||||
$this->migrations = $migrations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var callable[]|string[] */
|
|
||||||
protected $migrations;
|
|
||||||
|
|
||||||
function migrate(Sqlite $sqlite): void {
|
|
||||||
$sqlite->exec("create table if not exists _migration(key varchar primary key, value varchar not null, done integer default 0)");
|
|
||||||
foreach ($this->migrations as $key => $migration) {
|
|
||||||
$exists = $sqlite->get("select 1 from _migration where key = :key and done = 1", [
|
|
||||||
"key" => $key,
|
|
||||||
]);
|
|
||||||
if (!$exists) {
|
|
||||||
$sqlite->exec("insert or replace into _migration(key, value, done) values(:key, :value, :done)", [
|
|
||||||
"key" => $key,
|
|
||||||
"value" => $migration,
|
|
||||||
"done" => 0,
|
|
||||||
]);
|
|
||||||
if (is_string($migration) && !func::is_method($migration)) {
|
|
||||||
$sqlite->exec($migration);
|
|
||||||
} else {
|
|
||||||
func::with($migration)->bind($this, true)->invoke([$sqlite, $key]);
|
|
||||||
}
|
|
||||||
$sqlite->exec("update _migration set done = 1 where key = :key", [
|
|
||||||
"key" => $key,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
57
php/src/db/sqlite/_sqliteMigration.php
Normal file
57
php/src/db/sqlite/_sqliteMigration.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
namespace nulib\db\sqlite;
|
||||||
|
|
||||||
|
use nulib\db\_private\_migration;
|
||||||
|
|
||||||
|
class _sqliteMigration extends _migration {
|
||||||
|
static function with($migration): self {
|
||||||
|
if ($migration instanceof self) return $migration;
|
||||||
|
else return new static($migration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup(): void {
|
||||||
|
$this->db->exec([
|
||||||
|
"create table if not exists _migration",
|
||||||
|
"cols" => [
|
||||||
|
"channel" => "varchar not null",
|
||||||
|
"key" => "varchar not null",
|
||||||
|
"done" => "integer not null default 0",
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function beforeMigrate(string $key): bool {
|
||||||
|
$db = $this->db;
|
||||||
|
$migrated = $db->get([
|
||||||
|
"select 1 from _migration",
|
||||||
|
"where" => [
|
||||||
|
"channel" => $this->channel,
|
||||||
|
"key" => $key,
|
||||||
|
"done" => 1,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
if ($migrated) return false;
|
||||||
|
$db->exec([
|
||||||
|
"insert or replace into _migration",
|
||||||
|
"values" => [
|
||||||
|
"channel" => $this->channel,
|
||||||
|
"key" => $key,
|
||||||
|
"done" => 0,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterMigrate(string $key): void {
|
||||||
|
$this->db->exec([
|
||||||
|
"update _migration",
|
||||||
|
"values" => [
|
||||||
|
"done" => 1,
|
||||||
|
],
|
||||||
|
"where" => [
|
||||||
|
"channel" => $this->channel,
|
||||||
|
"key" => $key,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ use nulib\ValueException;
|
|||||||
use SQLite3;
|
use SQLite3;
|
||||||
use SQLite3Stmt;
|
use SQLite3Stmt;
|
||||||
|
|
||||||
class query extends _base {
|
class _sqliteQuery extends _base {
|
||||||
use Tbindings;
|
use Tbindings;
|
||||||
|
|
||||||
const DEBUG_QUERIES = false;
|
const DEBUG_QUERIES = false;
|
@ -437,7 +437,7 @@ class func {
|
|||||||
return new ValueException($reason);
|
return new ValueException($reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function with($func, ?array $args=null, bool $strict=true): self {
|
private static function _with($func, ?array $args=null, bool $strict=true, ?string &$reason=null): ?self {
|
||||||
if (!is_array($func)) {
|
if (!is_array($func)) {
|
||||||
if ($func instanceof Closure) {
|
if ($func instanceof Closure) {
|
||||||
return new self(self::TYPE_CLOSURE, $func, $args);
|
return new self(self::TYPE_CLOSURE, $func, $args);
|
||||||
@ -458,6 +458,12 @@ class func {
|
|||||||
} elseif (self::verifix_static($func, $strict, $bound, $reason)) {
|
} elseif (self::verifix_static($func, $strict, $bound, $reason)) {
|
||||||
return new self(self::TYPE_STATIC, $func, $args, $bound, $reason);
|
return new self(self::TYPE_STATIC, $func, $args, $bound, $reason);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function with($func, ?array $args=null, bool $strict=true): self {
|
||||||
|
$func = self::_with($func, $args, $strict, $reason);
|
||||||
|
if ($func !== null) return $func;
|
||||||
throw self::not_a_callable($func, $reason);
|
throw self::not_a_callable($func, $reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,6 +484,13 @@ class func {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function is_callable($func): bool {
|
||||||
|
$func = self::_with($func);
|
||||||
|
if ($func === null) return false;
|
||||||
|
if (!$func->isBound()) return false;
|
||||||
|
return $func->type !== self::TYPE_CLASS;
|
||||||
|
}
|
||||||
|
|
||||||
static function call($func, ...$args) {
|
static function call($func, ...$args) {
|
||||||
return self::with($func)->invoke($args);
|
return self::with($func)->invoke($args);
|
||||||
}
|
}
|
||||||
@ -638,7 +651,7 @@ class func {
|
|||||||
|
|
||||||
function bind($object, bool $unlessAlreadyBound=false, bool $replace=false): self {
|
function bind($object, bool $unlessAlreadyBound=false, bool $replace=false): self {
|
||||||
if ($this->type !== self::TYPE_METHOD) return $this;
|
if ($this->type !== self::TYPE_METHOD) return $this;
|
||||||
if ($this->object !== null && $unlessAlreadyBound) return $this;
|
if ($this->bound && $unlessAlreadyBound) return $this;
|
||||||
|
|
||||||
[$c, $f] = $this->func;
|
[$c, $f] = $this->func;
|
||||||
if ($replace) {
|
if ($replace) {
|
||||||
|
@ -11,7 +11,7 @@ class SqliteTest extends TestCase {
|
|||||||
|
|
||||||
function testMigration() {
|
function testMigration() {
|
||||||
$sqlite = new Sqlite(":memory:", [
|
$sqlite = new Sqlite(":memory:", [
|
||||||
"migrate" => [
|
"migration" => [
|
||||||
self::CREATE_PERSON,
|
self::CREATE_PERSON,
|
||||||
self::INSERT_JEPHTE,
|
self::INSERT_JEPHTE,
|
||||||
],
|
],
|
||||||
@ -49,7 +49,7 @@ class SqliteTest extends TestCase {
|
|||||||
}
|
}
|
||||||
function testInsert() {
|
function testInsert() {
|
||||||
$sqlite = new Sqlite(":memory:", [
|
$sqlite = new Sqlite(":memory:", [
|
||||||
"migrate" => "create table mapping (i integer, s varchar)",
|
"migration" => "create table mapping (i integer, s varchar)",
|
||||||
]);
|
]);
|
||||||
$sqlite->exec(["insert into mapping", "values" => ["i" => 1, "s" => "un"]]);
|
$sqlite->exec(["insert into mapping", "values" => ["i" => 1, "s" => "un"]]);
|
||||||
$sqlite->exec(["insert mapping", "values" => ["i" => 2, "s" => "deux"]]);
|
$sqlite->exec(["insert mapping", "values" => ["i" => 2, "s" => "deux"]]);
|
||||||
@ -78,7 +78,7 @@ class SqliteTest extends TestCase {
|
|||||||
|
|
||||||
function testSelect() {
|
function testSelect() {
|
||||||
$sqlite = new Sqlite(":memory:", [
|
$sqlite = new Sqlite(":memory:", [
|
||||||
"migrate" => "create table user (name varchar, amount integer)",
|
"migration" => "create table user (name varchar, amount integer)",
|
||||||
]);
|
]);
|
||||||
$sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]);
|
$sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]);
|
||||||
$sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 2]]);
|
$sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 2]]);
|
||||||
@ -130,7 +130,7 @@ class SqliteTest extends TestCase {
|
|||||||
|
|
||||||
function testSelectGroupBy() {
|
function testSelectGroupBy() {
|
||||||
$sqlite = new Sqlite(":memory:", [
|
$sqlite = new Sqlite(":memory:", [
|
||||||
"migrate" => "create table user (name varchar, amount integer)",
|
"migration" => "create table user (name varchar, amount integer)",
|
||||||
]);
|
]);
|
||||||
$sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]);
|
$sqlite->exec(["insert into user", "values" => ["name" => "jclain1", "amount" => 1]]);
|
||||||
$sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 1]]);
|
$sqlite->exec(["insert into user", "values" => ["name" => "jclain2", "amount" => 1]]);
|
||||||
|
@ -6,119 +6,119 @@ use PHPUnit\Framework\TestCase;
|
|||||||
class _queryTest extends TestCase {
|
class _queryTest extends TestCase {
|
||||||
function testParseConds(): void {
|
function testParseConds(): void {
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(null, $sql, $params);
|
_sqliteQuery::parse_conds(null, $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds([], $sql, $params);
|
_sqliteQuery::parse_conds([], $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => null], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => null], $sql, $params);
|
||||||
self::assertSame(["col is null"], $sql);
|
self::assertSame(["col is null"], $sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col = 'value'"], $sql, $params);
|
_sqliteQuery::parse_conds(["col = 'value'"], $sql, $params);
|
||||||
self::assertSame(["col = 'value'"], $sql);
|
self::assertSame(["col = 'value'"], $sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds([["col = 'value'"]], $sql, $params);
|
_sqliteQuery::parse_conds([["col = 'value'"]], $sql, $params);
|
||||||
self::assertSame(["col = 'value'"], $sql);
|
self::assertSame(["col = 'value'"], $sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["int" => 42, "string" => "value"], $sql, $params);
|
_sqliteQuery::parse_conds(["int" => 42, "string" => "value"], $sql, $params);
|
||||||
self::assertSame(["(int = :int and string = :string)"], $sql);
|
self::assertSame(["(int = :int and string = :string)"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value"], $params);
|
self::assertSame(["int" => 42, "string" => "value"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["or", "int" => 42, "string" => "value"], $sql, $params);
|
_sqliteQuery::parse_conds(["or", "int" => 42, "string" => "value"], $sql, $params);
|
||||||
self::assertSame(["(int = :int or string = :string)"], $sql);
|
self::assertSame(["(int = :int or string = :string)"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value"], $params);
|
self::assertSame(["int" => 42, "string" => "value"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
_sqliteQuery::parse_conds([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
||||||
self::assertSame(["((int = :int and string = :string) and (int = :int2 and string = :string2))"], $sql);
|
self::assertSame(["((int = :int and string = :string) and (int = :int2 and string = :string2))"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params);
|
self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["int" => ["is null"], "string" => ["<>", "value"]], $sql, $params);
|
_sqliteQuery::parse_conds(["int" => ["is null"], "string" => ["<>", "value"]], $sql, $params);
|
||||||
self::assertSame(["(int is null and string <> :string)"], $sql);
|
self::assertSame(["(int is null and string <> :string)"], $sql);
|
||||||
self::assertSame(["string" => "value"], $params);
|
self::assertSame(["string" => "value"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => ["between", "lower", "upper"]], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => ["between", "lower", "upper"]], $sql, $params);
|
||||||
self::assertSame(["col between :col and :col2"], $sql);
|
self::assertSame(["col between :col and :col2"], $sql);
|
||||||
self::assertSame(["col" => "lower", "col2" => "upper"], $params);
|
self::assertSame(["col" => "lower", "col2" => "upper"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => ["in", "one"]], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => ["in", "one"]], $sql, $params);
|
||||||
self::assertSame(["col in (:col)"], $sql);
|
self::assertSame(["col in (:col)"], $sql);
|
||||||
self::assertSame(["col" => "one"], $params);
|
self::assertSame(["col" => "one"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => ["in", ["one", "two"]]], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => ["in", ["one", "two"]]], $sql, $params);
|
||||||
self::assertSame(["col in (:col, :col2)"], $sql);
|
self::assertSame(["col in (:col, :col2)"], $sql);
|
||||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => ["=", ["one", "two"]]], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => ["=", ["one", "two"]]], $sql, $params);
|
||||||
self::assertSame(["col = :col and col = :col2"], $sql);
|
self::assertSame(["col = :col and col = :col2"], $sql);
|
||||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["or", "col" => ["=", ["one", "two"]]], $sql, $params);
|
_sqliteQuery::parse_conds(["or", "col" => ["=", ["one", "two"]]], $sql, $params);
|
||||||
self::assertSame(["col = :col or col = :col2"], $sql);
|
self::assertSame(["col = :col or col = :col2"], $sql);
|
||||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["col" => ["<>", ["one", "two"]]], $sql, $params);
|
_sqliteQuery::parse_conds(["col" => ["<>", ["one", "two"]]], $sql, $params);
|
||||||
self::assertSame(["col <> :col and col <> :col2"], $sql);
|
self::assertSame(["col <> :col and col <> :col2"], $sql);
|
||||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_conds(["or", "col" => ["<>", ["one", "two"]]], $sql, $params);
|
_sqliteQuery::parse_conds(["or", "col" => ["<>", ["one", "two"]]], $sql, $params);
|
||||||
self::assertSame(["col <> :col or col <> :col2"], $sql);
|
self::assertSame(["col <> :col or col <> :col2"], $sql);
|
||||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testParseValues(): void {
|
function testParseValues(): void {
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values(null, $sql, $params);
|
_sqliteQuery::parse_set_values(null, $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values([], $sql, $params);
|
_sqliteQuery::parse_set_values([], $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values(["col = 'value'"], $sql, $params);
|
_sqliteQuery::parse_set_values(["col = 'value'"], $sql, $params);
|
||||||
self::assertSame(["col = 'value'"], $sql);
|
self::assertSame(["col = 'value'"], $sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values([["col = 'value'"]], $sql, $params);
|
_sqliteQuery::parse_set_values([["col = 'value'"]], $sql, $params);
|
||||||
self::assertSame(["col = 'value'"], $sql);
|
self::assertSame(["col = 'value'"], $sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
_sqliteQuery::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
||||||
self::assertSame(["int = :int", "string = :string"], $sql);
|
self::assertSame(["int = :int", "string = :string"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value"], $params);
|
self::assertSame(["int" => 42, "string" => "value"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
_sqliteQuery::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
||||||
self::assertSame(["int = :int", "string = :string"], $sql);
|
self::assertSame(["int = :int", "string = :string"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value"], $params);
|
self::assertSame(["int" => 42, "string" => "value"], $params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
query::parse_set_values([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
_sqliteQuery::parse_set_values([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
||||||
self::assertSame(["int = :int", "string = :string", "int = :int2", "string = :string2"], $sql);
|
self::assertSame(["int = :int", "string = :string", "int = :int2", "string = :string2"], $sql);
|
||||||
self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params);
|
self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user