Skip to content

Commit

Permalink
#50 Major refactoring of mssql helper to align with other implementat…
Browse files Browse the repository at this point in the history
…ions

+ Added passing of sql object which includes user/pass to remove hardcoded
  • Loading branch information
czprz committed Mar 29, 2022
1 parent ee5acfd commit d6a002a
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 136 deletions.
168 changes: 92 additions & 76 deletions bin/common/helper/mssql.js
Original file line number Diff line number Diff line change
@@ -1,91 +1,107 @@
module.exports = {
createDatabase: createDatabase,
databaseExists: databaseExists,
createTable: createTable,
tableExists: tableExists,
insertInto: insertInto
}

const sql = require('mssql');

const DB_USERNAME = 'sa';
const DB_PASSWORD = '123456789Qwerty';
module.exports = new class {
/**
* Creates an MSSQL database
* @param query {DbQuery}
* @returns {Promise<void>}
*/
async createDatabase(query) {
await this.#connect(query);
await sql.query(`CREATE DATABASE ${query.database}`);
await sql.close();
}

/**
* Creates an MSSQL database
* @param dbName {string}
* @returns {Promise<void>}
*/
async function createDatabase(dbName) {
await connect();
await sql.query(`CREATE DATABASE ${dbName}`);
await sql.close();
}
/**
* Checks if database name already exists
* @param query {DbQuery}
* @returns {Promise<*>}
*/
async databaseExists(query) {
await this.#connect(query);
const value = await sql.query(`SELECT CAST(CASE WHEN (SELECT name FROM master.sys.databases WHERE name = '${query.database}') IS NULL THEN 0 ELSE 1 END As bit) as dbExists`);
await sql.close();

/**
* Checks if database name already exists
* @param dbName {string}
* @returns {Promise<*>}
*/
async function databaseExists(dbName) {
await connect();
const value = await sql.query(`SELECT CAST(CASE WHEN (SELECT name FROM master.sys.databases WHERE name = '${dbName}') IS NULL THEN 0 ELSE 1 END As bit) as dbExists`);
await sql.close();
if (value.recordset == null || value.recordset.length === 0) {
throw 'Could not check if database exists';
}

if (value.recordset == null || value.recordset.length === 0) {
throw 'Could not check if database exists';
return value.recordset[0].dbExists;
}

return value.recordset[0].dbExists;
}
/**
* Create table within specific database
* @param query {DbQuery}
* @returns {Promise<void>}
*/
async createTable(query) {
await this.#connect(query);
await sql.query(`CREATE TABLE ${query.database}`);
await sql.close();
}

/**
* Create table within specific database
* @param command {string}
* @returns {Promise<void>}
*/
async function createTable(command) {
await connect();
await sql.query(`CREATE TABLE ${command}`);
await sql.close();
}
/**
* Check if table already exists in database
* @param query {DbQuery}
* @returns {Promise<boolean>}
*/
async tableExists(query) {
await this.#connect(query);
const value = await sql.query(`SELECT CAST(CASE WHEN (SELECT TABLE_NAME FROM ${query.database}.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${query.table}') IS NULL THEN 0 ELSE 1 END as bit) as tableExists`);
await sql.close();

/**
* Check if table already exists in database
* @param databaseName string
* @param tableName string
* @returns {Promise<boolean>}
*/
async function tableExists(databaseName, tableName) {
await connect();
const value = await sql.query(`SELECT CAST(CASE WHEN (SELECT TABLE_NAME FROM ${databaseName}.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${tableName}') IS NULL THEN 0 ELSE 1 END as bit) as tableExists`);
await sql.close();
if (value.recordset == null || value.recordset.length === 0) {
throw 'could not check if table exists';
}

if (value.recordset == null || value.recordset.length === 0) {
throw 'could not check if table exists';
return value.recordset[0].tableExists;
}

return value.recordset[0].tableExists;
}
/**
* INSERT INTO mssql command
* @param query {DbQuery}
* @returns {Promise<void>}
*/
async insertInto(query) {
await this.#connect(query);
const insert = this.#mapDbDataToInsertQuery(query.data);
await sql.query(`INSERT INTO ${insert}`);
await sql.close();
}

/**
* INSERT INTO mssql command
* @param command {string}
* @returns {Promise<void>}
*/
async function insertInto(command) {
await connect();
await sql.query(`INSERT INTO ${command}`);
await sql.close();
}
/**
* Maps DbData into query string
* @param dbData {DbData[]}
* @return {string}
*/
#mapDbDataToInsertQuery(dbData) {
let columns = '';
let values = '';

async function connect() {
await sql.connect({
server: "localhost",
user: DB_USERNAME,
password: DB_PASSWORD,
options: {
trustServerCertificate: true
for (const data of dbData) {
columns += `'${data.key}',`;
values += `'${data.value}',`;
}
});
}

columns = columns.slice(0, -1);
values = columns.slice(0, -1);

return `(${columns}) VALUES (${values})`;
}

/**
* Establish SQL connection
* @param query {DbQuery}
* @return {Promise<void>}
*/
async #connect(query) {
await sql.connect({
server: "localhost",
user: query.username,
password: query.password,
options: {
trustServerCertificate: true
}
});
}
}
62 changes: 56 additions & 6 deletions bin/configuration/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ class Execution {
command;

/**
* Container object only used when type is 'docker-container'
* @return {Container | null}
* Sql object only used when type is 'mssql'
* @return {DbQuery | null}
*/
container;
sql;

/**
* Currently only used to select between mssql options
* @return {string | null}
* Container object only used when type is 'docker-container'
* @return {Container | null}
*/
option;
container;

/**
* Custom options that will be passed along to dependency
Expand Down Expand Up @@ -128,6 +128,56 @@ class Step {
command;
}

class DbQuery {
/**
* Username for SQL connection
* @var {string}
*/
username;

/**
* Password for SQL connection
* @var {string}
*/
password;

/**
* Used for selecting between ('create-database', 'create-table', 'insert')
* @var {string}
*/
option;

/**
* Database name necessary for DB Creation, Table Creation and Query execution
* @var {string}
*/
database;

/**
* Table name necessary for Table Creation and Query Execution
* @var {string}
*/
table;

/**
* Data currently only necessary for ('insert')
* @var {DbData[]}
*/
data;
}

class DbData {
/**
* Column name
*/
key;

/**
* Column value
*/
value;
}

class Container {
/**
* Name
Expand Down
Loading

0 comments on commit d6a002a

Please sign in to comment.