Skip to content

Commit

Permalink
Added own sqlite implementation (#746)
Browse files Browse the repository at this point in the history
* Added own sqlite implementation

* Fixed doBulk

* Fixed findKeys

---------

Co-authored-by: SamTV12345 <[email protected]>
  • Loading branch information
SamTV12345 and SamTV12345 authored Sep 6, 2024
1 parent a8e6f7e commit 5d1fb0a
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 274 deletions.
15 changes: 3 additions & 12 deletions databases/rusty_db.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import AbstractDatabase from "../lib/AbstractDatabase";
import {KeyValueDB} from 'rusty-store-kv'

export default class Rusty_db extends AbstractDatabase {
db: any | null | undefined

db: KeyValueDB |null| undefined

constructor(settings: {filename: string}) {
super(settings);
Expand Down Expand Up @@ -34,16 +34,7 @@ export default class Rusty_db extends AbstractDatabase {
}

async init() {
let RUSTY_DB
try {
RUSTY_DB = await import('rusty-store-kv');
} catch (err) {
throw new Error(
'better-sqlite3 not found. It was removed from ueberdb\'s dependencies because it requires ' +
'compilation which fails on several systems. If you still want to use sqlite, run ' +
'"pnpm install rusty-store-kv" in your etherpad-lite ./src directory.');
}
this.db = new RUSTY_DB.KeyValueDB(this.settings.filename!);
this.db = new KeyValueDB(this.settings.filename!);
}

close() {
Expand Down
79 changes: 22 additions & 57 deletions databases/sqlite_db.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
import {BulkObject} from "./cassandra_db";
import AbstractDatabase, {Settings} from "../lib/AbstractDatabase";
import {SQLite} from 'rusty-store-kv'

/**
* 2011 Peter 'Pita' Martischka
Expand All @@ -25,7 +26,7 @@ type RequestVal = {
}

export default class SQLiteDB extends AbstractDatabase {
public db: any|null;
public db: SQLite|null;
constructor(settings:Settings) {
super(settings);
this.db = null;
Expand All @@ -49,82 +50,46 @@ export default class SQLiteDB extends AbstractDatabase {
}

init(callback: Function) {
let SQLITEDB
try {
SQLITEDB = require('better-sqlite3');
} catch (err) {
throw new Error(
'better-sqlite3 not found. It was removed from ueberdb\'s dependencies because it requires ' +
'compilation which fails on several systems. If you still want to use sqlite, run ' +
'"pnpm install better-sqlite3" in your etherpad-lite ./src directory.');
}
this.db = new SQLITEDB(this.settings.filename as string)
this._query('CREATE TABLE IF NOT EXISTS store (key TEXT PRIMARY KEY, value TEXT)');
this.db = new SQLite(this.settings.filename as string)
callback();
}

async _query(sql:string, params = []) {
// It is unclear how util.promisify() deals with variadic functions, so it is not used here.
// According to sqlite3's documentation, .run() method (and maybe .all() and .get(); the
// documentation is unclear) might call the callback multiple times. That's OK -- ECMAScript
// guarantees that it is safe to call a Promise executor's resolve and reject functions
// multiple times. The subsequent calls are ignored, except Node.js's 'process' object emits a
// 'multipleResolves' event to aid in debugging.
return this.db!.prepare(sql).run(params)
}



get(key:string, callback:Function) {
const res = this.db!.prepare('SELECT value FROM store WHERE key = ?').get(key) as RequestVal
callback(null, res ? res.value : null)
const res = this.db!.get(key)
callback(null, res ? res : null)
}

findKeys(key:string, notKey:string, callback:Function) {
let query = 'SELECT key FROM store WHERE key LIKE ?';
const params = [];
// desired keys are %key:%, e.g. pad:%
key = key.replace(/\*/g, '%');
params.push(key);

if (notKey != null) {
// not desired keys are notKey:%, e.g. %:%:%
notKey = notKey.replace(/\*/g, '%');
query += ' AND key NOT LIKE ?';
params.push(notKey);
}
const res = this.db!.prepare(query).all(params).map((row:any) => row.key)
const res = this.db?.findKeys(key, notKey)

callback(null, res);
}

set(key:string, value:string, callback:Function) {
const res = this.db!.prepare('REPLACE INTO store VALUES (?,?)').run(key, value);
res.changes === 0 ? callback(null, null) : callback(null, res.lastInsertRowid)
const res = this.db!.set(key, value)
res ? callback(null, null) : callback(null, res)
}

remove(key:string, callback:Function) {
this.db!.prepare('DELETE FROM store WHERE key = ?').run(key)
this.db!.remove(key)
callback(null, null)
}

handleBulk(bulk:BulkObject){
let statement = '';
if (bulk.type === 'set') {
statement = `REPLACE INTO store VALUES (${escape(bulk.key)}, ${escape(bulk.value as string)});`;
} else if (bulk.type === 'remove') {
statement = `DELETE FROM store WHERE key = ${escape(bulk.key)};\n`;
}
return statement
}

doBulk(bulk:BulkObject[], callback:Function) {
const transaction = this.db!.transaction((bulk:BulkObject[])=>{
bulk.forEach(b=>{
let sql = this.handleBulk(b)
this.db!.prepare(sql).run()
})
});
transaction(bulk);
const convertedBulk = bulk.map(b=>{
if (b.value === null) {
return {
key: b.key,
type: b.type
} satisfies BulkObject
} else {
return b
}
})

this.db!.doBulk(convertedBulk)
callback();
}

Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,12 @@
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@types/async": "^3.2.24",
"@types/better-sqlite3": "^7.6.11",
"@types/mssql": "^9.1.5",
"@types/node": "^22.5.4",
"@types/pg": "^8.11.8",
"@types/rethinkdb": "^2.3.21",
"@types/wtfnode": "^0.7.3",
"async": "^3.2.6",
"better-sqlite3": "^11.2.1",
"cassandra-driver": "^4.7.2",
"cli-table3": "^0.6.5",
"dirty-ts": "^1.1.8",
Expand All @@ -53,7 +51,7 @@
"rethinkdb": "^2.4.2",
"rollup": "^4.21.2",
"rollup-plugin-typescript2": "^0.36.0",
"rusty-store-kv": "^1.1.4",
"rusty-store-kv": "^1.2.0",
"semver": "^7.6.3",
"simple-git": "^3.26.0",
"surrealdb.js": "^0.11.1",
Expand Down
Loading

0 comments on commit 5d1fb0a

Please sign in to comment.