début pgsql

This commit is contained in:
Jephté Clain 2025-04-10 14:33:24 +04:00
parent ecd01777c1
commit bab9ba81fe
11 changed files with 226 additions and 44 deletions

View File

@ -25,6 +25,7 @@
"ext-pcntl": "*", "ext-pcntl": "*",
"ext-curl": "*", "ext-curl": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-pgsql": "*",
"ext-sqlite3": "*" "ext-sqlite3": "*"
}, },
"autoload": { "autoload": {

View File

@ -3,7 +3,6 @@ namespace nulib;
use ArrayAccess; use ArrayAccess;
use nulib\php\func; use nulib\php\func;
use nulib\php\nur_func;
use Traversable; use Traversable;
/** /**

View File

@ -11,12 +11,13 @@ interface ITransactor {
*/ */
function willUpdate(...$transactors): self; function willUpdate(...$transactors): self;
/** Indiquer si une transaction est en cours */
function inTransaction(): bool; function inTransaction(): bool;
/** /**
* démarrer une transaction * démarrer une transaction
* *
* si $func!==null, l'apppeler. ensuite, si $commit===true, commiter la * si $func!==null, l'apppeler. ensuite, si $commit===true, valider la
* transaction. si une erreur se produit lors de l'appel de la fonction, * transaction. si une erreur se produit lors de l'appel de la fonction,
* annuler la transaction * annuler la transaction
* *
@ -24,7 +25,9 @@ interface ITransactor {
*/ */
function beginTransaction(?callable $func=null, bool $commit=true): void; function beginTransaction(?callable $func=null, bool $commit=true): void;
/** valider la transaction */
function commit(): void; function commit(): void;
/** annuler la transaction */
function rollback(): void; function rollback(): void;
} }

View File

