sql: sqlite > mariadb

This commit is contained in:
SolPuffy 2024-12-29 00:07:30 +02:00
parent a4c314ca36
commit e2c28f8735
3 changed files with 201 additions and 64 deletions

View file

@ -28,7 +28,7 @@ const bazaarPrice = {
}; };
async function initialize() { async function initialize() {
await SqlSystem.InitTable(); await SqlSystem.InitDB()
const matches = process.env.WEBHOOK_URL.match(webhookRegex); const matches = process.env.WEBHOOK_URL.match(webhookRegex);
if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`); if (!matches) return console.log(`[Main thread] Couldn't parse Webhook URL`);
const webhook = new WebhookClient({ id: matches[1], token: matches[2] }); const webhook = new WebhookClient({ id: matches[1], token: matches[2] });

View file

@ -17,11 +17,11 @@
"copy-paste": "^1.5.3", "copy-paste": "^1.5.3",
"discord.js": "^14.16.3", "discord.js": "^14.16.3",
"express": "^4.21.2", "express": "^4.21.2",
"mariadb": "^3.4.0",
"node-notifier": "^10.0.1", "node-notifier": "^10.0.1",
"open": "^8.4.2", "open": "^8.4.2",
"prismarine-nbt": "^2.7.0", "prismarine-nbt": "^2.7.0",
"socket.io": "^4.8.1", "socket.io": "^4.8.1",
"sqlite3": "^5.1.7",
"toastify-js": "^1.12.0", "toastify-js": "^1.12.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.7.2" "typescript": "^5.7.2"

View file

@ -1,72 +1,209 @@
import sqlite3 from 'sqlite3'; import mariadb from 'mariadb';
import { loadConfig } from './configLoader';
const config = loadConfig();
//TODO
// MUTEX functions for adding/removing/upsert
// basic read function by id
// complex read function by value range
class SqlSystem { class SqlSystem {
private static db: sqlite3.Database;
public static async InitTable() { private static pool: mariadb.Pool = mariadb.createPool({ database: process.env.DATABASE, host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, connectionLimit: config.data.worker_count ?? 10 })
const db = new sqlite3.Database('bot_data');
public static async InitDB() {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
//Setup tables for auctions and lifetimes
await conn.query(`
CREATE TABLE if NOT EXISTS auctions (
id INT AUTO_INCREMENT PRIMARY KEY,
auctionid VARCHAR(255) NOT NULL,
lbin DECIMAL(65,5) SIGNED,
UNIQUE INDEX 'auctionid' ('auctionid')
);
CREATE TABLE if NOT EXISTS lifetimes (id INT PRIMARY KEY, insertedon DATETIME(2));
`)
//Setup lifetime Trigger
await conn.query(`
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS insertLifetime
AFTER INSERT ON auctions
FOR EACH ROW
BEGIN
INSERT INTO lifetimes (id, insertedon)
VALUES (NEW.ID, NOW());
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS updateLifetime
AFTER UPDATE ON auctions
FOR EACH ROW
BEGIN
UPDATE lifetimes SET insertedon = NOW() WHERE id=NEW.ID;
END$$
DELIMITER ;
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS removeLifetime
BEFORE DELETE ON auctions
FOR EACH ROW
BEGIN
DELETE FROM lifetimes WHERE id=OLD.ID;
END$$
DELIMITER ;
`)
//Setup Table sanitation
await conn.query(`
DELIMITER $$
CREATE PROCEDURE IF NOT EXISTS CleanupOldEntries()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE temp_id INT;
DECLARE cur CURSOR FOR
SELECT id
FROM lifetimes
WHERE TIMESTAMPDIFF(HOUR, insertedon, NOW()) >= 6;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
FETCH cur INTO temp_id;
IF done THEN
LEAVE read_loop;
END IF;
DELETE FROM auctions WHERE id = temp_id;
END LOOP;
CLOSE cur;
END$$
DELIMITER ;
SET GLOBAL event_scheduler = ON;
CREATE EVENT IF NOT EXISTS CleanupOldEntriesEvent
ON SCHEDULE EVERY 2 MINUTE
DO
CALL CleanupOldEntries();
`)
}
catch (error) {
console.error("InitDB Error: ", error);
throw error;
}
finally {
if (conn) conn.release();
}
}
//INSERT ELEMENT IN AUCTIONS TABLE OR UPDATE IF IT ALREADY EXISTS
public static async Upsert(auctionid: string, lbin: number) {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
await conn.beginTransaction();
await conn.query(`
INSERT INTO auctions (auctionid, LBin)
VALUES (?,?)
ON DUPLICATE KEY UPDATE
LBin = VALUES(LBin);
`, [auctionid, lbin]);
await conn.commit();
}
catch (error) {
console.error("InitDB Error: ", error);
if(conn) await conn.rollback();
throw error;
}
finally {
if (conn) conn.release();
}
}
//REMOVE ELEMENT IN AUCTIONS TABLE
public static async Remove(auctionId: string) {
let conn: mariadb.PoolConnection | undefined;
try {
conn = await this.pool.getConnection();
await conn.beginTransaction();
await conn.query(`
DELETE FROM auctions WHERE auctionid = ?
`,[auctionId]);
await conn.commit();
}
catch (error) {
console.error("InitDB Error: ", error);
if(conn) await conn.rollback();
throw error;
}
finally {
if (conn) conn.release();
}
}
//MATCH PROVIDED ELEMENTS IN AUCTIONS TABLE - returns true/false
public static async Match(auctionid:string|string[],lbin:number|number[]): Promise<boolean|any> {
let conn: mariadb.PoolConnection | undefined;
let result;
try{ try{
await this.runQuery('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)') conn = await this.pool.getConnection();
console.log('Table created successfully.'); if(Array.isArray(auctionid) && Array.isArray(lbin))
if(auctionid.length === lbin.length) {
result = await conn.query(`
CREATE TEMPORARY TABLE IF NOT EXISTS TEMP (
auctionID VARCHAR(255) PRIMARY KEY,
lbin DECIMAL(65,5)
);
INSERT INTO TEMP (auctionID, lbin) VALUES ?
SELECT tmp.*
FROM TEMP AS tmp
WHERE NOT EXISTS (
SELECT 1
FROM auctions AS auc
WHERE auc.auctionID = tmp.auctionID
AND auc.lbin = tmp.lbin);
`,[await this.UnifiedArray(auctionid,lbin)])
return result;
}
else if(Array.isArray(auctionid) || Array.isArray(lbin)) throw Error('Match SQL Function error - cannot match collection to singlet');
else {
result = await conn.query(`
SELECT CASE
WHEN COUNT(*) > 0
THEN true
ELSE false
END AS user_exists
FROM auctions WHERE auctionID = ?;
`,[auctionid])
return Boolean(result[0].result)
}
}
catch(error)
{
console.error("message_before_error: ", error);
throw error;
}
finally
{
if (conn) conn.release();
}
}
// Insert data //EXAMPLE BLOCK OF CODE FOR ADDING DATABASE FUNCTIONS
await this.runQuery('INSERT INTO users (name) VALUES (?)', ['Alice']); /*
console.log('Data inserted successfully.'); public static async example_name() {
let conn:mariadb.PoolConnection|undefined;
try{
conn = await this.pool.getConnection();
await conn.beginTransaction();
// Retrieve a single row //CODE HERE//
const row = await this.getQuery('SELECT * FROM users WHERE name = ?', ['Alice']);
console.log('Retrieved row:', row);
// Retrieve all rows await conn.commit();
const rows = await this.allQuery('SELECT * FROM users'); }
console.log('All rows:', rows); catch(error)
} catch (err: any) { {
console.error('Database error:', err.message); console.error("message_before_error: ", error);
} finally { if(conn) await conn.rollback();
db.close(); throw error;
}
finally
{
if(conn) conn.release();
}
*/
private static async UnifiedArray<T1, T2>(auctionid: string[], lbin: number[]): Promise<{ x: string[], y: number[] }> {
return { x: [...auctionid], y: [...lbin] };
} }
} }
public static runQuery(query: string, params: string[] = []) {
return new Promise((resolve,reject) => {
this.db.run(query, params, function (err: Error | null | undefined) {
if(err){
reject(err);
}
else{
resolve(this);
}
});
});
}
public static getQuery(query: string, params: string[] = []) {
return new Promise((resolve, reject) => {
this.db.get(query, params, (err: Error | null | undefined, row: sqlite3.RunResult) => {
if (err) {
reject(err);
} else {
resolve(row);
}
});
});
}
public static allQuery(query: string, params: string[] = []) {
return new Promise((resolve, reject) => {
this.db.all(query, params, (err: Error | null | undefined, rows: sqlite3.RunResult) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
}
}
export { export {
SqlSystem SqlSystem
} }