modifs.mineures sans commentaires
This commit is contained in:
parent
f35b0a400d
commit
2fbe3ec09c
|
@ -11,6 +11,7 @@ use nur\sery\db\Capacitor;
|
|||
use nur\sery\db\CapacitorChannel;
|
||||
use nur\sery\db\mysql\MysqlStorage;
|
||||
use nur\sery\db\sqlite\SqliteStorage;
|
||||
use nur\sery\file\Stream;
|
||||
use nur\yaml;
|
||||
|
||||
Application::run(new class extends Application {
|
||||
|
@ -68,12 +69,17 @@ Application::run(new class extends Application {
|
|||
$args = $this->args;
|
||||
if (!$args) {
|
||||
# lister les id
|
||||
$rows = $storage->mysql()->all([
|
||||
"select id_",
|
||||
$out = new Stream(STDOUT);
|
||||
$primaryKeys = $storage->getPrimaryKeys($channel);
|
||||
$rows = $storage->db()->all([
|
||||
"select",
|
||||
"cols" => $primaryKeys,
|
||||
"from" => $channel->getTableName(),
|
||||
]);
|
||||
$out->fputcsv($primaryKeys);
|
||||
foreach ($rows as $row) {
|
||||
echo "$row[id_]\n";
|
||||
$rowIds = $storage->getRowIds($channel, $row);
|
||||
$out->fputcsv($rowIds);
|
||||
}
|
||||
} else {
|
||||
# afficher les lignes correspondantes
|
||||
|
|
|
@ -9,6 +9,7 @@ use nur\path;
|
|||
use nur\sery\db\Capacitor;
|
||||
use nur\sery\db\CapacitorChannel;
|
||||
use nur\sery\db\sqlite\SqliteStorage;
|
||||
use nur\sery\file\Stream;
|
||||
use nur\yaml;
|
||||
|
||||
Application::run(new class extends Application {
|
||||
|
@ -64,12 +65,17 @@ Application::run(new class extends Application {
|
|||
$args = $this->args;
|
||||
if (!$args) {
|
||||
# lister les id
|
||||
$rows = $storage->sqlite()->all([
|
||||
"select id_",
|
||||
$out = new Stream(STDOUT);
|
||||
$primaryKeys = $storage->getPrimaryKeys($channel);
|
||||
$rows = $storage->db()->all([
|
||||
"select",
|
||||
"cols" => $primaryKeys,
|
||||
"from" => $channel->getTableName(),
|
||||
]);
|
||||
$out->fputcsv($primaryKeys);
|
||||
foreach ($rows as $row) {
|
||||
echo "$row[id_]\n";
|
||||
$rowIds = $storage->getRowIds($channel, $row);
|
||||
$out->fputcsv($rowIds);
|
||||
}
|
||||
} else {
|
||||
# afficher les lignes correspondantes
|
||||
|
|
|
@ -153,7 +153,7 @@ class CapacitorChannel {
|
|||
|
||||
const SUM_DEFINITION = "varchar(40)";
|
||||
|
||||
final function sum(string $string): string {
|
||||
final function sum(?string $string): string {
|
||||
return sha1($string);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,13 +93,13 @@ abstract class CapacitorStorage {
|
|||
return $values;
|
||||
}
|
||||
|
||||
protected function getPrimaryKeys(CapacitorChannel $channel): array {
|
||||
function getPrimaryKeys(CapacitorChannel $channel): array {
|
||||
$primaryKeys = $channel->getPrimaryKeys();
|
||||
if ($primaryKeys === null) $primaryKeys = ["id_"];
|
||||
return $primaryKeys;
|
||||
}
|
||||
|
||||
protected function getRowIds(CapacitorChannel $channel, ?array $row, ?array &$primaryKeys=null): ?array {
|
||||
function getRowIds(CapacitorChannel $channel, ?array $row, ?array &$primaryKeys=null): ?array {
|
||||
$primaryKeys = $this->getPrimaryKeys($channel);
|
||||
$rowIds = cl::select($row, $primaryKeys);
|
||||
if (cl::all_n($rowIds)) return null;
|
||||
|
|
|
@ -84,71 +84,89 @@ abstract class _base {
|
|||
$condkey++;
|
||||
}
|
||||
$op = strtolower($op);
|
||||
$condvalues = null;
|
||||
switch ($op) {
|
||||
case "between":
|
||||
# ["between", $upper, $lower]
|
||||
$condsep = " and ";
|
||||
$values = null;
|
||||
if (array_key_exists("lower", $cond)) {
|
||||
$values[] = $cond["lower"];
|
||||
$condvalues[] = $cond["lower"];
|
||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||
$values[] = $cond[$condkeys[$condkey]];
|
||||
$condvalues[] = $cond[$condkeys[$condkey]];
|
||||
$condkey++;
|
||||
}
|
||||
if (array_key_exists("upper", $cond)) {
|
||||
$values[] = $cond["upper"];
|
||||
$condvalues[] = $cond["upper"];
|
||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||
$values[] = $cond[$condkeys[$condkey]];
|
||||
$condvalues[] = $cond[$condkeys[$condkey]];
|
||||
$condkey++;
|
||||
}
|
||||
break;
|
||||
case "in":
|
||||
# ["in", $values]
|
||||
$condprefix = "(";
|
||||
$condsep = ", ";
|
||||
$condsuffix = ")";
|
||||
$values = null;
|
||||
$condvalues = null;
|
||||
if (array_key_exists("values", $cond)) {
|
||||
$values = cl::with($cond["values"]);
|
||||
$condvalues = cl::with($cond["values"]);
|
||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||
$values = cl::with($cond[$condkeys[$condkey]]);
|
||||
$condvalues = cl::with($cond[$condkeys[$condkey]]);
|
||||
$condkey++;
|
||||
}
|
||||
break;
|
||||
case "null":
|
||||
case "is null":
|
||||
$op = "is null";
|
||||
$values = null;
|
||||
break;
|
||||
case "not null":
|
||||
case "is not null":
|
||||
$op = "is not null";
|
||||
$values = null;
|
||||
break;
|
||||
default:
|
||||
$values = null;
|
||||
if (array_key_exists("value", $cond)) {
|
||||
$values = [$cond["value"]];
|
||||
$condvalues = [$cond["value"]];
|
||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||
$values = [$cond[$condkeys[$condkey]]];
|
||||
$condvalues = [$cond[$condkeys[$condkey]]];
|
||||
$condkey++;
|
||||
}
|
||||
}
|
||||
} elseif ($cond !== null) {
|
||||
$op = "=";
|
||||
$values = [$cond];
|
||||
$condvalues = [$cond];
|
||||
} else {
|
||||
$op = "is null";
|
||||
$values = null;
|
||||
$condvalues = null;
|
||||
}
|
||||
$cond = [$key, $op];
|
||||
if ($values !== null) {
|
||||
if ($condvalues !== null) {
|
||||
$parts = [];
|
||||
foreach ($values as $value) {
|
||||
foreach ($condvalues as $condvalue) {
|
||||
if (is_array($condvalue)) {
|
||||
$first = true;
|
||||
foreach ($condvalue as $value) {
|
||||
if ($first) {
|
||||
$first = false;
|
||||
} else {
|
||||
if ($sep === null) $sep = "and";
|
||||
$parts[] = " $sep ";
|
||||
$parts[] = $key;
|
||||
$parts[] = " $op ";
|
||||
}
|
||||
$param = "$key$i";
|
||||
$parts[] = ":$param";
|
||||
$bindings[$param] = $value;
|
||||
if ($i === false) $i = 2;
|
||||
else $i++;
|
||||
}
|
||||
} else {
|
||||
$param = "$key$i";
|
||||
$parts[] = ":$param";
|
||||
$bindings[$param] = $condvalue;
|
||||
if ($i === false) $i = 2;
|
||||
else $i++;
|
||||
}
|
||||
}
|
||||
$cond[] = $condprefix.implode($condsep, $parts).$condsuffix;
|
||||
}
|
||||
$condsql[] = implode(" ", $cond);
|
||||
|
@ -183,7 +201,7 @@ abstract class _base {
|
|||
# paramètre
|
||||
$param = $key;
|
||||
if ($bindings !== null && array_key_exists($param, $bindings)) {
|
||||
$i = 1;
|
||||
$i = 2;
|
||||
while (array_key_exists("$key$i", $bindings)) {
|
||||
$i++;
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ use nur\sery\ValueException;
|
|||
*/
|
||||
class MysqlStorage extends CapacitorStorage {
|
||||
function __construct($mysql) {
|
||||
$this->mysql = Mysql::with($mysql);
|
||||
$this->db = Mysql::with($mysql);
|
||||
}
|
||||
|
||||
/** @var Mysql */
|
||||
protected $mysql;
|
||||
protected $db;
|
||||
|
||||
function mysql(): Mysql {
|
||||
return $this->mysql;
|
||||
function db(): Mysql {
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
const PRIMARY_KEY_DEFINITION = [
|
||||
|
@ -29,7 +29,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
protected function _create(CapacitorChannel $channel): void {
|
||||
if (!$channel->isCreated()) {
|
||||
$cols = $this->ColumnDefinitions($channel);
|
||||
$this->mysql->exec([
|
||||
$this->db->exec([
|
||||
"create table if not exists",
|
||||
"table" => $channel->getTableName(),
|
||||
"cols" => $cols,
|
||||
|
@ -39,7 +39,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _exists(CapacitorChannel $channel): bool {
|
||||
$mysql = $this->mysql;
|
||||
$mysql = $this->db;
|
||||
$tableName = $mysql->get([
|
||||
"select table_name from information_schema.tables",
|
||||
"where" => [
|
||||
|
@ -55,7 +55,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _reset(CapacitorChannel $channel): void {
|
||||
$this->mysql->exec([
|
||||
$this->db->exec([
|
||||
"drop table if exists",
|
||||
$channel->getTableName(),
|
||||
]);
|
||||
|
@ -73,7 +73,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
$rowIds = $this->getRowIds($channel, $row, $primaryKeys);
|
||||
if ($rowIds !== null) {
|
||||
# modification
|
||||
$prow = $this->mysql->one([
|
||||
$prow = $this->db->one([
|
||||
"select",
|
||||
"from" => $tableName,
|
||||
"where" => $rowIds,
|
||||
|
@ -120,13 +120,13 @@ class MysqlStorage extends CapacitorStorage {
|
|||
# aucune modification
|
||||
return 0;
|
||||
} elseif ($insert) {
|
||||
$this->mysql->exec([
|
||||
$this->db->exec([
|
||||
"insert",
|
||||
"into" => $tableName,
|
||||
"values" => $row,
|
||||
]);
|
||||
} else {
|
||||
$this->mysql->exec([
|
||||
$this->db->exec([
|
||||
"update",
|
||||
"table" => $tableName,
|
||||
"values" => $row,
|
||||
|
@ -137,7 +137,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _discharge(CapacitorChannel $channel, bool $reset=true): iterable {
|
||||
$rows = $this->mysql->all([
|
||||
$rows = $this->db->all([
|
||||
"select item__",
|
||||
"from" => $channel->getTableName(),
|
||||
]);
|
||||
|
@ -158,7 +158,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
|
||||
function _count(CapacitorChannel $channel, $filter): int {
|
||||
$this->verifixFilter($channel, $filter);
|
||||
return $this->mysql->get([
|
||||
return $this->db->get([
|
||||
"select count(*)",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -168,7 +168,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
function _one(CapacitorChannel $channel, $filter): ?array {
|
||||
if ($filter === null) throw ValueException::null("filter");
|
||||
$this->verifixFilter($channel, $filter);
|
||||
$row = $this->mysql->one([
|
||||
$row = $this->db->one([
|
||||
"select",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -178,7 +178,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
|
||||
function _all(CapacitorChannel $channel, $filter): iterable {
|
||||
$this->verifixFilter($channel, $filter);
|
||||
$rows = $this->mysql->all([
|
||||
$rows = $this->db->all([
|
||||
"select",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -192,7 +192,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||
if ($func === null) $func = "->onEach";
|
||||
func::ensure_func($func, $channel, $args);
|
||||
$onEach = func::_prepare($func);
|
||||
$mysql = $this->mysql;
|
||||
$mysql = $this->db;
|
||||
$tableName = $channel->getTableName();
|
||||
$commited = false;
|
||||
$count = 0;
|
||||
|
@ -233,6 +233,6 @@ class MysqlStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function close(): void {
|
||||
$this->mysql->close();
|
||||
$this->db->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ use nur\sery\ValueException;
|
|||
*/
|
||||
class SqliteStorage extends CapacitorStorage {
|
||||
function __construct($sqlite) {
|
||||
$this->sqlite = Sqlite::with($sqlite);
|
||||
$this->db = Sqlite::with($sqlite);
|
||||
}
|
||||
|
||||
/** @var Sqlite */
|
||||
protected $sqlite;
|
||||
protected $db;
|
||||
|
||||
function sqlite(): Sqlite {
|
||||
return $this->sqlite;
|
||||
function db(): Sqlite {
|
||||
return $this->db;
|
||||
}
|
||||
|
||||
const PRIMARY_KEY_DEFINITION = [
|
||||
|
@ -29,7 +29,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
protected function _create(CapacitorChannel $channel): void {
|
||||
if (!$channel->isCreated()) {
|
||||
$cols = $this->ColumnDefinitions($channel);
|
||||
$this->sqlite->exec([
|
||||
$this->db->exec([
|
||||
"create table if not exists",
|
||||
"table" => $channel->getTableName(),
|
||||
"cols" => $cols,
|
||||
|
@ -39,7 +39,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _exists(CapacitorChannel $channel): bool {
|
||||
$tableName = $this->sqlite->get([
|
||||
$tableName = $this->db->get([
|
||||
"select name from sqlite_schema",
|
||||
"where" => [
|
||||
"name" => $channel->getTableName(),
|
||||
|
@ -53,7 +53,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _reset(CapacitorChannel $channel): void {
|
||||
$this->sqlite->exec([
|
||||
$this->db->exec([
|
||||
"drop table if exists",
|
||||
$channel->getTableName(),
|
||||
]);
|
||||
|
@ -71,7 +71,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
$rowIds = $this->getRowIds($channel, $row, $primaryKeys);
|
||||
if ($rowIds !== null) {
|
||||
# modification
|
||||
$prow = $this->sqlite->one([
|
||||
$prow = $this->db->one([
|
||||
"select",
|
||||
"from" => $tableName,
|
||||
"where" => $rowIds,
|
||||
|
@ -118,13 +118,13 @@ class SqliteStorage extends CapacitorStorage {
|
|||
# aucune modification
|
||||
return 0;
|
||||
} elseif ($insert) {
|
||||
$this->sqlite->exec([
|
||||
$this->db->exec([
|
||||
"insert",
|
||||
"into" => $tableName,
|
||||
"values" => $row,
|
||||
]);
|
||||
} else {
|
||||
$this->sqlite->exec([
|
||||
$this->db->exec([
|
||||
"update",
|
||||
"table" => $tableName,
|
||||
"values" => $row,
|
||||
|
@ -135,7 +135,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function _discharge(CapacitorChannel $channel, bool $reset=true): iterable {
|
||||
$rows = $this->sqlite->all([
|
||||
$rows = $this->db->all([
|
||||
"select item__",
|
||||
"from" => $channel->getTableName(),
|
||||
]);
|
||||
|
@ -156,7 +156,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
|
||||
function _count(CapacitorChannel $channel, $filter): int {
|
||||
$this->verifixFilter($channel, $filter);
|
||||
return $this->sqlite->get([
|
||||
return $this->db->get([
|
||||
"select count(*)",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -166,7 +166,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
function _one(CapacitorChannel $channel, $filter): ?array {
|
||||
if ($filter === null) throw ValueException::null("filter");
|
||||
$this->verifixFilter($channel, $filter);
|
||||
$row = $this->sqlite->one([
|
||||
$row = $this->db->one([
|
||||
"select",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -176,7 +176,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
|
||||
function _all(CapacitorChannel $channel, $filter): iterable {
|
||||
$this->verifixFilter($channel, $filter);
|
||||
$rows = $this->sqlite->all([
|
||||
$rows = $this->db->all([
|
||||
"select",
|
||||
"from" => $channel->getTableName(),
|
||||
"where" => $filter,
|
||||
|
@ -190,7 +190,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||
if ($func === null) $func = "->onEach";
|
||||
func::ensure_func($func, $channel, $args);
|
||||
$onEach = func::_prepare($func);
|
||||
$sqlite = $this->sqlite;
|
||||
$sqlite = $this->db;
|
||||
$tableName = $channel->getTableName();
|
||||
$commited = false;
|
||||
$count = 0;
|
||||
|
@ -231,6 +231,6 @@ class SqliteStorage extends CapacitorStorage {
|
|||
}
|
||||
|
||||
function close(): void {
|
||||
$this->sqlite->close();
|
||||
$this->db->close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,23 @@ use nur\sery\ValueException;
|
|||
class Stream extends AbstractIterator implements IReader, IWriter {
|
||||
use TStreamFilter;
|
||||
|
||||
protected static function probe_fd($fd, ?bool &$seekable=null, ?bool &$readable=null): void {
|
||||
$md = stream_get_meta_data($fd);
|
||||
$seekable = $md["seekable"];
|
||||
$mode = $md["mode"];
|
||||
$readable = strpos($mode, "r") !== false || strpos($mode, "+") !== false;
|
||||
}
|
||||
|
||||
protected static function fd_is_seekable($fd): bool {
|
||||
self::probe_fd($fd, $seekable);
|
||||
return $seekable;
|
||||
}
|
||||
|
||||
protected static function fd_is_readable($fd): bool {
|
||||
$mode = stream_get_meta_data($fd)["mode"];
|
||||
return strpos($mode, "r") !== false || strpos($mode, "+") !== false;
|
||||
}
|
||||
|
||||
/** @var bool les opérations de verrouillages sont-elle activées? */
|
||||
const USE_LOCKING = false;
|
||||
|
||||
|
@ -153,6 +170,8 @@ class Stream extends AbstractIterator implements IReader, IWriter {
|
|||
protected function getCsvParams($fd): array {
|
||||
$flavour = $this->csvFlavour;
|
||||
if ($flavour === null) {
|
||||
self::probe_fd($fd, $seekable, $readable);
|
||||
if (!$seekable || !$readable) $fd = null;
|
||||
if ($fd === null) {
|
||||
# utiliser la valeur par défaut
|
||||
$flavour = static::DEFAULT_CSV_FLAVOUR;
|
||||
|
@ -309,8 +328,8 @@ class Stream extends AbstractIterator implements IReader, IWriter {
|
|||
}
|
||||
|
||||
private function _rewindFd(): void {
|
||||
$md = stream_get_meta_data($this->fd);
|
||||
if ($md["seekable"]) $this->fseek(0);
|
||||
self::probe_fd($this->fd, $seekable);
|
||||
if ($seekable) $this->fseek(0);
|
||||
}
|
||||
|
||||
protected function _teardown(): void {
|
||||
|
|
|
@ -64,6 +64,26 @@ class _queryTest extends TestCase {
|
|||
_query_base::parse_conds(["col" => ["in", ["one", "two"]]], $sql, $params);
|
||||
self::assertSame(["col in (:col, :col2)"], $sql);
|
||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||
|
||||
$sql = $params = null;
|
||||
_query_base::parse_conds(["col" => ["=", ["one", "two"]]], $sql, $params);
|
||||
self::assertSame(["col = :col and col = :col2"], $sql);
|
||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||
|
||||
$sql = $params = null;
|
||||
_query_base::parse_conds(["or", "col" => ["=", ["one", "two"]]], $sql, $params);
|
||||
self::assertSame(["col = :col or col = :col2"], $sql);
|
||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||
|
||||
$sql = $params = null;
|
||||
_query_base::parse_conds(["col" => ["<>", ["one", "two"]]], $sql, $params);
|
||||
self::assertSame(["col <> :col and col <> :col2"], $sql);
|
||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||
|
||||
$sql = $params = null;
|
||||
_query_base::parse_conds(["or", "col" => ["<>", ["one", "two"]]], $sql, $params);
|
||||
self::assertSame(["col <> :col or col <> :col2"], $sql);
|
||||
self::assertSame(["col" => "one", "col2" => "two"], $params);
|
||||
}
|
||||
|
||||
function testParseValues(): void {
|
||||
|
@ -99,7 +119,7 @@ class _queryTest extends TestCase {
|
|||
|
||||
$sql = $params = null;
|
||||
_query_base::parse_set_values([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
||||
self::assertSame(["int = :int", "string = :string", "int = :int1", "string = :string1"], $sql);
|
||||
self::assertSame(["int" => 42, "string" => "value", "int1" => 24, "string1" => "eulav"], $params);
|
||||
self::assertSame(["int = :int", "string = :string", "int = :int2", "string = :string2"], $sql);
|
||||
self::assertSame(["int" => 42, "string" => "value", "int2" => 24, "string2" => "eulav"], $params);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue