DK2/src/util/database.php

122 lines
2.9 KiB
PHP

<?php
define('DBP', SRC . '/../database');
/**
* Open a connection to a database.
*/
function db_open($path)
{
$db = new SQLite3($path);
// Increase cache size to 32MB
$db->exec('PRAGMA cache_size = 32000');
// Enable WAL mode
$db->exec('PRAGMA journal_mode = WAL');
// Move temp store to memory
$db->exec('PRAGMA temp_store = MEMORY');
return $db;
}
/**
* Return a connection to the auth database.
*/
function db_auth()
{
return $GLOBALS['db_auth'] ??= db_open(DBP . '/auth.db');
}
/**
* Return a connection to the live database.
*/
function db_live()
{
return $GLOBALS['db_live'] ??= db_open(DBP . '/live.db');
}
/**
* Return a connection to the fights database.
*/
function db_fights()
{
return $GLOBALS['db_fights'] ??= db_open(DBP . '/fights.db');
}
/**
* Return a connection to the blueprints database.
*/
function db_blueprints()
{
return $GLOBALS['db_blueprints'] ??= db_open(DBP . '/blueprints.db');
}
/**
* Take a SQLite3 database connection, a query string, and an array of parameters. Prepare the query and
* bind the parameters with proper type casting. Then execute the query and return the result.
*/
function db_query(SQLite3 $db, string $query, array $params = []): SQLite3Result|false
{
$p = strpos($query, '?') !== false; // are generic placeholders?
$stmt = $db->prepare($query);
if (!empty($params)) {
foreach ($params as $k => $v) $stmt->bindValue($p ? $k + 1 : $k, $v, getSQLiteType($v));
}
$start = microtime(true);
$r = $stmt->execute();
db_log($query, microtime(true) - $start);
return $r;
}
/**
* Take a SQLite3 database connection and a query string. Execute the query and return the result.
*/
function db_exec($db, $query)
{
$start = microtime(true);
$r = $db->exec($query);
db_log($query, microtime(true) - $start);
return $r;
}
/**
* Take a SQLite3 database connection, a column name, and a value. Execute a SELECT query to see if the value
* exists in the column. Return true if the value exists, false otherwise.
*/
function db_exists(SQLite3 $db, string $table, string $column, mixed $value, bool $caseInsensitive = true): bool
{
if ($caseInsensitive) {
$query = "SELECT 1 FROM $table WHERE $column = :v COLLATE NOCASE LIMIT 1";
} else {
$query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1";
}
$result = db_query($db, $query, [':v' => $value]);
return $result->fetchArray(SQLITE3_NUM) !== false;
}
/**
* Return the appropriate SQLite type casting for the value.
*/
function getSQLiteType($value): int
{
return match (true) {
is_int($value) => SQLITE3_INTEGER,
is_float($value) => SQLITE3_FLOAT,
is_null($value) => SQLITE3_NULL,
default => SQLITE3_TEXT
};
}
/**
* Log the given query string to the db debug log.
*/
function db_log($query, $timeTaken = 0)
{
$GLOBALS['queries']++;
$GLOBALS['query_time'] += $timeTaken;
if (env('debug', false)) $GLOBALS['query_log'][] = [$query, $timeTaken];
}