réorganiser le code de génération sql
This commit is contained in:
parent
1536e091fb
commit
bd1f901b70
@ -24,6 +24,7 @@
|
|||||||
"ext-posix": "*",
|
"ext-posix": "*",
|
||||||
"ext-pcntl": "*",
|
"ext-pcntl": "*",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
|
"ext-pdo": "*",
|
||||||
"ext-sqlite3": "*"
|
"ext-sqlite3": "*"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
trait Tcreate {
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
//return preg_match("/^create(?:\s+table)?\b/i", $sql);
|
|
||||||
#XXX implémentation minimale
|
|
||||||
return preg_match("/^create\s+table\b/i", $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
|
||||||
#XXX implémentation minimale
|
|
||||||
$sql = [self::merge_seq($query)];
|
|
||||||
|
|
||||||
## préfixe
|
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
|
||||||
|
|
||||||
## table
|
|
||||||
$sql[] = $query["table"];
|
|
||||||
|
|
||||||
## columns
|
|
||||||
$cols = $query["cols"];
|
|
||||||
$index = 0;
|
|
||||||
foreach ($cols as $col => &$definition) {
|
|
||||||
if ($col === $index) {
|
|
||||||
$index++;
|
|
||||||
} else {
|
|
||||||
$definition = "$col $definition";
|
|
||||||
}
|
|
||||||
}; unset($definition);
|
|
||||||
$sql[] = "(\n ".implode("\n, ", $cols)."\n)";
|
|
||||||
|
|
||||||
## suffixe
|
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
|
||||||
|
|
||||||
## fin de la requête
|
|
||||||
return implode(" ", $sql);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
trait Tdelete {
|
|
||||||
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
return preg_match("/^delete(?:\s+from)?\b/i", $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
|
||||||
#XXX implémentation minimale
|
|
||||||
$tmpsql = self::merge_seq($query);
|
|
||||||
self::consume('delete(?:\s+from)?\b', $tmpsql);
|
|
||||||
$sql = ["delete from", $tmpsql];
|
|
||||||
|
|
||||||
## préfixe
|
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
|
||||||
|
|
||||||
## table
|
|
||||||
$sql[] = $query["from"];
|
|
||||||
|
|
||||||
## where
|
|
||||||
$where = $query["where"] ?? null;
|
|
||||||
if ($where !== null) {
|
|
||||||
self::parse_conds($where, $wheresql, $bindings);
|
|
||||||
if ($wheresql) {
|
|
||||||
$sql[] = "where";
|
|
||||||
$sql[] = implode(" and ", $wheresql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## suffixe
|
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
|
||||||
|
|
||||||
## fin de la requête
|
|
||||||
return implode(" ", $sql);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\ValueException;
|
|
||||||
|
|
||||||
trait Tgeneric {
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
return preg_match('/^(?:drop\s+table)\b/i', $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
return self::merge_seq($query);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\ValueException;
|
|
||||||
|
|
||||||
trait Tinsert {
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
return preg_match("/^insert\b/i", $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parser une chaine de la forme
|
|
||||||
* "insert [into] [TABLE] [(COLS)] [values (VALUES)]"
|
|
||||||
*/
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
|
||||||
# fusionner d'abord toutes les parties séquentielles
|
|
||||||
$usersql = $tmpsql = self::merge_seq($query);
|
|
||||||
|
|
||||||
### vérifier la présence des parties nécessaires
|
|
||||||
$sql = [];
|
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
|
||||||
|
|
||||||
## insert
|
|
||||||
self::consume('(insert(?:\s+or\s+(?:ignore|replace))?)\s*', $tmpsql, $ms);
|
|
||||||
$sql[] = $ms[1];
|
|
||||||
|
|
||||||
## into
|
|
||||||
self::consume('into\s*', $tmpsql);
|
|
||||||
$sql[] = "into";
|
|
||||||
$into = $query["into"] ?? null;
|
|
||||||
if (self::consume('([a-z_][a-z0-9_]*)\s*', $tmpsql, $ms)) {
|
|
||||||
if ($into === null) $into = $ms[1];
|
|
||||||
$sql[] = $into;
|
|
||||||
} elseif ($into !== null) {
|
|
||||||
$sql[] = $into;
|
|
||||||
} else {
|
|
||||||
throw new ValueException("expected table name: $usersql");
|
|
||||||
}
|
|
||||||
|
|
||||||
## cols & values
|
|
||||||
$usercols = [];
|
|
||||||
$uservalues = [];
|
|
||||||
if (self::consume('\(([^)]*)\)\s*', $tmpsql, $ms)) {
|
|
||||||
$usercols = array_merge($usercols, preg_split("/\s*,\s*/", $ms[1]));
|
|
||||||
}
|
|
||||||
$cols = cl::withn($query["cols"] ?? null);
|
|
||||||
$values = cl::withn($query["values"] ?? null);
|
|
||||||
$schema = $query["schema"] ?? null;
|
|
||||||
if ($cols === null) {
|
|
||||||
if ($usercols) {
|
|
||||||
$cols = $usercols;
|
|
||||||
} elseif ($values) {
|
|
||||||
$cols = array_keys($values);
|
|
||||||
$usercols = array_merge($usercols, $cols);
|
|
||||||
} elseif ($schema && is_array($schema)) {
|
|
||||||
#XXX implémenter support AssocSchema
|
|
||||||
$cols = array_keys($schema);
|
|
||||||
$usercols = array_merge($usercols, $cols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (self::consume('values\s+\(\s*(.*)\s*\)\s*', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $uservalues[] = $ms[1];
|
|
||||||
}
|
|
||||||
if ($cols !== null && !$uservalues) {
|
|
||||||
if (!$usercols) $usercols = $cols;
|
|
||||||
foreach ($cols as $col) {
|
|
||||||
$uservalues[] = ":$col";
|
|
||||||
$bindings[$col] = $values[$col] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$sql[] = "(" . implode(", ", $usercols) . ")";
|
|
||||||
$sql[] = "values (" . implode(", ", $uservalues) . ")";
|
|
||||||
|
|
||||||
## suffixe
|
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
|
||||||
|
|
||||||
## fin de la requête
|
|
||||||
self::check_eof($tmpsql, $usersql);
|
|
||||||
return implode(" ", $sql);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\str;
|
|
||||||
use nulib\ValueException;
|
|
||||||
|
|
||||||
trait Tselect {
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
return preg_match("/^select\b/i", $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function add_prefix(string $col, ?string $prefix): string {
|
|
||||||
if ($prefix === null) return $col;
|
|
||||||
if (strpos($col, ".") !== false) return $col;
|
|
||||||
return "$prefix$col";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* parser une chaine de la forme
|
|
||||||
* "select [COLS] [from TABLE] [where CONDS] [order by ORDERS] [group by GROUPS] [having CONDS]"
|
|
||||||
*/
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
|
||||||
# fusionner d'abord toutes les parties séquentielles
|
|
||||||
$usersql = $tmpsql = self::merge_seq($query);
|
|
||||||
|
|
||||||
### vérifier la présence des parties nécessaires
|
|
||||||
$sql = [];
|
|
||||||
|
|
||||||
## préfixe
|
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
|
||||||
|
|
||||||
## select
|
|
||||||
self::consume('(select(?:\s*distinct)?)\s*', $tmpsql, $ms);
|
|
||||||
$sql[] = $ms[1];
|
|
||||||
|
|
||||||
## cols
|
|
||||||
$usercols = [];
|
|
||||||
if (self::consume('(.*?)\s*(?=$|\bfrom\b)', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $usercols[] = $ms[1];
|
|
||||||
}
|
|
||||||
$colPrefix = $query["col_prefix"] ?? null;
|
|
||||||
if ($colPrefix !== null) str::add_suffix($colPrefix, ".");
|
|
||||||
$tmpcols = cl::withn($query["cols"] ?? null);
|
|
||||||
$schema = $query["schema"] ?? null;
|
|
||||||
if ($tmpcols !== null) {
|
|
||||||
$cols = [];
|
|
||||||
$index = 0;
|
|
||||||
foreach ($tmpcols as $key => $col) {
|
|
||||||
if ($key === $index) {
|
|
||||||
$index++;
|
|
||||||
$cols[] = $col;
|
|
||||||
$usercols[] = self::add_prefix($col, $colPrefix);
|
|
||||||
} else {
|
|
||||||
$cols[] = $key;
|
|
||||||
$usercols[] = self::add_prefix($col, $colPrefix)." as $key";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$cols = null;
|
|
||||||
if ($schema && is_array($schema) && !in_array("*", $usercols)) {
|
|
||||||
$cols = array_keys($schema);
|
|
||||||
foreach ($cols as $col) {
|
|
||||||
$usercols[] = self::add_prefix($col, $colPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$usercols && !$cols) $usercols = [self::add_prefix("*", $colPrefix)];
|
|
||||||
$sql[] = implode(", ", $usercols);
|
|
||||||
|
|
||||||
## from
|
|
||||||
$from = $query["from"] ?? null;
|
|
||||||
if (self::consume('from\s+([a-z_][a-z0-9_]*)\s*(?=;?\s*$|\bwhere\b)', $tmpsql, $ms)) {
|
|
||||||
if ($from === null) $from = $ms[1];
|
|
||||||
$sql[] = "from";
|
|
||||||
$sql[] = $from;
|
|
||||||
} elseif ($from !== null) {
|
|
||||||
$sql[] = "from";
|
|
||||||
$sql[] = $from;
|
|
||||||
} else {
|
|
||||||
throw new ValueException("expected table name: $usersql");
|
|
||||||
}
|
|
||||||
|
|
||||||
## where
|
|
||||||
$userwhere = [];
|
|
||||||
if (self::consume('where\b\s*(.*?)(?=;?\s*$|\border\s+by\b)', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $userwhere[] = $ms[1];
|
|
||||||
}
|
|
||||||
$where = cl::withn($query["where"] ?? null);
|
|
||||||
if ($where !== null) self::parse_conds($where, $userwhere, $bindings);
|
|
||||||
if ($userwhere) {
|
|
||||||
$sql[] = "where";
|
|
||||||
$sql[] = implode(" and ", $userwhere);
|
|
||||||
}
|
|
||||||
|
|
||||||
## order by
|
|
||||||
$userorderby = [];
|
|
||||||
if (self::consume('order\s+by\b\s*(.*?)(?=;?\s*$|\bgroup\s+by\b)', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $userorderby[] = $ms[1];
|
|
||||||
}
|
|
||||||
$orderby = cl::withn($query["order by"] ?? null);
|
|
||||||
if ($orderby !== null) {
|
|
||||||
$index = 0;
|
|
||||||
foreach ($orderby as $key => $value) {
|
|
||||||
if ($key === $index) {
|
|
||||||
$userorderby[] = $value;
|
|
||||||
$index++;
|
|
||||||
} else {
|
|
||||||
if ($value === null) $value = false;
|
|
||||||
if (!is_bool($value)) {
|
|
||||||
$userorderby[] = "$key $value";
|
|
||||||
} elseif ($value) {
|
|
||||||
$userorderby[] = $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($userorderby) {
|
|
||||||
$sql[] = "order by";
|
|
||||||
$sql[] = implode(", ", $userorderby);
|
|
||||||
}
|
|
||||||
## group by
|
|
||||||
$usergroupby = [];
|
|
||||||
if (self::consume('group\s+by\b\s*(.*?)(?=;?\s*$|\bhaving\b)', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $usergroupby[] = $ms[1];
|
|
||||||
}
|
|
||||||
$groupby = cl::withn($query["group by"] ?? null);
|
|
||||||
if ($groupby !== null) {
|
|
||||||
$index = 0;
|
|
||||||
foreach ($groupby as $key => $value) {
|
|
||||||
if ($key === $index) {
|
|
||||||
$usergroupby[] = $value;
|
|
||||||
$index++;
|
|
||||||
} else {
|
|
||||||
if ($value === null) $value = false;
|
|
||||||
if (!is_bool($value)) {
|
|
||||||
$usergroupby[] = "$key $value";
|
|
||||||
} elseif ($value) {
|
|
||||||
$usergroupby[] = $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($usergroupby) {
|
|
||||||
$sql[] = "group by";
|
|
||||||
$sql[] = implode(", ", $usergroupby);
|
|
||||||
}
|
|
||||||
|
|
||||||
## having
|
|
||||||
$userhaving = [];
|
|
||||||
if (self::consume('having\b\s*(.*?)(?=;?\s*$)', $tmpsql, $ms)) {
|
|
||||||
if ($ms[1]) $userhaving[] = $ms[1];
|
|
||||||
}
|
|
||||||
$having = cl::withn($query["having"] ?? null);
|
|
||||||
if ($having !== null) self::parse_conds($having, $userhaving, $bindings);
|
|
||||||
if ($userhaving) {
|
|
||||||
$sql[] = "having";
|
|
||||||
$sql[] = implode(" and ", $userhaving);
|
|
||||||
}
|
|
||||||
|
|
||||||
## suffixe
|
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
|
||||||
|
|
||||||
## fin de la requête
|
|
||||||
self::check_eof($tmpsql, $usersql);
|
|
||||||
return implode(" ", $sql);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\_private;
|
|
||||||
|
|
||||||
trait Tupdate {
|
|
||||||
static function isa(string $sql): bool {
|
|
||||||
return preg_match("/^update\b/i", $sql);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function parse(array $query, ?array &$bindings=null): string {
|
|
||||||
#XXX implémentation minimale
|
|
||||||
$sql = [self::merge_seq($query)];
|
|
||||||
|
|
||||||
## préfixe
|
|
||||||
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
|
||||||
|
|
||||||
## table
|
|
||||||
$sql[] = $query["table"];
|
|
||||||
|
|
||||||
## set
|
|
||||||
self::parse_set_values($query["values"], $setsql, $bindings);
|
|
||||||
$sql[] = "set";
|
|
||||||
$sql[] = implode(", ", $setsql);
|
|
||||||
|
|
||||||
## where
|
|
||||||
$where = $query["where"] ?? null;
|
|
||||||
if ($where !== null) {
|
|
||||||
self::parse_conds($where, $wheresql, $bindings);
|
|
||||||
if ($wheresql) {
|
|
||||||
$sql[] = "where";
|
|
||||||
$sql[] = implode(" and ", $wheresql);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## suffixe
|
|
||||||
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
|
||||||
|
|
||||||
## fin de la requête
|
|
||||||
return implode(" ", $sql);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,255 +5,13 @@ use nulib\cl;
|
|||||||
use nulib\str;
|
use nulib\str;
|
||||||
use nulib\ValueException;
|
use nulib\ValueException;
|
||||||
|
|
||||||
abstract class _base {
|
abstract class _base extends _common {
|
||||||
protected static function consume(string $pattern, string &$string, ?array &$ms=null): bool {
|
abstract protected static function verifix(&$sql, ?array &$bindings=null, ?array &$meta=null): void;
|
||||||
if (!preg_match("/^$pattern/i", $string, $ms)) return false;
|
|
||||||
$string = substr($string, strlen($ms[0]));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** fusionner toutes les parties séquentielles d'une requête */
|
static function with($sql, ?array $params=null): array {
|
||||||
protected static function merge_seq(array $query): string {
|
static::verifix($sql, $params);
|
||||||
$index = 0;
|
return [$sql, $params];
|
||||||
$sql = "";
|
|
||||||
foreach ($query as $key => $value) {
|
|
||||||
if ($key === $index) {
|
|
||||||
$index++;
|
|
||||||
if ($sql && !str::ends_with(" ", $sql) && !str::starts_with(" ", $value)) {
|
|
||||||
$sql .= " ";
|
|
||||||
}
|
}
|
||||||
$sql .= $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $sql;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function is_sep(&$cond): bool {
|
|
||||||
if (!is_string($cond)) return false;
|
|
||||||
if (!preg_match('/^\s*(and|or|not)\s*$/i', $cond, $ms)) return false;
|
|
||||||
$cond = $ms[1];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function parse_conds(?array $conds, ?array &$sql, ?array &$bindings): void {
|
|
||||||
if (!$conds) return;
|
|
||||||
$sep = null;
|
|
||||||
$index = 0;
|
|
||||||
$condsql = [];
|
|
||||||
foreach ($conds as $key => $cond) {
|
|
||||||
if ($key === $index) {
|
|
||||||
## séquentiel
|
|
||||||
if ($index === 0 && self::is_sep($cond)) {
|
|
||||||
$sep = $cond;
|
|
||||||
} elseif (is_bool($cond)) {
|
|
||||||
# ignorer les valeurs true et false
|
|
||||||
} elseif (is_array($cond)) {
|
|
||||||
# condition récursive
|
|
||||||
self::parse_conds($cond, $condsql, $bindings);
|
|
||||||
} else {
|
|
||||||
# condition litérale
|
|
||||||
$condsql[] = strval($cond);
|
|
||||||
}
|
|
||||||
$index++;
|
|
||||||
} elseif ($cond === false) {
|
|
||||||
## associatif
|
|
||||||
# condition litérale ignorée car condition false
|
|
||||||
} elseif ($cond === true) {
|
|
||||||
# condition litérale sélectionnée car condition true
|
|
||||||
$condsql[] = strval($key);
|
|
||||||
} else {
|
|
||||||
## associatif
|
|
||||||
# paramètre
|
|
||||||
$param0 = preg_replace('/^.+\./', "", $key);
|
|
||||||
$i = false;
|
|
||||||
if ($bindings !== null && array_key_exists($param0, $bindings)) {
|
|
||||||
$i = 2;
|
|
||||||
while (array_key_exists("$param0$i", $bindings)) {
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# value ou [operator, value]
|
|
||||||
$condprefix = $condsep = $condsuffix = null;
|
|
||||||
if (is_array($cond)) {
|
|
||||||
$condkey = 0;
|
|
||||||
$condkeys = array_keys($cond);
|
|
||||||
$op = null;
|
|
||||||
if (array_key_exists("op", $cond)) {
|
|
||||||
$op = $cond["op"];
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$op = $cond[$condkeys[$condkey]];
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
$op = strtolower($op);
|
|
||||||
$condvalues = null;
|
|
||||||
switch ($op) {
|
|
||||||
case "between":
|
|
||||||
# ["between", $upper, $lower]
|
|
||||||
$condsep = " and ";
|
|
||||||
if (array_key_exists("lower", $cond)) {
|
|
||||||
$condvalues[] = $cond["lower"];
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$condvalues[] = $cond[$condkeys[$condkey]];
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
if (array_key_exists("upper", $cond)) {
|
|
||||||
$condvalues[] = $cond["upper"];
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$condvalues[] = $cond[$condkeys[$condkey]];
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "any":
|
|
||||||
case "all":
|
|
||||||
case "not any":
|
|
||||||
case "not all":
|
|
||||||
# ["list", $values]
|
|
||||||
if ($op === "any" || $op === "all") {
|
|
||||||
$condprefix = $op;
|
|
||||||
$op = "=";
|
|
||||||
} elseif ($op === "not any" || $op === "not all") {
|
|
||||||
$condprefix = substr($op, strlen("not "));
|
|
||||||
$op = "<>";
|
|
||||||
}
|
|
||||||
$condprefix .= "(array[";
|
|
||||||
$condsep = ", ";
|
|
||||||
$condsuffix = "])";
|
|
||||||
$condvalues = null;
|
|
||||||
if (array_key_exists("values", $cond)) {
|
|
||||||
$condvalues = cl::with($cond["values"]);
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$condvalues = cl::with($cond[$condkeys[$condkey]]);
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "in":
|
|
||||||
# ["in", $values]
|
|
||||||
$condprefix = "(";
|
|
||||||
$condsep = ", ";
|
|
||||||
$condsuffix = ")";
|
|
||||||
$condvalues = null;
|
|
||||||
if (array_key_exists("values", $cond)) {
|
|
||||||
$condvalues = cl::with($cond["values"]);
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$condvalues = cl::with($cond[$condkeys[$condkey]]);
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "null":
|
|
||||||
case "is null":
|
|
||||||
$op = "is null";
|
|
||||||
break;
|
|
||||||
case "not null":
|
|
||||||
case "is not null":
|
|
||||||
$op = "is not null";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (array_key_exists("value", $cond)) {
|
|
||||||
$condvalues = [$cond["value"]];
|
|
||||||
} elseif (array_key_exists($condkey, $condkeys)) {
|
|
||||||
$condvalues = [$cond[$condkeys[$condkey]]];
|
|
||||||
$condkey++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elseif ($cond !== null) {
|
|
||||||
$op = "=";
|
|
||||||
$condvalues = [$cond];
|
|
||||||
} else {
|
|
||||||
$op = "is null";
|
|
||||||
$condvalues = null;
|
|
||||||
}
|
|
||||||
$cond = [$key, $op];
|
|
||||||
if ($condvalues !== null) {
|
|
||||||
$parts = [];
|
|
||||||
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 = "$param0$i";
|
|
||||||
$parts[] = ":$param";
|
|
||||||
$bindings[$param] = $value;
|
|
||||||
if ($i === false) $i = 2;
|
|
||||||
else $i++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$param = "$param0$i";
|
|
||||||
$parts[] = ":$param";
|
|
||||||
$bindings[$param] = $condvalue;
|
|
||||||
if ($i === false) $i = 2;
|
|
||||||
else $i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$cond[] = $condprefix.implode($condsep, $parts).$condsuffix;
|
|
||||||
}
|
|
||||||
$condsql[] = implode(" ", $cond);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($sep === null) $sep = "and";
|
|
||||||
$count = count($condsql);
|
|
||||||
if ($count > 1) {
|
|
||||||
$sql[] = "(" . implode(" $sep ", $condsql) . ")";
|
|
||||||
} elseif ($count == 1) {
|
|
||||||
$sql[] = $condsql[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function parse_set_values(?array $values, ?array &$sql, ?array &$bindings): void {
|
|
||||||
if (!$values) return;
|
|
||||||
$index = 0;
|
|
||||||
$parts = [];
|
|
||||||
foreach ($values as $key => $part) {
|
|
||||||
if ($key === $index) {
|
|
||||||
## séquentiel
|
|
||||||
if (is_array($part)) {
|
|
||||||
# paramètres récursifs
|
|
||||||
self::parse_set_values($part, $parts, $bindings);
|
|
||||||
} else {
|
|
||||||
# paramètre litéral
|
|
||||||
$parts[] = strval($part);
|
|
||||||
}
|
|
||||||
$index++;
|
|
||||||
} else {
|
|
||||||
## associatif
|
|
||||||
# paramètre
|
|
||||||
$param = $param0 = preg_replace('/^.+\./', "", $key);
|
|
||||||
if ($bindings !== null && array_key_exists($param0, $bindings)) {
|
|
||||||
$i = 2;
|
|
||||||
while (array_key_exists("$param0$i", $bindings)) {
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
$param = "$param0$i";
|
|
||||||
}
|
|
||||||
# value
|
|
||||||
$value = $part;
|
|
||||||
$part = [$key, "="];
|
|
||||||
if ($value === null) {
|
|
||||||
$part[] = "null";
|
|
||||||
} else {
|
|
||||||
$part[] = ":$param";
|
|
||||||
$bindings[$param] = $value;
|
|
||||||
}
|
|
||||||
$parts[] = implode(" ", $part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$sql = cl::merge($sql, $parts);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function check_eof(string $tmpsql, string $usersql): void {
|
|
||||||
self::consume(';\s*', $tmpsql);
|
|
||||||
if ($tmpsql) {
|
|
||||||
throw new ValueException("unexpected value at end: $usersql");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract protected static function verifix(&$sql, ?array &$bindinds=null, ?array &$meta=null): void;
|
|
||||||
|
|
||||||
function __construct($sql, ?array $bindings=null) {
|
function __construct($sql, ?array $bindings=null) {
|
||||||
static::verifix($sql, $bindings, $meta);
|
static::verifix($sql, $bindings, $meta);
|
||||||
|
255
php/src/db/_private/_common.php
Normal file
255
php/src/db/_private/_common.php
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
|
use nulib\cl;
|
||||||
|
use nulib\str;
|
||||||
|
use nulib\ValueException;
|
||||||
|
|
||||||
|
class _common {
|
||||||
|
protected static function consume(string $pattern, string &$string, ?array &$ms=null): bool {
|
||||||
|
if (!preg_match("/^$pattern/i", $string, $ms)) return false;
|
||||||
|
$string = substr($string, strlen($ms[0]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** fusionner toutes les parties séquentielles d'une requête */
|
||||||
|
protected static function merge_seq(array $query): string {
|
||||||
|
$index = 0;
|
||||||
|
$sql = "";
|
||||||
|
foreach ($query as $key => $value) {
|
||||||
|
if ($key === $index) {
|
||||||
|
$index++;
|
||||||
|
if ($sql && !str::ends_with(" ", $sql) && !str::starts_with(" ", $value)) {
|
||||||
|
$sql .= " ";
|
||||||
|
}
|
||||||
|
$sql .= $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function is_sep(&$cond): bool {
|
||||||
|
if (!is_string($cond)) return false;
|
||||||
|
if (!preg_match('/^\s*(and|or|not)\s*$/i', $cond, $ms)) return false;
|
||||||
|
$cond = $ms[1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse_conds(?array $conds, ?array &$sql, ?array &$bindings): void {
|
||||||
|
if (!$conds) return;
|
||||||
|
$sep = null;
|
||||||
|
$index = 0;
|
||||||
|
$condsql = [];
|
||||||
|
foreach ($conds as $key => $cond) {
|
||||||
|
if ($key === $index) {
|
||||||
|
## séquentiel
|
||||||
|
if ($index === 0 && self::is_sep($cond)) {
|
||||||
|
$sep = $cond;
|
||||||
|
} elseif (is_bool($cond)) {
|
||||||
|
# ignorer les valeurs true et false
|
||||||
|
} elseif (is_array($cond)) {
|
||||||
|
# condition récursive
|
||||||
|
self::parse_conds($cond, $condsql, $bindings);
|
||||||
|
} else {
|
||||||
|
# condition litérale
|
||||||
|
$condsql[] = strval($cond);
|
||||||
|
}
|
||||||
|
$index++;
|
||||||
|
} elseif ($cond === false) {
|
||||||
|
## associatif
|
||||||
|
# condition litérale ignorée car condition false
|
||||||
|
} elseif ($cond === true) {
|
||||||
|
# condition litérale sélectionnée car condition true
|
||||||
|
$condsql[] = strval($key);
|
||||||
|
} else {
|
||||||
|
## associatif
|
||||||
|
# paramètre
|
||||||
|
$param0 = preg_replace('/^.+\./', "", $key);
|
||||||
|
$i = false;
|
||||||
|
if ($bindings !== null && array_key_exists($param0, $bindings)) {
|
||||||
|
$i = 2;
|
||||||
|
while (array_key_exists("$param0$i", $bindings)) {
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# value ou [operator, value]
|
||||||
|
$condprefix = $condsep = $condsuffix = null;
|
||||||
|
if (is_array($cond)) {
|
||||||
|
$condkey = 0;
|
||||||
|
$condkeys = array_keys($cond);
|
||||||
|
$op = null;
|
||||||
|
if (array_key_exists("op", $cond)) {
|
||||||
|
$op = $cond["op"];
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$op = $cond[$condkeys[$condkey]];
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
$op = strtolower($op);
|
||||||
|
$condvalues = null;
|
||||||
|
switch ($op) {
|
||||||
|
case "between":
|
||||||
|
# ["between", $upper, $lower]
|
||||||
|
$condsep = " and ";
|
||||||
|
if (array_key_exists("lower", $cond)) {
|
||||||
|
$condvalues[] = $cond["lower"];
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$condvalues[] = $cond[$condkeys[$condkey]];
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
if (array_key_exists("upper", $cond)) {
|
||||||
|
$condvalues[] = $cond["upper"];
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$condvalues[] = $cond[$condkeys[$condkey]];
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "any":
|
||||||
|
case "all":
|
||||||
|
case "not any":
|
||||||
|
case "not all":
|
||||||
|
# ["list", $values]
|
||||||
|
if ($op === "any" || $op === "all") {
|
||||||
|
$condprefix = $op;
|
||||||
|
$op = "=";
|
||||||
|
} elseif ($op === "not any" || $op === "not all") {
|
||||||
|
$condprefix = substr($op, strlen("not "));
|
||||||
|
$op = "<>";
|
||||||
|
}
|
||||||
|
$condprefix .= "(array[";
|
||||||
|
$condsep = ", ";
|
||||||
|
$condsuffix = "])";
|
||||||
|
$condvalues = null;
|
||||||
|
if (array_key_exists("values", $cond)) {
|
||||||
|
$condvalues = cl::with($cond["values"]);
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$condvalues = cl::with($cond[$condkeys[$condkey]]);
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "in":
|
||||||
|
# ["in", $values]
|
||||||
|
$condprefix = "(";
|
||||||
|
$condsep = ", ";
|
||||||
|
$condsuffix = ")";
|
||||||
|
$condvalues = null;
|
||||||
|
if (array_key_exists("values", $cond)) {
|
||||||
|
$condvalues = cl::with($cond["values"]);
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$condvalues = cl::with($cond[$condkeys[$condkey]]);
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "null":
|
||||||
|
case "is null":
|
||||||
|
$op = "is null";
|
||||||
|
break;
|
||||||
|
case "not null":
|
||||||
|
case "is not null":
|
||||||
|
$op = "is not null";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (array_key_exists("value", $cond)) {
|
||||||
|
$condvalues = [$cond["value"]];
|
||||||
|
} elseif (array_key_exists($condkey, $condkeys)) {
|
||||||
|
$condvalues = [$cond[$condkeys[$condkey]]];
|
||||||
|
$condkey++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($cond !== null) {
|
||||||
|
$op = "=";
|
||||||
|
$condvalues = [$cond];
|
||||||
|
} else {
|
||||||
|
$op = "is null";
|
||||||
|
$condvalues = null;
|
||||||
|
}
|
||||||
|
$cond = [$key, $op];
|
||||||
|
if ($condvalues !== null) {
|
||||||
|
$parts = [];
|
||||||
|
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 = "$param0$i";
|
||||||
|
$parts[] = ":$param";
|
||||||
|
$bindings[$param] = $value;
|
||||||
|
if ($i === false) $i = 2;
|
||||||
|
else $i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$param = "$param0$i";
|
||||||
|
$parts[] = ":$param";
|
||||||
|
$bindings[$param] = $condvalue;
|
||||||
|
if ($i === false) $i = 2;
|
||||||
|
else $i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cond[] = $condprefix.implode($condsep, $parts).$condsuffix;
|
||||||
|
}
|
||||||
|
$condsql[] = implode(" ", $cond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($sep === null) $sep = "and";
|
||||||
|
$count = count($condsql);
|
||||||
|
if ($count > 1) {
|
||||||
|
$sql[] = "(" . implode(" $sep ", $condsql) . ")";
|
||||||
|
} elseif ($count == 1) {
|
||||||
|
$sql[] = $condsql[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse_set_values(?array $values, ?array &$sql, ?array &$bindings): void {
|
||||||
|
if (!$values) return;
|
||||||
|
$index = 0;
|
||||||
|
$parts = [];
|
||||||
|
foreach ($values as $key => $part) {
|
||||||
|
if ($key === $index) {
|
||||||
|
## séquentiel
|
||||||
|
if (is_array($part)) {
|
||||||
|
# paramètres récursifs
|
||||||
|
self::parse_set_values($part, $parts, $bindings);
|
||||||
|
} else {
|
||||||
|
# paramètre litéral
|
||||||
|
$parts[] = strval($part);
|
||||||
|
}
|
||||||
|
$index++;
|
||||||
|
} else {
|
||||||
|
## associatif
|
||||||
|
# paramètre
|
||||||
|
$param = $param0 = preg_replace('/^.+\./', "", $key);
|
||||||
|
if ($bindings !== null && array_key_exists($param0, $bindings)) {
|
||||||
|
$i = 2;
|
||||||
|
while (array_key_exists("$param0$i", $bindings)) {
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
$param = "$param0$i";
|
||||||
|
}
|
||||||
|
# value
|
||||||
|
$value = $part;
|
||||||
|
$part = [$key, "="];
|
||||||
|
if ($value === null) {
|
||||||
|
$part[] = "null";
|
||||||
|
} else {
|
||||||
|
$part[] = ":$param";
|
||||||
|
$bindings[$param] = $value;
|
||||||
|
}
|
||||||
|
$parts[] = implode(" ", $part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sql = cl::merge($sql, $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function check_eof(string $tmpsql, string $usersql): void {
|
||||||
|
self::consume(';\s*', $tmpsql);
|
||||||
|
if ($tmpsql) {
|
||||||
|
throw new ValueException("unexpected value at end: $usersql");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _create {
|
class _create extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
"prefix" => "?string",
|
"prefix" => "?string",
|
||||||
"table" => "string",
|
"table" => "string",
|
||||||
@ -9,4 +9,39 @@ class _create {
|
|||||||
"cols" => "?array",
|
"cols" => "?array",
|
||||||
"suffix" => "?string",
|
"suffix" => "?string",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
//return preg_match("/^create(?:\s+table)?\b/i", $sql);
|
||||||
|
#XXX implémentation minimale
|
||||||
|
return preg_match("/^create\s+table\b/i", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
#XXX implémentation minimale
|
||||||
|
$sql = [self::merge_seq($query)];
|
||||||
|
|
||||||
|
## préfixe
|
||||||
|
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
|
## table
|
||||||
|
$sql[] = $query["table"];
|
||||||
|
|
||||||
|
## columns
|
||||||
|
$cols = $query["cols"];
|
||||||
|
$index = 0;
|
||||||
|
foreach ($cols as $col => &$definition) {
|
||||||
|
if ($col === $index) {
|
||||||
|
$index++;
|
||||||
|
} else {
|
||||||
|
$definition = "$col $definition";
|
||||||
|
}
|
||||||
|
}; unset($definition);
|
||||||
|
$sql[] = "(\n ".implode("\n, ", $cols)."\n)";
|
||||||
|
|
||||||
|
## suffixe
|
||||||
|
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
|
## fin de la requête
|
||||||
|
return implode(" ", $sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,44 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _delete {
|
class _delete extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
"prefix" => "?string",
|
"prefix" => "?string",
|
||||||
"from" => "?string",
|
"from" => "?string",
|
||||||
"where" => "?array",
|
"where" => "?array",
|
||||||
"suffix" => "?string",
|
"suffix" => "?string",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
return preg_match("/^delete(?:\s+from)?\b/i", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
#XXX implémentation minimale
|
||||||
|
$tmpsql = self::merge_seq($query);
|
||||||
|
self::consume('delete(?:\s+from)?\b', $tmpsql);
|
||||||
|
$sql = ["delete from", $tmpsql];
|
||||||
|
|
||||||
|
## préfixe
|
||||||
|
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
|
## table
|
||||||
|
$sql[] = $query["from"];
|
||||||
|
|
||||||
|
## where
|
||||||
|
$where = $query["where"] ?? null;
|
||||||
|
if ($where !== null) {
|
||||||
|
self::parse_conds($where, $wheresql, $bindings);
|
||||||
|
if ($wheresql) {
|
||||||
|
$sql[] = "where";
|
||||||
|
$sql[] = implode(" and ", $wheresql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## suffixe
|
||||||
|
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
|
## fin de la requête
|
||||||
|
return implode(" ", $sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _generic {
|
use nulib\cl;
|
||||||
|
use nulib\ValueException;
|
||||||
|
|
||||||
|
class _generic extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
return preg_match('/^(?:drop\s+table)\b/i', $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
return self::merge_seq($query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _insert {
|
use nulib\cl;
|
||||||
|
use nulib\ValueException;
|
||||||
|
|
||||||
|
class _insert extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
"prefix" => "?string",
|
"prefix" => "?string",
|
||||||
"into" => "?string",
|
"into" => "?string",
|
||||||
@ -10,4 +13,79 @@ class _insert {
|
|||||||
"values" => "?array",
|
"values" => "?array",
|
||||||
"suffix" => "?string",
|
"suffix" => "?string",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
return preg_match("/^insert\b/i", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parser une chaine de la forme
|
||||||
|
* "insert [into] [TABLE] [(COLS)] [values (VALUES)]"
|
||||||
|
*/
|
||||||
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
# fusionner d'abord toutes les parties séquentielles
|
||||||
|
$usersql = $tmpsql = self::merge_seq($query);
|
||||||
|
|
||||||
|
### vérifier la présence des parties nécessaires
|
||||||
|
$sql = [];
|
||||||
|
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
|
## insert
|
||||||
|
self::consume('(insert(?:\s+or\s+(?:ignore|replace))?)\s*', $tmpsql, $ms);
|
||||||
|
$sql[] = $ms[1];
|
||||||
|
|
||||||
|
## into
|
||||||
|
self::consume('into\s*', $tmpsql);
|
||||||
|
$sql[] = "into";
|
||||||
|
$into = $query["into"] ?? null;
|
||||||
|
if (self::consume('([a-z_][a-z0-9_]*)\s*', $tmpsql, $ms)) {
|
||||||
|
if ($into === null) $into = $ms[1];
|
||||||
|
$sql[] = $into;
|
||||||
|
} elseif ($into !== null) {
|
||||||
|
$sql[] = $into;
|
||||||
|
} else {
|
||||||
|
throw new ValueException("expected table name: $usersql");
|
||||||
|
}
|
||||||
|
|
||||||
|
## cols & values
|
||||||
|
$usercols = [];
|
||||||
|
$uservalues = [];
|
||||||
|
if (self::consume('\(([^)]*)\)\s*', $tmpsql, $ms)) {
|
||||||
|
$usercols = array_merge($usercols, preg_split("/\s*,\s*/", $ms[1]));
|
||||||
|
}
|
||||||
|
$cols = cl::withn($query["cols"] ?? null);
|
||||||
|
$values = cl::withn($query["values"] ?? null);
|
||||||
|
$schema = $query["schema"] ?? null;
|
||||||
|
if ($cols === null) {
|
||||||
|
if ($usercols) {
|
||||||
|
$cols = $usercols;
|
||||||
|
} elseif ($values) {
|
||||||
|
$cols = array_keys($values);
|
||||||
|
$usercols = array_merge($usercols, $cols);
|
||||||
|
} elseif ($schema && is_array($schema)) {
|
||||||
|
#XXX implémenter support AssocSchema
|
||||||
|
$cols = array_keys($schema);
|
||||||
|
$usercols = array_merge($usercols, $cols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self::consume('values\s+\(\s*(.*)\s*\)\s*', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $uservalues[] = $ms[1];
|
||||||
|
}
|
||||||
|
if ($cols !== null && !$uservalues) {
|
||||||
|
if (!$usercols) $usercols = $cols;
|
||||||
|
foreach ($cols as $col) {
|
||||||
|
$uservalues[] = ":$col";
|
||||||
|
$bindings[$col] = $values[$col] ?? null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sql[] = "(" . implode(", ", $usercols) . ")";
|
||||||
|
$sql[] = "values (" . implode(", ", $uservalues) . ")";
|
||||||
|
|
||||||
|
## suffixe
|
||||||
|
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
|
## fin de la requête
|
||||||
|
self::check_eof($tmpsql, $usersql);
|
||||||
|
return implode(" ", $sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _select {
|
use nulib\cl;
|
||||||
|
use nulib\str;
|
||||||
|
use nulib\ValueException;
|
||||||
|
|
||||||
|
class _select extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
"prefix" => "?string",
|
"prefix" => "?string",
|
||||||
"schema" => "?array",
|
"schema" => "?array",
|
||||||
@ -14,4 +18,164 @@ class _select {
|
|||||||
"having" => "?array",
|
"having" => "?array",
|
||||||
"suffix" => "?string",
|
"suffix" => "?string",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
return preg_match("/^select\b/i", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function add_prefix(string $col, ?string $prefix): string {
|
||||||
|
if ($prefix === null) return $col;
|
||||||
|
if (strpos($col, ".") !== false) return $col;
|
||||||
|
return "$prefix$col";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parser une chaine de la forme
|
||||||
|
* "select [COLS] [from TABLE] [where CONDS] [order by ORDERS] [group by GROUPS] [having CONDS]"
|
||||||
|
*/
|
||||||
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
# fusionner d'abord toutes les parties séquentielles
|
||||||
|
$usersql = $tmpsql = self::merge_seq($query);
|
||||||
|
|
||||||
|
### vérifier la présence des parties nécessaires
|
||||||
|
$sql = [];
|
||||||
|
|
||||||
|
## préfixe
|
||||||
|
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
|
## select
|
||||||
|
self::consume('(select(?:\s*distinct)?)\s*', $tmpsql, $ms);
|
||||||
|
$sql[] = $ms[1];
|
||||||
|
|
||||||
|
## cols
|
||||||
|
$usercols = [];
|
||||||
|
if (self::consume('(.*?)\s*(?=$|\bfrom\b)', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $usercols[] = $ms[1];
|
||||||
|
}
|
||||||
|
$colPrefix = $query["col_prefix"] ?? null;
|
||||||
|
if ($colPrefix !== null) str::add_suffix($colPrefix, ".");
|
||||||
|
$tmpcols = cl::withn($query["cols"] ?? null);
|
||||||
|
$schema = $query["schema"] ?? null;
|
||||||
|
if ($tmpcols !== null) {
|
||||||
|
$cols = [];
|
||||||
|
$index = 0;
|
||||||
|
foreach ($tmpcols as $key => $col) {
|
||||||
|
if ($key === $index) {
|
||||||
|
$index++;
|
||||||
|
$cols[] = $col;
|
||||||
|
$usercols[] = self::add_prefix($col, $colPrefix);
|
||||||
|
} else {
|
||||||
|
$cols[] = $key;
|
||||||
|
$usercols[] = self::add_prefix($col, $colPrefix)." as $key";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$cols = null;
|
||||||
|
if ($schema && is_array($schema) && !in_array("*", $usercols)) {
|
||||||
|
$cols = array_keys($schema);
|
||||||
|
foreach ($cols as $col) {
|
||||||
|
$usercols[] = self::add_prefix($col, $colPrefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$usercols && !$cols) $usercols = [self::add_prefix("*", $colPrefix)];
|
||||||
|
$sql[] = implode(", ", $usercols);
|
||||||
|
|
||||||
|
## from
|
||||||
|
$from = $query["from"] ?? null;
|
||||||
|
if (self::consume('from\s+([a-z_][a-z0-9_]*)\s*(?=;?\s*$|\bwhere\b)', $tmpsql, $ms)) {
|
||||||
|
if ($from === null) $from = $ms[1];
|
||||||
|
$sql[] = "from";
|
||||||
|
$sql[] = $from;
|
||||||
|
} elseif ($from !== null) {
|
||||||
|
$sql[] = "from";
|
||||||
|
$sql[] = $from;
|
||||||
|
} else {
|
||||||
|
throw new ValueException("expected table name: $usersql");
|
||||||
|
}
|
||||||
|
|
||||||
|
## where
|
||||||
|
$userwhere = [];
|
||||||
|
if (self::consume('where\b\s*(.*?)(?=;?\s*$|\border\s+by\b)', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $userwhere[] = $ms[1];
|
||||||
|
}
|
||||||
|
$where = cl::withn($query["where"] ?? null);
|
||||||
|
if ($where !== null) self::parse_conds($where, $userwhere, $bindings);
|
||||||
|
if ($userwhere) {
|
||||||
|
$sql[] = "where";
|
||||||
|
$sql[] = implode(" and ", $userwhere);
|
||||||
|
}
|
||||||
|
|
||||||
|
## order by
|
||||||
|
$userorderby = [];
|
||||||
|
if (self::consume('order\s+by\b\s*(.*?)(?=;?\s*$|\bgroup\s+by\b)', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $userorderby[] = $ms[1];
|
||||||
|
}
|
||||||
|
$orderby = cl::withn($query["order by"] ?? null);
|
||||||
|
if ($orderby !== null) {
|
||||||
|
$index = 0;
|
||||||
|
foreach ($orderby as $key => $value) {
|
||||||
|
if ($key === $index) {
|
||||||
|
$userorderby[] = $value;
|
||||||
|
$index++;
|
||||||
|
} else {
|
||||||
|
if ($value === null) $value = false;
|
||||||
|
if (!is_bool($value)) {
|
||||||
|
$userorderby[] = "$key $value";
|
||||||
|
} elseif ($value) {
|
||||||
|
$userorderby[] = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($userorderby) {
|
||||||
|
$sql[] = "order by";
|
||||||
|
$sql[] = implode(", ", $userorderby);
|
||||||
|
}
|
||||||
|
## group by
|
||||||
|
$usergroupby = [];
|
||||||
|
if (self::consume('group\s+by\b\s*(.*?)(?=;?\s*$|\bhaving\b)', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $usergroupby[] = $ms[1];
|
||||||
|
}
|
||||||
|
$groupby = cl::withn($query["group by"] ?? null);
|
||||||
|
if ($groupby !== null) {
|
||||||
|
$index = 0;
|
||||||
|
foreach ($groupby as $key => $value) {
|
||||||
|
if ($key === $index) {
|
||||||
|
$usergroupby[] = $value;
|
||||||
|
$index++;
|
||||||
|
} else {
|
||||||
|
if ($value === null) $value = false;
|
||||||
|
if (!is_bool($value)) {
|
||||||
|
$usergroupby[] = "$key $value";
|
||||||
|
} elseif ($value) {
|
||||||
|
$usergroupby[] = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($usergroupby) {
|
||||||
|
$sql[] = "group by";
|
||||||
|
$sql[] = implode(", ", $usergroupby);
|
||||||
|
}
|
||||||
|
|
||||||
|
## having
|
||||||
|
$userhaving = [];
|
||||||
|
if (self::consume('having\b\s*(.*?)(?=;?\s*$)', $tmpsql, $ms)) {
|
||||||
|
if ($ms[1]) $userhaving[] = $ms[1];
|
||||||
|
}
|
||||||
|
$having = cl::withn($query["having"] ?? null);
|
||||||
|
if ($having !== null) self::parse_conds($having, $userhaving, $bindings);
|
||||||
|
if ($userhaving) {
|
||||||
|
$sql[] = "having";
|
||||||
|
$sql[] = implode(" and ", $userhaving);
|
||||||
|
}
|
||||||
|
|
||||||
|
## suffixe
|
||||||
|
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
|
## fin de la requête
|
||||||
|
self::check_eof($tmpsql, $usersql);
|
||||||
|
return implode(" ", $sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\_private;
|
namespace nulib\db\_private;
|
||||||
|
|
||||||
class _update {
|
class _update extends _common {
|
||||||
const SCHEMA = [
|
const SCHEMA = [
|
||||||
"prefix" => "?string",
|
"prefix" => "?string",
|
||||||
"table" => "?string",
|
"table" => "?string",
|
||||||
@ -11,4 +11,40 @@ class _update {
|
|||||||
"where" => "?array",
|
"where" => "?array",
|
||||||
"suffix" => "?string",
|
"suffix" => "?string",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static function isa(string $sql): bool {
|
||||||
|
return preg_match("/^update\b/i", $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse(array $query, ?array &$bindings=null): string {
|
||||||
|
#XXX implémentation minimale
|
||||||
|
$sql = [self::merge_seq($query)];
|
||||||
|
|
||||||
|
## préfixe
|
||||||
|
if (($prefix = $query["prefix"] ?? null) !== null) $sql[] = $prefix;
|
||||||
|
|
||||||
|
## table
|
||||||
|
$sql[] = $query["table"];
|
||||||
|
|
||||||
|
## set
|
||||||
|
self::parse_set_values($query["values"], $setsql, $bindings);
|
||||||
|
$sql[] = "set";
|
||||||
|
$sql[] = implode(", ", $setsql);
|
||||||
|
|
||||||
|
## where
|
||||||
|
$where = $query["where"] ?? null;
|
||||||
|
if ($where !== null) {
|
||||||
|
self::parse_conds($where, $wheresql, $bindings);
|
||||||
|
if ($wheresql) {
|
||||||
|
$sql[] = "where";
|
||||||
|
$sql[] = implode(" and ", $wheresql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## suffixe
|
||||||
|
if (($suffix = $query["suffix"] ?? null) !== null) $sql[] = $suffix;
|
||||||
|
|
||||||
|
## fin de la requête
|
||||||
|
return implode(" ", $sql);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class MysqlStorage extends CapacitorStorage {
|
|||||||
];
|
];
|
||||||
|
|
||||||
function _getCreateSql(CapacitorChannel $channel): string {
|
function _getCreateSql(CapacitorChannel $channel): string {
|
||||||
$query = new _query_base($this->_createSql($channel));
|
$query = new query($this->_createSql($channel));
|
||||||
return self::format_sql($channel, $query->getSql());
|
return self::format_sql($channel, $query->getSql());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\ValueException;
|
|
||||||
|
|
||||||
class _query_base extends \nulib\db\pdo\_query_base {
|
|
||||||
protected static function verifix(&$sql, ?array &$bindinds=null, ?array &$meta=null): void {
|
|
||||||
if (is_array($sql)) {
|
|
||||||
$prefix = $sql[0] ?? null;
|
|
||||||
if ($prefix === null) {
|
|
||||||
throw new ValueException("requête invalide");
|
|
||||||
} elseif (_query_create::isa($prefix)) {
|
|
||||||
$sql = _query_create::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "create", "type" => "ddl"];
|
|
||||||
} elseif (_query_select::isa($prefix)) {
|
|
||||||
$sql = _query_select::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "select", "type" => "dql"];
|
|
||||||
} elseif (_query_insert::isa($prefix)) {
|
|
||||||
$sql = _query_insert::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "insert", "type" => "dml"];
|
|
||||||
} elseif (_query_update::isa($prefix)) {
|
|
||||||
$sql = _query_update::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "update", "type" => "dml"];
|
|
||||||
} elseif (_query_delete::isa($prefix)) {
|
|
||||||
$sql = _query_delete::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "delete", "type" => "dml"];
|
|
||||||
} elseif (_query_generic::isa($prefix)) {
|
|
||||||
$sql = _query_generic::parse($sql, $bindinds);
|
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
|
||||||
} else {
|
|
||||||
throw ValueException::invalid_kind($sql, "query");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!is_string($sql)) $sql = strval($sql);
|
|
||||||
if (_query_create::isa($sql)) {
|
|
||||||
$meta = ["isa" => "create", "type" => "ddl"];
|
|
||||||
} elseif (_query_select::isa($sql)) {
|
|
||||||
$meta = ["isa" => "select", "type" => "dql"];
|
|
||||||
} elseif (_query_insert::isa($sql)) {
|
|
||||||
$meta = ["isa" => "insert", "type" => "dml"];
|
|
||||||
} elseif (_query_update::isa($sql)) {
|
|
||||||
$meta = ["isa" => "update", "type" => "dml"];
|
|
||||||
} elseif (_query_delete::isa($sql)) {
|
|
||||||
$meta = ["isa" => "delete", "type" => "dml"];
|
|
||||||
} elseif (_query_generic::isa($sql)) {
|
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
|
||||||
} else {
|
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_create;
|
|
||||||
use nulib\db\_private\Tcreate;
|
|
||||||
|
|
||||||
class _query_create extends _query_base {
|
|
||||||
use Tcreate;
|
|
||||||
const SCHEMA = _create::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_delete;
|
|
||||||
use nulib\db\_private\Tdelete;
|
|
||||||
|
|
||||||
class _query_delete extends _query_base {
|
|
||||||
use Tdelete;
|
|
||||||
const SCHEMA = _delete::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_generic;
|
|
||||||
use nulib\db\_private\Tgeneric;
|
|
||||||
|
|
||||||
class _query_generic extends _query_base {
|
|
||||||
use Tgeneric;
|
|
||||||
const SCHEMA = _generic::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_insert;
|
|
||||||
use nulib\db\_private\Tinsert;
|
|
||||||
|
|
||||||
class _query_insert extends _query_base {
|
|
||||||
use Tinsert;
|
|
||||||
const SCHEMA = _insert::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_select;
|
|
||||||
use nulib\db\_private\Tselect;
|
|
||||||
|
|
||||||
class _query_select extends _query_base {
|
|
||||||
use Tselect;
|
|
||||||
const SCHEMA = _select::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\mysql;
|
|
||||||
|
|
||||||
use nulib\db\_private\_update;
|
|
||||||
use nulib\db\_private\Tupdate;
|
|
||||||
|
|
||||||
class _query_update extends _query_base {
|
|
||||||
use Tupdate;
|
|
||||||
const SCHEMA = _update::SCHEMA;
|
|
||||||
}
|
|
@ -1,12 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\db\mysql;
|
namespace nulib\db\mysql;
|
||||||
|
|
||||||
/**
|
class query extends \nulib\db\pdo\query {
|
||||||
* Class query: classe outil temporaire pour générer les requêtes
|
|
||||||
*/
|
|
||||||
class query extends _query_base {
|
|
||||||
static function with($sql, ?array $params=null): array {
|
|
||||||
self::verifix($sql, $params);
|
|
||||||
return [$sql, $params];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,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_base($query, $params);
|
$query = new query($query, $params);
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($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();
|
||||||
@ -222,7 +222,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_base($query, $params);
|
$query = new query($query, $params);
|
||||||
$stmt = null;
|
$stmt = null;
|
||||||
try {
|
try {
|
||||||
/** @var \PDOStatement $stmt */
|
/** @var \PDOStatement $stmt */
|
||||||
@ -251,7 +251,7 @@ class Pdo implements IDatabase {
|
|||||||
*/
|
*/
|
||||||
function all($query, ?array $params=null, $primaryKeys=null): Generator {
|
function all($query, ?array $params=null, $primaryKeys=null): Generator {
|
||||||
$db = $this->db();
|
$db = $this->db();
|
||||||
$query = new _query_base($query, $params);
|
$query = new query($query, $params);
|
||||||
$stmt = null;
|
$stmt = null;
|
||||||
try {
|
try {
|
||||||
/** @var \PDOStatement $stmt */
|
/** @var \PDOStatement $stmt */
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_create;
|
|
||||||
use nulib\db\_private\Tcreate;
|
|
||||||
|
|
||||||
class _query_create extends _query_base {
|
|
||||||
use Tcreate;
|
|
||||||
const SCHEMA = _create::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_delete;
|
|
||||||
use nulib\db\_private\Tdelete;
|
|
||||||
|
|
||||||
class _query_delete extends _query_base {
|
|
||||||
use Tdelete;
|
|
||||||
const SCHEMA = _delete::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_generic;
|
|
||||||
use nulib\db\_private\Tgeneric;
|
|
||||||
|
|
||||||
class _query_generic extends _query_base {
|
|
||||||
use Tgeneric;
|
|
||||||
const SCHEMA = _generic::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_insert;
|
|
||||||
use nulib\db\_private\Tinsert;
|
|
||||||
|
|
||||||
class _query_insert extends _query_base {
|
|
||||||
use Tinsert;
|
|
||||||
const SCHEMA = _insert::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_select;
|
|
||||||
use nulib\db\_private\Tselect;
|
|
||||||
|
|
||||||
class _query_select extends _query_base {
|
|
||||||
use Tselect;
|
|
||||||
const SCHEMA = _select::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\pdo;
|
|
||||||
|
|
||||||
use nulib\db\_private\_update;
|
|
||||||
use nulib\db\_private\Tupdate;
|
|
||||||
|
|
||||||
class _query_update extends _query_base {
|
|
||||||
use Tupdate;
|
|
||||||
const SCHEMA = _update::SCHEMA;
|
|
||||||
}
|
|
@ -2,51 +2,57 @@
|
|||||||
namespace nulib\db\pdo;
|
namespace nulib\db\pdo;
|
||||||
|
|
||||||
use nulib\db\_private\_base;
|
use nulib\db\_private\_base;
|
||||||
|
use nulib\db\_private\_create;
|
||||||
|
use nulib\db\_private\_delete;
|
||||||
|
use nulib\db\_private\_generic;
|
||||||
|
use nulib\db\_private\_insert;
|
||||||
|
use nulib\db\_private\_select;
|
||||||
|
use nulib\db\_private\_update;
|
||||||
use nulib\db\_private\Tbindings;
|
use nulib\db\_private\Tbindings;
|
||||||
use nulib\ValueException;
|
use nulib\ValueException;
|
||||||
|
|
||||||
class _query_base extends _base {
|
class query extends _base {
|
||||||
use Tbindings;
|
use Tbindings;
|
||||||
|
|
||||||
protected static function verifix(&$sql, ?array &$bindinds=null, ?array &$meta=null): void {
|
protected static function verifix(&$sql, ?array &$bindings=null, ?array &$meta=null): void {
|
||||||
if (is_array($sql)) {
|
if (is_array($sql)) {
|
||||||
$prefix = $sql[0] ?? null;
|
$prefix = $sql[0] ?? null;
|
||||||
if ($prefix === null) {
|
if ($prefix === null) {
|
||||||
throw new ValueException("requête invalide");
|
throw new ValueException("requête invalide");
|
||||||
} elseif (_query_create::isa($prefix)) {
|
} elseif (_create::isa($prefix)) {
|
||||||
$sql = _query_create::parse($sql, $bindinds);
|
$sql = _create::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "create", "type" => "ddl"];
|
$meta = ["isa" => "create", "type" => "ddl"];
|
||||||
} elseif (_query_select::isa($prefix)) {
|
} elseif (_select::isa($prefix)) {
|
||||||
$sql = _query_select::parse($sql, $bindinds);
|
$sql = _select::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "select", "type" => "dql"];
|
$meta = ["isa" => "select", "type" => "dql"];
|
||||||
} elseif (_query_insert::isa($prefix)) {
|
} elseif (_insert::isa($prefix)) {
|
||||||
$sql = _query_insert::parse($sql, $bindinds);
|
$sql = _insert::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "insert", "type" => "dml"];
|
$meta = ["isa" => "insert", "type" => "dml"];
|
||||||
} elseif (_query_update::isa($prefix)) {
|
} elseif (_update::isa($prefix)) {
|
||||||
$sql = _query_update::parse($sql, $bindinds);
|
$sql = _update::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "update", "type" => "dml"];
|
$meta = ["isa" => "update", "type" => "dml"];
|
||||||
} elseif (_query_delete::isa($prefix)) {
|
} elseif (_delete::isa($prefix)) {
|
||||||
$sql = _query_delete::parse($sql, $bindinds);
|
$sql = _delete::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "delete", "type" => "dml"];
|
$meta = ["isa" => "delete", "type" => "dml"];
|
||||||
} elseif (_query_generic::isa($prefix)) {
|
} elseif (_generic::isa($prefix)) {
|
||||||
$sql = _query_generic::parse($sql, $bindinds);
|
$sql = _generic::parse($sql, $bindings);
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
$meta = ["isa" => "generic", "type" => null];
|
||||||
} else {
|
} else {
|
||||||
throw ValueException::invalid_kind($sql, "query");
|
throw ValueException::invalid_kind($sql, "query");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!is_string($sql)) $sql = strval($sql);
|
if (!is_string($sql)) $sql = strval($sql);
|
||||||
if (_query_create::isa($sql)) {
|
if (_create::isa($sql)) {
|
||||||
$meta = ["isa" => "create", "type" => "ddl"];
|
$meta = ["isa" => "create", "type" => "ddl"];
|
||||||
} elseif (_query_select::isa($sql)) {
|
} elseif (_select::isa($sql)) {
|
||||||
$meta = ["isa" => "select", "type" => "dql"];
|
$meta = ["isa" => "select", "type" => "dql"];
|
||||||
} elseif (_query_insert::isa($sql)) {
|
} elseif (_insert::isa($sql)) {
|
||||||
$meta = ["isa" => "insert", "type" => "dml"];
|
$meta = ["isa" => "insert", "type" => "dml"];
|
||||||
} elseif (_query_update::isa($sql)) {
|
} elseif (_update::isa($sql)) {
|
||||||
$meta = ["isa" => "update", "type" => "dml"];
|
$meta = ["isa" => "update", "type" => "dml"];
|
||||||
} elseif (_query_delete::isa($sql)) {
|
} elseif (_delete::isa($sql)) {
|
||||||
$meta = ["isa" => "delete", "type" => "dml"];
|
$meta = ["isa" => "delete", "type" => "dml"];
|
||||||
} elseif (_query_generic::isa($sql)) {
|
} elseif (_generic::isa($sql)) {
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
$meta = ["isa" => "generic", "type" => null];
|
||||||
} else {
|
} else {
|
||||||
$meta = ["isa" => "generic", "type" => null];
|
$meta = ["isa" => "generic", "type" => null];
|
@ -187,7 +187,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_base($query, $params);
|
$query = new query($query, $params);
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
$result = $stmt->execute();
|
$result = $stmt->execute();
|
||||||
@ -274,7 +274,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_base($query, $params);
|
$query = new query($query, $params);
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
try {
|
try {
|
||||||
$result = $this->checkResult($stmt->execute());
|
$result = $this->checkResult($stmt->execute());
|
||||||
@ -323,7 +323,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_base($query, $params);
|
$query = new query($query, $params);
|
||||||
if ($query->useStmt($db, $stmt, $sql)) {
|
if ($query->useStmt($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);
|
||||||
|
@ -24,7 +24,7 @@ class SqliteStorage extends CapacitorStorage {
|
|||||||
];
|
];
|
||||||
|
|
||||||
function _getCreateSql(CapacitorChannel $channel): string {
|
function _getCreateSql(CapacitorChannel $channel): string {
|
||||||
$query = new _query_base($this->_createSql($channel));
|
$query = new query($this->_createSql($channel));
|
||||||
return self::format_sql($channel, $query->getSql());
|
return self::format_sql($channel, $query->getSql());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_create;
|
|
||||||
use nulib\db\_private\Tcreate;
|
|
||||||
|
|
||||||
class _query_create extends _query_base {
|
|
||||||
use Tcreate;
|
|
||||||
const SCHEMA = _create::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_delete;
|
|
||||||
use nulib\db\_private\Tdelete;
|
|
||||||
|
|
||||||
class _query_delete extends _query_base {
|
|
||||||
use Tdelete;
|
|
||||||
const SCHEMA = _delete::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_generic;
|
|
||||||
use nulib\db\_private\Tgeneric;
|
|
||||||
|
|
||||||
class _query_generic extends _query_base {
|
|
||||||
use Tgeneric;
|
|
||||||
const SCHEMA = _generic::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_insert;
|
|
||||||
use nulib\db\_private\Tinsert;
|
|
||||||
|
|
||||||
class _query_insert extends _query_base {
|
|
||||||
use Tinsert;
|
|
||||||
const SCHEMA = _insert::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_select;
|
|
||||||
use nulib\db\_private\Tselect;
|
|
||||||
|
|
||||||
class _query_select extends _query_base {
|
|
||||||
use Tselect;
|
|
||||||
const SCHEMA = _select::SCHEMA;
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace nulib\db\sqlite;
|
|
||||||
|
|
||||||
use nulib\db\_private\_update;
|
|
||||||
use nulib\db\_private\Tupdate;
|
|
||||||
|
|
||||||
class _query_update extends _query_base {
|
|
||||||
use Tupdate;
|
|
||||||
const SCHEMA = _update::SCHEMA;
|
|
||||||
}
|
|
@ -2,32 +2,38 @@
|
|||||||
namespace nulib\db\sqlite;
|
namespace nulib\db\sqlite;
|
||||||
|
|
||||||
use nulib\db\_private\_base;
|
use nulib\db\_private\_base;
|
||||||
|
use nulib\db\_private\_create;
|
||||||
|
use nulib\db\_private\_delete;
|
||||||
|
use nulib\db\_private\_generic;
|
||||||
|
use nulib\db\_private\_insert;
|
||||||
|
use nulib\db\_private\_select;
|
||||||
|
use nulib\db\_private\_update;
|
||||||
use nulib\db\_private\Tbindings;
|
use nulib\db\_private\Tbindings;
|
||||||
use nulib\output\msg;
|
use nulib\output\msg;
|
||||||
use nulib\ValueException;
|
use nulib\ValueException;
|
||||||
use SQLite3;
|
use SQLite3;
|
||||||
use SQLite3Stmt;
|
use SQLite3Stmt;
|
||||||
|
|
||||||
class _query_base extends _base {
|
class query extends _base {
|
||||||
use Tbindings;
|
use Tbindings;
|
||||||
|
|
||||||
protected static function verifix(&$sql, ?array &$bindinds=null, ?array &$meta=null): void {
|
protected static function verifix(&$sql, ?array &$bindings=null, ?array &$meta=null): void {
|
||||||
if (is_array($sql)) {
|
if (is_array($sql)) {
|
||||||
$prefix = $sql[0] ?? null;
|
$prefix = $sql[0] ?? null;
|
||||||
if ($prefix === null) {
|
if ($prefix === null) {
|
||||||
throw new ValueException("requête invalide");
|
throw new ValueException("requête invalide");
|
||||||
} elseif (_query_create::isa($prefix)) {
|
} elseif (_create::isa($prefix)) {
|
||||||
$sql = _query_create::parse($sql, $bindinds);
|
$sql = _create::parse($sql, $bindings);
|
||||||
} elseif (_query_select::isa($prefix)) {
|
} elseif (_select::isa($prefix)) {
|
||||||
$sql = _query_select::parse($sql, $bindinds);
|
$sql = _select::parse($sql, $bindings);
|
||||||
} elseif (_query_insert::isa($prefix)) {
|
} elseif (_insert::isa($prefix)) {
|
||||||
$sql = _query_insert::parse($sql, $bindinds);
|
$sql = _insert::parse($sql, $bindings);
|
||||||
} elseif (_query_update::isa($prefix)) {
|
} elseif (_update::isa($prefix)) {
|
||||||
$sql = _query_update::parse($sql, $bindinds);
|
$sql = _update::parse($sql, $bindings);
|
||||||
} elseif (_query_delete::isa($prefix)) {
|
} elseif (_delete::isa($prefix)) {
|
||||||
$sql = _query_delete::parse($sql, $bindinds);
|
$sql = _delete::parse($sql, $bindings);
|
||||||
} elseif (_query_generic::isa($prefix)) {
|
} elseif (_generic::isa($prefix)) {
|
||||||
$sql = _query_generic::parse($sql, $bindinds);
|
$sql = _generic::parse($sql, $bindings);
|
||||||
} else {
|
} else {
|
||||||
throw SqliteException::wrap(ValueException::invalid_kind($sql, "query"));
|
throw SqliteException::wrap(ValueException::invalid_kind($sql, "query"));
|
||||||
}
|
}
|
@ -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_base::parse_conds(null, $sql, $params);
|
query::parse_conds(null, $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
_query_base::parse_conds([], $sql, $params);
|
query::parse_conds([], $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
_query_base::parse_conds(["col" => null], $sql, $params);
|
query::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_base::parse_conds(["col = 'value'"], $sql, $params);
|
query::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_base::parse_conds([["col = 'value'"]], $sql, $params);
|
query::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_base::parse_conds(["int" => 42, "string" => "value"], $sql, $params);
|
query::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_base::parse_conds(["or", "int" => 42, "string" => "value"], $sql, $params);
|
query::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_base::parse_conds([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
query::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_base::parse_conds(["int" => ["is null"], "string" => ["<>", "value"]], $sql, $params);
|
query::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_base::parse_conds(["col" => ["between", "lower", "upper"]], $sql, $params);
|
query::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_base::parse_conds(["col" => ["in", "one"]], $sql, $params);
|
query::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_base::parse_conds(["col" => ["in", ["one", "two"]]], $sql, $params);
|
query::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_base::parse_conds(["col" => ["=", ["one", "two"]]], $sql, $params);
|
query::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_base::parse_conds(["or", "col" => ["=", ["one", "two"]]], $sql, $params);
|
query::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_base::parse_conds(["col" => ["<>", ["one", "two"]]], $sql, $params);
|
query::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_base::parse_conds(["or", "col" => ["<>", ["one", "two"]]], $sql, $params);
|
query::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_base::parse_set_values(null, $sql, $params);
|
query::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_base::parse_set_values([], $sql, $params);
|
query::parse_set_values([], $sql, $params);
|
||||||
self::assertNull($sql);
|
self::assertNull($sql);
|
||||||
self::assertNull($params);
|
self::assertNull($params);
|
||||||
|
|
||||||
$sql = $params = null;
|
$sql = $params = null;
|
||||||
_query_base::parse_set_values(["col = 'value'"], $sql, $params);
|
query::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_base::parse_set_values([["col = 'value'"]], $sql, $params);
|
query::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_base::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
query::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_base::parse_set_values(["int" => 42, "string" => "value"], $sql, $params);
|
query::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_base::parse_set_values([["int" => 42, "string" => "value"], ["int" => 24, "string" => "eulav"]], $sql, $params);
|
query::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