Implement MySQL table prefix

The table prefix can be used to differentiate installs on the same
MySQL database. By default, no prefix is set.
This commit is contained in:
Wolvan 2022-01-30 17:54:07 +01:00
parent 59f1c7db6e
commit ee4e83bebc
2 changed files with 8 additions and 6 deletions

View file

@ -7,7 +7,7 @@ import { BackendPoll as Poll } from "./Poll";
export default class MySQLStorage extends Storage { export default class MySQLStorage extends Storage {
#db: mysql.Connection; #db: mysql.Connection;
#options: mysql.ConnectionOptions; #options: mysql.ConnectionOptions & { tablePrefix?: string };
#createConnection(mysqlInstance?: mysql.Connection): void { #createConnection(mysqlInstance?: mysql.Connection): void {
if (!mysqlInstance) this.#db = mysql.createConnection(this.#options); if (!mysqlInstance) this.#db = mysql.createConnection(this.#options);
this.#db.on("error", (err: mysql.QueryError) => { this.#db.on("error", (err: mysql.QueryError) => {
@ -15,7 +15,7 @@ export default class MySQLStorage extends Storage {
}); });
} }
constructor(options: mysql.ConnectionOptions) { constructor(options: mysql.ConnectionOptions & { tablePrefix?: string }) {
super(); super();
this.#options = options; this.#options = options;
console.debug("Initiating MySQLStorage."); console.debug("Initiating MySQLStorage.");
@ -25,7 +25,7 @@ export default class MySQLStorage extends Storage {
async init(): Promise<this> { async init(): Promise<this> {
await this.#db.promise().query(` await this.#db.promise().query(`
CREATE TABLE IF NOT EXISTS polls ( CREATE TABLE IF NOT EXISTS ${ this.#options.tablePrefix || "" }polls (
id_str VARCHAR(32) NOT NULL PRIMARY KEY, id_str VARCHAR(32) NOT NULL PRIMARY KEY,
title VARCHAR(${MAX_CHARACTER_LENGTH}) NOT NULL DEFAULT '', title VARCHAR(${MAX_CHARACTER_LENGTH}) NOT NULL DEFAULT '',
dupe_check_mode ENUM('none', 'ip', 'cookie') NOT NULL DEFAULT 'ip', dupe_check_mode ENUM('none', 'ip', 'cookie') NOT NULL DEFAULT 'ip',
@ -42,7 +42,7 @@ export default class MySQLStorage extends Storage {
} }
async getItem(key: string): Promise<Poll|null> { async getItem(key: string): Promise<Poll|null> {
const [rows] = await this.#db.promise().execute("SELECT * FROM polls WHERE id_str = ? AND deleted_at IS NULL;", [key]); const [rows] = await this.#db.promise().execute(`SELECT * FROM ${ this.#options.tablePrefix || "" }polls WHERE id_str = ? AND deleted_at IS NULL;`, [key]);
if (!rows || !Array.isArray(rows) || !rows.length) return null; if (!rows || !Array.isArray(rows) || !rows.length) return null;
const row = rows[0] as { const row = rows[0] as {
id_str: string, id_str: string,
@ -68,7 +68,7 @@ export default class MySQLStorage extends Storage {
async setItem(key: string, value: Poll): Promise<void> { async setItem(key: string, value: Poll): Promise<void> {
await this.#db.promise().execute(` await this.#db.promise().execute(`
INSERT INTO polls INSERT INTO ${ this.#options.tablePrefix || "" }polls
(id_str, title, dupe_check_mode, multi_select, captcha, dupe_data, options, creation_time) (id_str, title, dupe_check_mode, multi_select, captcha, dupe_data, options, creation_time)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE

View file

@ -24,6 +24,7 @@ async function main(): Promise<void> {
["--mysql-user <user>", "MySQL user", "root"], ["--mysql-user <user>", "MySQL user", "root"],
["--mysql-password <password>", "MySQL password", "root"], ["--mysql-password <password>", "MySQL password", "root"],
["--mysql-database <database>", "MySQL database", "polls"], ["--mysql-database <database>", "MySQL database", "polls"],
["--mysql-table-prefix <prefix>", "MySQL table prefix", ""],
["--mysql-ssl", "Use SSL for MySQL connection"], ["--mysql-ssl", "Use SSL for MySQL connection"],
["--backend-base-url <url>", "Base URL for the backend server", null], ["--backend-base-url <url>", "Base URL for the backend server", null],
], ".poll-horse-config"); ], ".poll-horse-config");
@ -56,7 +57,8 @@ async function main(): Promise<void> {
user: opts.mysqlUser, user: opts.mysqlUser,
password: opts.mysqlPassword, password: opts.mysqlPassword,
database: opts.mysqlDatabase, database: opts.mysqlDatabase,
ssl: opts.mysqlSsl ssl: opts.mysqlSsl,
tablePrefix: opts.mysqlTablePrefix,
}) : }) :
new FlatFileStorage({ dir: resolve(process.cwd(), program.opts().dataDirectory) }); new FlatFileStorage({ dir: resolve(process.cwd(), program.opts().dataDirectory) });
await storage.init(); await storage.init();