Dragon-Knight/server/app/Database.php

123 lines
2.8 KiB
PHP

<?php
/*
SQLite database wrapper class.
By default, foreign keys are enabled and the database is in WAL mode. In general
these defaults should be perfect for most use cases.
*/
class Database
{
private PDO $c;
private int $queries = 0;
private array $log = [];
private float $time = 0;
public function __construct(string $path, array $opts = [])
{
$opts = !empty($opts) ? $opts : [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$this->c = new PDO("sqlite:$path", null, null, $opts);
$this->c->exec('PRAGMA foreign_keys = ON;'); // Enable foreign keys
$this->c->exec('PRAGMA journal_mode = WAL;'); // Enable WAL
} catch (PDOException $e) {
throw $e;
}
}
public function do(string $query, array $params = []): PDOStatement|false
{
$start = microtime(true);
try {
$stmt = $this->c->prepare($query);
$stmt->execute($params);
$this->record($query, $start);
return $stmt;
} catch (PDOException $e) {
print_r($query);
throw $e;
}
}
public function q(string $query): PDOStatement|false
{
$start = microtime(true);
try {
$stmt = $this->c->query($query);
$this->record($query, $start);
return $stmt;
} catch (PDOException $e) {
print_r($query);
throw $e;
}
}
private function record(string $query, float $start): void
{
$time = microtime(true) - $start;
$this->queries++;
$this->log[] = [$query, $time];
$this->time += $time;
}
public function queries(): int
{
return $this->queries;
}
public function log(): array
{
return $this->log;
}
public function time(): float
{
return $this->time;
}
public function lastInsertID(): int
{
return $this->c->lastInsertId();
}
public function insertFromCSV(string $table, string $path): PDOStatement|false
{
// open the file
$handle = fopen($path, 'r');
if ($handle === false) return false;
// reduce the column names to lower case with underscores
$columns = array_map(function ($column) {
return strtolower(str_replace(' ', '_', $column));
}, fgetcsv($handle));
// set up the query
$query = "INSERT INTO $table (" . implode(',', $columns) . ') VALUES ';
// read the rows and add them to the query
while (($row = fgetcsv($handle)) !== false) {
// go through the row and put strings into single quotes
$row = array_map(function ($column) {
if (is_numeric($column)) return $column;
return "'" . str_replace("'", "''", $column) . "'";
}, $row);
// add the row to the query
$query .= '(' . implode(',', $row) . '),';
}
// remove the trailing comma
$query = rtrim($query, ',') . ';';
// execute the insert
return $this->q($query);
}
}