From bab9ba81fe90b393150d004a6fb7e2252fda00e5 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 10 Apr 2025 14:33:24 +0400 Subject: [PATCH] =?UTF-8?q?d=C3=A9but=20pgsql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 1 + php/src/cl.php | 1 - php/src/db/ITransactor.php | 5 +- php/src/db/{pdo => _private}/_config.php | 9 +- php/src/db/pdo/Pdo.php | 3 +- php/src/db/pgsql/Pgsql.php | 201 +++++++++++++++++++++++ php/src/db/pgsql/PgsqlException.php | 12 ++ php/src/db/sqlite/Sqlite.php | 1 + php/src/db/sqlite/_config.php | 35 ---- php/src/db/sqlite/_migration.php | 1 - php/src/file/tab/AbstractBuilder.php | 1 - 11 files changed, 226 insertions(+), 44 deletions(-) rename php/src/db/{pdo => _private}/_config.php (79%) create mode 100644 php/src/db/pgsql/Pgsql.php create mode 100644 php/src/db/pgsql/PgsqlException.php delete mode 100644 php/src/db/sqlite/_config.php diff --git a/composer.json b/composer.json index 346a248..f423241 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ "ext-pcntl": "*", "ext-curl": "*", "ext-pdo": "*", + "ext-pgsql": "*", "ext-sqlite3": "*" }, "autoload": { diff --git a/php/src/cl.php b/php/src/cl.php index c0e64e8..4978afe 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -3,7 +3,6 @@ namespace nulib; use ArrayAccess; use nulib\php\func; -use nulib\php\nur_func; use Traversable; /** diff --git a/php/src/db/ITransactor.php b/php/src/db/ITransactor.php index 3738bb7..03dd549 100644 --- a/php/src/db/ITransactor.php +++ b/php/src/db/ITransactor.php @@ -11,12 +11,13 @@ interface ITransactor { */ function willUpdate(...$transactors): self; + /** Indiquer si une transaction est en cours */ function inTransaction(): bool; /** * 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, * annuler la transaction * @@ -24,7 +25,9 @@ interface ITransactor { */ function beginTransaction(?callable $func=null, bool $commit=true): void; + /** valider la transaction */ function commit(): void; + /** annuler la transaction */ function rollback(): void; } diff --git a/php/src/db/pdo/_config.php b/php/src/db/_private/_config.php similarity index 79% rename from php/src/db/pdo/_config.php rename to php/src/db/_private/_config.php index 2cc9c96..e72b526 100644 --- a/php/src/db/pdo/_config.php +++ b/php/src/db/_private/_config.php @@ -1,6 +1,7 @@ configs as $key => $config) { if (is_string($config) && !func::is_method($config)) { - $pdo->exec($config); + $db->exec($config); } else { - func::with($config)->bind($this, true)->invoke([$pdo, $key]); + func::with($config)->bind($this, true)->invoke([$db, $key]); } } } diff --git a/php/src/db/pdo/Pdo.php b/php/src/db/pdo/Pdo.php index 2fa8bf0..fb8b9b8 100644 --- a/php/src/db/pdo/Pdo.php +++ b/php/src/db/pdo/Pdo.php @@ -3,6 +3,7 @@ namespace nulib\db\pdo; use Generator; use nulib\cl; +use nulib\db\_private\_config; use nulib\db\_private\Tvalues; use nulib\db\IDatabase; use nulib\db\ITransactor; @@ -104,7 +105,7 @@ class Pdo implements IDatabase { protected ?array $dbconn; /** @var array|callable */ - protected array $options; + protected $options; /** @var array|string|callable */ protected $config; diff --git a/php/src/db/pgsql/Pgsql.php b/php/src/db/pgsql/Pgsql.php new file mode 100644 index 0000000..7484cd8 --- /dev/null +++ b/php/src/db/pgsql/Pgsql.php @@ -0,0 +1,201 @@ + $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. + } +} diff --git a/php/src/db/pgsql/PgsqlException.php b/php/src/db/pgsql/PgsqlException.php new file mode 100644 index 0000000..056bf41 --- /dev/null +++ b/php/src/db/pgsql/PgsqlException.php @@ -0,0 +1,12 @@ +getMessage(), $e->getCode(), $e); + } +} diff --git a/php/src/db/sqlite/Sqlite.php b/php/src/db/sqlite/Sqlite.php index 89db30b..b797eb9 100644 --- a/php/src/db/sqlite/Sqlite.php +++ b/php/src/db/sqlite/Sqlite.php @@ -3,6 +3,7 @@ namespace nulib\db\sqlite; use Generator; use nulib\cl; +use nulib\db\_private\_config; use nulib\db\_private\Tvalues; use nulib\db\IDatabase; use nulib\db\ITransactor; diff --git a/php/src/db/sqlite/_config.php b/php/src/db/sqlite/_config.php deleted file mode 100644 index bcfe8fb..0000000 --- a/php/src/db/sqlite/_config.php +++ /dev/null @@ -1,35 +0,0 @@ -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]); - } - } - } -} diff --git a/php/src/db/sqlite/_migration.php b/php/src/db/sqlite/_migration.php index b5ee6f4..cafb991 100644 --- a/php/src/db/sqlite/_migration.php +++ b/php/src/db/sqlite/_migration.php @@ -2,7 +2,6 @@ namespace nulib\db\sqlite; use nulib\php\func; -use nulib\php\nur_func; class _migration { static function with($migrations): self { diff --git a/php/src/file/tab/AbstractBuilder.php b/php/src/file/tab/AbstractBuilder.php index 77d61b7..23ab27a 100644 --- a/php/src/file/tab/AbstractBuilder.php +++ b/php/src/file/tab/AbstractBuilder.php @@ -6,7 +6,6 @@ use nulib\cl; use nulib\file\TempStream; use nulib\os\path; use nulib\php\func; -use nulib\php\nur_func; use nulib\php\time\DateTime; use nulib\web\http;