diff --git a/databases/_sponsorTimes.db.sql b/databases/_sponsorTimes.db.sql index 03d02f1..9856d28 100644 --- a/databases/_sponsorTimes.db.sql +++ b/databases/_sponsorTimes.db.sql @@ -33,4 +33,7 @@ CREATE TABLE IF NOT EXISTS "config" ( CREATE INDEX IF NOT EXISTS sponsorTimes_videoID on sponsorTimes(videoID); CREATE INDEX IF NOT EXISTS sponsorTimes_UUID on sponsorTimes(UUID); + +CREATE EXTENSION IF NOT EXISTS pgcrypto; --!sqlite-ignore + COMMIT; \ No newline at end of file diff --git a/src/databases/Postgres.ts b/src/databases/Postgres.ts index 3f63707..6001a38 100644 --- a/src/databases/Postgres.ts +++ b/src/databases/Postgres.ts @@ -2,6 +2,8 @@ import { Logger } from '../utils/logger'; import { IDatabase, QueryType } from './IDatabase'; import { Pool } from 'pg'; +import fs from "fs"; + export class Mysql implements IDatabase { private pool: Pool; @@ -9,10 +11,25 @@ export class Mysql implements IDatabase { init(): void { this.pool = new Pool(); + + if (!this.config.readOnly) { + // Upgrade database if required + this.upgradeDB(this.config.fileNamePrefix, this.config.dbSchemaFolder); + } } async prepare(type: QueryType, query: string, params?: any[]) { Logger.debug(`prepare (postgres): type: ${type}, query: ${query}, params: ${params}`); + + // Convert query to use numbered parameters + let count = 1; + for (let char = 0; char < query.length; char++) { + if (query.charAt(char) === '?') { + query = query.slice(0, char) + "$" + count + query.slice(char + 1); + count++; + } + } + const queryResult = await this.pool.query(query, params); switch (type) { @@ -27,5 +44,28 @@ export class Mysql implements IDatabase { } } } + + private async upgradeDB(fileNamePrefix: string, schemaFolder: string) { + const versionCodeInfo = await this.pool.query("SELECT value FROM config WHERE key = 'version'"); + let versionCode = versionCodeInfo ? versionCodeInfo.rows[0].value : 0; + + let path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql"; + Logger.debug('db update: trying ' + path); + while (fs.existsSync(path)) { + Logger.debug('db update: updating ' + path); + await this.pool.query(this.processUpgradeQuery(fs.readFileSync(path).toString())); + + versionCode = (await this.pool.query("SELECT value FROM config WHERE key = 'version'"))?.rows[0]?.value; + path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql"; + Logger.debug('db update: trying ' + path); + } + Logger.debug('db update: no file ' + path); + } + + private processUpgradeQuery(query: string): string { + let result = query.replace(/sha256\((.*?)\)/gm, "digest($1, 'sha256')"); + + return result; + } } diff --git a/src/databases/Sqlite.ts b/src/databases/Sqlite.ts index ec3055d..1ef1823 100644 --- a/src/databases/Sqlite.ts +++ b/src/databases/Sqlite.ts @@ -84,7 +84,7 @@ export class Sqlite implements IDatabase { Logger.debug('db update: trying ' + path); while (fs.existsSync(path)) { Logger.debug('db update: updating ' + path); - db.exec(fs.readFileSync(path).toString()); + db.exec(this.processUpgradeQuery(fs.readFileSync(path).toString())); versionCode = db.prepare("SELECT value FROM config WHERE key = ?").get("version").value; path = schemaFolder + "/_upgrade_" + fileNamePrefix + "_" + (parseInt(versionCode) + 1) + ".sql"; @@ -92,6 +92,12 @@ export class Sqlite implements IDatabase { } Logger.debug('db update: no file ' + path); } + + private static processUpgradeQuery(query: string): string { + let result = query.replace(/^.*--!sqlite-ignore/gm, ""); + + return result; + } } export interface SqliteConfig {