@ -1,6 +1,7 @@
<?php <?php
namespace nulib\db\pdo; namespace nulib\db\_private;
use nulib\db\IDatabase;
use nulib\php\func; use nulib\php\func;
class _config { class _config {
@ -23,12 +24,12 @@ class _config {
/** @var array */ /** @var array */
protected $configs; protected $configs;
function configure(Pdo $pdo): void { function configure(IDatabase $db): void {
foreach ($this->configs as $key => $config) { foreach ($this->configs as $key => $config) {
if (is_string($config) && !func::is_method($config)) { if (is_string($config) && !func::is_method($config)) {
$pdo->exec($config); $db->exec($config);
} else { } else {
func::with($config)->bind($this, true)->invoke([$pdo, $key]); func::with($config)->bind($this, true)->invoke([$db, $key]);
} }
} }
} }

View File

@ -3,6 +3,7 @@ namespace nulib\db\pdo;
use Generator; use Generator;
use nulib\cl; use nulib\cl;
use nulib\db\_private\_config;
use nulib\db\_private\Tvalues; use nulib\db\_private\Tvalues;
use nulib\db\IDatabase; use nulib\db\IDatabase;
use nulib\db\ITransactor; use nulib\db\ITransactor;
@ -104,7 +105,7 @@ class Pdo implements IDatabase {
protected ?array $dbconn; protected ?array $dbconn;
/** @var array|callable */ /** @var array|callable */
protected array $options; protected $options;
/** @var array|string|callable */ /** @var array|string|callable */
protected $config; protected $config;

201
php/src/db/pgsql/Pgsql.php Normal file
View File

@ -0,0 +1,201 @@
<?php
namespace nulib\db\pgsql;
use nulib\cl;
use nulib\db\_private\_config;
use nulib\db\_private\Tvalues;
use nulib\db\IDatabase;
use nulib\db\ITransactor;
use nulib\php\func;
class Pgsql implements IDatabase {
use Tvalues;
static function with($pgsql, ?array $params=null): self {
if ($pgsql instanceof static) {
return $pgsql;
} elseif ($pgsql instanceof self) {
# recréer avec les mêmes paramètres
return new static(null, cl::merge([
"dbconn" => $pgsql->dbconn,
"options" => $pgsql->options,
"config" => $pgsql->config,
"migrate" => $pgsql->migration,
], $params));
} else {
return new static($pgsql, $params);
}
}
protected const OPTIONS = [
"persistent" => true,
"force_new" => false,
];
const CONFIG = null;
const MIGRATE = null;
const params_SCHEMA = [
"dbconn" => ["array"],
"options" => ["?array|callable"],
"replace_config" => ["?array|callable"],
"config" => ["?array|callable"],
"migrate" => ["?array|string|callable"],
"auto_open" => ["bool", true],
];
const dbconn_SCHEMA = [
"" => "?string",
"host" => "string",
"hostaddr" => "?string",
"port" => "?int",
"dbname" => "string",
"user" => "string",
"password" => "string",
"connect_timeout" => "?int",
"options" => "?string",
"sslmode" => "?string",
"service" => "?string",
];
protected const dbconn_MAP = [
"name" => "dbname",
"pass" => "password",
];
const options_SCHEMA = [
"persistent" => ["bool", self::OPTIONS["persistent"]],
"force_new" => ["bool", self::OPTIONS["force_new"]],
];
function __construct($dbconn=null, ?array $params=null) {
if ($dbconn !== null) {
if (!is_array($dbconn)) {
$dbconn = ["" => $dbconn];
#XXX à terme, il faudra interroger config
#$tmp = config::db($dbconn);
#if ($tmp !== null) $dbconn = $tmp;
#else $dbconn = ["" => $dbconn];
}
$params["dbconn"] = $dbconn;
}
# dbconn
$this->dbconn = $params["dbconn"] ?? null;
# options
$this->options = $params["options"] ?? static::OPTIONS;
# configuration
$config = $params["replace_config"] ?? null;
if ($config === null) {
$config = $params["config"] ?? static::CONFIG;
if (is_callable($config)) $config = [$config];
}
$this->config = $config;
# migrations
$this->migration = $params["migrate"] ?? static::MIGRATE;
#
$defaultAutoOpen = self::params_SCHEMA["auto_open"][1];
if ($params["auto_open"] ?? $defaultAutoOpen) {
$this->open();
}
}
protected ?array $dbconn;
/** @var array|callable|null */
protected $options;
/** @var array|string|callable */
protected $config;
/** @var array|string|callable */
protected $migration;
/** @var resource */
protected $db = null;
function open(): self {
if ($this->db === null) {
$dbconn = $this->dbconn;
$connection_string = [$dbconn[""] ?? null];
unset($dbconn[""]);
foreach ($dbconn as $key => $value) {
if ($value === null) continue;
$value = strval($value);
if ($value === "" || preg_match("/[ '\\\\]/", $value)) {
$value = str_replace("\\", "\\\\", $value);
$value = str_replace("'", "\\'", $value);
$value = "'$value'";
}
$key = cl::get(self::dbconn_MAP, $key, $key);
$connection_string[] = "$key=$value";
}
$connection_string = implode(" ", array_filter($connection_string));
$options = $this->options;
if (is_callable($options)) {
$options = func::with($options)->bind($this, true)->invoke();
}
$forceNew = $options["force_new"] ?? false;
$flags = $forceNew? PGSQL_CONNECT_FORCE_NEW: 0;
if ($options["persistent"] ?? true) $db = pg_pconnect($connection_string, $flags);
else $db = pg_connect($connection_string, $flags);
if ($db === false) throw new PgsqlException("unable to connect");
$this->db = $db;
_config::with($this->config)->configure($this);
//_migration::with($this->migration)->migrate($this);
}
return $this;
}
function close(): self {
if ($this->db !== null) {
pg_close($this->db);
$this->db = null;
}
return $this;
}
protected function db() {
$this->open();
return $this->db;
}
function exec($query, ?array $params = null) {
// TODO: Implement exec() method.
}
function willUpdate(...$transactors): \nulib\db\ITransactor {
// TODO: Implement willUpdate() method.
}
function inTransaction(): bool {
// TODO: Implement inTransaction() method.
}
function beginTransaction(?callable $func = null, bool $commit = true): void {
// TODO: Implement beginTransaction() method.
}
function commit(): void {
// TODO: Implement commit() method.
}
function rollback(): void {
// TODO: Implement rollback() method.
}
function get($query, ?array $params = null, bool $entireRow = false) {
// TODO: Implement get() method.
}
function one($query, ?array $params = null): ?array {
// TODO: Implement one() method.
}
function all($query, ?array $params = null, $primaryKeys = null): iterable {
// TODO: Implement all() method.
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace nulib\db\pgsql;
use Exception;
use RuntimeException;
use SQLite3;
class PgsqlException extends RuntimeException {
static final function wrap(Exception $e): self {
return new static($e->getMessage(), $e->getCode(), $e);
}
}

View File

@ -3,6 +3,7 @@ namespace nulib\db\sqlite;
use Generator; use Generator;
use nulib\cl; use nulib\cl;
use nulib\db\_private\_config;
use nulib\db\_private\Tvalues; use nulib\db\_private\Tvalues;
use nulib\db\IDatabase; use nulib\db\IDatabase;
use nulib\db\ITransactor; use nulib\db\ITransactor;

View File

@ -1,35 +0,0 @@
<?php
namespace nulib\db\sqlite;
use nulib\php\func;
class _config {
static function with($configs): self {
if ($configs instanceof static) return $configs;
return new static($configs);
}
const CONFIG = null;
function __construct($configs) {
if ($configs === null) $configs = static::CONFIG;
if ($configs === null) $configs = [];
elseif (is_string($configs)) $configs = [$configs];
elseif (is_callable($configs)) $configs = [$configs];
elseif (!is_array($configs)) $configs = [strval($configs)];
$this->configs = $configs;
}
/** @var array */
protected $configs;
function configure(Sqlite $sqlite): void {
foreach ($this->configs as $key => $config) {
if (is_string($config) && !func::is_method($config)) {
$sqlite->exec($config);
} else {
func::with($config)->bind($this, true)->invoke([$sqlite, $key]);
}
}
}
}

View File

@ -2,7 +2,6 @@
namespace nulib\db\sqlite; namespace nulib\db\sqlite;
use nulib\php\func; use nulib\php\func;
use nulib\php\nur_func;
class _migration { class _migration {
static function with($migrations): self { static function with($migrations): self {

View File

@ -6,7 +6,6 @@ use nulib\cl;
use nulib\file\TempStream; use nulib\file\TempStream;
use nulib\os\path; use nulib\os\path;
use nulib\php\func; use nulib\php\func;
use nulib\php\nur_func;
use nulib\php\time\DateTime; use nulib\php\time\DateTime;
use nulib\web\http; use nulib\web\http;