mirror of
https://github.com/danog/MadelineProto.git
synced 2024-11-30 10:59:02 +01:00
Optimize mysql usage. Remove prepare.
This commit is contained in:
parent
9094c19687
commit
7fe10430be
@ -15,7 +15,6 @@ use danog\MadelineProto\Settings\Database\Mysql as DatabaseMysql;
|
|||||||
class MysqlArray extends SqlArray
|
class MysqlArray extends SqlArray
|
||||||
{
|
{
|
||||||
protected DatabaseMysql $dbSettings;
|
protected DatabaseMysql $dbSettings;
|
||||||
private Pool $db;
|
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
protected array $settings;
|
protected array $settings;
|
||||||
@ -35,38 +34,36 @@ class MysqlArray extends SqlArray
|
|||||||
*
|
*
|
||||||
* @param SqlArray::STATEMENT_* $type
|
* @param SqlArray::STATEMENT_* $type
|
||||||
*
|
*
|
||||||
* @return Promise
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function prepareStatements(int $type): Promise
|
protected function getSqlQuery(int $type): string
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case SqlArray::STATEMENT_GET:
|
case SqlArray::SQL_GET:
|
||||||
return $this->db->prepare(
|
return "SELECT `value` FROM `{$this->table}` WHERE `key` = :index LIMIT 1";
|
||||||
"SELECT `value` FROM `{$this->table}` WHERE `key` = :index LIMIT 1"
|
case SqlArray::SQL_SET:
|
||||||
);
|
return "
|
||||||
case SqlArray::STATEMENT_SET:
|
INSERT INTO `{$this->table}`
|
||||||
return $this->db->prepare("
|
SET `key` = :index, `value` = :value
|
||||||
INSERT INTO `{$this->table}`
|
ON DUPLICATE KEY UPDATE `value` = :value
|
||||||
SET `key` = :index, `value` = :value
|
";
|
||||||
ON DUPLICATE KEY UPDATE `value` = :value
|
case SqlArray::SQL_UNSET:
|
||||||
");
|
return "
|
||||||
case SqlArray::STATEMENT_UNSET:
|
DELETE FROM `{$this->table}`
|
||||||
return $this->db->prepare("
|
WHERE `key` = :index
|
||||||
DELETE FROM `{$this->table}`
|
";
|
||||||
WHERE `key` = :index
|
case SqlArray::SQL_COUNT:
|
||||||
");
|
return "
|
||||||
case SqlArray::STATEMENT_COUNT:
|
SELECT count(`key`) as `count` FROM `{$this->table}`
|
||||||
return $this->db->prepare("
|
";
|
||||||
SELECT count(`key`) as `count` FROM `{$this->table}`
|
case SqlArray::SQL_ITERATE:
|
||||||
");
|
return "
|
||||||
case SqlArray::STATEMENT_ITERATE:
|
SELECT `key`, `value` FROM `{$this->table}`
|
||||||
return $this->db->prepare("
|
";
|
||||||
SELECT `key`, `value` FROM `{$this->table}`
|
case SqlArray::SQL_CLEAR:
|
||||||
");
|
return "
|
||||||
case SqlArray::STATEMENT_CLEAR:
|
DELETE FROM `{$this->table}`
|
||||||
return $this->db->prepare("
|
";
|
||||||
DELETE FROM `{$this->table}`
|
|
||||||
");
|
|
||||||
}
|
}
|
||||||
throw new Exception("An invalid statement type $type was provided!");
|
throw new Exception("An invalid statement type $type was provided!");
|
||||||
}
|
}
|
||||||
@ -97,6 +94,7 @@ class MysqlArray extends SqlArray
|
|||||||
*/
|
*/
|
||||||
public function initConnection($settings): \Generator
|
public function initConnection($settings): \Generator
|
||||||
{
|
{
|
||||||
|
$this->pdo = new \PDO('mysql:');
|
||||||
if (!isset($this->db)) {
|
if (!isset($this->db)) {
|
||||||
$this->db = yield from Mysql::getConnection($settings);
|
$this->db = yield from Mysql::getConnection($settings);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ use danog\MadelineProto\Settings\Database\Postgres as DatabasePostgres;
|
|||||||
class PostgresArray extends SqlArray
|
class PostgresArray extends SqlArray
|
||||||
{
|
{
|
||||||
public DatabasePostgres $dbSettings;
|
public DatabasePostgres $dbSettings;
|
||||||
private Pool $db;
|
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
protected array $settings;
|
protected array $settings;
|
||||||
@ -27,39 +26,37 @@ class PostgresArray extends SqlArray
|
|||||||
*
|
*
|
||||||
* @param SqlArray::STATEMENT_* $type
|
* @param SqlArray::STATEMENT_* $type
|
||||||
*
|
*
|
||||||
* @return Promise
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function prepareStatements(int $type): Promise
|
protected function getSqlQuery(int $type): string
|
||||||
{
|
{
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case SqlArray::STATEMENT_GET:
|
case SqlArray::SQL_GET:
|
||||||
return $this->db->prepare(
|
return "SELECT value FROM \"{$this->table}\" WHERE key = :index LIMIT 1";
|
||||||
"SELECT value FROM \"{$this->table}\" WHERE key = :index LIMIT 1",
|
case SqlArray::SQL_SET:
|
||||||
);
|
return "
|
||||||
case SqlArray::STATEMENT_SET:
|
|
||||||
return $this->db->prepare("
|
|
||||||
INSERT INTO \"{$this->table}\"
|
INSERT INTO \"{$this->table}\"
|
||||||
(key,value)
|
(key,value)
|
||||||
VALUES (:index, :value)
|
VALUES (:index, :value)
|
||||||
ON CONFLICT (key) DO UPDATE SET value = :value
|
ON CONFLICT (key) DO UPDATE SET value = :value
|
||||||
");
|
";
|
||||||
case SqlArray::STATEMENT_UNSET:
|
case SqlArray::SQL_UNSET:
|
||||||
return $this->db->prepare("
|
return "
|
||||||
DELETE FROM \"{$this->table}\"
|
DELETE FROM \"{$this->table}\"
|
||||||
WHERE key = :index
|
WHERE key = :index
|
||||||
");
|
";
|
||||||
case SqlArray::STATEMENT_COUNT:
|
case SqlArray::SQL_COUNT:
|
||||||
return $this->db->prepare("
|
return "
|
||||||
SELECT count(key) as count FROM \"{$this->table}\"
|
SELECT count(key) as count FROM \"{$this->table}\"
|
||||||
");
|
";
|
||||||
case SqlArray::STATEMENT_ITERATE:
|
case SqlArray::SQL_ITERATE:
|
||||||
return $this->db->prepare("
|
return "
|
||||||
SELECT key, value FROM \"{$this->table}\"
|
SELECT key, value FROM \"{$this->table}\"
|
||||||
");
|
";
|
||||||
case SqlArray::STATEMENT_CLEAR:
|
case SqlArray::SQL_CLEAR:
|
||||||
return $this->db->prepare("
|
return "
|
||||||
DELETE FROM \"{$this->table}\"
|
DELETE FROM \"{$this->table}\"
|
||||||
");
|
";
|
||||||
}
|
}
|
||||||
throw new Exception("An invalid statement type $type was provided!");
|
throw new Exception("An invalid statement type $type was provided!");
|
||||||
}
|
}
|
||||||
@ -81,6 +78,7 @@ class PostgresArray extends SqlArray
|
|||||||
*/
|
*/
|
||||||
public function initConnection($settings): \Generator
|
public function initConnection($settings): \Generator
|
||||||
{
|
{
|
||||||
|
$this->pdo = new \PDO('postgre:');
|
||||||
if (!isset($this->db)) {
|
if (!isset($this->db)) {
|
||||||
$this->db = yield from Postgres::getConnection($settings);
|
$this->db = yield from Postgres::getConnection($settings);
|
||||||
}
|
}
|
||||||
@ -130,7 +128,7 @@ class PostgresArray extends SqlArray
|
|||||||
$this->setCache($index, $value);
|
$this->setCache($index, $value);
|
||||||
|
|
||||||
$request = $this->execute(
|
$request = $this->execute(
|
||||||
self::STATEMENT_SET,
|
$this->getSqlQuery(self::SQL_SET),
|
||||||
[
|
[
|
||||||
'index' => $index,
|
'index' => $index,
|
||||||
'value' => new ByteA(\serialize($value)),
|
'value' => new ByteA(\serialize($value)),
|
||||||
|
@ -4,8 +4,9 @@ namespace danog\MadelineProto\Db;
|
|||||||
|
|
||||||
use Amp\Producer;
|
use Amp\Producer;
|
||||||
use Amp\Promise;
|
use Amp\Promise;
|
||||||
|
use Amp\Sql\CommandResult;
|
||||||
|
use Amp\Sql\Pool;
|
||||||
use Amp\Sql\ResultSet;
|
use Amp\Sql\ResultSet;
|
||||||
use Amp\Sql\Statement;
|
|
||||||
use Amp\Success;
|
use Amp\Success;
|
||||||
use danog\MadelineProto\Logger;
|
use danog\MadelineProto\Logger;
|
||||||
|
|
||||||
@ -16,19 +17,16 @@ use function Amp\call;
|
|||||||
*/
|
*/
|
||||||
abstract class SqlArray extends DriverArray
|
abstract class SqlArray extends DriverArray
|
||||||
{
|
{
|
||||||
/**
|
protected Pool $db;
|
||||||
* Statement array.
|
//Pdo driver used for value quoting, to prevent sql injections.
|
||||||
*
|
protected \PDO $pdo;
|
||||||
* @var Statement[]
|
|
||||||
*/
|
|
||||||
private array $statements = [];
|
|
||||||
|
|
||||||
protected const STATEMENT_GET = 0;
|
protected const SQL_GET = 0;
|
||||||
protected const STATEMENT_SET = 1;
|
protected const SQL_SET = 1;
|
||||||
protected const STATEMENT_UNSET = 2;
|
protected const SQL_UNSET = 2;
|
||||||
protected const STATEMENT_COUNT = 3;
|
protected const SQL_COUNT = 3;
|
||||||
protected const STATEMENT_ITERATE = 4;
|
protected const SQL_ITERATE = 4;
|
||||||
protected const STATEMENT_CLEAR = 5;
|
protected const SQL_CLEAR = 5;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +34,9 @@ abstract class SqlArray extends DriverArray
|
|||||||
*
|
*
|
||||||
* @param SqlArray::STATEMENT_* $type
|
* @param SqlArray::STATEMENT_* $type
|
||||||
*
|
*
|
||||||
* @return Promise
|
* @return string
|
||||||
*/
|
*/
|
||||||
abstract protected function prepareStatements(int $type): Promise;
|
abstract protected function getSqlQuery(int $type): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get value from row.
|
* Get value from row.
|
||||||
@ -51,11 +49,9 @@ abstract class SqlArray extends DriverArray
|
|||||||
|
|
||||||
public function getIterator(): Producer
|
public function getIterator(): Producer
|
||||||
{
|
{
|
||||||
|
debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
|
||||||
return new Producer(function (callable $emit) {
|
return new Producer(function (callable $emit) {
|
||||||
if (!isset($this->statements[self::STATEMENT_ITERATE])) {
|
$request = yield from $this->executeRaw($this->getSqlQuery(self::SQL_ITERATE));
|
||||||
$this->statements[self::STATEMENT_ITERATE] = yield $this->prepareStatements(self::STATEMENT_ITERATE);
|
|
||||||
}
|
|
||||||
$request = yield $this->statements[self::STATEMENT_ITERATE]->execute();
|
|
||||||
|
|
||||||
while (yield $request->advance()) {
|
while (yield $request->advance()) {
|
||||||
$row = $request->getCurrent();
|
$row = $request->getCurrent();
|
||||||
@ -106,7 +102,7 @@ abstract class SqlArray extends DriverArray
|
|||||||
$this->unsetCache($index);
|
$this->unsetCache($index);
|
||||||
|
|
||||||
return $this->execute(
|
return $this->execute(
|
||||||
self::STATEMENT_UNSET,
|
$this->getSqlQuery(self::SQL_UNSET),
|
||||||
['index' => $index]
|
['index' => $index]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -122,7 +118,7 @@ abstract class SqlArray extends DriverArray
|
|||||||
public function count(): Promise
|
public function count(): Promise
|
||||||
{
|
{
|
||||||
return call(function () {
|
return call(function () {
|
||||||
$row = yield $this->execute(self::STATEMENT_COUNT);
|
$row = yield $this->execute($this->getSqlQuery(self::SQL_COUNT));
|
||||||
return $row[0]['count'] ?? 0;
|
return $row[0]['count'] ?? 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,7 +130,7 @@ abstract class SqlArray extends DriverArray
|
|||||||
*/
|
*/
|
||||||
public function clear(): Promise
|
public function clear(): Promise
|
||||||
{
|
{
|
||||||
return $this->execute(self::STATEMENT_CLEAR);
|
return $this->execute($this->getSqlQuery(self::SQL_CLEAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function offsetGet($offset): Promise
|
public function offsetGet($offset): Promise
|
||||||
@ -144,7 +140,7 @@ abstract class SqlArray extends DriverArray
|
|||||||
return $cached;
|
return $cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = yield $this->execute(self::STATEMENT_GET, ['index' => $offset]);
|
$row = yield $this->execute($this->getSqlQuery(self::SQL_GET), ['index' => $offset]);
|
||||||
|
|
||||||
if ($value = $this->getValue($row)) {
|
if ($value = $this->getValue($row)) {
|
||||||
$this->setCache($offset, $value);
|
$this->setCache($offset, $value);
|
||||||
@ -176,7 +172,7 @@ abstract class SqlArray extends DriverArray
|
|||||||
$this->setCache($index, $value);
|
$this->setCache($index, $value);
|
||||||
|
|
||||||
$request = $this->execute(
|
$request = $this->execute(
|
||||||
self::STATEMENT_SET,
|
$this->getSqlQuery(self::SQL_SET),
|
||||||
[
|
[
|
||||||
'index' => $index,
|
'index' => $index,
|
||||||
'value' => \serialize($value),
|
'value' => \serialize($value),
|
||||||
@ -192,34 +188,18 @@ abstract class SqlArray extends DriverArray
|
|||||||
/**
|
/**
|
||||||
* Perform async request to db.
|
* Perform async request to db.
|
||||||
*
|
*
|
||||||
* @param int $stmt
|
* @param string $sql
|
||||||
* @param array $params
|
* @param array $params
|
||||||
*
|
*
|
||||||
* @psalm-param self::STATEMENT_* $stmt
|
* @psalm-param self::STATEMENT_* $stmt
|
||||||
*
|
*
|
||||||
* @return Promise
|
* @return Promise<array>
|
||||||
* @throws \Throwable
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
protected function execute(int $stmt, array $params = []): Promise
|
protected function execute(string $sql, array $params = []): Promise
|
||||||
{
|
{
|
||||||
return call(function () use ($stmt, $params) {
|
return call(function () use ($sql, $params) {
|
||||||
if (
|
$request = yield from $this->executeRaw($sql, $params);
|
||||||
!empty($params['index'])
|
|
||||||
&& !\mb_check_encoding($params['index'], 'UTF-8')
|
|
||||||
) {
|
|
||||||
$params['index'] = \mb_convert_encoding($params['index'], 'UTF-8');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($this->statements[$stmt])) {
|
|
||||||
$this->statements[$stmt] = yield $this->prepareStatements($stmt);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$request = yield $this->statements[$stmt]->execute($params);
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
Logger::log($e->getMessage(), Logger::ERROR);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$result = [];
|
$result = [];
|
||||||
if ($request instanceof ResultSet) {
|
if ($request instanceof ResultSet) {
|
||||||
while (yield $request->advance()) {
|
while (yield $request->advance()) {
|
||||||
@ -229,4 +209,37 @@ abstract class SqlArray extends DriverArray
|
|||||||
return $result;
|
return $result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return raw query result.
|
||||||
|
*
|
||||||
|
* @param string $sql
|
||||||
|
* @param array $params
|
||||||
|
*
|
||||||
|
* @return \Generator<CommandResult|ResultSet>
|
||||||
|
*/
|
||||||
|
protected function executeRaw(string $sql, array $params = []): \Generator
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
!empty($params['index'])
|
||||||
|
&& !\mb_check_encoding($params['index'], 'UTF-8')
|
||||||
|
) {
|
||||||
|
$params['index'] = \mb_convert_encoding($params['index'], 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
$value = $this->pdo->quote($value);
|
||||||
|
$sql = str_replace(":$key", $value, $sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = yield $this->db->query($sql);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Logger::log($e->getMessage(), Logger::ERROR);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user