This repository has been archived on 2024-09-05. You can view files and clone it, but cannot push or open issues or pull requests.
shimmie2/core/dbengine.php

237 lines
6.2 KiB
PHP
Raw Normal View History

2021-12-14 18:32:47 +00:00
<?php
declare(strict_types=1);
namespace Shimmie2;
use FFSPHP\PDO;
2019-09-29 13:30:55 +00:00
abstract class SCORE
{
2021-12-14 18:32:47 +00:00
public const AIPK = "SCORE_AIPK";
public const INET = "SCORE_INET";
2019-06-27 03:29:52 +00:00
}
abstract class DBEngine
{
2022-10-28 00:45:35 +00:00
public DatabaseDriverID $id;
2024-01-15 15:08:22 +00:00
public function init(PDO $db): void
{
}
public function scoreql_to_sql(string $data): string
{
return $data;
}
public function create_table_sql(string $name, string $data): string
{
return 'CREATE TABLE '.$name.' ('.$data.')';
}
2024-01-15 15:08:22 +00:00
abstract public function set_timeout(PDO $db, ?int $time): void;
2020-03-26 16:57:08 +00:00
abstract public function get_version(PDO $db): string;
2020-10-03 12:50:37 +00:00
2023-11-11 21:49:12 +00:00
abstract public function notify(PDO $db, string $channel, ?string $data = null): void;
}
class MySQL extends DBEngine
{
2022-10-28 00:45:35 +00:00
public DatabaseDriverID $id = DatabaseDriverID::MYSQL;
2024-01-15 15:08:22 +00:00
public function init(PDO $db): void
{
$db->exec("SET NAMES utf8;");
}
public function scoreql_to_sql(string $data): string
{
2019-06-27 03:29:52 +00:00
$data = str_replace(SCORE::AIPK, "INTEGER PRIMARY KEY auto_increment", $data);
$data = str_replace(SCORE::INET, "VARCHAR(45)", $data);
return $data;
}
public function create_table_sql(string $name, string $data): string
{
$data = $this->scoreql_to_sql($data);
$ctes = "ENGINE=InnoDB DEFAULT CHARSET='utf8'";
return 'CREATE TABLE '.$name.' ('.$data.') '.$ctes;
}
public function set_timeout(PDO $db, ?int $time): void
{
// These only apply to read-only queries, which appears to be the best we can to mysql-wise
2020-01-30 09:01:19 +00:00
// $db->exec("SET SESSION MAX_EXECUTION_TIME=".$time.";");
}
2020-03-26 16:57:08 +00:00
2023-11-11 21:49:12 +00:00
public function notify(PDO $db, string $channel, ?string $data = null): void
2020-10-03 12:50:37 +00:00
{
}
2020-03-26 16:57:08 +00:00
public function get_version(PDO $db): string
{
2024-01-20 19:47:26 +00:00
return false_throws($db->query('select version()'))->fetch()[0];
2020-03-26 16:57:08 +00:00
}
}
class PostgreSQL extends DBEngine
{
2022-10-28 00:45:35 +00:00
public DatabaseDriverID $id = DatabaseDriverID::PGSQL;
2024-01-15 15:08:22 +00:00
public function init(PDO $db): void
{
if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
$db->exec("SET application_name TO 'shimmie [{$_SERVER['REMOTE_ADDR']}]';");
} else {
$db->exec("SET application_name TO 'shimmie [local]';");
}
if (defined("DATABASE_TIMEOUT")) {
$this->set_timeout($db, DATABASE_TIMEOUT);
}
}
public function scoreql_to_sql(string $data): string
{
$data = str_replace(SCORE::AIPK, "INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY", $data);
2019-06-27 03:29:52 +00:00
$data = str_replace(SCORE::INET, "INET", $data);
return $data;
}
public function create_table_sql(string $name, string $data): string
{
$data = $this->scoreql_to_sql($data);
return "CREATE TABLE $name ($data)";
}
public function set_timeout(PDO $db, ?int $time): void
{
2021-09-22 15:02:33 +00:00
if (is_null($time)) {
$time = 0;
}
$db->exec("SET statement_timeout TO ".$time.";");
}
2020-03-26 16:57:08 +00:00
2023-11-11 21:49:12 +00:00
public function notify(PDO $db, string $channel, ?string $data = null): void
2020-10-03 12:50:37 +00:00
{
if ($data) {
$db->exec("NOTIFY $channel, '$data';");
} else {
$db->exec("NOTIFY $channel;");
}
}
2020-03-26 16:57:08 +00:00
public function get_version(PDO $db): string
{
2024-01-20 19:47:26 +00:00
return false_throws($db->query('select version()'))->fetch()[0];
2020-03-26 16:57:08 +00:00
}
}
// shimmie functions for export to sqlite
function _unix_timestamp(string $date): int
{
2024-01-20 20:48:47 +00:00
return strtotime_ex($date);
}
function _now(): string
{
return date("Y-m-d H:i:s");
}
function _floor(float|int $a): float
{
return floor($a);
}
function _log(float $a, ?float $b = null): float
{
if (is_null($b)) {
return log($a);
} else {
return log($b, $a);
}
}
function _isnull(mixed $a): bool
{
return is_null($a);
}
function _md5(string $a): string
{
return md5($a);
}
function _concat(string $a, string $b): string
{
return $a . $b;
}
function _lower(string $a): string
{
return strtolower($a);
}
function _rand(): int
{
return rand();
}
function _ln(float $n): float
{
return log($n);
}
class SQLite extends DBEngine
{
2022-10-28 00:45:35 +00:00
public DatabaseDriverID $id = DatabaseDriverID::SQLITE;
2024-01-15 15:08:22 +00:00
public function init(PDO $db): void
{
2020-01-26 13:19:35 +00:00
ini_set('sqlite.assoc_case', '0');
$db->exec("PRAGMA foreign_keys = ON;");
$db->sqliteCreateFunction('UNIX_TIMESTAMP', 'Shimmie2\_unix_timestamp', 1);
$db->sqliteCreateFunction('now', 'Shimmie2\_now', 0);
$db->sqliteCreateFunction('floor', 'Shimmie2\_floor', 1);
$db->sqliteCreateFunction('log', 'Shimmie2\_log');
$db->sqliteCreateFunction('isnull', 'Shimmie2\_isnull', 1);
$db->sqliteCreateFunction('md5', 'Shimmie2\_md5', 1);
$db->sqliteCreateFunction('concat', 'Shimmie2\_concat', 2);
$db->sqliteCreateFunction('lower', 'Shimmie2\_lower', 1);
$db->sqliteCreateFunction('rand', 'Shimmie2\_rand', 0);
$db->sqliteCreateFunction('ln', 'Shimmie2\_ln', 1);
}
public function scoreql_to_sql(string $data): string
{
2019-06-27 03:29:52 +00:00
$data = str_replace(SCORE::AIPK, "INTEGER PRIMARY KEY", $data);
$data = str_replace(SCORE::INET, "VARCHAR(45)", $data);
return $data;
}
public function create_table_sql(string $name, string $data): string
{
$data = $this->scoreql_to_sql($data);
$cols = [];
$extras = "";
foreach (explode(",", $data) as $bit) {
$matches = [];
if (preg_match("/(UNIQUE)? ?INDEX\s*\((.*)\)/", $bit, $matches)) {
$uni = $matches[1];
$col = $matches[2];
$extras .= "CREATE $uni INDEX {$name}_{$col} ON {$name}({$col});";
} else {
$cols[] = $bit;
}
}
$cols_redone = implode(", ", $cols);
return "CREATE TABLE $name ($cols_redone); $extras";
}
public function set_timeout(PDO $db, ?int $time): void
{
// There doesn't seem to be such a thing for SQLite, so it does nothing
}
2020-03-26 16:57:08 +00:00
2023-11-11 21:49:12 +00:00
public function notify(PDO $db, string $channel, ?string $data = null): void
2020-10-03 12:50:37 +00:00
{
}
2020-03-26 16:57:08 +00:00
public function get_version(PDO $db): string
{
2024-01-20 19:47:26 +00:00
return false_throws($db->query('select sqlite_version()'))->fetch()[0];
2020-03-26 16:57:08 +00:00
}
}