mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +00:00
SQLite3 database driver in working condition
PDO stub for now; other drivers to come
This commit is contained in:
parent
03b86c222f
commit
6ffe942f99
19 changed files with 380 additions and 112 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,7 +4,7 @@ vendor/simplepie/*
|
||||||
#temp files
|
#temp files
|
||||||
cache/*
|
cache/*
|
||||||
test.php
|
test.php
|
||||||
newssync.db*
|
/db
|
||||||
|
|
||||||
# Windows image file caches
|
# Windows image file caches
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
130
schema.sql
130
schema.sql
|
@ -1,109 +1,111 @@
|
||||||
begin;
|
begin;
|
||||||
|
|
||||||
|
create table main.newssync_settings(
|
||||||
|
key varchar(255) primary key not null, --
|
||||||
|
value varchar(255), --
|
||||||
|
type varchar(255) not null check(
|
||||||
|
type in('numeric','text','timestamp', 'date', 'time', 'bool')
|
||||||
|
) --
|
||||||
|
);
|
||||||
|
insert into main.newssync_settings values('schema_version',1,'int');
|
||||||
|
|
||||||
-- users
|
-- users
|
||||||
create table newssync_users(
|
create table main.newssync_users(
|
||||||
id TEXT primary key not null, -- user id
|
id TEXT primary key not null, -- user id
|
||||||
password TEXT, -- password, salted and hashed; if using external authentication this would be blank
|
password TEXT, -- password, salted and hashed; if using external authentication this would be blank
|
||||||
name TEXT, -- display name
|
name TEXT, -- display name
|
||||||
avatar_type TEXT, -- avatar image's MIME content type
|
avatar_type TEXT, -- avatar image's MIME content type
|
||||||
avatar_data BLOB, -- avatar image's binary data
|
avatar_data BLOB, -- avatar image's binary data
|
||||||
admin boolean not null default 0 -- whether the user is an administrator
|
admin boolean not null default 0 -- whether the user is an administrator
|
||||||
);
|
);
|
||||||
|
|
||||||
-- TT-RSS categories and ownCloud folders
|
-- TT-RSS categories and ownCloud folders
|
||||||
create table newssync_categories(
|
create table main.newssync_categories(
|
||||||
id integer primary key not null, -- sequence number
|
id integer primary key not null, -- sequence number
|
||||||
owner TEXT references users(id) on delete cascade on update cascade, -- owner of category
|
owner TEXT not null references users(id) on delete cascade on update cascade, -- owner of category
|
||||||
parent integer, -- parent category id
|
parent integer, -- parent category id
|
||||||
folder integer not null, -- first-level category (ownCloud folder)
|
folder integer not null, -- first-level category (ownCloud folder)
|
||||||
name TEXT not null, -- category name
|
name TEXT not null, -- category name
|
||||||
modified datetime not null default CURRENT_TIMESTAMP, --
|
modified datetime not null default CURRENT_TIMESTAMP, --
|
||||||
unique(owner,name,parent) -- cannot have multiple categories with the same name under the same parent for the same owner
|
unique(owner,name,parent) -- cannot have multiple categories with the same name under the same parent for the same owner
|
||||||
);
|
);
|
||||||
|
|
||||||
-- newsfeeds, deduplicated
|
-- newsfeeds, deduplicated
|
||||||
create table newssync_feeds(
|
create table feeds.newssync_feeds(
|
||||||
id integer primary key not null, -- sequence number
|
id integer primary key not null, -- sequence number
|
||||||
url TEXT not null, -- URL of feed
|
url TEXT not null, -- URL of feed
|
||||||
title TEXT, -- default title of feed
|
title TEXT, -- default title of feed
|
||||||
favicon TEXT, -- URL of favicon
|
favicon TEXT, -- URL of favicon
|
||||||
source TEXT, -- URL of site to which the feed belongs
|
source TEXT, -- URL of site to which the feed belongs
|
||||||
updated datetime, -- time at which the feed was last fetched
|
updated datetime, -- time at which the feed was last fetched
|
||||||
modified datetime not null default CURRENT_TIMESTAMP, --
|
modified datetime not null default CURRENT_TIMESTAMP, --
|
||||||
err_count integer not null default 0, -- count of successive times update resulted in error since last successful update
|
err_count integer not null default 0, -- count of successive times update resulted in error since last successful update
|
||||||
err_msg TEXT, -- last error message
|
err_msg TEXT, -- last error message
|
||||||
username TEXT, -- HTTP authentication username
|
username TEXT, -- HTTP authentication username
|
||||||
password TEXT, -- HTTP authentication password (this is stored in plain text)
|
password TEXT, -- HTTP authentication password (this is stored in plain text)
|
||||||
unique(url,username,password) -- a URL with particular credentials should only appear once
|
unique(url,username,password) -- a URL with particular credentials should only appear once
|
||||||
);
|
);
|
||||||
|
|
||||||
-- users' subscriptions to newsfeeds, with settings
|
-- users' subscriptions to newsfeeds, with settings
|
||||||
create table newssync_subscriptions(
|
create table main.newssync_subscriptions(
|
||||||
id integer primary key not null, -- sequence number
|
id integer primary key not null, -- sequence number
|
||||||
owner TEXT references users(id) on delete cascade on update cascade, -- owner of subscription
|
owner TEXT not null references users(id) on delete cascade on update cascade, -- owner of subscription
|
||||||
feed integer references feeds(id) on delete cascade, -- feed for the subscription
|
feed integer not null references feeds(id) on delete cascade, -- feed for the subscription
|
||||||
added datetime not null default CURRENT_TIMESTAMP, -- time at which feed was added
|
added datetime not null default CURRENT_TIMESTAMP, -- time at which feed was added
|
||||||
modified datetime not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified
|
modified datetime not null default CURRENT_TIMESTAMP, -- date at which subscription properties were last modified
|
||||||
title TEXT, -- user-supplied title
|
title TEXT, -- user-supplied title
|
||||||
order_type int not null default 0, -- ownCloud sort order
|
order_type int not null default 0, -- ownCloud sort order
|
||||||
pinned boolean not null default 0, -- whether feed is pinned (always sorts at top)
|
pinned boolean not null default 0, -- whether feed is pinned (always sorts at top)
|
||||||
category integer references categories(id) on delete set null, -- TT-RSS category (nestable); the first-level category (which acts as ownCloud folder) is joined in when needed
|
category integer not null references categories(id) on delete set null, -- TT-RSS category (nestable); the first-level category (which acts as ownCloud folder) is joined in when needed
|
||||||
unique(owner,feed) -- a given feed should only appear once for a given owner
|
unique(owner,feed) -- a given feed should only appear once for a given owner
|
||||||
);
|
);
|
||||||
|
|
||||||
-- entries in newsfeeds
|
-- entries in newsfeeds
|
||||||
create table newssync_articles(
|
create table feeds.newssync_articles(
|
||||||
id integer primary key not null, -- sequence number
|
id integer primary key not null, -- sequence number
|
||||||
feed integer references feeds(id) on delete cascade, -- feed for the subscription
|
feed integer not null references feeds(id) on delete cascade, -- feed for the subscription
|
||||||
url TEXT not null, -- URL of article
|
url TEXT not null, -- URL of article
|
||||||
title TEXT, -- article title
|
title TEXT, -- article title
|
||||||
author TEXT, -- author's name
|
author TEXT, -- author's name
|
||||||
published datetime, -- time of original publication
|
published datetime, -- time of original publication
|
||||||
edited datetime, -- time of last edit
|
edited datetime, -- time of last edit
|
||||||
guid TEXT, -- GUID
|
guid TEXT, -- GUID
|
||||||
content TEXT, -- content, as (X)HTML
|
content TEXT, -- content, as (X)HTML
|
||||||
modified datetime not null default CURRENT_TIMESTAMP, -- date when article properties were last modified
|
modified datetime not null default CURRENT_TIMESTAMP, -- date when article properties were last modified
|
||||||
hash varchar(64) not null, -- ownCloud hash
|
hash varchar(64) not null, -- ownCloud hash
|
||||||
fingerprint varchar(64) not null, -- ownCloud fingerprint
|
fingerprint varchar(64) not null, -- ownCloud fingerprint
|
||||||
enclosures_hash varchar(64), -- hash of enclosures, if any; since enclosures are not uniquely identified, we need to know when they change
|
enclosures_hash varchar(64), -- hash of enclosures, if any; since enclosures are not uniquely identified, we need to know when they change
|
||||||
tags_hash varchar(64) -- hash of RSS/Atom categories included in article; since these categories are not uniquely identified, we need to know when they change
|
tags_hash varchar(64) -- hash of RSS/Atom categories included in article; since these categories are not uniquely identified, we need to know when they change
|
||||||
);
|
);
|
||||||
|
|
||||||
-- users' actions on newsfeed entries
|
-- users' actions on newsfeed entries
|
||||||
create table newssync_subscription_articles(
|
create table main.newssync_subscription_articles(
|
||||||
id integer primary key not null,
|
id integer primary key not null,
|
||||||
article integer references articles(id) on delete cascade,
|
article integer not null references articles(id) on delete cascade,
|
||||||
read boolean not null default 0,
|
read boolean not null default 0,
|
||||||
starred boolean not null default 0,
|
starred boolean not null default 0,
|
||||||
modified datetime not null default CURRENT_TIMESTAMP
|
modified datetime not null default CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
-- enclosures associated with articles
|
-- enclosures associated with articles
|
||||||
create table newssync_enclosures(
|
create table main.newssync_enclosures(
|
||||||
article integer references articles(id) on delete cascade,
|
article integer not null references articles(id) on delete cascade,
|
||||||
url TEXT,
|
url TEXT,
|
||||||
type varchar(255)
|
type varchar(255)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- author labels ("categories" in RSS/Atom parlance) associated with newsfeed entries
|
-- author labels ("categories" in RSS/Atom parlance) associated with newsfeed entries
|
||||||
create table newssync_tags(
|
create table main.newssync_tags(
|
||||||
article integer references articles(id) on delete cascade,
|
article integer not null references articles(id) on delete cascade,
|
||||||
name TEXT
|
name TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- user labels associated with newsfeed entries
|
-- user labels associated with newsfeed entries
|
||||||
create table newssync_labels(
|
create table main.newssync_labels(
|
||||||
sub_article integer references subscription_articles(id) on delete cascade,
|
sub_article integer not null references subscription_articles(id) on delete cascade,
|
||||||
owner TEXT references users(id) on delete cascade on update cascade,
|
owner TEXT not null references users(id) on delete cascade on update cascade,
|
||||||
name TEXT
|
name TEXT
|
||||||
);
|
);
|
||||||
create index newssync_label_names on newssync_labels(name);
|
create index main.newssync_label_names on newssync_labels(name);
|
||||||
|
|
||||||
create table newssync_settings(
|
|
||||||
key varchar(255) primary key not null,
|
|
||||||
value varchar(255),
|
|
||||||
type varchar(255) not null
|
|
||||||
);
|
|
||||||
insert into newssync_settings values('schema_version',0,'int');
|
|
||||||
|
|
||||||
commit;
|
commit;
|
|
@ -2,7 +2,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync\Auth;
|
namespace JKingWeb\NewsSync\Auth;
|
||||||
|
|
||||||
Interface AuthInterface {
|
Interface Driver {
|
||||||
public function __construct($conf, $db);
|
public function __construct($conf, $db);
|
||||||
public function auth(): bool;
|
public function auth(): bool;
|
||||||
public function authHTTP(): bool;
|
public function authHTTP(): bool;
|
|
@ -2,7 +2,7 @@
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync\Auth;
|
namespace JKingWeb\NewsSync\Auth;
|
||||||
|
|
||||||
class Internal implements AuthInterface {
|
class Internal implements Driver {
|
||||||
protected $conf;
|
protected $conf;
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
|
|
2
vendor/JKingWeb/NewsSync/Conf.php
vendored
2
vendor/JKingWeb/NewsSync/Conf.php
vendored
|
@ -6,7 +6,7 @@ class Conf {
|
||||||
public $lang = "en";
|
public $lang = "en";
|
||||||
|
|
||||||
public $dbClass = NS_BASE."Db\\DriverSQLite3";
|
public $dbClass = NS_BASE."Db\\DriverSQLite3";
|
||||||
public $dbSQLite3File = BASE."newssync.db";
|
public $dbSQLite3Path = BASE."db";
|
||||||
public $dbSQLite3Key = "";
|
public $dbSQLite3Key = "";
|
||||||
public $dbPostgreSQLHost = "localhost";
|
public $dbPostgreSQLHost = "localhost";
|
||||||
public $dbPostgreSQLUser = "newssync";
|
public $dbPostgreSQLUser = "newssync";
|
||||||
|
|
23
vendor/JKingWeb/NewsSync/Database.php
vendored
23
vendor/JKingWeb/NewsSync/Database.php
vendored
|
@ -1,4 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync;
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
|
@ -6,10 +7,26 @@ class Database {
|
||||||
|
|
||||||
public function __construct(Conf $conf) {
|
public function __construct(Conf $conf) {
|
||||||
$driver = $conf->dbClass;
|
$driver = $conf->dbClass;
|
||||||
$this->drv = new $driver($conf);
|
$this->drv = $driver::create($conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function listDrivers() {
|
static public function listDrivers(): array {
|
||||||
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
|
$path = __DIR__.$sep."Db".$sep;
|
||||||
|
$classes = [];
|
||||||
|
foreach(glob($path."Driver?*.php") as $file) {
|
||||||
|
$name = basename($file, ".php");
|
||||||
|
if(substr($name,-3) != "PDO") {
|
||||||
|
$name = NS_BASE."Db\\$name";
|
||||||
|
if(class_exists($name)) {
|
||||||
|
$classes[$name] = $name::driverName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schemaVersion(): int {
|
||||||
|
return $this->drv->schemaVersion();
|
||||||
}
|
}
|
||||||
}
|
}
|
47
vendor/JKingWeb/NewsSync/Db/Common.php
vendored
Normal file
47
vendor/JKingWeb/NewsSync/Db/Common.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
Trait Common {
|
||||||
|
protected $transDepth;
|
||||||
|
|
||||||
|
public function begin(): bool {
|
||||||
|
if($this->transDepth==0) {
|
||||||
|
$this->exec("BEGIN TRANSACTION");
|
||||||
|
} else{
|
||||||
|
$this->exec("SAVEPOINT newssync_".$this->transDepth);
|
||||||
|
}
|
||||||
|
$this->transDepth += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function commit(bool $all = false): bool {
|
||||||
|
if($this->transDepth==0) return false;
|
||||||
|
if(!$all) {
|
||||||
|
$this->exec("RELEASE SAVEPOINT newssync_".$this->transDepth-1);
|
||||||
|
$this->transDepth -= 1;
|
||||||
|
} else {
|
||||||
|
$this->exec("COMMIT TRANSACTION");
|
||||||
|
$this->transDepth = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rollback(bool $all = false): bool {
|
||||||
|
if($this->transDepth==0) return false;
|
||||||
|
if(!$all) {
|
||||||
|
$this->exec("ROLLBACK TRANSACTION TO SAVEPOINT newssync_".$this->transDepth-1);
|
||||||
|
$this->transDepth -= 1;
|
||||||
|
if($this->transDepth==0) $this->exec("ROLLBACK TRANSACTION");
|
||||||
|
} else {
|
||||||
|
$this->exec("ROLLBACK TRANSACTION");
|
||||||
|
$this->transDepth = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepare(string $query, string ...$paramType): Statement {
|
||||||
|
return $this->prepareArray($query, $paramType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
vendor/JKingWeb/NewsSync/Db/CommonPDO.php
vendored
Normal file
17
vendor/JKingWeb/NewsSync/Db/CommonPDO.php
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
Trait CommonPDO {
|
||||||
|
public function unsafeQuery(string $query): Result {
|
||||||
|
return new ResultPDO($this->db->query($query));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareArray(string $query, array $paramTypes): Statement {
|
||||||
|
return new StatementPDO($query, $paramTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepare(string $query, string ...$paramType): Statement {
|
||||||
|
return $this->prepareArray($query, $paramType);
|
||||||
|
}
|
||||||
|
}
|
18
vendor/JKingWeb/NewsSync/Db/CommonSQLite3.php
vendored
Normal file
18
vendor/JKingWeb/NewsSync/Db/CommonSQLite3.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
Trait CommonSQLite3 {
|
||||||
|
|
||||||
|
static public function driverName(): string {
|
||||||
|
return "SQLite 3";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function schemaVersion(string $schema = "main"): int {
|
||||||
|
return $this->unsafeQuery("PRAGMA $schema.user_version")->getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exec(string $query): bool {
|
||||||
|
return (bool) $this->db->exec($query);
|
||||||
|
}
|
||||||
|
}
|
15
vendor/JKingWeb/NewsSync/Db/Driver.php
vendored
Normal file
15
vendor/JKingWeb/NewsSync/Db/Driver.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
interface Driver {
|
||||||
|
static function create(\JKingWeb\NewsSync\Conf $conf, bool $install = false): Driver;
|
||||||
|
static function driverName(): string;
|
||||||
|
function schemaVersion(): int;
|
||||||
|
function begin(): bool;
|
||||||
|
function commit(): bool;
|
||||||
|
function rollback(): bool;
|
||||||
|
function exec(string $query): bool;
|
||||||
|
function unsafeQuery(string $query): Result;
|
||||||
|
function prepare(string $query, string ...$paramType): Statement;
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace JKingWeb\NewsSync\Db;
|
|
||||||
|
|
||||||
interface DriverInterface {
|
|
||||||
function __construct(\JKingWeb\NewsSync\Conf $conf);
|
|
||||||
static function driverName(): string;
|
|
||||||
}
|
|
81
vendor/JKingWeb/NewsSync/Db/DriverSQLite3.php
vendored
81
vendor/JKingWeb/NewsSync/Db/DriverSQLite3.php
vendored
|
@ -1,44 +1,65 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync\Db;
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
class DriverSQLite3 implements DriverInterface {
|
class DriverSQLite3 implements Driver {
|
||||||
protected $db;
|
use Common, CommonSQLite3;
|
||||||
protected $pdo = false;
|
|
||||||
|
|
||||||
public function __construct(\JKingWeb\NewsSync\Conf $conf, bool $install = false) {
|
protected $db;
|
||||||
|
|
||||||
|
private function __construct(\JKingWeb\NewsSync\Conf $conf, bool $install = false) {
|
||||||
|
// normalize the path
|
||||||
|
$path = $conf->dbSQLite3Path;
|
||||||
|
$sep = \DIRECTORY_SEPARATOR;
|
||||||
|
if(substr($path,-(strlen($sep))) != $sep) $path .= $sep;
|
||||||
|
$mainfile = $path."newssync-main.db";
|
||||||
|
$feedfile = $path."newssync-feeds.db";
|
||||||
|
// if the files exists (or we're initializing the database), try to open it and set initial options
|
||||||
|
try {
|
||||||
|
$this->db = new \SQLite3($mainfile, ($install) ? \SQLITE3_OPEN_READWRITE | \SQLITE3_OPEN_CREATE : \SQLITE3_OPEN_READWRITE, $conf->dbSQLite3Key);
|
||||||
|
$this->db->enableExceptions(true);
|
||||||
|
$attach = "'".$this->db->escapeString($feedfile)."'";
|
||||||
|
$this->exec("ATTACH DATABASE $attach AS feeds");
|
||||||
|
$this->exec("PRAGMA main.jounral_mode = wal");
|
||||||
|
$this->exec("PRAGMA feeds.jounral_mode = wal");
|
||||||
|
$this->exec("PRAGMA foreign_keys = yes");
|
||||||
|
} catch(\Throwable $e) {
|
||||||
|
// if opening the database doesn't work, check various pre-conditions to find out what the problem might be
|
||||||
|
foreach([$mainfile, $mainfile."-wal", $mainfile."-shm", $feedfile, $feedfile."-wal", $feedfile."-shm"] as $file) {
|
||||||
|
if(!file_exists($file)) {
|
||||||
|
if($install && !is_writable(dirname($file))) throw new Exception("fileUncreatable", dirname($file));
|
||||||
|
throw new Exception("fileMissing", $file);
|
||||||
|
}
|
||||||
|
if(!is_readable($file) && !is_writable($file)) throw new Exception("fileUnusable", $file);
|
||||||
|
if(!is_readable($file)) throw new Exception("fileUnreadable", $file);
|
||||||
|
if(!is_writable($file)) throw new Exception("fileUnwritable", $file);
|
||||||
|
}
|
||||||
|
// otherwise the database is probably corrupt
|
||||||
|
throw new Exception("fileCorrupt", $mainfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$this->db->close();
|
||||||
|
unset($this->db);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function create(\JKingWeb\NewsSync\Conf $conf, bool $install = false): Driver {
|
||||||
// check to make sure required extensions are loaded
|
// check to make sure required extensions are loaded
|
||||||
if(class_exists("SQLite3")) {
|
if(class_exists("SQLite3")) {
|
||||||
$this->pdo = false;
|
return new self($conf, $install);
|
||||||
} else if(class_exists("PDO") && in_array("sqlite",\PDO::getAvailableDrivers())) {
|
} else if(class_exists("PDO") && in_array("sqlite",\PDO::getAvailableDrivers())) {
|
||||||
$this->pdo = true;
|
return new DriverSQLite3PDO($conf, $install);
|
||||||
} else {
|
} else {
|
||||||
throw new Exception("extMissing", self::driverName());
|
throw new Exception("extMissing", self::driverName());
|
||||||
}
|
}
|
||||||
// if the file exists (or we're initializing the database), try to open it and set initial options
|
|
||||||
if((!$install && file_exists($conf->dbSQLite3File)) || $install) {
|
|
||||||
try {
|
|
||||||
$this->db = ($this->PDO) ? (new \SQLite3($conf->dbSQLite3File, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $conf->dbSQLite3Key)) : (new PDO("sqlite:".$conf->dbSQLite3File));
|
|
||||||
//FIXME: add foreign key enforcement, WAL mode
|
|
||||||
} catch(\Throwable $e) {
|
|
||||||
// if opening the database doesn't work, check various pre-conditions to find out what the problem might be
|
|
||||||
foreach([$conf->dbSQLite3File, $conf->dbSQLite3File."-wal", $conf->dbSQLite3File."-shm"] as $file) {
|
|
||||||
if(!file_exists($file)) {
|
|
||||||
if($install && !is_writable(dirname($file))) throw new Exception("fileUncreatable", dirname($file));
|
|
||||||
throw new Exception("fileMissing", $file);
|
|
||||||
}
|
|
||||||
if(!is_readable($file) && !is_writable($file)) throw new Exception("fileUnusable", $file);
|
|
||||||
if(!is_readable($file)) throw new Exception("fileUnreadable", $file);
|
|
||||||
if(!is_writable($file)) throw new Exception("fileUnwritable", $file);
|
|
||||||
}
|
|
||||||
// otherwise the database is probably corrupt
|
|
||||||
throw new Exception("fileCorrupt", $conf->dbSQLite3File);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Exception("fileMissing", $conf->dbSQLite3File);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function driverName(): string {
|
public function unsafeQuery(string $query): Result {
|
||||||
return "SQLite3";
|
return new ResultSQLite3($this->db->query($query));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function prepareArray(string $query, array $paramTypes): Statement {
|
||||||
|
return new StatementSQLite3($query, $paramTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
28
vendor/JKingWeb/NewsSync/Db/DriverSQLite3PDO.php
vendored
Normal file
28
vendor/JKingWeb/NewsSync/Db/DriverSQLite3PDO.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
class DriverSQLite3 implements Driver {
|
||||||
|
use CommonPDO, CommonSQLite3;
|
||||||
|
|
||||||
|
protected $db;
|
||||||
|
|
||||||
|
private function __construct(\JKingWeb\NewsSync\Conf $conf, bool $install = false) {
|
||||||
|
// FIXME: stub
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
// FIXME: stub
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function create(\JKingWeb\NewsSync\Conf $conf, bool $install = false): Driver {
|
||||||
|
// check to make sure required extensions are loaded
|
||||||
|
if(class_exists("PDO") && in_array("sqlite",\PDO::getAvailableDrivers())) {
|
||||||
|
return new self($conf, $install);
|
||||||
|
} else if(class_exists("SQLite3")) {
|
||||||
|
return new DriverSQLite3($conf, $install);
|
||||||
|
} else {
|
||||||
|
throw new Exception("extMissing", self::driverName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
vendor/JKingWeb/NewsSync/Db/Result.php
vendored
Normal file
9
vendor/JKingWeb/NewsSync/Db/Result.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
interface Result {
|
||||||
|
function __invoke(); // alias of get()
|
||||||
|
function get();
|
||||||
|
function getSingle();
|
||||||
|
}
|
30
vendor/JKingWeb/NewsSync/Db/ResultSQLite3.php
vendored
Normal file
30
vendor/JKingWeb/NewsSync/Db/ResultSQLite3.php
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
class ResultSQLite3 implements Result {
|
||||||
|
protected $set;
|
||||||
|
|
||||||
|
public function __construct(\SQLite3Result $resultObj) {
|
||||||
|
$this->set = $resultObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$this->set->finalize();
|
||||||
|
unset($this->set);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke() {
|
||||||
|
return $this->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get() {
|
||||||
|
return $this->set->fetchArray(\SQLITE3_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSingle() {
|
||||||
|
$res = $this->get();
|
||||||
|
if($res===FALSE) return null;
|
||||||
|
return array_shift($res);
|
||||||
|
}
|
||||||
|
}
|
9
vendor/JKingWeb/NewsSync/Db/Statement.php
vendored
Normal file
9
vendor/JKingWeb/NewsSync/Db/Statement.php
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
interface Statement {
|
||||||
|
function __invoke(...$bindings); // alias of run()
|
||||||
|
function run(...$bindings): Result;
|
||||||
|
function runArray(array $bindings): Result;
|
||||||
|
}
|
62
vendor/JKingWeb/NewsSync/Db/StatementSQLite3.php
vendored
Normal file
62
vendor/JKingWeb/NewsSync/Db/StatementSQLite3.php
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
namespace JKingWeb\NewsSync\Db;
|
||||||
|
|
||||||
|
class StatementSQLite3 implements Statement {
|
||||||
|
protected $st;
|
||||||
|
protected $types;
|
||||||
|
|
||||||
|
public function __construct(\SQLite3Stmt $st, $bindings = null) {
|
||||||
|
$this->st = $st;
|
||||||
|
$this->types = [];
|
||||||
|
foreach($bindings as $binding) {
|
||||||
|
switch(trim(strtolower($binding))) {
|
||||||
|
case "int":
|
||||||
|
case "integer":
|
||||||
|
$this->types[] = \SQLITE3_INTEGER; break;
|
||||||
|
case "float":
|
||||||
|
case "double":
|
||||||
|
case "real":
|
||||||
|
case "numeric":
|
||||||
|
$this->types[] = \SQLITE3_FLOAT; break;
|
||||||
|
case "blob":
|
||||||
|
case "bin":
|
||||||
|
case "binary":
|
||||||
|
$this->types[] = \SQLITE3_BLOB; break;
|
||||||
|
case "text":
|
||||||
|
case "string":
|
||||||
|
case "str":
|
||||||
|
$this->types[] = \SQLITE3_TEXT; break;
|
||||||
|
default:
|
||||||
|
$this->types[] = \SQLITE3_TEXT; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$this->st->close();
|
||||||
|
unset($this->st);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(&...$values) {
|
||||||
|
return $this->runArray($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(&...$values): Result {
|
||||||
|
return $this->runArray($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runArray(array &$values = null): Result {
|
||||||
|
$this->st->clear();
|
||||||
|
$l = sizeof($values);
|
||||||
|
for($a = 0; $a < $l; $a++) {
|
||||||
|
if($values[$a]===null) {
|
||||||
|
$type = \SQLITE3_NULL;
|
||||||
|
} else {
|
||||||
|
$type = (array_key_exists($a,$this->types)) ? $this->types[$a] : \SQLITE3_TEXT;
|
||||||
|
}
|
||||||
|
$st->bindParam($a+1, $values[$a], $type);
|
||||||
|
}
|
||||||
|
return new ResultSQLite3($st->execute());
|
||||||
|
}
|
||||||
|
}
|
2
vendor/JKingWeb/NewsSync/Exception.php
vendored
2
vendor/JKingWeb/NewsSync/Exception.php
vendored
|
@ -13,7 +13,7 @@ class Exception extends \Exception {
|
||||||
"Lang/Exception.stringMissing" => 10105,
|
"Lang/Exception.stringMissing" => 10105,
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(string $msgID = "", $vars = null, Throwable $e = null) {
|
public function __construct(string $msgID = "", $vars = null, \Throwable $e = null) {
|
||||||
if($msgID=="") {
|
if($msgID=="") {
|
||||||
$msg = "";
|
$msg = "";
|
||||||
$code = 0;
|
$code = 0;
|
||||||
|
|
6
vendor/JKingWeb/NewsSync/RuntimeData.php
vendored
6
vendor/JKingWeb/NewsSync/RuntimeData.php
vendored
|
@ -3,9 +3,9 @@ declare(strict_types=1);
|
||||||
namespace JKingWeb\NewsSync;
|
namespace JKingWeb\NewsSync;
|
||||||
|
|
||||||
class RuntimeData {
|
class RuntimeData {
|
||||||
protected $conf;
|
public $conf;
|
||||||
protected $db;
|
public $db;
|
||||||
protected $auth;
|
public $auth;
|
||||||
|
|
||||||
public function __construct(Conf $conf) {
|
public function __construct(Conf $conf) {
|
||||||
$this->conf = $conf;
|
$this->conf = $conf;
|
||||||
|
|
Loading…
Reference in a new issue