Added more elegant method for statement caching.

This commit is contained in:
flash 2023-07-14 20:26:38 +00:00
parent 3e2183b7b2
commit 6d0d49171e
2 changed files with 90 additions and 100 deletions

40
src/DbStatementCache.php Normal file
View file

@ -0,0 +1,40 @@
<?php
namespace Misuzu;
use Index\Data\IDbConnection;
use Index\Data\IDbStatement;
class DbStatementCache {
private IDbConnection $dbConn;
private array $stmts = [];
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
}
private static function hash(string $query): string {
return hash('xxh3', $query, true);
}
public function get(string $query): IDbStatement {
$hash = self::hash($query);
if(array_key_exists($hash, $this->stmts)) {
$stmt = $this->stmts[$hash];
$stmt->reset();
return $stmt;
}
return $this->stmts[$hash] = $this->dbConn->prepare($query);
}
public function remove(string $query): void {
unset($this->stmts[self::hash($query)]);
}
public function clear(): void {
foreach($this->stmts as $stmt)
$stmt->close();
$this->stmts = [];
}
}

View file

@ -1,9 +1,10 @@
<?php
namespace Misuzu\Emoticons;
use InvalidArgumentException;
use RuntimeException;
use Index\Data\IDbConnection;
use Index\Data\IDbStatement;
use Misuzu\DbStatementCache;
class Emotes {
private const EMOTE_ORDER = [
@ -13,33 +14,19 @@ class Emotes {
];
private IDbConnection $dbConn;
private ?IDbStatement $getEmoteById = null;
private ?IDbStatement $checkEmoteUrl = null;
private ?IDbStatement $createEmote = null;
private ?IDbStatement $deleteEmote = null;
private ?IDbStatement $updateEmote = null;
private ?IDbStatement $updateEmoteOrderOffset = null;
private ?IDbStatement $getEmoteStrings = null;
private ?IDbStatement $checkEmoteString = null;
private ?IDbStatement $addEmoteString = null;
private ?IDbStatement $removeEmoteString = null;
private DbStatementCache $cache;
public function __construct(IDbConnection $dbConn) {
$this->dbConn = $dbConn;
$this->cache = new DbStatementCache($dbConn);
}
public function getEmoteById(string $emoteId, bool $withStrings = false): EmoteInfo {
if($this->getEmoteById === null)
$this->getEmoteById = $this->dbConn->prepare(
'SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_id = ?');
else
$this->getEmoteById->reset();
$stmt = $this->cache->get('SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_id = ?');
$stmt->addParameter(1, $emoteId);
$stmt->execute();
$this->getEmoteById->addParameter(1, $emoteId);
$this->getEmoteById->execute();
$result = $this->getEmoteById->getResult();
$result = $stmt->getResult();
if(!$result->next())
throw new RuntimeException('No emoticon with ID exists.');
@ -62,15 +49,15 @@ class Emotes {
if($minRank < 0) $minRank = PHP_INT_MAX;
$orderBy = self::EMOTE_ORDER[$orderBy] ?? self::EMOTE_ORDER[array_key_first(self::EMOTE_ORDER)];
$getAll = $this->dbConn->prepare(sprintf(
$stmt = $this->cache->get(sprintf(
'SELECT emote_id, emote_order, emote_hierarchy, emote_url FROM msz_emoticons WHERE emote_hierarchy <= ? ORDER BY %s %s',
$orderBy, ($desc ? 'DESC' : 'ASC')
));
$getAll->addParameter(1, $minRank);
$getAll->execute();
$stmt->addParameter(1, $minRank);
$stmt->execute();
$emotes = [];
$result = $getAll->getResult();
$result = $stmt->getResult();
if($withStrings) {
while($result->next())
@ -97,14 +84,10 @@ class Emotes {
if($check !== '')
return $check;
if($this->checkEmoteUrl === null)
$this->checkEmoteUrl = $this->dbConn->prepare('SELECT COUNT(*) FROM msz_emoticons WHERE emote_url = ?');
else
$this->checkEmoteUrl->reset();
$this->checkEmoteUrl->addParameter(1, $url);
$this->checkEmoteUrl->execute();
$result = $this->checkEmoteUrl->getResult();
$stmt = $this->cache->get('SELECT COUNT(*) FROM msz_emoticons WHERE emote_url = ?');
$stmt->addParameter(1, $url);
$stmt->execute();
$result = $stmt->getResult();
if($result->next() && $result->getInteger(0) > 0)
return 'used';
@ -117,15 +100,11 @@ class Emotes {
if($check !== '')
throw new InvalidArgumentException('$url is not correctly formatted: ' . $check);
if($this->createEmote === null)
$this->createEmote = $this->dbConn->prepare('INSERT INTO msz_emoticons (emote_url, emote_hierarchy, emote_order) SELECT ?, ?, COALESCE(?, (SELECT FLOOR(MAX(emote_order) / 10) * 10 + 10 FROM msz_emoticons), 10)');
else
$this->createEmote->reset();
$this->createEmote->addParameter(1, $url);
$this->createEmote->addParameter(2, $minRank);
$this->createEmote->addParameter(3, $order);
$this->createEmote->execute();
$stmt = $this->cache->get('INSERT INTO msz_emoticons (emote_url, emote_hierarchy, emote_order) SELECT ?, ?, COALESCE(?, (SELECT FLOOR(MAX(emote_order) / 10) * 10 + 10 FROM msz_emoticons), 10)');
$stmt->addParameter(1, $url);
$stmt->addParameter(2, $minRank);
$stmt->addParameter(3, $order);
$stmt->execute();
return $this->getEmoteById((string)$this->dbConn->getLastInsertId());
}
@ -134,13 +113,9 @@ class Emotes {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->deleteEmote === null)
$this->deleteEmote = $this->dbConn->prepare('DELETE FROM msz_emoticons WHERE emote_id = ?');
else
$this->deleteEmote->reset();
$this->deleteEmote->addParameter(1, $infoOrId);
$this->deleteEmote->execute();
$stmt = $this->cache->get('DELETE FROM msz_emoticons WHERE emote_id = ?');
$stmt->addParameter(1, $infoOrId);
$stmt->execute();
}
public function updateEmote(
@ -158,17 +133,12 @@ class Emotes {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->updateEmote === null)
$this->updateEmote = $this->dbConn->prepare(
'UPDATE msz_emoticons SET emote_order = COALESCE(?, emote_order), emote_hierarchy = COALESCE(?, emote_hierarchy), emote_url = COALESCE(?, emote_url) WHERE emote_id = ?');
else
$this->updateEmote->reset();
$this->updateEmote->addParameter(1, $order);
$this->updateEmote->addParameter(2, $minRank);
$this->updateEmote->addParameter(3, $url);
$this->updateEmote->addParameter(4, $infoOrId);
$this->updateEmote->execute();
$stmt = $this->cache->get('UPDATE msz_emoticons SET emote_order = COALESCE(?, emote_order), emote_hierarchy = COALESCE(?, emote_hierarchy), emote_url = COALESCE(?, emote_url) WHERE emote_id = ?');
$stmt->addParameter(1, $order);
$stmt->addParameter(2, $minRank);
$stmt->addParameter(3, $url);
$stmt->addParameter(4, $infoOrId);
$stmt->execute();
}
public function updateEmoteOrderOffset(EmoteInfo|string $infoOrId, int $offset): void {
@ -176,30 +146,22 @@ class Emotes {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->updateEmoteOrderOffset === null)
$this->updateEmoteOrderOffset = $this->dbConn->prepare('UPDATE msz_emoticons SET emote_order = emote_order + ? WHERE emote_id = ?');
else
$this->updateEmoteOrderOffset->reset();
$this->updateEmoteOrderOffset->addParameter(1, $offset);
$this->updateEmoteOrderOffset->addParameter(2, $infoOrId);
$this->updateEmoteOrderOffset->execute();
$stmt = $this->cache->get('UPDATE msz_emoticons SET emote_order = emote_order + ? WHERE emote_id = ?');
$stmt->addParameter(1, $offset);
$stmt->addParameter(2, $infoOrId);
$stmt->execute();
}
public function getEmoteStrings(EmoteInfo|string $infoOrId): array {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->getEmoteStrings === null)
$this->getEmoteStrings = $this->dbConn->prepare('SELECT emote_id, emote_string_order, emote_string FROM msz_emoticons_strings WHERE emote_id = ? ORDER BY emote_string_order');
else
$this->getEmoteStrings->reset();
$this->getEmoteStrings->addParameter(1, $infoOrId);
$this->getEmoteStrings->execute();
$stmt = $this->cache->get('SELECT emote_id, emote_string_order, emote_string FROM msz_emoticons_strings WHERE emote_id = ? ORDER BY emote_string_order');
$stmt->addParameter(1, $infoOrId);
$stmt->execute();
$strings = [];
$result = $this->getEmoteStrings->getResult();
$result = $stmt->getResult();
while($result->next())
$strings[] = new EmoteStringInfo($result);
@ -225,14 +187,10 @@ class Emotes {
if($check !== '')
return $check;
if($this->checkEmoteString === null)
$this->checkEmoteString = $this->dbConn->prepare('SELECT COUNT(*) FROM msz_emoticons_strings WHERE emote_string = ?');
else
$this->checkEmoteString->reset();
$this->checkEmoteString->addParameter(1, $string);
$this->checkEmoteString->execute();
$result = $this->checkEmoteString->getResult();
$stmt = $this->cache->get('SELECT COUNT(*) FROM msz_emoticons_strings WHERE emote_string = ?');
$stmt->addParameter(1, $string);
$stmt->execute();
$result = $stmt->getResult();
if($result->next() && $result->getInteger(0) > 0)
return 'used';
@ -248,27 +206,19 @@ class Emotes {
if($infoOrId instanceof EmoteInfo)
$infoOrId = $infoOrId->getId();
if($this->addEmoteString === null)
$this->addEmoteString = $this->dbConn->prepare('INSERT INTO msz_emoticons_strings (emote_id, emote_string, emote_string_order) SELECT ? AS target_emote_id, ?, COALESCE(?, (SELECT MAX(emote_string_order) + 1 FROM msz_emoticons_strings WHERE emote_id = target_emote_id), 1)');
else
$this->addEmoteString->reset();
$this->addEmoteString->addParameter(1, $infoOrId);
$this->addEmoteString->addParameter(2, $string);
$this->addEmoteString->addParameter(3, $order);
$this->addEmoteString->execute();
$stmt = $this->cache->get('INSERT INTO msz_emoticons_strings (emote_id, emote_string, emote_string_order) SELECT ? AS target_emote_id, ?, COALESCE(?, (SELECT MAX(emote_string_order) + 1 FROM msz_emoticons_strings WHERE emote_id = target_emote_id), 1)');
$stmt->addParameter(1, $infoOrId);
$stmt->addParameter(2, $string);
$stmt->addParameter(3, $order);
$stmt->execute();
}
public function removeEmoteString(EmoteStringInfo|string $infoOrString): void {
if($infoOrString instanceof EmoteStringInfo)
$infoOrString = $infoOrString->getString();
if($this->removeEmoteString === null)
$this->removeEmoteString = $this->dbConn->prepare('DELETE FROM msz_emoticons_strings WHERE emote_string = ?');
else
$this->removeEmoteString->reset();
$this->removeEmoteString->addParameter(1, $infoOrString);
$this->removeEmoteString->execute();
$stmt = $this->cache->get('DELETE FROM msz_emoticons_strings WHERE emote_string = ?');
$stmt->addParameter(1, $infoOrString);
$stmt->execute();
}
}