209 lines
6.2 KiB
TypeScript
209 lines
6.2 KiB
TypeScript
import mariadb from 'mariadb';
|
|
import { loadConfig } from './configLoader';
|
|
const config = loadConfig();
|
|
|
|
class SqlSystem {
|
|
|
|
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 })
|
|
|
|
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{
|
|
conn = await this.pool.getConnection();
|
|
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();
|
|
}
|
|
}
|
|
|
|
//EXAMPLE BLOCK OF CODE FOR ADDING DATABASE FUNCTIONS
|
|
/*
|
|
public static async example_name() {
|
|
let conn:mariadb.PoolConnection|undefined;
|
|
try{
|
|
conn = await this.pool.getConnection();
|
|
await conn.beginTransaction();
|
|
|
|
//CODE HERE//
|
|
|
|
await conn.commit();
|
|
}
|
|
catch(error)
|
|
{
|
|
console.error("message_before_error: ", error);
|
|
if(conn) await conn.rollback();
|
|
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] };
|
|
}
|
|
}
|
|
export {
|
|
SqlSystem
|
|
}
|