72 lines
2.0 KiB
PHP
72 lines
2.0 KiB
PHP
<?php
|
|
|
|
/**
|
|
* An extension to the SQLite3 class to add our own logging and binding semantics!
|
|
*/
|
|
class Database extends SQLite3
|
|
{
|
|
public int $count = 0;
|
|
public array $log = [];
|
|
public float $query_time = 0;
|
|
|
|
public function __construct(string $db_path)
|
|
{
|
|
parent::__construct($db_path);
|
|
|
|
parent::exec('PRAGMA cache_size = 32000');
|
|
parent::exec('PRAGMA journal_mode = WAL');
|
|
parent::exec('PRAGMA temp_store = MEMORY');
|
|
}
|
|
|
|
public function query(string $query, array $params = []): SQLite3Result|false
|
|
{
|
|
$p = strpos($query, '?') !== false;
|
|
$stmt = $this->prepare($query);
|
|
|
|
foreach ($params ?? [] as $k => $v) $stmt->bindValue($p ? $k + 1 : $k, $v, $this->getSQLiteType($v));
|
|
|
|
$start = microtime(true);
|
|
$r = $stmt->execute();
|
|
$this->log($query, microtime(true) - $start);
|
|
|
|
return $r;
|
|
}
|
|
|
|
public function exec(string $query): bool
|
|
{
|
|
$start = microtime(true);
|
|
$r = parent::exec($query);
|
|
$this->log($query, microtime(true) - $start);
|
|
return $r;
|
|
}
|
|
|
|
public function exists(string $table, string $column, mixed $value, bool $case_insensitive = true): bool
|
|
{
|
|
if ($case_insensitive) {
|
|
$query = "SELECT 1 FROM $table WHERE $column = :v COLLATE NOCASE LIMIT 1";
|
|
} else {
|
|
$query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1";
|
|
}
|
|
|
|
$result = $this->query($query, [':v' => $value]);
|
|
return $result->fetchArray(SQLITE3_NUM) !== false;
|
|
}
|
|
|
|
private function log(string $query, float $time_taken): void
|
|
{
|
|
$this->count++;
|
|
$this->query_time += $time_taken;
|
|
$this->log[] = [$query, $time_taken];
|
|
}
|
|
|
|
private function getSQLiteType(mixed $value): int
|
|
{
|
|
return match (true) {
|
|
is_int($value) => SQLITE3_INTEGER,
|
|
is_float($value) => SQLITE3_FLOAT,
|
|
is_null($value) => SQLITE3_NULL,
|
|
default => SQLITE3_TEXT
|
|
};
|
|
}
|
|
}
|