Add updateBatch method to query builder
This commit is contained in:
parent
a94038cd47
commit
4064a99419
68
.eslintrc
68
.eslintrc
@ -1,39 +1,43 @@
|
||||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
"commonjs": true,
|
||||
"es6": true,
|
||||
"jest": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": ["eslint:recommended", "happiness"],
|
||||
"rules": {
|
||||
"arrow-parens": [2, "as-needed"],
|
||||
"no-console": [1],
|
||||
"no-constant-condition": [1],
|
||||
"no-extra-semi": [1],
|
||||
"no-func-assign": [1],
|
||||
"no-obj-calls": [2],
|
||||
"no-unexpected-multiline" : [2],
|
||||
"no-unneeded-ternary": [2],
|
||||
"radix": [2],
|
||||
"no-with": [2],
|
||||
"no-eval": [2],
|
||||
"no-unreachable": [1],
|
||||
"no-irregular-whitespace": [1],
|
||||
"no-new-wrappers": [2],
|
||||
"no-new-func": [2],
|
||||
"curly" : [2, "multi-line"],
|
||||
"no-implied-eval": [2],
|
||||
"no-invalid-this": [2],
|
||||
"constructor-super": [2],
|
||||
"no-dupe-args": [2],
|
||||
"no-dupe-keys": [2],
|
||||
"no-dupe-class-members": [2],
|
||||
"no-this-before-super": [2],
|
||||
"prefer-arrow-callback": [1],
|
||||
"no-var": [2],
|
||||
"valid-jsdoc": [1],
|
||||
"strict": [2, "global"],
|
||||
"callback-return": [1],
|
||||
"object-shorthand": [1, "methods"],
|
||||
"prefer-template": [1]
|
||||
"arrow-parens": ["error", "as-needed"],
|
||||
"callback-return": ["warn"],
|
||||
"constructor-super": ["error"],
|
||||
"curly" : ["error", "multi-line"],
|
||||
"no-case-declarations": "off",
|
||||
"no-console": ["warn"],
|
||||
"no-constant-condition": ["warn"],
|
||||
"no-dupe-args": ["error"],
|
||||
"no-dupe-class-members": ["error"],
|
||||
"no-dupe-keys": ["error"],
|
||||
"no-eval": ["error"],
|
||||
"no-extra-semi": ["warn"],
|
||||
"no-func-assign": ["warn"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-invalid-this": ["error"],
|
||||
"no-irregular-whitespace": ["warn"],
|
||||
"no-new-func": ["error"],
|
||||
"no-new-wrappers": ["error"],
|
||||
"no-obj-calls": ["error"],
|
||||
"no-this-before-super": ["error"],
|
||||
"no-unexpected-multiline" : ["error"],
|
||||
"no-unneeded-ternary": ["error"],
|
||||
"no-unreachable": ["warn"],
|
||||
"no-var": ["error"],
|
||||
"no-with": ["error"],
|
||||
"object-shorthand": ["warn", "methods"],
|
||||
"prefer-arrow-callback": ["warn"],
|
||||
"prefer-template": ["warn"],
|
||||
"radix": ["error"],
|
||||
"strict": ["error", "global"],
|
||||
"valid-jsdoc": ["warn"]
|
||||
},
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
const array = require('locutus/php/array');
|
||||
const Helpers = require('./Helpers');
|
||||
|
||||
/**
|
||||
@ -64,36 +65,38 @@ const Driver = {
|
||||
* @return {String|Array} - Quoted identifier(s)
|
||||
*/
|
||||
quoteIdentifiers (str) {
|
||||
let hiers, raw;
|
||||
let pattern = new RegExp(
|
||||
const pattern = new RegExp(
|
||||
`${Driver.identifierStartChar}(` +
|
||||
'([a-zA-Z0-9_]+)' + '(((.*?)))' +
|
||||
`)${Driver.identifierEndChar}`, 'ig');
|
||||
|
||||
// Recurse for arrays of identifiiers
|
||||
// Recurse for arrays of identifiers
|
||||
if (Array.isArray(str)) {
|
||||
return str.map(Driver.quoteIdentifiers);
|
||||
}
|
||||
|
||||
// cast to string so that you don't have undefined method errors with junk data
|
||||
str = String(str);
|
||||
|
||||
// Handle commas
|
||||
if (str.includes(',')) {
|
||||
let parts = str.split(',').map(Helpers.stringTrim);
|
||||
const parts = str.split(',').map(Helpers.stringTrim);
|
||||
str = parts.map(Driver.quoteIdentifiers).join(',');
|
||||
}
|
||||
|
||||
// Split identifiers by period
|
||||
hiers = str.split('.').map(Driver._quote);
|
||||
raw = hiers.join('.');
|
||||
const hierarchies = str.split('.').map(Driver._quote);
|
||||
let raw = hierarchies.join('.');
|
||||
|
||||
// Fix functions
|
||||
if (raw.includes('(') && raw.includes(')')) {
|
||||
let funcs = pattern.exec(raw);
|
||||
const functionCalls = pattern.exec(raw);
|
||||
|
||||
// Unquote the function
|
||||
raw = raw.replace(funcs[0], funcs[1]);
|
||||
raw = raw.replace(functionCalls[0], functionCalls[1]);
|
||||
|
||||
// Quote the identifiers inside of the parens
|
||||
let inParens = funcs[3].substring(1, funcs[3].length - 1);
|
||||
const inParens = functionCalls[3].substring(1, functionCalls[3].length - 1);
|
||||
raw = raw.replace(inParens, Driver.quoteIdentifiers(inParens));
|
||||
}
|
||||
|
||||
@ -126,7 +129,7 @@ const Driver = {
|
||||
* @return {String} - Query and data to insert
|
||||
*/
|
||||
insertBatch (table, data) {
|
||||
const vals = [];
|
||||
const values = [];
|
||||
const fields = Object.keys(data[0]);
|
||||
let sql = '';
|
||||
|
||||
@ -134,7 +137,7 @@ const Driver = {
|
||||
// be parameterized
|
||||
data.forEach(obj => {
|
||||
Object.keys(obj).forEach(key => {
|
||||
vals.push(obj[key]);
|
||||
values.push(obj[key]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -145,16 +148,79 @@ const Driver = {
|
||||
sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `;
|
||||
|
||||
// Create placeholder groups
|
||||
let params = Array(fields.length).fill('?');
|
||||
let paramString = `(${params.join(',')})`;
|
||||
let paramList = Array(data.length).fill(paramString);
|
||||
const params = Array(fields.length).fill('?');
|
||||
const paramString = `(${params.join(',')})`;
|
||||
const paramList = Array(data.length).fill(paramString);
|
||||
|
||||
sql += paramList.join(',');
|
||||
|
||||
return {
|
||||
sql: sql,
|
||||
values: vals
|
||||
values: values
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a batch update sql statement
|
||||
*
|
||||
* @private
|
||||
* @param {String} table
|
||||
* @param {Array<Object>} data
|
||||
* @param {String} updateKey
|
||||
* @return {Array<String,Object,Number>} array
|
||||
*/
|
||||
updateBatch (table, data, updateKey) {
|
||||
let affectedRows = 0;
|
||||
let insertData = [];
|
||||
const fieldLines = [];
|
||||
|
||||
let sql = `UPDATE ${Driver.quoteTable(table)} SET `;
|
||||
|
||||
// get the keys of the current set of data, except the one used to
|
||||
// set the update condition
|
||||
const fields = data.reduce((previous, current) => {
|
||||
affectedRows++;
|
||||
const keys = Object.keys(current).filter(key => {
|
||||
return key !== updateKey && !previous.includes(key);
|
||||
});
|
||||
return previous.concat(keys);
|
||||
}, []);
|
||||
|
||||
// Create the CASE blocks for each data set
|
||||
fields.forEach(field => {
|
||||
let line = `${Driver.quoteIdentifiers(field)} = CASE\n`;
|
||||
const cases = [];
|
||||
data.forEach(currentCase => {
|
||||
insertData.push(currentCase[updateKey]);
|
||||
insertData.push(currentCase[field]);
|
||||
|
||||
const newCase = `WHEN ${Driver.quoteIdentifiers(updateKey)} =? THEN ? `;
|
||||
cases.push(newCase);
|
||||
});
|
||||
|
||||
line += `${cases.join('\n')}\n`;
|
||||
line += `ELSE ${Driver.quoteIdentifiers(field)} END`;
|
||||
|
||||
fieldLines.push(line);
|
||||
});
|
||||
|
||||
sql += `${fieldLines.join(',\n')}\n`;
|
||||
|
||||
const whereValues = [];
|
||||
data.forEach(entry => {
|
||||
const insertValue = entry[updateKey];
|
||||
whereValues.push(insertValue);
|
||||
insertData.push(insertValue);
|
||||
});
|
||||
|
||||
// Create the placeholders for the WHERE IN clause
|
||||
const placeholders = Array(whereValues.length);
|
||||
placeholders.fill('?');
|
||||
|
||||
sql += `WHERE ${Driver.quoteIdentifiers(updateKey)} IN `;
|
||||
sql += `( ${placeholders.join(',')} )`;
|
||||
|
||||
return [sql, insertData, affectedRows];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,7 @@ class Helpers {
|
||||
* @return {String} - Type of the object
|
||||
*/
|
||||
static type (o) {
|
||||
let type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||
const type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||
|
||||
// handle NaN and Infinity
|
||||
if (type === 'number') {
|
||||
@ -62,11 +62,10 @@ class Helpers {
|
||||
* Determine whether an object is scalar
|
||||
*
|
||||
* @param {mixed} obj - Object to test
|
||||
* @return {bool} - Is object scalar
|
||||
* @return {boolean} - Is object scalar
|
||||
*/
|
||||
static isScalar (obj) {
|
||||
let scalar = ['string', 'number', 'boolean'];
|
||||
return scalar.indexOf(Helpers.type(obj)) !== -1;
|
||||
return ['string', 'number', 'boolean'].includes(Helpers.type(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,7 +76,7 @@ class Helpers {
|
||||
* @return {Array} - The new array of plucked values
|
||||
*/
|
||||
static arrayPluck (arr, key) {
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
// Empty case
|
||||
if (arr.length === 0) {
|
||||
@ -119,20 +118,20 @@ class Helpers {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first letter of the string uppercase
|
||||
* Make the first constter of the string uppercase
|
||||
*
|
||||
* @param {String} str - The string to modify
|
||||
* @return {String} - The modified string
|
||||
*/
|
||||
static upperCaseFirst (str) {
|
||||
str += '';
|
||||
let first = str.charAt(0).toUpperCase();
|
||||
const first = str.charAt(0).toUpperCase();
|
||||
return first + str.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Define an 'is' method for each type
|
||||
let types = [
|
||||
const types = [
|
||||
'Null',
|
||||
'Undefined',
|
||||
'Object',
|
||||
|
@ -50,17 +50,16 @@ class NodeQuery {
|
||||
this.instance = null;
|
||||
|
||||
if (config !== undefined) {
|
||||
let drivername = dbDriverMap.get(config.driver);
|
||||
const driverName = dbDriverMap.get(config.driver);
|
||||
|
||||
if (!drivername) {
|
||||
if (!driverName) {
|
||||
throw new Error(`Selected driver (${config.driver}) does not exist!`);
|
||||
}
|
||||
|
||||
const driver = require(`./drivers/${drivername}`);
|
||||
const Adapter = require(`./adapters/${drivername}`);
|
||||
const driver = require(`./drivers/${driverName}`);
|
||||
const Adapter = require(`./adapters/${driverName}`);
|
||||
|
||||
let adapter = Adapter(config);
|
||||
this.instance = new QueryBuilder(driver, adapter);
|
||||
this.instance = new QueryBuilder(driver, Adapter(config));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
}
|
||||
});
|
||||
|
||||
let safeArray = this.driver.quoteIdentifiers(fields);
|
||||
const safeArray = this.driver.quoteIdentifiers(fields);
|
||||
|
||||
// Join the strings back together
|
||||
safeArray.forEach((field, index) => {
|
||||
@ -378,8 +378,8 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
table = table.join(' ');
|
||||
|
||||
// Parse out the join condition
|
||||
let parsedCondition = this.parser.compileJoin(cond);
|
||||
let condition = `${table} ON ${parsedCondition}`;
|
||||
const parsedCondition = this.parser.compileJoin(cond);
|
||||
const condition = `${table} ON ${parsedCondition}`;
|
||||
|
||||
// Append the join condition to the query map
|
||||
this._appendMap(`\n${type.toUpperCase()} JOIN `, condition, 'join');
|
||||
@ -395,7 +395,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
*/
|
||||
groupBy (field) {
|
||||
if (!Helpers.isScalar(field)) {
|
||||
let newGroupArray = field.map(this.driver.quoteIdentifiers);
|
||||
const newGroupArray = field.map(this.driver.quoteIdentifiers);
|
||||
this.state.groupArray = this.state.groupArray.concat(newGroupArray);
|
||||
} else {
|
||||
this.state.groupArray.push(this.driver.quoteIdentifiers(field));
|
||||
@ -421,7 +421,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
|
||||
this.state.orderArray[field] = type;
|
||||
|
||||
let orderClauses = [];
|
||||
const orderClauses = [];
|
||||
|
||||
// Flatten key/val pairs into an array of space-separated pairs
|
||||
Object.keys(this.state.orderArray).forEach(key => {
|
||||
@ -454,7 +454,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||
*/
|
||||
groupStart () {
|
||||
let conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
|
||||
const conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
|
||||
this._appendMap(conj, '(', 'groupStart');
|
||||
|
||||
return this;
|
||||
@ -549,7 +549,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
* @return {Promise<Result>} - Promise containing the result of the query
|
||||
*/
|
||||
insertBatch (table, data) {
|
||||
let batch = this.driver.insertBatch(table, data);
|
||||
const batch = this.driver.insertBatch(table, data);
|
||||
|
||||
// Run the query
|
||||
return this.query(batch.sql, batch.values);
|
||||
@ -571,6 +571,20 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
return this._run('update', this.driver.quoteTable(table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a batch update sql statement
|
||||
*
|
||||
* @param {String} table - The table to update
|
||||
* @param {Object} data - Batch insert data
|
||||
* @param {String} updateKey - The field in the table to compare against for updating
|
||||
* @return {Number} Number of rows updated
|
||||
*/
|
||||
updateBatch (table, data, updateKey) {
|
||||
const [sql, insertData, affectedRows] = this.driver.updateBatch(table, data, updateKey);
|
||||
this._run('', table, sql, insertData);
|
||||
return affectedRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the generated delete query
|
||||
*
|
||||
@ -613,7 +627,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledInsert (table, reset) {
|
||||
getCompiledInsert (table, reset = true) {
|
||||
return this._getCompile('insert', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
@ -624,7 +638,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledUpdate (table, reset) {
|
||||
getCompiledUpdate (table, reset = true) {
|
||||
return this._getCompile('update', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
|
||||
@ -635,7 +649,7 @@ class QueryBuilder extends QueryBuilderBase {
|
||||
* @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
|
||||
* @return {String} - The compiled sql statement
|
||||
*/
|
||||
getCompiledDelete (table, reset) {
|
||||
getCompiledDelete (table, reset = true) {
|
||||
return this._getCompile('delete', this.driver.quoteTable(table), reset);
|
||||
}
|
||||
}
|
||||
|
@ -16,74 +16,6 @@ class QueryBuilderBase {
|
||||
this.state = new State();
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the sql building based on the type provided
|
||||
*
|
||||
* @private
|
||||
* @param {String} type - Type of SQL query
|
||||
* @param {String} table - The table to run the query on
|
||||
* @return {String} - The compiled sql
|
||||
*/
|
||||
_compile (type, table) {
|
||||
// Put together the basic query
|
||||
let sql = this._compileType(type, table);
|
||||
|
||||
// Set each subClause
|
||||
['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => {
|
||||
let param = this.state[clause];
|
||||
|
||||
if (!Helpers.isScalar(param)) {
|
||||
Object.keys(param).forEach(part => {
|
||||
sql += param[part].conjunction + param[part].string;
|
||||
});
|
||||
} else {
|
||||
sql += param;
|
||||
}
|
||||
});
|
||||
|
||||
// Append the limit, if it exists
|
||||
if (Helpers.isNumber(this.state.limit)) {
|
||||
sql = this.driver.limit(sql, this.state.limit, this.state.offset);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_compileType (type, table) {
|
||||
let sql = '';
|
||||
|
||||
switch (type) {
|
||||
case 'insert':
|
||||
let params = Array(this.state.setArrayKeys.length).fill('?');
|
||||
|
||||
sql = `INSERT INTO ${table} (`;
|
||||
sql += this.state.setArrayKeys.join(',');
|
||||
sql += `) VALUES (${params.join(',')})`;
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
sql = `UPDATE ${table} SET ${this.state.setString}`;
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
sql = `DELETE FROM ${table}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
sql = `SELECT * FROM ${this.state.fromString}`;
|
||||
|
||||
// Set the select string
|
||||
if (this.state.selectString.length > 0) {
|
||||
// Replace the star with the selected fields
|
||||
sql = sql.replace('*', this.state.selectString);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_like (field, val, pos, like, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
|
||||
@ -147,7 +79,7 @@ class QueryBuilderBase {
|
||||
Object.keys(obj).forEach(k => {
|
||||
// If a single value for the return
|
||||
if (['key', 'value'].indexOf(valType) !== -1) {
|
||||
let pushVal = (valType === 'key') ? k : obj[k];
|
||||
const pushVal = (valType === 'key') ? k : obj[k];
|
||||
this.state[letName].push(pushVal);
|
||||
} else {
|
||||
this.state[letName][k] = obj[k];
|
||||
@ -166,8 +98,8 @@ class QueryBuilderBase {
|
||||
}
|
||||
|
||||
_fixConjunction (conj) {
|
||||
let lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
||||
let conjunctionList = Helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
||||
const lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
||||
const conjunctionList = Helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
||||
|
||||
if (this.state.queryMap.length === 0 || (!Helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) {
|
||||
conj = ' WHERE ';
|
||||
@ -189,7 +121,7 @@ class QueryBuilderBase {
|
||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||
|
||||
this.state.whereMap.forEach(clause => {
|
||||
let conj = this._fixConjunction(defaultConj);
|
||||
const conj = this._fixConjunction(defaultConj);
|
||||
this._appendMap(conj, clause, 'where');
|
||||
});
|
||||
|
||||
@ -198,7 +130,7 @@ class QueryBuilderBase {
|
||||
|
||||
_whereNull (field, stmt, conj) {
|
||||
field = this.driver.quoteIdentifiers(field);
|
||||
let item = `${field} ${stmt}`;
|
||||
const item = `${field} ${stmt}`;
|
||||
|
||||
this._appendMap(this._fixConjunction(conj), item, 'whereNull');
|
||||
}
|
||||
@ -225,7 +157,7 @@ class QueryBuilderBase {
|
||||
|
||||
_whereIn (key, val, inClause, conj) {
|
||||
key = this.driver.quoteIdentifiers(key);
|
||||
let params = Array(val.length);
|
||||
const params = Array(val.length);
|
||||
params.fill('?');
|
||||
|
||||
val.forEach(value => {
|
||||
@ -233,7 +165,7 @@ class QueryBuilderBase {
|
||||
});
|
||||
|
||||
conj = (this.state.queryMap.length > 0) ? ` ${conj} ` : ' WHERE ';
|
||||
let str = `${key} ${inClause} (${params.join(',')}) `;
|
||||
const str = `${key} ${inClause} (${params.join(',')}) `;
|
||||
|
||||
this._appendMap(conj, str, 'whereIn');
|
||||
}
|
||||
@ -257,7 +189,7 @@ class QueryBuilderBase {
|
||||
_getCompile (type, table, reset) {
|
||||
reset = reset || false;
|
||||
|
||||
let sql = this._compile(type, table);
|
||||
const sql = this._compile(type, table);
|
||||
|
||||
if (reset) {
|
||||
this._resetState();
|
||||
@ -266,6 +198,74 @@ class QueryBuilderBase {
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete the sql building based on the type provided
|
||||
*
|
||||
* @private
|
||||
* @param {String} type - Type of SQL query
|
||||
* @param {String} table - The table to run the query on
|
||||
* @return {String} - The compiled sql
|
||||
*/
|
||||
_compile (type, table) {
|
||||
// Put together the basic query
|
||||
let sql = this._compileType(type, table);
|
||||
|
||||
// Set each subClause
|
||||
['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(clause => {
|
||||
const param = this.state[clause];
|
||||
|
||||
if (!Helpers.isScalar(param)) {
|
||||
Object.keys(param).forEach(part => {
|
||||
sql += param[part].conjunction + param[part].string;
|
||||
});
|
||||
} else {
|
||||
sql += param;
|
||||
}
|
||||
});
|
||||
|
||||
// Append the limit, if it exists
|
||||
if (Helpers.isNumber(this.state.limit)) {
|
||||
sql = this.driver.limit(sql, this.state.limit, this.state.offset);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_compileType (type, table) {
|
||||
let sql = '';
|
||||
|
||||
switch (type) {
|
||||
case 'insert':
|
||||
const params = Array(this.state.setArrayKeys.length).fill('?');
|
||||
|
||||
sql = `INSERT INTO ${table} (`;
|
||||
sql += this.state.setArrayKeys.join(',');
|
||||
sql += `) VALUES (${params.join(',')})`;
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
sql = `UPDATE ${table} SET ${this.state.setString}`;
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
sql = `DELETE FROM ${table}`;
|
||||
break;
|
||||
|
||||
default:
|
||||
sql = `SELECT * FROM ${this.state.fromString}`;
|
||||
|
||||
// Set the select string
|
||||
if (this.state.selectString.length > 0) {
|
||||
// Replace the star with the selected fields
|
||||
sql = sql.replace('*', this.state.selectString);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
_resetState () {
|
||||
this.state = new State();
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class QueryParser {
|
||||
* @return {Array|null} - Filtered set of possible matches
|
||||
*/
|
||||
filterMatches (array) {
|
||||
let output = [];
|
||||
const output = [];
|
||||
|
||||
// Return non-array matches
|
||||
if (Helpers.isNull(array)) {
|
||||
@ -85,8 +85,8 @@ class QueryParser {
|
||||
* @return {Object} - Join condition components
|
||||
*/
|
||||
parseJoin (sql) {
|
||||
let matches = {};
|
||||
let output = {
|
||||
const matches = {};
|
||||
const output = {
|
||||
functions: [],
|
||||
identifiers: [],
|
||||
operators: [],
|
||||
@ -117,7 +117,7 @@ class QueryParser {
|
||||
* @return {String} - The parsed/escaped join condition
|
||||
*/
|
||||
compileJoin (condition) {
|
||||
let parts = this.parseJoin(condition);
|
||||
const parts = this.parseJoin(condition);
|
||||
|
||||
// Quote the identifiers
|
||||
parts.combined.forEach((part, i) => {
|
||||
@ -137,11 +137,11 @@ class QueryParser {
|
||||
* @return {String} - The parsed/escaped where condition
|
||||
*/
|
||||
parseWhere (driver, state) {
|
||||
let whereMap = state.whereMap;
|
||||
const whereMap = state.whereMap;
|
||||
let whereValues = state.rawWhereValues;
|
||||
|
||||
let outputMap = [];
|
||||
let outputValues = [];
|
||||
const outputMap = [];
|
||||
const outputValues = [];
|
||||
|
||||
Object.keys(whereMap).forEach(key => {
|
||||
// Combine fields, operators, functions and values into a full clause
|
||||
@ -158,16 +158,16 @@ class QueryParser {
|
||||
}
|
||||
|
||||
// Separate the clause into separate pieces
|
||||
let parts = this.parseJoin(fullClause);
|
||||
const parts = this.parseJoin(fullClause);
|
||||
|
||||
// Filter explicit literals from lists of matches
|
||||
if (whereValues.indexOf(whereMap[key]) !== -1) {
|
||||
let value = whereMap[key];
|
||||
let identIndex = parts.identifiers.indexOf(value);
|
||||
let litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||
let combIndex = parts.combined.indexOf(value);
|
||||
let funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||
let inOutputArray = outputValues.indexOf(value) !== -1;
|
||||
const value = whereMap[key];
|
||||
const identIndex = parts.identifiers.indexOf(value);
|
||||
const litIndex = (Helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||
const combIndex = parts.combined.indexOf(value);
|
||||
const funcIndex = (Helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||
let inOutputArray = outputValues.includes(value);
|
||||
|
||||
// Remove the identifier in question,
|
||||
// and add to the output values array
|
||||
@ -201,8 +201,8 @@ class QueryParser {
|
||||
|
||||
// Filter false positive identifiers
|
||||
parts.identifiers = parts.identifiers.filter(item => {
|
||||
let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||
let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||
const isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||
const isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||
|
||||
return isInCombinedMatches && isNotInBlackList;
|
||||
}, this);
|
||||
@ -210,7 +210,7 @@ class QueryParser {
|
||||
// Quote identifiers
|
||||
if (Helpers.isArray(parts.identifiers)) {
|
||||
parts.identifiers.forEach(ident => {
|
||||
let index = parts.combined.indexOf(ident);
|
||||
const index = parts.combined.indexOf(ident);
|
||||
if (index !== -1) {
|
||||
parts.combined[index] = driver.quoteIdentifiers(ident);
|
||||
}
|
||||
@ -224,7 +224,7 @@ class QueryParser {
|
||||
// a where condition,
|
||||
if (Helpers.isArray(parts.literals)) {
|
||||
parts.literals.forEach(lit => {
|
||||
let litIndex = parts.combined.indexOf(lit);
|
||||
const litIndex = parts.combined.indexOf(lit);
|
||||
|
||||
if (litIndex !== -1) {
|
||||
parts.combined[litIndex] = '?';
|
||||
|
@ -1,5 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = config => {
|
||||
|
||||
};
|
||||
|
@ -36,7 +36,7 @@ class Mysql extends Adapter {
|
||||
* Run the sql query as a prepared statement
|
||||
*
|
||||
* @param {String} sql - The sql with placeholders
|
||||
* @param {Array|undefined} params - The values to insert into the query
|
||||
* @param {Array} params - The values to insert into the query
|
||||
* @return {Promise} Result of query
|
||||
*/
|
||||
execute (sql, params) {
|
||||
|
@ -7,28 +7,10 @@ const url = require('url');
|
||||
class Pg extends Adapter {
|
||||
constructor (config) {
|
||||
let instance = null;
|
||||
let connectionString = '';
|
||||
if (Helpers.isObject(config)) {
|
||||
let host = config.host || 'localhost';
|
||||
let user = config.user || 'postgres';
|
||||
let password = `:${config.password}` || '';
|
||||
let port = config.port || 5432;
|
||||
|
||||
let conn = {
|
||||
protocol: 'postgres',
|
||||
slashes: true,
|
||||
host: `${host}:${port}`,
|
||||
auth: `${user}${password}`,
|
||||
pathname: config.database
|
||||
};
|
||||
|
||||
connectionString = url.format(conn);
|
||||
} else if (Helpers.isString(config)) {
|
||||
connectionString = config;
|
||||
}
|
||||
let connectionString = Pg.formatConnectionString(config);
|
||||
|
||||
if (connectionString !== '') {
|
||||
let conn = new pg.Client(connectionString);
|
||||
const conn = new pg.Client(connectionString);
|
||||
conn.connect(err => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
@ -41,6 +23,37 @@ class Pg extends Adapter {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the connection object to a connection string
|
||||
*
|
||||
* @param {Object} config - the configuration object
|
||||
* @return {String} - the connection string
|
||||
*/
|
||||
static formatConnectionString (config) {
|
||||
let connectionString = '';
|
||||
|
||||
if (Helpers.isObject(config)) {
|
||||
const host = config.host || 'localhost';
|
||||
const user = config.user || 'postgres';
|
||||
const password = `:${config.password}` || '';
|
||||
const port = config.port || 5432;
|
||||
|
||||
const conn = {
|
||||
protocol: 'postgres',
|
||||
slashes: true,
|
||||
host: `${host}:${port}`,
|
||||
auth: `${user}${password}`,
|
||||
pathname: config.database
|
||||
};
|
||||
|
||||
connectionString = url.format(conn);
|
||||
} else if (Helpers.isString(config)) {
|
||||
connectionString = config;
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the adapter's result into a standard format
|
||||
*
|
||||
@ -52,9 +65,9 @@ class Pg extends Adapter {
|
||||
return new Result();
|
||||
}
|
||||
|
||||
let cols = [];
|
||||
const cols = [];
|
||||
result.fields.forEach(field => {
|
||||
cols = field.name;
|
||||
cols.push(field.name);
|
||||
});
|
||||
|
||||
return new Result(result.rows, cols);
|
||||
|
@ -1,25 +0,0 @@
|
||||
const Pg = require('./Pg');
|
||||
const pg = require('pg').native;
|
||||
|
||||
class PgNative extends Pg {
|
||||
constructor (config) {
|
||||
super(config);
|
||||
let instance = null;
|
||||
let connectionString = Pg._formatConnectionString(config);
|
||||
|
||||
if (connectionString !== '') {
|
||||
let conn = new pg.Client(connectionString);
|
||||
conn.connect(err => {
|
||||
if (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
});
|
||||
|
||||
instance = Promise.resolve(conn);
|
||||
}
|
||||
|
||||
super.instance = instance;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PgNative;
|
@ -1,8 +1,2 @@
|
||||
const Pg = require('./Pg');
|
||||
const PgNative = require('./PgNative');
|
||||
|
||||
module.exports = config => {
|
||||
return (config.native)
|
||||
? new PgNative(config.connection)
|
||||
: new Pg(config.connection);
|
||||
};
|
||||
module.exports = config => new Pg(config.connection);
|
||||
|
@ -5,10 +5,10 @@ const dbliteAdapter = require('dblite');
|
||||
|
||||
class SqliteDblite extends Adapter {
|
||||
constructor (config) {
|
||||
let file = (Helpers.isString(config)) ? config : config.file;
|
||||
const file = (Helpers.isString(config)) ? config : config.file;
|
||||
|
||||
const instance = new Promise((resolve, reject) => {
|
||||
let conn = dbliteAdapter(file);
|
||||
const conn = dbliteAdapter(file);
|
||||
|
||||
// Stop the stupid 'bye bye' message being output
|
||||
conn.on('close', () => {});
|
||||
|
@ -5,10 +5,10 @@ const sqlite3 = require('sqlite3').verbose();
|
||||
|
||||
class SqliteSqlite3 extends Adapter {
|
||||
constructor (config) {
|
||||
let file = (Helpers.isString(config)) ? config : config.file;
|
||||
const file = (Helpers.isString(config)) ? config : config.file;
|
||||
|
||||
const instance = new Promise((resolve, reject) => {
|
||||
let conn = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, err => {
|
||||
const conn = new sqlite3.Database(file, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, err => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Driver for Microsoft SQL Server databases
|
||||
*
|
||||
@ -8,7 +6,6 @@
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
const driver = require('../Driver');
|
||||
const Helpers = require('../Helpers');
|
||||
|
||||
driver.identifierStartChar = '[';
|
||||
driver.identifierEndChar = ']';
|
||||
|
@ -5,7 +5,5 @@
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
let driver = require('../Driver');
|
||||
|
||||
return driver;
|
||||
return require('../Driver');
|
||||
})();
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
module.exports = (() => {
|
||||
delete require.cache[require.resolve('../Driver')];
|
||||
let driver = require('../Driver');
|
||||
const driver = require('../Driver');
|
||||
|
||||
// Sqlite doesn't have a truncate command
|
||||
driver.hasTruncate = false;
|
||||
@ -22,11 +22,11 @@ module.exports = (() => {
|
||||
// Get the data values to insert, so they can
|
||||
// be parameterized
|
||||
let sql = '';
|
||||
let first = data.shift();
|
||||
const first = data.shift();
|
||||
|
||||
let vals = [];
|
||||
const vals = [];
|
||||
data.forEach(obj => {
|
||||
let row = [];
|
||||
const row = [];
|
||||
Object.keys(obj).forEach(key => {
|
||||
row.push(obj[key]);
|
||||
});
|
||||
@ -37,8 +37,8 @@ module.exports = (() => {
|
||||
|
||||
// Get the field names from the keys of the first
|
||||
// object to be inserted
|
||||
let fields = Object.keys(first);
|
||||
let cols = [];
|
||||
const fields = Object.keys(first);
|
||||
const cols = [];
|
||||
fields.forEach(key => {
|
||||
cols.push(`'${driver._quote(first[key])}' AS ${driver.quoteIdentifiers(key)}`);
|
||||
});
|
||||
@ -46,7 +46,7 @@ module.exports = (() => {
|
||||
sql += `SELECT ${cols.join(', ')}\n`;
|
||||
|
||||
vals.forEach(rowValues => {
|
||||
let quoted = rowValues.map(value => String(value).replace('\'', '\'\''));
|
||||
const quoted = rowValues.map(value => String(value).replace('\'', '\'\''));
|
||||
sql += `UNION ALL SELECT '${quoted.join('\', \'')}'\n`;
|
||||
});
|
||||
|
||||
|
30
package.json
30
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ci-node-query",
|
||||
"version": "6.0.0",
|
||||
"version": "5.0.0",
|
||||
"description": "A query builder for node based on the one in CodeIgniter",
|
||||
"author": "Timothy J Warren <tim@timshomepage.net>",
|
||||
"engines": {
|
||||
@ -42,27 +42,31 @@
|
||||
"glob": "^7.0.3",
|
||||
"mysql2": "^1.2.0",
|
||||
"pg": "^7.4",
|
||||
"require-reload": "~0.2.2",
|
||||
"sqlite3": "^3.1.8",
|
||||
"tedious": "^2.0.0",
|
||||
"xregexp": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^8.2.1",
|
||||
"chai": "^4.1",
|
||||
"chai-as-promised": "^7.1",
|
||||
"documentation": "latest",
|
||||
"eslint": "^4.16.0",
|
||||
"eslint-config-happiness": "^10.2.1",
|
||||
"eslint-plugin-import": "^2.8.0",
|
||||
"eslint-plugin-node": "^5.2.1",
|
||||
"eslint-plugin-promise": "^3.6.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"globstar": "^1.0.0",
|
||||
"happiness": "^10.0",
|
||||
"jest": "^22.0.0",
|
||||
"jsdoc": "^3.4.3",
|
||||
"npm-run-all": "^4.0.2",
|
||||
"nsp": "^3.1",
|
||||
"pg-native": "^2.2"
|
||||
"require-reload": "~0.2.2"
|
||||
},
|
||||
"license": "MIT",
|
||||
"jest": {
|
||||
"collectCoverageFrom": [
|
||||
"lib/**/*.js"
|
||||
],
|
||||
"coverageDirectory": "coverage",
|
||||
"coverageReporters": [
|
||||
"html",
|
||||
@ -82,21 +86,11 @@
|
||||
"default": "npm-run-all --parallel audit lint:src lint:tests && npm run test",
|
||||
"predocs": "globstar -- documentation build -f md -o API.md \"lib/*.js\"",
|
||||
"docs": "globstar -- documentation build -f html -o docs \"lib/*.js\"",
|
||||
"fix": "happiness --fix \"lib/**/*.js\" \"test/**/*.js\"",
|
||||
"fix": "eslint --fix ./lib ./test",
|
||||
"postdocs": "jsdoc lib -r -d documentation",
|
||||
"happy": "happiness \"lib/**/*.js\" \"test/**/*.js\"",
|
||||
"happy:src": "happiness \"lib/**/*.js\"",
|
||||
"happy:tests": "happiness \"test/**/*.js\"",
|
||||
"lint": "npm-run-all lint:tests lint:src happy",
|
||||
"lint": "npm-run-all lint:src lint:tests",
|
||||
"lint:src": "eslint ./lib",
|
||||
"lint:tests": "eslint ./test",
|
||||
"test": "jest"
|
||||
},
|
||||
"happiness": {
|
||||
"env": {
|
||||
"es6": true,
|
||||
"jest": true
|
||||
},
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
}
|
||||
|
11
test/adapters/__snapshots__/dblite_test.js.snap
Normal file
11
test/adapters/__snapshots__/dblite_test.js.snap
Normal file
@ -0,0 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Dblite adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`;
|
||||
|
||||
exports[`Dblite adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`;
|
||||
|
||||
exports[`Dblite adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Dblite adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Dblite adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`;
|
11
test/adapters/__snapshots__/mysql2_test.js.snap
Normal file
11
test/adapters/__snapshots__/mysql2_test.js.snap
Normal file
@ -0,0 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Mysql2 adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \`create_test\` WHERE \`id\` = ?"`;
|
||||
|
||||
exports[`Mysql2 adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \`create_test\` (\`id\`,\`key\`,\`val\`) VALUES (?,?,?)"`;
|
||||
|
||||
exports[`Mysql2 adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \`id\`, \`key\` AS \`k\`, \`val\` FROM \`create_test\` WHERE (\`id\` > ? AND \`id\` < ?) LIMIT 1,2"`;
|
||||
|
||||
exports[`Mysql2 adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \`id\`, \`key\` AS \`k\`, \`val\` FROM \`create_test\` WHERE (\`id\` > ? AND \`id\` < ?) LIMIT 1,2"`;
|
||||
|
||||
exports[`Mysql2 adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \`create_test\` SET \`id\`=?,\`key\`=?,\`val\`=? WHERE \`id\` = ?"`;
|
11
test/adapters/__snapshots__/pg_test.js.snap
Normal file
11
test/adapters/__snapshots__/pg_test.js.snap
Normal file
@ -0,0 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Pg adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`;
|
||||
|
||||
exports[`Pg adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`;
|
||||
|
||||
exports[`Pg adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Pg adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Pg adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`;
|
11
test/adapters/__snapshots__/sqlite3_test.js.snap
Normal file
11
test/adapters/__snapshots__/sqlite3_test.js.snap
Normal file
@ -0,0 +1,11 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Sqlite3 adapter tests - Get compiled - getCompiledDelete 1`] = `"DELETE FROM \\"create_test\\" WHERE \\"id\\" = ?"`;
|
||||
|
||||
exports[`Sqlite3 adapter tests - Get compiled - getCompiledInsert 1`] = `"INSERT INTO \\"create_test\\" (\\"id\\",\\"key\\",\\"val\\") VALUES (?,?,?)"`;
|
||||
|
||||
exports[`Sqlite3 adapter tests - Get compiled - getCompiledSelect 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Sqlite3 adapter tests - Get compiled - getCompiledSelect 2 1`] = `"SELECT \\"id\\", \\"key\\" AS \\"k\\", \\"val\\" FROM \\"create_test\\" WHERE (\\"id\\" > ? AND \\"id\\" < ?) LIMIT 2 OFFSET 1"`;
|
||||
|
||||
exports[`Sqlite3 adapter tests - Get compiled - getCompiledUpdate 1`] = `"UPDATE \\"create_test\\" SET \\"id\\"=?,\\"key\\"=?,\\"val\\"=? WHERE \\"id\\" = ?"`;
|
@ -19,7 +19,7 @@ describe('Dblite adapter tests -', () => {
|
||||
});
|
||||
|
||||
testRunner(qb);
|
||||
it('Promise - Select with function and argument in WHERE clause', async () => {
|
||||
it('Select with function and argument in WHERE clause', async () => {
|
||||
let promise = await qb.select('id')
|
||||
.from('create_test')
|
||||
.where('id', 'ABS(-88)')
|
||||
@ -27,26 +27,6 @@ describe('Dblite adapter tests -', () => {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Insert Batch', async () => {
|
||||
let data = [
|
||||
{
|
||||
id: 544,
|
||||
key: 3,
|
||||
val: Buffer.from('7')
|
||||
}, {
|
||||
id: 89,
|
||||
key: 34,
|
||||
val: Buffer.from('10 o\'clock')
|
||||
}, {
|
||||
id: 48,
|
||||
key: 403,
|
||||
val: Buffer.from('97')
|
||||
}
|
||||
];
|
||||
|
||||
let promise = await qb.insertBatch('create_test', data);
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
afterAll(() => {
|
||||
qb.end();
|
||||
});
|
||||
|
@ -24,7 +24,7 @@ describe('Mysql2 adapter tests -', () => {
|
||||
});
|
||||
|
||||
testRunner(qb);
|
||||
it('Promise - Select with function and argument in WHERE clause', async () => {
|
||||
it('Select with function and argument in WHERE clause', async () => {
|
||||
let promise = await qb.select('id')
|
||||
.from('create_test')
|
||||
.where('id', 'CEILING(SQRT(88))')
|
||||
@ -36,28 +36,7 @@ describe('Mysql2 adapter tests -', () => {
|
||||
let promise = await qb.truncate('create_test');
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Test Insert Batch', async () => {
|
||||
let data = [
|
||||
{
|
||||
id: 5442,
|
||||
key: 4,
|
||||
val: Buffer.from('7')
|
||||
}, {
|
||||
id: 892,
|
||||
key: 35,
|
||||
val: Buffer.from('10 o\'clock')
|
||||
}, {
|
||||
id: 482,
|
||||
key: 404,
|
||||
val: 97
|
||||
}
|
||||
];
|
||||
|
||||
const promise = await qb.insertBatch('create_test', data);
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
|
||||
/* describeTeardown(() => {
|
||||
afterAll(() => {
|
||||
qb.end();
|
||||
}); */
|
||||
});
|
||||
});
|
||||
|
@ -45,36 +45,16 @@ describe('Pg adapter tests -', () => {
|
||||
});
|
||||
|
||||
testRunner(qb);
|
||||
it('Promise - Select with function and argument in WHERE clause', async () => {
|
||||
let promise = await qb.select('id')
|
||||
it('Select with function and argument in WHERE clause', async () => {
|
||||
const promise = await qb.select('id')
|
||||
.from('create_test')
|
||||
.where('id', 'CEILING(SQRT(88))')
|
||||
.get();
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Truncate', async () => {
|
||||
let promise = await qb.truncate('create_test');
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Insert Batch', async () => {
|
||||
let data = [
|
||||
{
|
||||
id: 544,
|
||||
key: 3,
|
||||
val: Buffer.from('7')
|
||||
}, {
|
||||
id: 89,
|
||||
key: 34,
|
||||
val: Buffer.from('10 o\'clock')
|
||||
}, {
|
||||
id: 48,
|
||||
key: 403,
|
||||
val: Buffer.from('97')
|
||||
}
|
||||
];
|
||||
|
||||
let promise = await qb.insertBatch('create_test', data);
|
||||
it('Test Truncate', async () => {
|
||||
const promise = await qb.truncate('create_test');
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
afterAll(() => {
|
||||
|
@ -20,7 +20,7 @@ describe('Sqlite3 adapter tests -', () => {
|
||||
});
|
||||
|
||||
testRunner(qb);
|
||||
it('Promise - Select with function and argument in WHERE clause', async () => {
|
||||
it('Select with function and argument in WHERE clause', async () => {
|
||||
let promise = await qb.select('id')
|
||||
.from('create_test')
|
||||
.where('id', 'ABS(-88)')
|
||||
@ -28,26 +28,6 @@ describe('Sqlite3 adapter tests -', () => {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Insert Batch', async () => {
|
||||
let data = [
|
||||
{
|
||||
id: 544,
|
||||
key: 3,
|
||||
val: Buffer.from('7')
|
||||
}, {
|
||||
id: 89,
|
||||
key: 34,
|
||||
val: Buffer.from('10 o\'clock')
|
||||
}, {
|
||||
id: 48,
|
||||
key: 403,
|
||||
val: Buffer.from('97')
|
||||
}
|
||||
];
|
||||
|
||||
let promise = await qb.insertBatch('create_test', data);
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
afterAll(() => {
|
||||
qb.end();
|
||||
});
|
||||
|
@ -1,13 +1,8 @@
|
||||
const chai = require('chai');
|
||||
const chaiAsPromised = require('chai-as-promised');
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
// Load the test config file
|
||||
const configFile = './config.json';
|
||||
|
||||
module.exports = {
|
||||
config: require(configFile),
|
||||
expect: chai.expect,
|
||||
tests: require('./base/tests'),
|
||||
promiseTestRunner: require('./base/adapterPromiseTestRunner')
|
||||
};
|
||||
|
@ -37,13 +37,14 @@ module.exports = function promiseTestRunner (qb) {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('DB update tests -', async () => {
|
||||
|
||||
describe('DB update tests -', () => {
|
||||
beforeAll(done => {
|
||||
let sql = qb.driver.truncate('create_test');
|
||||
qb.query(sql).then(res => done())
|
||||
qb.query(sql).then(() => done())
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it('Promise - Test Insert', async () => {
|
||||
it('Test Insert', async () => {
|
||||
const promise = await qb.set('id', 98)
|
||||
.set('key', '84')
|
||||
.set('val', Buffer.from('120'))
|
||||
@ -51,7 +52,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Insert Object', async () => {
|
||||
it('Test Insert Object', async () => {
|
||||
const promise = await qb.insert('create_test', {
|
||||
id: 587,
|
||||
key: 1,
|
||||
@ -60,7 +61,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test Update', async () => {
|
||||
it('Test Update', async () => {
|
||||
const promise = await qb.where('id', 7)
|
||||
.update('create_test', {
|
||||
id: 7,
|
||||
@ -70,7 +71,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test set Array Update', async () => {
|
||||
it('Test set Array Update', async () => {
|
||||
let object = {
|
||||
id: 22,
|
||||
key: 'gogle',
|
||||
@ -83,7 +84,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test where set update', async () => {
|
||||
it('Test where set update', async () => {
|
||||
const promise = await qb.where('id', 36)
|
||||
.set('id', 36)
|
||||
.set('key', 'gogle')
|
||||
@ -92,17 +93,17 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Test delete', async () => {
|
||||
it('Test delete', async () => {
|
||||
const promise = await qb.delete('create_test', {id: 5});
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Delete with where', async () => {
|
||||
it('Delete with where', async () => {
|
||||
const promise = await qb.where('id', 5)
|
||||
.delete('create_test');
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Delete multiple where values', async () => {
|
||||
it('Delete multiple where values', async () => {
|
||||
const promise = await qb.delete('create_test', {
|
||||
id: 5,
|
||||
key: 'gogle'
|
||||
@ -111,8 +112,46 @@ module.exports = function promiseTestRunner (qb) {
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
});
|
||||
describe('Grouping tests -', async () => {
|
||||
it('Promise - Using grouping method', async () => {
|
||||
|
||||
describe('Batch tests -', () => {
|
||||
it('Test Insert Batch', async () => {
|
||||
const data = [
|
||||
{
|
||||
id: 544,
|
||||
key: 3,
|
||||
val: Buffer.from('7')
|
||||
}, {
|
||||
id: 89,
|
||||
key: 34,
|
||||
val: Buffer.from('10 o\'clock')
|
||||
}, {
|
||||
id: 48,
|
||||
key: 403,
|
||||
val: Buffer.from('97')
|
||||
}
|
||||
];
|
||||
|
||||
const promise = await qb.insertBatch('create_test', data);
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Test Update Batch', async () => {
|
||||
const data = [{
|
||||
id: 480,
|
||||
key: 49,
|
||||
val: '7x7'
|
||||
}, {
|
||||
id: 890,
|
||||
key: 100,
|
||||
val: '10x10'
|
||||
}];
|
||||
|
||||
const affectedRows = qb.updateBatch('create_test', data, 'id');
|
||||
expect(affectedRows).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Grouping tests -', () => {
|
||||
it('Using grouping method', async () => {
|
||||
const promise = await qb.select('id, key as k, val')
|
||||
.from('create_test')
|
||||
.groupStart()
|
||||
@ -124,7 +163,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Using where first grouping', async () => {
|
||||
it('Using where first grouping', async () => {
|
||||
const promise = await qb.select('id, key as k, val')
|
||||
.from('create_test')
|
||||
.where('id !=', 5)
|
||||
@ -137,7 +176,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Using or grouping method', async () => {
|
||||
it('Using or grouping method', async () => {
|
||||
const promise = await qb.select('id, key as k, val')
|
||||
.from('create_test')
|
||||
.groupStart()
|
||||
@ -152,7 +191,7 @@ module.exports = function promiseTestRunner (qb) {
|
||||
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
it('Promise - Using or not grouping method', async () => {
|
||||
it('Using or not grouping method', async () => {
|
||||
const promise = await qb.select('id, key as k, val')
|
||||
.from('create_test')
|
||||
.groupStart()
|
||||
@ -168,4 +207,51 @@ module.exports = function promiseTestRunner (qb) {
|
||||
expect(promise).toEqual(expect.anything());
|
||||
});
|
||||
});
|
||||
describe('Get compiled - ', () => {
|
||||
it('getCompiledSelect', () => {
|
||||
const sql = qb.select('id, key as k, val')
|
||||
.from('create_test')
|
||||
.groupStart()
|
||||
.where('id >', 1)
|
||||
.where('id <', 900)
|
||||
.groupEnd()
|
||||
.limit(2, 1)
|
||||
.getCompiledSelect();
|
||||
|
||||
expect(sql).toMatchSnapshot();
|
||||
});
|
||||
it('getCompiledSelect 2', () => {
|
||||
const sql = qb.select('id, key as k, val')
|
||||
.groupStart()
|
||||
.where('id >', 1)
|
||||
.where('id <', 900)
|
||||
.groupEnd()
|
||||
.limit(2, 1)
|
||||
.getCompiledSelect('create_test');
|
||||
|
||||
expect(sql).toMatchSnapshot();
|
||||
});
|
||||
it('getCompiledInsert', () => {
|
||||
const sql = qb.set({
|
||||
id: 587,
|
||||
key: 1,
|
||||
val: Buffer.from('2')
|
||||
}).getCompiledInsert('create_test');
|
||||
|
||||
expect(sql).toMatchSnapshot();
|
||||
});
|
||||
it('getCompiledUpdate', () => {
|
||||
const sql = qb.where('id', 36)
|
||||
.set('id', 36)
|
||||
.set('key', 'gogle')
|
||||
.set('val', Buffer.from('non-word'))
|
||||
.getCompiledUpdate('create_test');
|
||||
|
||||
expect(sql).toMatchSnapshot();
|
||||
});
|
||||
it('getCompiledDelete', () => {
|
||||
const sql = qb.where({id: 5}).getCompiledDelete('create_test');
|
||||
expect(sql).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -18,6 +18,18 @@
|
||||
"database": "test"
|
||||
}
|
||||
},
|
||||
"pg-native": {
|
||||
"driver": "pg",
|
||||
"native": true,
|
||||
"connection": "postgres://test:test@posgres/test"
|
||||
},
|
||||
"pg-object-native": {
|
||||
"driver": "pg",
|
||||
"native": true,
|
||||
"connection": {
|
||||
"database": "test"
|
||||
}
|
||||
},
|
||||
"dblite": {
|
||||
"adapter": "dblite",
|
||||
"driver": "sqlite",
|
||||
@ -26,14 +38,5 @@
|
||||
"sqlite3": {
|
||||
"driver": "sqlite",
|
||||
"connection": ":memory:"
|
||||
},
|
||||
"node-firebird": {
|
||||
"driver": "firebird",
|
||||
"connection": {
|
||||
"host": "127.0.0.1",
|
||||
"database": "/../FB_TEST_DB.FDB",
|
||||
"user": "SYSDBA",
|
||||
"password": "masterkey"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user