DB: start using ORM
This commit is contained in:
4
dub.sdl
4
dub.sdl
@@ -5,7 +5,7 @@ copyright "Copyright © 2024, Marisa"
|
|||||||
license "MIT"
|
license "MIT"
|
||||||
dependency "slf4d" version="~>3.0.0"
|
dependency "slf4d" version="~>3.0.0"
|
||||||
dependency "handy-httpd" version="~>8.2.0"
|
dependency "handy-httpd" version="~>8.2.0"
|
||||||
|
dependency "ddbc" version="~>0.5.8"
|
||||||
dependency "requests" version="~>2.1.3"
|
dependency "requests" version="~>2.1.3"
|
||||||
dependency "ddbc" version="~>0.6.0"
|
dependency "hibernated" version="~>0.4.0"
|
||||||
|
|
||||||
subConfiguration "ddbc" "PGSQL"
|
subConfiguration "ddbc" "PGSQL"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"automem": "0.6.9",
|
"automem": "0.6.9",
|
||||||
"cachetools": "0.3.1",
|
"cachetools": "0.3.1",
|
||||||
"d-unit": "0.10.2",
|
"d-unit": "0.10.2",
|
||||||
"ddbc": "0.6.0",
|
"ddbc": "0.5.9",
|
||||||
"derelict-pq": "2.2.0",
|
"derelict-pq": "2.2.0",
|
||||||
"derelict-util": "2.0.6",
|
"derelict-util": "2.0.6",
|
||||||
"handy-httpd": "8.2.0",
|
"handy-httpd": "8.2.0",
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ module db.db;
|
|||||||
import slf4d;
|
import slf4d;
|
||||||
|
|
||||||
import ddbc.core;
|
import ddbc.core;
|
||||||
|
import hibernated.core;
|
||||||
|
import db.types;
|
||||||
|
|
||||||
enum DBConnector {
|
enum DBConnector {
|
||||||
DB_MYSQL,
|
DB_MYSQL,
|
||||||
@@ -21,68 +23,60 @@ struct DBSettings {
|
|||||||
|
|
||||||
class DB {
|
class DB {
|
||||||
protected DBSettings m_settings;
|
protected DBSettings m_settings;
|
||||||
|
protected EntityMetaData m_schema;
|
||||||
protected DataSource m_ds;
|
protected DataSource m_ds;
|
||||||
protected Connection m_conn;
|
protected SessionFactory m_factory;
|
||||||
protected Statement m_stmt = null;
|
protected Session m_session;
|
||||||
|
|
||||||
this(DBSettings settings) {
|
this(DBSettings settings) {
|
||||||
this.m_settings = settings;
|
this.m_settings = settings;
|
||||||
|
this.m_schema = new SchemaInfoImpl!(User);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DB getDB(DBSettings settings) {
|
|
||||||
switch (settings.connector) {
|
|
||||||
case DBConnector.DB_PGSQL:
|
|
||||||
import db.pgsql;
|
|
||||||
|
|
||||||
debugF!"DB type is PostgreSQL";
|
|
||||||
return new PostgresDB(settings);
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Exception("DB not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract DataSource getDataSource();
|
|
||||||
|
|
||||||
void connect() {
|
void connect() {
|
||||||
this.m_ds = this.getDataSource();
|
Driver driver;
|
||||||
this.m_conn = this.m_ds.getConnection();
|
string url;
|
||||||
this.m_conn.setAutoCommit(false);
|
string[string] params;
|
||||||
}
|
Dialect dialect;
|
||||||
|
|
||||||
int runUpdate(string statement) {
|
switch (this.m_settings.connector) {
|
||||||
if (this.m_stmt is null)
|
case DBConnector.DB_PGSQL:
|
||||||
this.m_stmt = this.m_conn.createStatement();
|
debugF!"Using PGSQL driver";
|
||||||
|
|
||||||
debugF!"Running update: %s"(statement);
|
import ddbc.drivers.pgsqlddbc;
|
||||||
|
|
||||||
return this.m_stmt.executeUpdate(statement);
|
driver = new PGSQLDriver();
|
||||||
}
|
|
||||||
|
|
||||||
ResultSet runQuery(string statement) {
|
with (this.m_settings) {
|
||||||
if (this.m_stmt is null)
|
url = PGSQLDriver.generateUrl(host, port, dbname);
|
||||||
this.m_stmt = this.m_conn.createStatement();
|
params = PGSQLDriver.setUserAndPassword(username, password);
|
||||||
|
}
|
||||||
|
|
||||||
debugF!"Running query: %s"(statement);
|
dialect = new PGSQLDialect();
|
||||||
|
break;
|
||||||
|
|
||||||
return this.m_stmt.executeQuery(statement);
|
default:
|
||||||
}
|
throw new Exception("Database connector not supported (yet)");
|
||||||
|
}
|
||||||
|
|
||||||
void runMigrations() {
|
debugF!"Connecting to DB with URL: %s"(url);
|
||||||
ResultSet rs = this.runQuery(
|
|
||||||
`select * from information_schema.tables where table_name = 'migrations';`,
|
|
||||||
);
|
|
||||||
|
|
||||||
bool exists = rs.next();
|
this.m_ds = new ConnectionPoolDataSourceImpl(driver, url, params);
|
||||||
int ret = 0;
|
this.m_factory = new SessionFactoryImpl(this.m_schema, dialect, this.m_ds);
|
||||||
|
|
||||||
if (exists == false) {
|
{ // Create schema if necessary
|
||||||
ret |= this.runUpdate(
|
Connection conn = this.m_ds.getConnection();
|
||||||
`create table migrations(
|
scope (exit)
|
||||||
id serial,
|
conn.close();
|
||||||
name character varying
|
this.m_factory.getDBMetaData().updateDBSchema(conn, false, true);
|
||||||
)`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if (this.m_session && this.m_session.isOpen())
|
||||||
|
this.m_session.close();
|
||||||
|
|
||||||
|
if (this.m_factory && this.m_factory.isClosed() == false)
|
||||||
|
this.m_factory.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
module db.migrations.m_001_initial;
|
|
||||||
|
|
||||||
import db.migrations.migration;
|
|
||||||
|
|
||||||
Migration Initial = Migration(
|
|
||||||
[
|
|
||||||
`create table users(
|
|
||||||
id uuid not null,
|
|
||||||
name character varying(255),
|
|
||||||
handle character varying(255),
|
|
||||||
local boolean not null,
|
|
||||||
ap_id character varying(255) not null,
|
|
||||||
ap_privkey text,
|
|
||||||
ap_pubkey text,
|
|
||||||
ap_shared_inbox text,
|
|
||||||
ap_inbox text,
|
|
||||||
ap_outbox text,
|
|
||||||
ap_followers_addr text,
|
|
||||||
ap_following_addr text
|
|
||||||
);`
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`drop table users;`
|
|
||||||
],
|
|
||||||
);
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
module db.migrations.migration;
|
|
||||||
|
|
||||||
import singletons;
|
|
||||||
import db.migrations.m_001_initial;
|
|
||||||
|
|
||||||
struct Migration {
|
|
||||||
string[] upStatements;
|
|
||||||
string[] downStatements;
|
|
||||||
|
|
||||||
bool up() {
|
|
||||||
int result;
|
|
||||||
|
|
||||||
foreach (string statement; upStatements)
|
|
||||||
result |= Db.runUpdate(statement);
|
|
||||||
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool down() {
|
|
||||||
int result;
|
|
||||||
|
|
||||||
foreach (string statement; downStatements)
|
|
||||||
result |= Db.runUpdate(statement);
|
|
||||||
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Migration[string] migrations = [
|
|
||||||
"001_initial": Initial,
|
|
||||||
];
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
module db.pgsql;
|
|
||||||
|
|
||||||
import db.db;
|
|
||||||
|
|
||||||
import ddbc.core;
|
|
||||||
import ddbc.common;
|
|
||||||
|
|
||||||
import slf4d;
|
|
||||||
|
|
||||||
class PostgresDB : DB {
|
|
||||||
this(Args...)(auto ref Args args) {
|
|
||||||
super(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override DataSource getDataSource() {
|
|
||||||
import ddbc.drivers.pgsqlddbc;
|
|
||||||
|
|
||||||
Driver driver = new PGSQLDriver();
|
|
||||||
string url;
|
|
||||||
string[string] params;
|
|
||||||
|
|
||||||
with (this.m_settings) {
|
|
||||||
url = PGSQLDriver.generateUrl(host, port, dbname);
|
|
||||||
params = PGSQLDriver.setUserAndPassword(username, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
debugF!"DB URL: %s"(url);
|
|
||||||
|
|
||||||
return new ConnectionPoolDataSourceImpl(driver, url, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,23 @@
|
|||||||
module db.types;
|
module db.types;
|
||||||
|
|
||||||
class User {
|
import hibernated.core;
|
||||||
string id;
|
|
||||||
string name;
|
|
||||||
string handle;
|
|
||||||
bool local;
|
|
||||||
|
|
||||||
string ap_id;
|
@Entity
|
||||||
string ap_privkey;
|
@Table("users")
|
||||||
string ap_pubkey;
|
class User {
|
||||||
string ap_shared_inbox;
|
@Generator(UUID_GENERATOR)
|
||||||
string ap_inbox;
|
string id;
|
||||||
string ap_outbox;
|
|
||||||
string ap_followers_addr;
|
@Column string name;
|
||||||
string ap_following_addr;
|
@Column string handle;
|
||||||
|
@Column bool local;
|
||||||
|
|
||||||
|
@Column string ap_id;
|
||||||
|
@Column string ap_privkey;
|
||||||
|
@Column string ap_pubkey;
|
||||||
|
@Column string ap_shared_inbox;
|
||||||
|
@Column string ap_inbox;
|
||||||
|
@Column string ap_outbox;
|
||||||
|
@Column string ap_followers_addr;
|
||||||
|
@Column string ap_following_addr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,11 @@ int main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Db = DB.getDB(dbSettings);
|
Db = new DB(dbSettings);
|
||||||
Db.connect();
|
Db.connect();
|
||||||
Db.runMigrations();
|
|
||||||
|
scope (exit)
|
||||||
|
Db.close();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user