2022-12-30 21:54:44 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2020-07-30 19:51:16 +02:00
|
|
|
|
|
|
|
namespace danog\MadelineProto\Db;
|
|
|
|
|
2023-05-02 18:42:46 +02:00
|
|
|
use Amp\Postgres\ByteA;
|
2023-01-11 21:06:10 +01:00
|
|
|
use Amp\Postgres\PostgresConfig;
|
2020-09-12 17:12:23 +02:00
|
|
|
use danog\MadelineProto\Db\Driver\Postgres;
|
2020-11-26 21:49:31 +01:00
|
|
|
use danog\MadelineProto\Exception;
|
2020-07-30 19:51:16 +02:00
|
|
|
use danog\MadelineProto\Logger;
|
2020-09-22 11:48:12 +02:00
|
|
|
use danog\MadelineProto\Settings\Database\Postgres as DatabasePostgres;
|
2023-05-02 18:42:46 +02:00
|
|
|
use danog\MadelineProto\Settings\Database\SerializerType;
|
2022-12-30 19:21:36 +01:00
|
|
|
use PDO;
|
2020-09-22 11:48:12 +02:00
|
|
|
|
2020-10-07 19:31:52 +02:00
|
|
|
/**
|
|
|
|
* Postgres database backend.
|
2023-01-25 16:32:48 +01:00
|
|
|
*
|
|
|
|
* @internal
|
|
|
|
* @template TKey as array-key
|
|
|
|
* @template TValue
|
2023-01-25 16:37:15 +01:00
|
|
|
* @extends SqlArray<TKey, TValue>
|
2020-10-07 19:31:52 +02:00
|
|
|
*/
|
2020-09-12 17:12:23 +02:00
|
|
|
class PostgresArray extends SqlArray
|
2020-07-30 19:51:16 +02:00
|
|
|
{
|
2020-09-22 11:48:12 +02:00
|
|
|
// Legacy
|
|
|
|
protected array $settings;
|
|
|
|
|
2020-10-04 16:27:22 +02:00
|
|
|
/**
|
2020-10-23 00:14:40 +02:00
|
|
|
* Prepare statements.
|
2020-10-04 16:27:22 +02:00
|
|
|
*
|
2023-01-14 19:18:23 +01:00
|
|
|
* @param SqlArray::SQL_* $type
|
2020-10-04 16:27:22 +02:00
|
|
|
*/
|
2021-02-27 20:58:01 +01:00
|
|
|
protected function getSqlQuery(int $type): string
|
2020-10-04 16:27:22 +02:00
|
|
|
{
|
2020-11-26 21:49:31 +01:00
|
|
|
switch ($type) {
|
2022-12-08 20:16:40 +01:00
|
|
|
case SqlArray::SQL_GET:
|
|
|
|
return "SELECT value FROM \"{$this->table}\" WHERE key = :index";
|
|
|
|
case SqlArray::SQL_SET:
|
|
|
|
return "
|
2020-11-26 21:49:31 +01:00
|
|
|
INSERT INTO \"{$this->table}\"
|
|
|
|
(key,value)
|
|
|
|
VALUES (:index, :value)
|
|
|
|
ON CONFLICT (key) DO UPDATE SET value = :value
|
2021-02-27 20:58:01 +01:00
|
|
|
";
|
2022-12-08 20:16:40 +01:00
|
|
|
case SqlArray::SQL_UNSET:
|
|
|
|
return "
|
2020-11-26 21:49:31 +01:00
|
|
|
DELETE FROM \"{$this->table}\"
|
|
|
|
WHERE key = :index
|
2021-02-27 20:58:01 +01:00
|
|
|
";
|
2022-12-08 20:16:40 +01:00
|
|
|
case SqlArray::SQL_COUNT:
|
|
|
|
return "
|
2020-11-26 21:49:31 +01:00
|
|
|
SELECT count(key) as count FROM \"{$this->table}\"
|
2021-02-27 20:58:01 +01:00
|
|
|
";
|
2022-12-08 20:16:40 +01:00
|
|
|
case SqlArray::SQL_ITERATE:
|
|
|
|
return "
|
2020-11-26 21:49:31 +01:00
|
|
|
SELECT key, value FROM \"{$this->table}\"
|
2021-02-27 20:58:01 +01:00
|
|
|
";
|
2022-12-08 20:16:40 +01:00
|
|
|
case SqlArray::SQL_CLEAR:
|
|
|
|
return "
|
2020-11-26 21:49:31 +01:00
|
|
|
DELETE FROM \"{$this->table}\"
|
2021-02-27 20:58:01 +01:00
|
|
|
";
|
2020-11-26 21:49:31 +01:00
|
|
|
}
|
|
|
|
throw new Exception("An invalid statement type $type was provided!");
|
2020-10-04 16:27:22 +02:00
|
|
|
}
|
2020-10-23 00:14:40 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize on startup.
|
|
|
|
*/
|
2023-01-03 22:07:58 +01:00
|
|
|
public function initStartup(): void
|
2020-10-04 16:27:22 +02:00
|
|
|
{
|
2022-06-25 19:15:30 +02:00
|
|
|
$this->setTable($this->table);
|
2022-12-30 22:31:20 +01:00
|
|
|
$this->initConnection($this->dbSettings);
|
2020-10-04 16:27:22 +02:00
|
|
|
}
|
2020-09-22 11:48:12 +02:00
|
|
|
/**
|
|
|
|
* Initialize connection.
|
|
|
|
*/
|
2023-01-03 22:07:58 +01:00
|
|
|
public function initConnection(DatabasePostgres $settings): void
|
2020-09-12 19:06:42 +02:00
|
|
|
{
|
2023-01-11 21:06:10 +01:00
|
|
|
$config = PostgresConfig::fromString('host='.\str_replace('tcp://', '', $settings->getUri()));
|
2021-04-07 00:13:59 +02:00
|
|
|
$host = $config->getHost();
|
|
|
|
$port = $config->getPort();
|
2022-12-30 19:21:36 +01:00
|
|
|
$this->pdo = new PDO(
|
2021-04-25 16:50:19 +02:00
|
|
|
"pgsql:host={$host};port={$port}",
|
2021-02-27 22:24:55 +01:00
|
|
|
$settings->getUsername(),
|
2022-12-30 19:21:36 +01:00
|
|
|
$settings->getPassword(),
|
2021-02-27 22:24:55 +01:00
|
|
|
);
|
2020-09-12 19:06:42 +02:00
|
|
|
if (!isset($this->db)) {
|
2022-12-30 22:31:20 +01:00
|
|
|
$this->db = Postgres::getConnection($settings);
|
2020-09-12 19:06:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-02 18:42:46 +02:00
|
|
|
protected function setSerializer(SerializerType $serializer): void
|
2020-10-23 00:14:40 +02:00
|
|
|
{
|
2023-05-02 18:42:46 +02:00
|
|
|
$this->serializer = match ($serializer) {
|
|
|
|
SerializerType::SERIALIZE => fn ($v) => new ByteA(\serialize($v)),
|
|
|
|
SerializerType::IGBINARY => fn ($v) => new ByteA(\igbinary_serialize($v)),
|
|
|
|
SerializerType::JSON => fn ($value) => \json_encode($value, JSON_THROW_ON_ERROR|JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),
|
|
|
|
SerializerType::STRING => strval(...),
|
|
|
|
};
|
|
|
|
$this->deserializer = match ($serializer) {
|
|
|
|
SerializerType::SERIALIZE => \unserialize(...),
|
|
|
|
SerializerType::IGBINARY => \igbinary_unserialize(...),
|
|
|
|
SerializerType::JSON => fn ($value) => \json_decode($value, true, 256, JSON_THROW_ON_ERROR),
|
|
|
|
SerializerType::STRING => fn ($v) => $v,
|
|
|
|
};
|
2020-10-23 00:14:40 +02:00
|
|
|
}
|
2020-07-30 19:51:16 +02:00
|
|
|
/**
|
|
|
|
* Create table for property.
|
|
|
|
*/
|
2023-01-03 22:07:58 +01:00
|
|
|
protected function prepareTable(): void
|
2020-07-30 19:51:16 +02:00
|
|
|
{
|
|
|
|
Logger::log("Creating/checking table {$this->table}", Logger::WARNING);
|
2020-08-27 18:04:55 +02:00
|
|
|
|
2022-12-30 22:31:20 +01:00
|
|
|
$this->db->query("
|
2020-07-30 19:51:16 +02:00
|
|
|
CREATE TABLE IF NOT EXISTS \"{$this->table}\"
|
|
|
|
(
|
2022-06-25 19:15:30 +02:00
|
|
|
\"key\" VARCHAR(255) PRIMARY KEY NOT NULL,
|
2023-05-02 18:42:46 +02:00
|
|
|
\"value\" BYTEA NOT NULL
|
2020-10-23 00:14:40 +02:00
|
|
|
);
|
2020-07-30 19:51:16 +02:00
|
|
|
");
|
|
|
|
}
|
|
|
|
|
2023-01-03 22:07:58 +01:00
|
|
|
protected function renameTable(string $from, string $to): void
|
2020-07-30 19:51:16 +02:00
|
|
|
{
|
2021-03-04 20:09:21 +01:00
|
|
|
Logger::log("Moving data from {$from} to {$to}", Logger::WARNING);
|
2020-10-23 18:19:20 +02:00
|
|
|
|
2022-12-30 22:31:20 +01:00
|
|
|
$this->db->query(/** @lang PostgreSQL */ "
|
2022-06-25 19:29:01 +02:00
|
|
|
ALTER TABLE \"$from\" RENAME TO \"$to\";
|
2020-07-30 19:51:16 +02:00
|
|
|
");
|
|
|
|
}
|
2020-08-27 18:04:55 +02:00
|
|
|
}
|