hapiest-mysql
Version:
A wrapper around mysql that provides a very descriptive way of running queries.
767 lines (586 loc) • 33.5 kB
JavaScript
'use strict';
const Should = require('should');
const Mysql = require('mysql');
const Squel = require('squel');
const VO = require('hapiest-vo');
const Moment = require('moment');
const MysqlDaoQueryHelper = require('../../lib/mysqlDaoQueryHelper');
const cleanFunction = value => Mysql.escape(value, false, 'utc');
const mysqlDaoQueryHelper = new MysqlDaoQueryHelper('users', cleanFunction);
const localTimezoneCleanFunction = value => Mysql.escape(value);
const localMysqlDaoQueryHelper = new MysqlDaoQueryHelper('users', localTimezoneCleanFunction);
class UserCreateArgs extends VO {
constructor(args) {
super();
this._addProperties(args);
}
get firstName() { return this.get('firstName'); }
get lastName() { return this.get('lastName'); }
get password() { return this.get('password'); }
}
describe('MysqlDaoQueryHelper', function() {
describe('create', function() {
it('Should generate an INSERT statement for a single entry in users table', function() {
const sql = mysqlDaoQueryHelper.create({firstName: 'firstName', lastName: 'lastName', password: 'boom!', dateAdded: new Date('1990-01-05T13:30:00Z')});
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`, `date_added`) VALUES ('firstName', 'lastName', 'boom!', '1990-01-05 13:30:00.000')");
});
it('Should generate an INSERT statement for a single entry in users table from a VO', function() {
const sql = mysqlDaoQueryHelper.create(new UserCreateArgs({firstName: 'firstName', lastName: 'lastName', password: 'boom!'}));
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('firstName', 'lastName', 'boom!')");
});
it('Should generate an INSERT statement for a single entry in users table from an object with toJsObj() function defined', function() {
const obj = {
toJsObj: function() {
return {firstName: 'firstName', lastName: 'lastName', password: 'boom!'};
}
};
const sql = mysqlDaoQueryHelper.create(obj);
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('firstName', 'lastName', 'boom!')");
});
it('Should generate an INSERT statement for a single entry in users table from an object with toJSON() function defined', function() {
const obj = {
toJSON: function() {
return {firstName: 'Bob', lastName: 'Smith', password: 'another password'};
}
};
const sql = mysqlDaoQueryHelper.create(obj);
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('Bob', 'Smith', 'another password')");
});
it('Should generate an INSERT statement for a single entry in users table with raw inputs', function() {
const sql = mysqlDaoQueryHelper.create({firstName: 'firstName', lastName: 'lastName', password: { raw: 'TRIM(" mybadpasswordinput ")' }, dateAdded: new Date('1990-01-05T13:30:00Z')});
Should.exist(sql);
sql.should.eql(`INSERT INTO users (\`first_name\`, \`last_name\`, \`password\`, \`date_added\`) VALUES ('firstName', 'lastName', TRIM(" mybadpasswordinput "), '1990-01-05 13:30:00.000')`);
});
it('Should generate an INSERT statement to handle ignoring duplicate keys', function() {
const sql = mysqlDaoQueryHelper.create({
firstName: 'firstName',
lastName: 'lastName',
password: { raw: 'TRIM(" mybadpasswordinput ")' },
dateAdded: new Date('1990-01-05T13:30:00Z')
}, {ignoreOnDuplicateKey: true});
Should.exist(sql);
sql.should.eql(`INSERT INTO users (\`first_name\`, \`last_name\`, \`password\`, \`date_added\`) VALUES ('firstName', 'lastName', TRIM(" mybadpasswordinput "), '1990-01-05 13:30:00.000') ON DUPLICATE KEY UPDATE \`first_name\` = \`first_name\``);
});
});
describe('createBulk', function() {
it('Should generate an INSERT statement for multiple rows in users table', function() {
const sql = mysqlDaoQueryHelper.createBulk([
{firstName: 'firstName', lastName: 'lastName', password: 'boom!'},
{firstName: 'John', lastName: 'Doe', password: 'badpassword'},
{firstName: 'Jane', lastName: 'Doe', password: 'foundrydc'}
]);
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('firstName', 'lastName', 'boom!'), ('John', 'Doe', 'badpassword'), ('Jane', 'Doe', 'foundrydc')");
});
it('Should generate an INSERT statement to handle ignoring duplicate keys', function() {
const sql = mysqlDaoQueryHelper.createBulk([
{firstName: 'firstName', lastName: 'lastName', password: 'boom!'},
{firstName: 'John', lastName: 'Doe', password: 'badpassword'},
{firstName: 'Jane', lastName: 'Doe', password: 'foundrydc'}
], {ignoreOnDuplicateKey: true});
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('firstName', 'lastName', 'boom!'), ('John', 'Doe', 'badpassword'), ('Jane', 'Doe', 'foundrydc') ON DUPLICATE KEY UPDATE `first_name` = `first_name`");
});
});
describe('upsert', function() {
it('Should generate an INSERT ... ON DUPLICATE KEY UPDATE statement', function() {
const sql = mysqlDaoQueryHelper.upsert({firstName: 'firstName', lastName: 'lastName', password: 'boom!'}, {password: 'ka-boom!'});
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('firstName', 'lastName', 'boom!') ON DUPLICATE KEY UPDATE \`password\` = 'ka-boom!'");
});
it('Should generate an INSERT ... ON DUPLICATE KEY UPDATE statement for raw update args', function() {
const sql = mysqlDaoQueryHelper.upsert({firstName: 'firstName', lastName: 'lastName', password: 'boom!'}, {password: { raw: 'TRIM(" mybadpasswordinput ")' } });
Should.exist(sql);
sql.should.eql(`INSERT INTO users (\`first_name\`, \`last_name\`, \`password\`) VALUES ('firstName', 'lastName', 'boom!') ON DUPLICATE KEY UPDATE \`password\` = TRIM(" mybadpasswordinput ")`);
});
it('Should generate an INSERT ... ON DUPLICATE KEY UPDATE statement for multiple rows with insert values', function() {
const insertArgs = [
{firstName: 'f1', lastName: 'l1', password: 'p1'},
{firstName: 'f2', lastName: 'l2', password: 'p2'},
{firstName: 'f3', lastName: 'l3', password: 'p3'}
];
const updateArgs = [
'firstName', 'lastName', 'password'
];
const sql = mysqlDaoQueryHelper.upsertBulk(insertArgs, updateArgs);
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('f1', 'l1', 'p1'), ('f2', 'l2', 'p2'), ('f3', 'l3', 'p3') ON DUPLICATE KEY UPDATE `first_name` = VALUES(`first_name`), `last_name` = VALUES(`last_name`), `password` = VALUES(`password`)");
});
it('Should generate an INSERT ... ON DUPLICATE KEY UPDATE statement for multiple rows with specific values', function() {
const insertArgs = [
{firstName: 'f1', lastName: 'l1', password: 'p1'},
{firstName: 'f2', lastName: 'l2', password: 'p2'},
{firstName: 'f3', lastName: 'l3', password: 'p3'}
];
const updateArgs = {
password: 'newpassword1234'
};
const sql = mysqlDaoQueryHelper.upsertBulk(insertArgs, updateArgs);
Should.exist(sql);
sql.should.eql("INSERT INTO users (`first_name`, `last_name`, `password`) VALUES ('f1', 'l1', 'p1'), ('f2', 'l2', 'p2'), ('f3', 'l3', 'p3') ON DUPLICATE KEY UPDATE `password` = 'newpassword1234'");
});
});
describe('getOne', function() {
it('Should generate a SELECT statement for a single row', function() {
const sql = mysqlDaoQueryHelper.getOne({firstName: 'John', lastName: 'Doe'});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`first_name` = 'John') AND (`last_name` = 'Doe') LIMIT 1");
});
it('Should allow ? characters in the WHERE clause', function() {
const sql = mysqlDaoQueryHelper.getOne({url: 'http://www.youtube.com/?q=somevideo'});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`url` = 'http://www.youtube.com/?q=somevideo') LIMIT 1");
});
it('Should generate an IS NULL in where clause ', function() {
const sql = mysqlDaoQueryHelper.getOne({firstName: null, lastName: 'Doe'});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`first_name` IS NULL) AND (`last_name` = 'Doe') LIMIT 1");
});
it('Should generate dates with for a utc timezone ', function() {
const now = Moment();
const nowDate = now.toDate();
const utcDateString = now.utc().format('YYYY-MM-DD HH:mm:ss.SSS');
const sql = mysqlDaoQueryHelper.getOne({dateAdded: nowDate});
Should.exist(sql);
sql.should.eql(`SELECT * FROM users WHERE (\`date_added\` = '${utcDateString}') LIMIT 1`);
});
it('Should generate dates with for local timezone ', function() {
const now = Moment();
const nowDate = now.toDate();
const localDateString = now.local().format('YYYY-MM-DD HH:mm:ss.SSS');
const sql = localMysqlDaoQueryHelper.getOne({dateAdded: nowDate});
Should.exist(sql);
sql.should.eql(`SELECT * FROM users WHERE (\`date_added\` = '${localDateString}') LIMIT 1`);
});
});
describe('getAll', function() {
it('Should generate a SELECT statement for multiple rows', function() {
const sql = mysqlDaoQueryHelper.getAll({lastName: 'Doe'});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`last_name` = 'Doe')");
});
it('Should allow ? characters in the WHERE clause', function() {
const sql = mysqlDaoQueryHelper.getAll({url: 'http://www.youtube.com/?q=somevideo'});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`url` = 'http://www.youtube.com/?q=somevideo')");
});
it('Should allow an array to be passed to WHERE clause', function() {
const sql = mysqlDaoQueryHelper.getAll({id: [1,2,5,10]});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`id` IN (1,2,5,10))");
});
it('Should generate a SELECT statement with a query object and in operator', function() {
const sql = mysqlDaoQueryHelper.getAll({id: { in: [1,2,3] }});
Should.exist(sql);
sql.should.eql('SELECT * FROM users WHERE (`id` IN (1,2,3))');
});
it('Should generate a SELECT statement with a query object and nin operator', function() {
const sql = mysqlDaoQueryHelper.getAll({id: { nin: ['apple', 'banana', 'pear'] }});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`id` NOT IN ('apple','banana','pear'))");
});
it('Should generate a SELECT statement with a query object and notIn operator', function() {
const sql = mysqlDaoQueryHelper.getAll({id: { not_in: ['apple', 'banana', 'pear'] }});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`id` NOT IN ('apple','banana','pear'))");
});
it('Should generate a SELECT statement with a query object and in/nin operators', function() {
const sql = mysqlDaoQueryHelper.getAll({id: { in: [7,8,9], nin: [1,2,3] }});
Should.exist(sql);
sql.should.eql('SELECT * FROM users WHERE (`id` IN (7,8,9) AND `id` NOT IN (1,2,3))');
});
it('Should generate a SELECT statement with order by', function() {
const sql = mysqlDaoQueryHelper.getAll({}, { sort: { firstName: 'ASC', lastName: 'DESC' } });
Should.exist(sql);
sql.should.eql("SELECT * FROM users ORDER BY `first_name` ASC, `last_name` DESC");
});
it('Should generate a SELECT statement with limit', function() {
const sql = mysqlDaoQueryHelper.getAll({}, { limit: 2 });
Should.exist(sql);
sql.should.eql("SELECT * FROM users LIMIT 2");
});
it('Should generate a SELECT statement with offset and limit', function() {
const sql = mysqlDaoQueryHelper.getAll({}, { offset: 1, limit: 2 });
Should.exist(sql);
sql.should.eql("SELECT * FROM users LIMIT 2 OFFSET 1");
});
it('Should generate a SELECT statement with a query object and gt/lt', function() {
const sql = mysqlDaoQueryHelper.getAll({
dateAdded: {
gte: new Date('1990-01-05T13:30:00Z'),
lt: new Date('1990-01-10T13:30:00Z')
}
});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`date_added` >= '1990-01-05 13:30:00.000' AND `date_added` < '1990-01-10 13:30:00.000')");
});
it('Should generate a SELECT statement with a query object and gte/lte', function() {
const sql = mysqlDaoQueryHelper.getAll({
id: {
gte: 5,
lte: 10
}
});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`id` >= 5 AND `id` <= 10)");
});
it('Should generate a SELECT statement with a query object and ne: null', function() {
const sql = mysqlDaoQueryHelper.getAll({
id: {
ne: null
}
});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`id` IS NOT NULL)");
});
it('Should generate a SELECT statement with multiple query objects', function() {
const sql = mysqlDaoQueryHelper.getAll({
name: {
eq: 'Chas'
},
lastName: {
ne: 'Fantastic'
},
id: {
gt: 2
},
dateAdded: {
gt: new Date('1990-01-05T13:30:00Z'),
lte: new Date('1990-01-10T13:30:00Z')
},
luckyNumbers: {
in: [9,17,42]
}
});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`name` = 'Chas') AND (`last_name` != 'Fantastic') AND (`id` > 2) AND (`date_added` > '1990-01-05 13:30:00.000' AND `date_added` <= '1990-01-10 13:30:00.000') AND (`lucky_numbers` IN (9,17,42))");
});
it('Should generate a SELECT statement with a query object and like: foo%', function() {
const sql = mysqlDaoQueryHelper.getAll({
firstName: {
like: 'foo%'
}
});
Should.exist(sql);
sql.should.eql("SELECT * FROM users WHERE (`first_name` LIKE 'foo%')");
});
});
describe('getCount', function() {
it('Should generate a SELECT count(*) statement', function() {
const sql = mysqlDaoQueryHelper.getCount({lastName: 'Doe'});
Should.exist(sql);
sql.should.eql("SELECT COUNT(*) AS \"count\" FROM users WHERE (`last_name` = 'Doe')");
});
it('Should generate a SELECT count(*) statement with limit', function() {
const sql = mysqlDaoQueryHelper.getCount({lastName: 'Doe'}, { limit: 2 });
Should.exist(sql);
sql.should.eql("SELECT COUNT(*) AS \"count\" FROM users WHERE (`last_name` = 'Doe')");
});
it('Should generate a SELECT count(*) statement with limit and offset', function() {
const sql = mysqlDaoQueryHelper.getCount({lastName: 'Doe'}, { offset: 1, limit: 2 });
Should.exist(sql);
sql.should.eql("SELECT COUNT(*) AS \"count\" FROM users WHERE (`last_name` = 'Doe')");
});
});
describe('updateOne', function() {
it('Should generate an UPDATE statement for one row', function() {
const sql = mysqlDaoQueryHelper.updateOne({id: 1}, {email: 'john.doe@gmail.com', firstName: 'john'});
Should.exist(sql);
sql.should.eql("UPDATE users SET `email` = 'john.doe@gmail.com', `first_name` = 'john' WHERE (`id` = 1) LIMIT 1");
});
it('Should generate an UPDATE statement and not escape CURRENT_TIMESTAMP', function() {
const sql = mysqlDaoQueryHelper.updateOne({id: 1}, {email: 'john.doe@gmail.com', dateDeleted: 'CURRENT_TIMESTAMP'});
Should.exist(sql);
sql.should.eql("UPDATE users SET `email` = 'john.doe@gmail.com', `date_deleted` = CURRENT_TIMESTAMP WHERE (`id` = 1) LIMIT 1");
});
it('Should work even with ? in WHERE clause for one row', function() {
const sql = mysqlDaoQueryHelper.updateOne({url: 'http://some.com/?blah=hello'}, {email: 'john.doe@gmail.com', firstName: 'john'});
Should.exist(sql);
sql.should.eql("UPDATE users SET `email` = 'john.doe@gmail.com', `first_name` = 'john' WHERE (`url` = 'http://some.com/?blah=hello') LIMIT 1");
});
});
describe('update', function() {
it('Should generate an UPDATE statement that has no LIMIT clause', function() {
const sql = mysqlDaoQueryHelper.update({id: 1}, {email: 'john.doe@gmail.com', firstName: 'john', dateUpdated: new Date('2016-09-27T11:30:00Z')});
Should.exist(sql);
sql.should.eql("UPDATE users SET `email` = 'john.doe@gmail.com', `first_name` = 'john', `date_updated` = '2016-09-27 11:30:00.000' WHERE (`id` = 1)");
})
});
describe('deleteOne', function() {
it('Should generate an DELETE statement for one row', function() {
const sql = mysqlDaoQueryHelper.deleteOne({id: 1});
Should.exist(sql);
sql.should.eql("DELETE FROM users WHERE (`id` = 1) LIMIT 1");
});
it('Should generate an DELETE statement even with ? in WHERE clause for one row', function() {
const sql = mysqlDaoQueryHelper.deleteOne({url: 'http://some.com/?foo=bar'});
Should.exist(sql);
sql.should.eql("DELETE FROM users WHERE (`url` = 'http://some.com/?foo=bar') LIMIT 1");
});
});
describe('delete', function() {
it('Should generate an DELETE statement that has no LIMIT clause', function() {
const sql = mysqlDaoQueryHelper.delete({age: 30});
Should.exist(sql);
sql.should.eql("DELETE FROM users WHERE (`age` = 30)");
})
});
describe('clean', function() {
it('Should clean value passed in', function() {
const uncleanValue = "some unclean value with ' single quote";
const cleanValue = mysqlDaoQueryHelper.clean(uncleanValue);
Should.exist(cleanValue);
cleanValue.should.eql("'some unclean value with \\' single quote'");
});
it('Should escape all strings, even special MySQL functions', function() {
const currentTimestampUnclean = "current_timestamp";
const currentTimestampClean = mysqlDaoQueryHelper.clean(currentTimestampUnclean);
Should.exist(currentTimestampClean);
currentTimestampClean.should.eql("'current_timestamp'");
const nowUnclean = "NOW()";
const nowClean = mysqlDaoQueryHelper.clean(nowUnclean);
Should.exist(nowClean);
nowClean.should.eql("'NOW()'");
const isNullUnclean = "IS NULL";
const isNullClean = mysqlDaoQueryHelper.clean(isNullUnclean);
Should.exist(isNullClean);
isNullClean.should.eql("'IS NULL'");
const isNotNullUnclean = "IS NOT NULL";
const isNotNullClean = mysqlDaoQueryHelper.clean(isNotNullUnclean);
Should.exist(isNotNullClean);
isNotNullClean.should.eql("'IS NOT NULL'");
});
it('Should clean a date configured for utc time', function() {
const now = Moment();
const date = now.toDate();
const dateClean = mysqlDaoQueryHelper.clean(date);
const expectedDateString = now.utc().format('YYYY-MM-DD HH:mm:ss.SSS');
Should.exist(dateClean);
dateClean.should.eql(`'${expectedDateString}'`);
});
it('Should clean a date configured for local time', function() {
const now = Moment();
const date = now.toDate();
const dateClean = localMysqlDaoQueryHelper.clean(date);
const expectedDateString = now.local().format('YYYY-MM-DD HH:mm:ss.SSS');
Should.exist(dateClean);
dateClean.should.eql(`'${expectedDateString}'`);
})
});
describe('cleanSpecial', function() {
it('Should clean value passed in', function() {
const uncleanValue = "some unclean value with ' single quote";
const cleanValue = mysqlDaoQueryHelper.cleanSpecial(uncleanValue);
Should.exist(cleanValue);
cleanValue.should.eql("'some unclean value with \\' single quote'");
});
it('Should allow special MySQL functions to pass through uncleaned', function() {
const currentTimestampUnclean = "current_timestamp";
const currentTimestampClean = mysqlDaoQueryHelper.cleanSpecial(currentTimestampUnclean);
Should.exist(currentTimestampClean);
currentTimestampClean.should.eql("current_timestamp");
const nowUnclean = "NOW()";
const nowClean = mysqlDaoQueryHelper.cleanSpecial(nowUnclean);
Should.exist(nowClean);
nowClean.should.eql("NOW()");
const isNullUnclean = "IS NULL";
const isNullClean = mysqlDaoQueryHelper.cleanSpecial(isNullUnclean);
Should.exist(isNullClean);
isNullClean.should.eql("IS NULL");
const isNotNullUnclean = "IS NOT NULL";
const isNotNullClean = mysqlDaoQueryHelper.cleanSpecial(isNotNullUnclean);
Should.exist(isNotNullClean);
isNotNullClean.should.eql("IS NOT NULL");
});
});
describe('_cleanAndMapValues', function() {
it('Should convert camelCase property names to snakecase property names', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({firstName: 'John', lastName: 'Doe'});
Should.exist(output);
output.should.have.properties(['first_name','last_name']);
output.first_name.should.eql("'John'");
output.last_name.should.eql("'Doe'");
});
it('Should converts a VO to JS object and cleans that', function() {
const input = new UserCreateArgs({firstName: 'firstName', lastName: 'lastName', password: 'boom!'});
const output = mysqlDaoQueryHelper._cleanAndMapValues(input);
Should.exist(output);
output.should.have.properties(['first_name','last_name','password']);
output.first_name.should.eql("'firstName'");
output.last_name.should.eql("'lastName'");
output.password.should.eql("'boom!'");
});
it('Should converts an object with toJsObj defined cleans that', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
toJsObj: function() {
return {firstName: 'firstName', lastName: 'lastName', password: 'boom!'};
}
});
Should.exist(output);
output.should.have.properties(['first_name','last_name','password']);
output.first_name.should.eql("'firstName'");
output.last_name.should.eql("'lastName'");
output.password.should.eql("'boom!'");
});
it('Should converts an object with toJSON defined cleans that', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
toJSON: function() {
return {firstName: 'John', lastName: 'Doe', password: 'another'};
}
});
Should.exist(output);
output.should.have.properties(['first_name','last_name','password']);
output.first_name.should.eql("'John'");
output.last_name.should.eql("'Doe'");
output.password.should.eql("'another'");
});
it('Drops empty arrays and objects', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
firstName: 'firstName',
lastName: 'lastName',
password: 'boom!',
wontBeInOutput: [],
alsoWontBeThere: {}
});
Should.exist(output);
output.should.have.properties(['first_name','last_name','password']);
output.should.not.have.properties(['wont_be_in_output','also_wont_be_there']);
output.first_name.should.eql("'firstName'");
output.last_name.should.eql("'lastName'");
output.password.should.eql("'boom!'");
});
it('Escapes primitive values in arrays', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
firstName: 'firstName',
lastName: 'lastName',
password: 'boom!',
idArray: [1,2,{},"'bob",3,4]
});
Should.exist(output);
output.should.have.properties(['first_name','last_name','password','id_array']);
output.first_name.should.eql("'firstName'");
output.last_name.should.eql("'lastName'");
output.password.should.eql("'boom!'");
output.id_array.should.deepEqual(['1','2',"\'\\\'bob\'",'3','4'])
});
it('Allows special values (CURRENT_TIMESTAMP, NOW(), IS NULL, IS NOT NULL) and does not escape with quotes', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
firstName: 'firstName',
dateCreated: 'CURRENT_TIMESTAMP',
dateAgain: 'NOW()',
someNullField: 'IS NULL',
nonNullField: 'IS NOT NULL'
});
Should.exist(output);
output.should.have.properties(['first_name','date_created']);
output.first_name.should.eql("'firstName'");
output.date_created.should.eql("CURRENT_TIMESTAMP");
output.date_again.should.eql("NOW()");
output.some_null_field.should.eql("IS NULL");
output.non_null_field.should.eql("IS NOT NULL");
});
it('Escapes special values (CURRENT_TIMESTAMP, NOW(), IS NULL, IS NOT NULL) when explicitly asked', function() {
const output = mysqlDaoQueryHelper._cleanAndMapValues({
firstName: 'firstName',
dateCreated: 'CURRENT_TIMESTAMP',
dateAgain: 'NOW()',
someNullField: 'IS NULL',
nonNullField: 'IS NOT NULL'
}, false);
Should.exist(output);
output.should.have.properties(['first_name','date_created']);
output.first_name.should.eql("'firstName'");
output.date_created.should.eql("'CURRENT_TIMESTAMP'");
output.date_again.should.eql("'NOW()'");
output.some_null_field.should.eql("'IS NULL'");
output.non_null_field.should.eql("'IS NOT NULL'");
});
it('Convert undefined value to null', function() {
const someObj = {firstName: 'John', lastName: 'Doe'};
const output = mysqlDaoQueryHelper._cleanAndMapValues({
firstName: someObj.firstName,
lastName: someObj.lastName,
password: someObj.password
});
Should.exist(output);
output.should.have.properties(['first_name','last_name','password']);
output.first_name.should.eql("'John'");
output.last_name.should.eql("'Doe'");
output.password.should.eql("NULL");
});
});
describe('_appendWhereClause', function() {
it('Should generate good WHERE clause for standard object input', function() {
const sqlObj = Squel.select().from('users');
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {firstName: 'John', lastName: 'Doe'});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`first_name` = 'John') AND (`last_name` = 'Doe')");
});
it('Should generate good WHERE clause when input contains NULL value', function() {
const sqlObj = Squel.select().from('users');
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {firstName: 'John', lastName: null});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`first_name` = 'John') AND (`last_name` IS NULL)");
});
it('Should generate good WHERE clause when input contains undefined value (assumes it means NULL)', function() {
const sqlObj = Squel.select().from('users');
const someObj = {firstName: 'John'};
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {firstName: someObj.firstName, lastName: someObj.lastName});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`first_name` = 'John') AND (`last_name` IS NULL)");
});
it('Should generate good WHERE clause when input contains special functions', function() {
const sqlObj = Squel.select().from('users');
const someObj = {firstName: 'John'};
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {dateCreated: 'CURRENT_TIMESTAMP', dateUpdated: 'NOW()', email: 'IS NULL', firstName: 'IS NOT NULL'});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`date_created` = CURRENT_TIMESTAMP) AND (`date_updated` = NOW()) AND (`email` IS NULL) AND (`first_name` IS NOT NULL)");
});
it('Should generate good WHERE clause when input contains JSON path query', function() {
const sqlObj = Squel.select().from('users');
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {"meta->'$.is_active'": true});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`meta`->'$.is_active' = true)");
});
it('Should generate good WHERE clause when input contains JSON path query with already quoted column name', function() {
const sqlObj = Squel.select().from('users');
mysqlDaoQueryHelper._appendWhereClause(sqlObj, {"`meta`->'$.is_active'": true});
const sqlString = sqlObj.toString();
sqlString.should.eql("SELECT * FROM users WHERE (`meta`->'$.is_active' = true)");
});
});
describe('_getPropertyMappings', function() {
it('Should convert property keys to snake_case, but not JSON path fields', function() {
const mapped = MysqlDaoQueryHelper._getPropertyMappings({
propertyOne: 1,
propertyTwo: 2,
"meta->'$.is_active'": true
});
mapped.should.eql({
propertyOne: 'property_one',
propertyTwo: 'property_two',
"meta->'$.is_active'": "meta->'$.is_active'"
});
});
});
describe('_cleanValueForOperator', function() {
it('Should clean array values for in and in operators', function() {
const cleanedValue = mysqlDaoQueryHelper._cleanValueForOperator('in', ['\'a\'','\'b\'','\'c\'']);
cleanedValue.should.eql('(\'a\',\'b\',\'c\')');
});
it('Should pass the value for other operators through unchanged', function() {
const cleanedValue = mysqlDaoQueryHelper._cleanValueForOperator('gte', 5);
cleanedValue.should.eql(5);
})
});
describe('_cleanQueryOperator', function() {
it('Should clean array values for in and in operators', function() {
const cleanedValue = mysqlDaoQueryHelper._cleanQueryOperator('ne', 'NULL');
cleanedValue.should.eql('IS NOT');
});
});
});