Update dependencies and switch to Happiness code style
This commit is contained in:
parent
d3e5da66c4
commit
8d7e4aaa8c
7
.jscsrc
7
.jscsrc
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"preset": "airbnb",
|
|
||||||
"validateIndentation": null,
|
|
||||||
"requireLineFeedAtFileEnd": null,
|
|
||||||
"disallowSpaceAfterPrefixUnaryOperators": null,
|
|
||||||
"disallowMultipleVarDecl": null
|
|
||||||
}
|
|
2
API.md
2
API.md
@ -1,3 +1,5 @@
|
|||||||
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
||||||
|
|
||||||
# limit
|
# limit
|
||||||
|
|
||||||
Set the limit clause
|
Set the limit clause
|
||||||
|
@ -95,3 +95,5 @@ As of version 2, `where` and `having` type methods parse the values passed to lo
|
|||||||
* The `tests/adapters` folder contains examples of how to set up a connection for the appropriate database library
|
* The `tests/adapters` folder contains examples of how to set up a connection for the appropriate database library
|
||||||
* The documentation generated for the latest dev build is also [Available](https://github.timshomepage.net/node-query/docs/index.html)
|
* The documentation generated for the latest dev build is also [Available](https://github.timshomepage.net/node-query/docs/index.html)
|
||||||
|
|
||||||
|
[![js-happiness-style](https://cdn.rawgit.com/JedWatson/happiness/master/badge.svg)](https://github.com/JedWatson/happiness)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const helpers = require('./helpers');
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
let Driver = {
|
const Driver = {
|
||||||
identifierStartChar: '"',
|
identifierStartChar: '"',
|
||||||
identifierEndChar: '"',
|
identifierEndChar: '"',
|
||||||
tablePrefix: null,
|
tablePrefix: null,
|
||||||
@ -21,8 +21,8 @@ let Driver = {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_quote (str) {
|
_quote (str) {
|
||||||
return (helpers.isString(str)
|
return (helpers.isString(str) &&
|
||||||
&& ! (str.startsWith(Driver.identifierStartChar) || str.endsWith(Driver.identifierEndChar))
|
!(str.startsWith(Driver.identifierStartChar) || str.endsWith(Driver.identifierEndChar))
|
||||||
)
|
)
|
||||||
? `${Driver.identifierStartChar}${str}${Driver.identifierEndChar}`
|
? `${Driver.identifierStartChar}${str}${Driver.identifierEndChar}`
|
||||||
: str;
|
: str;
|
||||||
@ -39,8 +39,7 @@ let Driver = {
|
|||||||
limit (sql, limit, offset) {
|
limit (sql, limit, offset) {
|
||||||
sql += ` LIMIT ${limit}`;
|
sql += ` LIMIT ${limit}`;
|
||||||
|
|
||||||
if (helpers.isNumber(offset))
|
if (helpers.isNumber(offset)) {
|
||||||
{
|
|
||||||
sql += ` OFFSET ${offset}`;
|
sql += ` OFFSET ${offset}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,19 +66,17 @@ let Driver = {
|
|||||||
quoteIdentifiers (str) {
|
quoteIdentifiers (str) {
|
||||||
let hiers, raw;
|
let hiers, raw;
|
||||||
let pattern = new RegExp(
|
let pattern = new RegExp(
|
||||||
`${Driver.identifierStartChar}(`
|
`${Driver.identifierStartChar}(` +
|
||||||
+ '([a-zA-Z0-9_]+)' + '(\((.*?)\))'
|
'([a-zA-Z0-9_]+)' + '(((.*?)))' +
|
||||||
+ `)${Driver.identifierEndChar}`, 'ig');
|
`)${Driver.identifierEndChar}`, 'ig');
|
||||||
|
|
||||||
// Recurse for arrays of identifiiers
|
// Recurse for arrays of identifiiers
|
||||||
if (Array.isArray(str))
|
if (Array.isArray(str)) {
|
||||||
{
|
|
||||||
return str.map(Driver.quoteIdentifiers);
|
return str.map(Driver.quoteIdentifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle commas
|
// Handle commas
|
||||||
if (str.includes(','))
|
if (str.includes(',')) {
|
||||||
{
|
|
||||||
let parts = str.split(',').map(helpers.stringTrim);
|
let parts = str.split(',').map(helpers.stringTrim);
|
||||||
str = parts.map(Driver.quoteIdentifiers).join(',');
|
str = parts.map(Driver.quoteIdentifiers).join(',');
|
||||||
}
|
}
|
||||||
@ -89,8 +86,7 @@ let Driver = {
|
|||||||
raw = hiers.join('.');
|
raw = hiers.join('.');
|
||||||
|
|
||||||
// Fix functions
|
// Fix functions
|
||||||
if (raw.includes('(') && raw.includes(')'))
|
if (raw.includes('(') && raw.includes(')')) {
|
||||||
{
|
|
||||||
let funcs = pattern.exec(raw);
|
let funcs = pattern.exec(raw);
|
||||||
|
|
||||||
// Unquote the function
|
// Unquote the function
|
||||||
@ -128,12 +124,9 @@ let Driver = {
|
|||||||
* @return {String} - Query and data to insert
|
* @return {String} - Query and data to insert
|
||||||
*/
|
*/
|
||||||
insertBatch (table, data) {
|
insertBatch (table, data) {
|
||||||
let vals = [],
|
const vals = [];
|
||||||
fields = Object.keys(data[0]),
|
const fields = Object.keys(data[0]);
|
||||||
sql = '',
|
let sql = '';
|
||||||
params = [],
|
|
||||||
paramString = '',
|
|
||||||
paramList = [];
|
|
||||||
|
|
||||||
// Get the data values to insert, so they can
|
// Get the data values to insert, so they can
|
||||||
// be parameterized
|
// be parameterized
|
||||||
@ -150,17 +143,17 @@ let Driver = {
|
|||||||
sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `;
|
sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `;
|
||||||
|
|
||||||
// Create placeholder groups
|
// Create placeholder groups
|
||||||
params = Array(fields.length).fill('?');
|
let params = Array(fields.length).fill('?');
|
||||||
paramString = `(${params.join(',')})`;
|
let paramString = `(${params.join(',')})`;
|
||||||
paramList = Array(data.length).fill(paramString);
|
let paramList = Array(data.length).fill(paramString);
|
||||||
|
|
||||||
sql += paramList.join(',');
|
sql += paramList.join(',');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sql: sql,
|
sql: sql,
|
||||||
values: vals,
|
values: vals
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Driver;
|
module.exports = Driver;
|
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const helpers = require('./helpers');
|
|
||||||
const QueryBuilder = require('./QueryBuilder');
|
const QueryBuilder = require('./QueryBuilder');
|
||||||
|
|
||||||
// Map config driver name to code class name
|
// Map config driver name to code class name
|
||||||
@ -14,7 +13,7 @@ const dbDriverMap = new Map([
|
|||||||
['postgres', 'Pg'],
|
['postgres', 'Pg'],
|
||||||
['pg', 'Pg'],
|
['pg', 'Pg'],
|
||||||
['sqlite3', 'Sqlite'],
|
['sqlite3', 'Sqlite'],
|
||||||
['sqlite', 'Sqlite'],
|
['sqlite', 'Sqlite']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +22,6 @@ const dbDriverMap = new Map([
|
|||||||
* @param {object} config - connection parameters
|
* @param {object} config - connection parameters
|
||||||
*/
|
*/
|
||||||
class NodeQuery {
|
class NodeQuery {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -52,10 +50,10 @@ class NodeQuery {
|
|||||||
throw new Error(`Selected driver (${config.driver}) does not exist!`);
|
throw new Error(`Selected driver (${config.driver}) does not exist!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let driver = require(`./drivers/${drivername}`);
|
const driver = require(`./drivers/${drivername}`);
|
||||||
let $adapter = require(`./adapters/${drivername}`);
|
const Adapter = require(`./adapters/${drivername}`);
|
||||||
|
|
||||||
let adapter = new $adapter(config.connection);
|
let adapter = new Adapter(config.connection);
|
||||||
this.instance = new QueryBuilder(driver, adapter);
|
this.instance = new QueryBuilder(driver, adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,4 +72,4 @@ class NodeQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (config => new NodeQuery(config));
|
module.exports = config => new NodeQuery(config);
|
||||||
|
@ -2,308 +2,16 @@
|
|||||||
|
|
||||||
const getArgs = require('getargs');
|
const getArgs = require('getargs');
|
||||||
const helpers = require('./helpers');
|
const helpers = require('./helpers');
|
||||||
const State = require('./State');
|
const QueryBuilderBase = require('./QueryBuilderBase');
|
||||||
const QueryParser = require('./QueryParser');
|
|
||||||
|
|
||||||
class QueryBuilderBase {
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @constructor
|
|
||||||
* @param {Driver} Driver - The syntax driver for the database
|
|
||||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
|
||||||
*/
|
|
||||||
constructor(Driver, Adapter) {
|
|
||||||
this.driver = Driver;
|
|
||||||
this.adapter = Adapter;
|
|
||||||
this.parser = new QueryParser(this.driver);
|
|
||||||
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);
|
|
||||||
|
|
||||||
like = `${field} ${like} ?`;
|
|
||||||
|
|
||||||
if (pos === 'before') {
|
|
||||||
val = `%${val}`;
|
|
||||||
} else if (pos === 'after') {
|
|
||||||
val = `${val}%`;
|
|
||||||
} else {
|
|
||||||
val = `%${val}%`;
|
|
||||||
}
|
|
||||||
|
|
||||||
conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;
|
|
||||||
this._appendMap(conj, like, 'like');
|
|
||||||
|
|
||||||
this.state.whereValues.push(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a clause to the query map
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {String} conjunction - linking keyword for the clause
|
|
||||||
* @param {String} string - pre-compiled sql fragment
|
|
||||||
* @param {String} type - type of sql clause
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
_appendMap(conjunction, string, type) {
|
|
||||||
this.state.queryMap.push({
|
|
||||||
type: type,
|
|
||||||
conjunction: conjunction,
|
|
||||||
string: string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle key/value pairs in an object the same way as individual arguments,
|
|
||||||
* when appending to state
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @return {Array} - modified state array
|
|
||||||
*/
|
|
||||||
_mixedSet(/* $letName, $valType, $key, [$val] */) {
|
|
||||||
const argPattern = '$letName:string, $valType:string, $key:object|string|number, [$val]';
|
|
||||||
let args = getArgs(argPattern, arguments);
|
|
||||||
|
|
||||||
let obj = {};
|
|
||||||
|
|
||||||
if (helpers.isScalar(args.$key) && !helpers.isUndefined(args.$val)) {
|
|
||||||
// Convert key/val pair to a simple object
|
|
||||||
obj[args.$key] = args.$val;
|
|
||||||
} else if (helpers.isScalar(args.$key) && helpers.isUndefined(args.$val)) {
|
|
||||||
// If just a string for the key, and no value, create a simple object with duplicate key/val
|
|
||||||
obj[args.$key] = args.$key;
|
|
||||||
} else {
|
|
||||||
obj = args.$key;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(obj).forEach(k => {
|
|
||||||
// If a single value for the return
|
|
||||||
if (['key', 'value'].indexOf(args.$valType) !== -1) {
|
|
||||||
let pushVal = (args.$valType === 'key') ? k : obj[k];
|
|
||||||
this.state[args.$letName].push(pushVal);
|
|
||||||
} else {
|
|
||||||
this.state[args.$letName][k] = obj[k];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.state[args.$letName];
|
|
||||||
}
|
|
||||||
|
|
||||||
_whereMixedSet(/*key, val*/) {
|
|
||||||
let args = getArgs('key:string|object, [val]', arguments);
|
|
||||||
|
|
||||||
this.state.whereMap = [];
|
|
||||||
this.state.rawWhereValues = [];
|
|
||||||
|
|
||||||
this._mixedSet('whereMap', 'both', args.key, args.val);
|
|
||||||
this._mixedSet('rawWhereValues', 'value', args.key, args.val);
|
|
||||||
}
|
|
||||||
|
|
||||||
_fixConjunction(conj) {
|
|
||||||
let lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
|
||||||
let conjunctionList = helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
|
||||||
|
|
||||||
if (this.state.queryMap.length === 0 || (! helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) {
|
|
||||||
conj = ' WHERE ';
|
|
||||||
} else if (lastItem.type === 'groupStart') {
|
|
||||||
conj = '';
|
|
||||||
} else {
|
|
||||||
conj = ` ${conj} `;
|
|
||||||
}
|
|
||||||
|
|
||||||
return conj;
|
|
||||||
}
|
|
||||||
|
|
||||||
_where(key, val, defaultConj) {
|
|
||||||
// Normalize key and value and insert into this.state.whereMap
|
|
||||||
this._whereMixedSet(key, val);
|
|
||||||
|
|
||||||
// Parse the where condition to account for operators,
|
|
||||||
// functions, identifiers, and literal values
|
|
||||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
|
||||||
|
|
||||||
this.state.whereMap.forEach(clause => {
|
|
||||||
let conj = this._fixConjunction(defaultConj);
|
|
||||||
this._appendMap(conj, clause, 'where');
|
|
||||||
});
|
|
||||||
|
|
||||||
this.state.whereMap = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
_whereNull(field, stmt, conj) {
|
|
||||||
field = this.driver.quoteIdentifiers(field);
|
|
||||||
let item = `${field} ${stmt}`;
|
|
||||||
|
|
||||||
this._appendMap(this._fixConjunction(conj), item, 'whereNull');
|
|
||||||
}
|
|
||||||
|
|
||||||
_having(/*key, val, conj*/) {
|
|
||||||
let args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments);
|
|
||||||
args.conj = args.conj || 'AND';
|
|
||||||
args.val = args.val || null;
|
|
||||||
|
|
||||||
// Normalize key/val and put in state.whereMap
|
|
||||||
this._whereMixedSet(args.key, args.val);
|
|
||||||
|
|
||||||
// Parse the having condition to account for operators,
|
|
||||||
// functions, identifiers, and literal values
|
|
||||||
this.state = this.parser.parseWhere(this.driver, this.state);
|
|
||||||
|
|
||||||
this.state.whereMap.forEach(clause => {
|
|
||||||
// Put in the having map
|
|
||||||
this.state.havingMap.push({
|
|
||||||
conjunction: (this.state.havingMap.length > 0) ? ` ${args.conj} ` : ' HAVING ',
|
|
||||||
string: clause,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear the where Map
|
|
||||||
this.state.whereMap = {};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
_whereIn(/*key, val, inClause, conj*/) {
|
|
||||||
let args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);
|
|
||||||
|
|
||||||
args.key = this.driver.quoteIdentifiers(args.key);
|
|
||||||
let params = Array(args.val.length);
|
|
||||||
params.fill('?');
|
|
||||||
|
|
||||||
args.val.forEach(value => {
|
|
||||||
this.state.whereValues.push(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
args.conj = (this.state.queryMap.length > 0) ? ` ${args.conj} ` : ' WHERE ';
|
|
||||||
let str = `${args.key} ${args.inClause} (${params.join(',')}) `;
|
|
||||||
|
|
||||||
this._appendMap(args.conj, str, 'whereIn');
|
|
||||||
}
|
|
||||||
|
|
||||||
_run(type, table, callback, sql, vals) {
|
|
||||||
|
|
||||||
if (! sql) {
|
|
||||||
sql = this._compile(type, table);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! vals) {
|
|
||||||
vals = this.state.values.concat(this.state.whereValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the state so another query can be built
|
|
||||||
this._resetState();
|
|
||||||
|
|
||||||
// Pass the sql and values to the adapter to run on the database
|
|
||||||
if (callback) {
|
|
||||||
return this.query(sql, vals, callback);
|
|
||||||
} else {
|
|
||||||
return this.query(sql, vals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_getCompile(type, table, reset) {
|
|
||||||
reset = reset || false;
|
|
||||||
|
|
||||||
let sql = this._compile(type, table);
|
|
||||||
|
|
||||||
if (reset) {
|
|
||||||
this._resetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
return sql;
|
|
||||||
}
|
|
||||||
|
|
||||||
_resetState() {
|
|
||||||
this.state = new State();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main object that builds SQL queries.
|
* Main object that builds SQL queries.
|
||||||
*
|
*
|
||||||
* @param {Driver} Driver - The syntax driver for the database
|
* @param {Driver} Driver - The syntax driver for the database
|
||||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||||
|
* @extends QueryBuilderBase
|
||||||
*/
|
*/
|
||||||
class QueryBuilder extends QueryBuilderBase {
|
class QueryBuilder extends QueryBuilderBase {
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @constructor
|
|
||||||
* @param {Driver} Driver - The syntax driver for the database
|
|
||||||
* @param {Adapter} Adapter - The database module adapter for running queries
|
|
||||||
*/
|
|
||||||
constructor(Driver, Adapter) {
|
|
||||||
super(Driver, Adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ! Miscellaneous Methods
|
// ! Miscellaneous Methods
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -376,7 +84,6 @@ class QueryBuilder extends QueryBuilderBase {
|
|||||||
* @return {QueryBuilder} - The Query Builder object, for chaining
|
* @return {QueryBuilder} - The Query Builder object, for chaining
|
||||||
*/
|
*/
|
||||||
select (fields) {
|
select (fields) {
|
||||||
|
|
||||||
// Split/trim fields by comma
|
// Split/trim fields by comma
|
||||||
fields = (Array.isArray(fields))
|
fields = (Array.isArray(fields))
|
||||||
? fields
|
? fields
|
||||||
|
288
lib/QueryBuilderBase.js
Normal file
288
lib/QueryBuilderBase.js
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const getArgs = require('getargs');
|
||||||
|
const helpers = require('./helpers');
|
||||||
|
const QueryParser = require('./QueryParser');
|
||||||
|
const State = require('./State');
|
||||||
|
|
||||||
|
class QueryBuilderBase {
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @constructor
|
||||||
|
* @param {Driver} Driver - The syntax driver for the database
|
||||||
|
* @param {Adapter} Adapter - The database module adapter for running queries
|
||||||
|
*/
|
||||||
|
constructor (Driver, Adapter) {
|
||||||
|
this.driver = Driver;
|
||||||
|
this.adapter = Adapter;
|
||||||
|
this.parser = new QueryParser(this.driver);
|
||||||
|
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);
|
||||||
|
|
||||||
|
like = `${field} ${like} ?`;
|
||||||
|
|
||||||
|
if (pos === 'before') {
|
||||||
|
val = `%${val}`;
|
||||||
|
} else if (pos === 'after') {
|
||||||
|
val = `${val}%`;
|
||||||
|
} else {
|
||||||
|
val = `%${val}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;
|
||||||
|
this._appendMap(conj, like, 'like');
|
||||||
|
|
||||||
|
this.state.whereValues.push(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a clause to the query map
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} conjunction - linking keyword for the clause
|
||||||
|
* @param {String} string - pre-compiled sql fragment
|
||||||
|
* @param {String} type - type of sql clause
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
_appendMap (conjunction, string, type) {
|
||||||
|
this.state.queryMap.push({
|
||||||
|
type: type,
|
||||||
|
conjunction: conjunction,
|
||||||
|
string: string
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle key/value pairs in an object the same way as individual arguments,
|
||||||
|
* when appending to state
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @return {Array} - modified state array
|
||||||
|
*/
|
||||||
|
_mixedSet (/* $letName, $valType, $key, [$val] */) {
|
||||||
|
const argPattern = '$letName:string, $valType:string, $key:object|string|number, [$val]';
|
||||||
|
let args = getArgs(argPattern, arguments);
|
||||||
|
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
if (helpers.isScalar(args.$key) && !helpers.isUndefined(args.$val)) {
|
||||||
|
// Convert key/val pair to a simple object
|
||||||
|
obj[args.$key] = args.$val;
|
||||||
|
} else if (helpers.isScalar(args.$key) && helpers.isUndefined(args.$val)) {
|
||||||
|
// If just a string for the key, and no value, create a simple object with duplicate key/val
|
||||||
|
obj[args.$key] = args.$key;
|
||||||
|
} else {
|
||||||
|
obj = args.$key;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(obj).forEach(k => {
|
||||||
|
// If a single value for the return
|
||||||
|
if (['key', 'value'].indexOf(args.$valType) !== -1) {
|
||||||
|
let pushVal = (args.$valType === 'key') ? k : obj[k];
|
||||||
|
this.state[args.$letName].push(pushVal);
|
||||||
|
} else {
|
||||||
|
this.state[args.$letName][k] = obj[k];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.state[args.$letName];
|
||||||
|
}
|
||||||
|
|
||||||
|
_whereMixedSet (/* key, val */) {
|
||||||
|
let args = getArgs('key:string|object, [val]', arguments);
|
||||||
|
|
||||||
|
this.state.whereMap = [];
|
||||||
|
this.state.rawWhereValues = [];
|
||||||
|
|
||||||
|
this._mixedSet('whereMap', 'both', args.key, args.val);
|
||||||
|
this._mixedSet('rawWhereValues', 'value', args.key, args.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fixConjunction (conj) {
|
||||||
|
let lastItem = this.state.queryMap[this.state.queryMap.length - 1];
|
||||||
|
let conjunctionList = helpers.arrayPluck(this.state.queryMap, 'conjunction');
|
||||||
|
|
||||||
|
if (this.state.queryMap.length === 0 || (!helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) {
|
||||||
|
conj = ' WHERE ';
|
||||||
|
} else if (lastItem.type === 'groupStart') {
|
||||||
|
conj = '';
|
||||||
|
} else {
|
||||||
|
conj = ` ${conj} `;
|
||||||
|
}
|
||||||
|
|
||||||
|
return conj;
|
||||||
|
}
|
||||||
|
|
||||||
|
_where (key, val, defaultConj) {
|
||||||
|
// Normalize key and value and insert into this.state.whereMap
|
||||||
|
this._whereMixedSet(key, val);
|
||||||
|
|
||||||
|
// Parse the where condition to account for operators,
|
||||||
|
// functions, identifiers, and literal values
|
||||||
|
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||||
|
|
||||||
|
this.state.whereMap.forEach(clause => {
|
||||||
|
let conj = this._fixConjunction(defaultConj);
|
||||||
|
this._appendMap(conj, clause, 'where');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.state.whereMap = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_whereNull (field, stmt, conj) {
|
||||||
|
field = this.driver.quoteIdentifiers(field);
|
||||||
|
let item = `${field} ${stmt}`;
|
||||||
|
|
||||||
|
this._appendMap(this._fixConjunction(conj), item, 'whereNull');
|
||||||
|
}
|
||||||
|
|
||||||
|
_having (/* key, val, conj */) {
|
||||||
|
let args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments);
|
||||||
|
args.conj = args.conj || 'AND';
|
||||||
|
args.val = args.val || null;
|
||||||
|
|
||||||
|
// Normalize key/val and put in state.whereMap
|
||||||
|
this._whereMixedSet(args.key, args.val);
|
||||||
|
|
||||||
|
// Parse the having condition to account for operators,
|
||||||
|
// functions, identifiers, and literal values
|
||||||
|
this.state = this.parser.parseWhere(this.driver, this.state);
|
||||||
|
|
||||||
|
this.state.whereMap.forEach(clause => {
|
||||||
|
// Put in the having map
|
||||||
|
this.state.havingMap.push({
|
||||||
|
conjunction: (this.state.havingMap.length > 0) ? ` ${args.conj} ` : ' HAVING ',
|
||||||
|
string: clause
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear the where Map
|
||||||
|
this.state.whereMap = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_whereIn (/* key, val, inClause, conj */) {
|
||||||
|
let args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);
|
||||||
|
|
||||||
|
args.key = this.driver.quoteIdentifiers(args.key);
|
||||||
|
let params = Array(args.val.length);
|
||||||
|
params.fill('?');
|
||||||
|
|
||||||
|
args.val.forEach(value => {
|
||||||
|
this.state.whereValues.push(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
args.conj = (this.state.queryMap.length > 0) ? ` ${args.conj} ` : ' WHERE ';
|
||||||
|
let str = `${args.key} ${args.inClause} (${params.join(',')}) `;
|
||||||
|
|
||||||
|
this._appendMap(args.conj, str, 'whereIn');
|
||||||
|
}
|
||||||
|
|
||||||
|
_run (type, table, callback, sql, vals) {
|
||||||
|
if (!sql) {
|
||||||
|
sql = this._compile(type, table);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vals) {
|
||||||
|
vals = this.state.values.concat(this.state.whereValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the state so another query can be built
|
||||||
|
this._resetState();
|
||||||
|
|
||||||
|
// Pass the sql and values to the adapter to run on the database
|
||||||
|
if (callback) {
|
||||||
|
return this.query(sql, vals, callback);
|
||||||
|
} else {
|
||||||
|
return this.query(sql, vals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getCompile (type, table, reset) {
|
||||||
|
reset = reset || false;
|
||||||
|
|
||||||
|
let sql = this._compile(type, table);
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
this._resetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
_resetState () {
|
||||||
|
this.state = new State();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = QueryBuilderBase;
|
@ -23,8 +23,8 @@ class QueryParser {
|
|||||||
|
|
||||||
const matchPatterns = {
|
const matchPatterns = {
|
||||||
function: /([a-z0-9_]+\((.*)\))/i,
|
function: /([a-z0-9_]+\((.*)\))/i,
|
||||||
operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
|
operator: /!=?|=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|-|%|OR|AND|NOT|XOR/ig,
|
||||||
literal: /([0-9]+)|'(.*?)'|true|false/ig,
|
literal: /([0-9]+)|'(.*?)'|true|false/ig
|
||||||
};
|
};
|
||||||
|
|
||||||
// Full pattern for identifiers
|
// Full pattern for identifiers
|
||||||
@ -92,7 +92,7 @@ class QueryParser {
|
|||||||
functions: [],
|
functions: [],
|
||||||
identifiers: [],
|
identifiers: [],
|
||||||
operators: [],
|
operators: [],
|
||||||
literals: [],
|
literals: []
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get clause components
|
// Get clause components
|
||||||
|
@ -31,5 +31,3 @@ class State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = State;
|
module.exports = State;
|
||||||
|
|
||||||
// End of module State
|
|
3
lib/adapters/MariaDB.js
Normal file
3
lib/adapters/MariaDB.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = require('./Mysql');
|
@ -23,7 +23,7 @@ class Pg extends Adapter {
|
|||||||
slashes: true,
|
slashes: true,
|
||||||
host: `${host}:${port}`,
|
host: `${host}:${port}`,
|
||||||
auth: `${user}${password}`,
|
auth: `${user}${password}`,
|
||||||
pathname: config.database,
|
pathname: config.database
|
||||||
};
|
};
|
||||||
|
|
||||||
connectionString = url.format(conn);
|
connectionString = url.format(conn);
|
||||||
@ -32,12 +32,8 @@ class Pg extends Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (connectionString !== '') {
|
if (connectionString !== '') {
|
||||||
let connected = false;
|
|
||||||
instance = new pg.Client(connectionString);
|
instance = new pg.Client(connectionString);
|
||||||
|
|
||||||
instance.connect(err => {
|
instance.connect(err => {
|
||||||
connected = true;
|
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
throw new Error(err);
|
throw new Error(err);
|
||||||
}
|
}
|
||||||
@ -59,7 +55,9 @@ class Pg extends Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let cols = [];
|
let cols = [];
|
||||||
result.fields.forEach(field => cols = field.name);
|
result.fields.forEach(field => {
|
||||||
|
cols = field.name;
|
||||||
|
});
|
||||||
|
|
||||||
return new Result(result.rows, cols);
|
return new Result(result.rows, cols);
|
||||||
}
|
}
|
||||||
|
8
lib/drivers/MariaDB.js
Normal file
8
lib/drivers/MariaDB.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Driver for MariaDB databases
|
||||||
|
*
|
||||||
|
* @module drivers/MariaDB
|
||||||
|
*/
|
||||||
|
module.exports = require('./Mysql');
|
@ -3,32 +3,31 @@
|
|||||||
/**
|
/**
|
||||||
* Driver for MySQL databases
|
* Driver for MySQL databases
|
||||||
*
|
*
|
||||||
* @module drivers/mysql
|
* @module drivers/Mysql
|
||||||
*/
|
*/
|
||||||
module.exports = (() => {
|
module.exports = (() => {
|
||||||
delete require.cache[require.resolve('../Driver')];
|
delete require.cache[require.resolve('../Driver')];
|
||||||
let driver = require('../Driver'),
|
const driver = require('../Driver');
|
||||||
helpers = require('../helpers');
|
const helpers = require('../helpers');
|
||||||
|
|
||||||
driver.identifierStartChar = '`';
|
driver.identifierStartChar = '`';
|
||||||
driver.identifierEndChar = '`';
|
driver.identifierEndChar = '`';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the limit clause
|
* Set the limit clause
|
||||||
|
*
|
||||||
* @param {String} sql - SQL statement to modify
|
* @param {String} sql - SQL statement to modify
|
||||||
* @param {Number} limit - Maximum number of rows to fetch
|
* @param {Number} limit - Maximum number of rows to fetch
|
||||||
* @param {Number|null} offset - Number of rows to skip
|
* @param {Number|null} offset - Number of rows to skip
|
||||||
* @return {String} - Modified SQL statement
|
* @return {String} - Modified SQL statement
|
||||||
*/
|
*/
|
||||||
driver.limit = (sql, limit, offset) => {
|
driver.limit = (sql, limit, offset) => {
|
||||||
if (! helpers.isNumber(offset)) {
|
sql += (helpers.isNumber(offset))
|
||||||
return sql += ` LIMIT ${limit}`;
|
? ` LIMIT ${offset},${limit}`
|
||||||
}
|
: ` LIMIT ${limit}`;
|
||||||
|
|
||||||
return sql += ` LIMIT ${offset},${limit}`;
|
return sql;
|
||||||
};
|
};
|
||||||
|
|
||||||
return driver;
|
return driver;
|
||||||
|
|
||||||
})();
|
})();
|
@ -3,7 +3,7 @@
|
|||||||
/**
|
/**
|
||||||
* Driver for PostgreSQL databases
|
* Driver for PostgreSQL databases
|
||||||
*
|
*
|
||||||
* @module drivers/pg
|
* @module drivers/Pg
|
||||||
*/
|
*/
|
||||||
module.exports = (() => {
|
module.exports = (() => {
|
||||||
delete require.cache[require.resolve('../Driver')];
|
delete require.cache[require.resolve('../Driver')];
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Driver for Sqlite databases
|
* Driver for SQLite databases
|
||||||
*
|
*
|
||||||
* @module drivers/sqlite
|
* @module drivers/Sqlite
|
||||||
*/
|
*/
|
||||||
module.exports = (() => {
|
module.exports = (() => {
|
||||||
delete require.cache[require.resolve('../Driver')];
|
delete require.cache[require.resolve('../Driver')];
|
||||||
@ -21,14 +21,13 @@ module.exports = (() => {
|
|||||||
* @return {String} - The generated sql statement
|
* @return {String} - The generated sql statement
|
||||||
*/
|
*/
|
||||||
driver.insertBatch = (table, data) => {
|
driver.insertBatch = (table, data) => {
|
||||||
|
|
||||||
// Get the data values to insert, so they can
|
// Get the data values to insert, so they can
|
||||||
// be parameterized
|
// be parameterized
|
||||||
let sql = '',
|
let sql = '';
|
||||||
vals = [],
|
let vals = [];
|
||||||
cols = [],
|
let cols = [];
|
||||||
fields = [],
|
let fields = [];
|
||||||
first = data.shift();
|
let first = data.shift();
|
||||||
|
|
||||||
data.forEach(obj => {
|
data.forEach(obj => {
|
||||||
let row = [];
|
let row = [];
|
||||||
@ -56,7 +55,7 @@ module.exports = (() => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
sql: sql,
|
sql: sql,
|
||||||
values: null,
|
values: null
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,9 +84,8 @@ let helpers = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let i, l = arr.length;
|
const l = arr.length;
|
||||||
|
for (let i = 0; i < l; i++) {
|
||||||
for (i = 0; i < l; i++) {
|
|
||||||
// Short circuit if any items match
|
// Short circuit if any items match
|
||||||
if (pattern.test(arr[i])) {
|
if (pattern.test(arr[i])) {
|
||||||
return true;
|
return true;
|
||||||
@ -105,7 +104,7 @@ let helpers = {
|
|||||||
str += '';
|
str += '';
|
||||||
let first = str.charAt(0).toUpperCase();
|
let first = str.charAt(0).toUpperCase();
|
||||||
return first + str.substr(1);
|
return first + str.substr(1);
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define an 'is' method for each type
|
// Define an 'is' method for each type
|
||||||
@ -120,7 +119,7 @@ let types = [
|
|||||||
'Function',
|
'Function',
|
||||||
'RegExp',
|
'RegExp',
|
||||||
'NaN',
|
'NaN',
|
||||||
'Infinite',
|
'Infinite'
|
||||||
];
|
];
|
||||||
types.forEach(t => {
|
types.forEach(t => {
|
||||||
/**
|
/**
|
||||||
|
30
package.json
30
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ci-node-query",
|
"name": "ci-node-query",
|
||||||
"version": "4.0.0",
|
"version": "4.0.1",
|
||||||
"description": "A query builder for node based on the one in CodeIgniter",
|
"description": "A query builder for node based on the one in CodeIgniter",
|
||||||
"author": "Timothy J Warren <tim@timshomepage.net>",
|
"author": "Timothy J Warren <tim@timshomepage.net>",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -21,13 +21,14 @@
|
|||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"codeigniter",
|
"codeigniter",
|
||||||
"mysql2",
|
"mariadb",
|
||||||
|
"mysql",
|
||||||
"query builder",
|
"query builder",
|
||||||
"pg",
|
|
||||||
"postgres",
|
"postgres",
|
||||||
"sqlite3",
|
"postgresql",
|
||||||
|
"sql",
|
||||||
"sqlite",
|
"sqlite",
|
||||||
"dblite"
|
"sqlite3"
|
||||||
],
|
],
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://git.timshomepage.net/timw4mail/node-query/issues"
|
"url": "https://git.timshomepage.net/timw4mail/node-query/issues"
|
||||||
@ -38,7 +39,7 @@
|
|||||||
"getargs": "~0.0.8",
|
"getargs": "~0.0.8",
|
||||||
"glob": "^7.0.3",
|
"glob": "^7.0.3",
|
||||||
"mysql2": "^1.0.0-rc.1",
|
"mysql2": "^1.0.0-rc.1",
|
||||||
"pg": "^4.5.1",
|
"pg": "^6.0.0",
|
||||||
"require-reload": "~0.2.2",
|
"require-reload": "~0.2.2",
|
||||||
"xregexp": "^3.0.0"
|
"xregexp": "^3.0.0"
|
||||||
},
|
},
|
||||||
@ -46,13 +47,13 @@
|
|||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
"chai-as-promised": "^5.2.0",
|
"chai-as-promised": "^5.2.0",
|
||||||
"documentation": "",
|
"documentation": "",
|
||||||
"eslint": "^2.4.0",
|
"eslint": "^3.5.0",
|
||||||
"glob": "~6.0.4",
|
"glob": "~6.0.4",
|
||||||
"globstar": "^1.0.0",
|
"globstar": "^1.0.0",
|
||||||
|
"happiness": "^5.5.0",
|
||||||
"istanbul": "~0.4.2",
|
"istanbul": "~0.4.2",
|
||||||
"jscs": "^2.11.0",
|
"mocha": "^3.0.0",
|
||||||
"mocha": "^2.4.5",
|
"npm-run-all": "^3.0.0",
|
||||||
"npm-run-all": "^1.6.0",
|
|
||||||
"nsp": "^2.2.1"
|
"nsp": "^2.2.1"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -63,9 +64,12 @@
|
|||||||
"default": "npm-run-all --parallel audit lint:src lint:tests && npm run test",
|
"default": "npm-run-all --parallel audit lint:src lint:tests && npm run test",
|
||||||
"predocs": "globstar -- documentation build -f md -o API.md \"lib/*.js\"",
|
"predocs": "globstar -- documentation build -f md -o API.md \"lib/*.js\"",
|
||||||
"docs": "globstar -- documentation build -f html -o docs \"lib/*.js\"",
|
"docs": "globstar -- documentation build -f html -o docs \"lib/*.js\"",
|
||||||
"lint": "npm-run-all lint:tests lint:src",
|
"happy": "happiness \"lib/**/*.js\" \"test/**/*.js\"",
|
||||||
"lint:src": "jscs ./lib && eslint ./lib",
|
"happy:src": "happiness \"lib/**/*.js\"",
|
||||||
"lint:tests": "jscs ./test && eslint ./test",
|
"happy:tests": "happiness \"test/**/*.js\"",
|
||||||
|
"lint": "npm-run-all lint:tests lint:src && happy",
|
||||||
|
"lint:src": "eslint ./lib",
|
||||||
|
"lint:tests": "eslint ./test",
|
||||||
"test": "mocha -R dot"
|
"test": "mocha -R dot"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Load the test base
|
// Load the test base
|
||||||
@ -8,7 +9,7 @@ const testBase = reload('../base');
|
|||||||
const expect = testBase.expect;
|
const expect = testBase.expect;
|
||||||
const promiseTestRunner = testBase.promiseTestRunner;
|
const promiseTestRunner = testBase.promiseTestRunner;
|
||||||
const testRunner = testBase.testRunner;
|
const testRunner = testBase.testRunner;
|
||||||
let tests = reload('../base/tests');
|
// let tests = reload('../base/tests');
|
||||||
|
|
||||||
// Load the test config file
|
// Load the test config file
|
||||||
const config = testBase.config;
|
const config = testBase.config;
|
||||||
@ -29,9 +30,9 @@ suite('Dblite adapter tests -', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
Callback Tests
|
// Callback Tests
|
||||||
---------------------------------------------------------------------------*/
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
testRunner(qb, (err, result, done) => {
|
testRunner(qb, (err, result, done) => {
|
||||||
expect(err).is.not.ok;
|
expect(err).is.not.ok;
|
||||||
@ -55,16 +56,16 @@ suite('Dblite adapter tests -', () => {
|
|||||||
{
|
{
|
||||||
id: 544,
|
id: 544,
|
||||||
key: 3,
|
key: 3,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 89,
|
id: 89,
|
||||||
key: 34,
|
key: 34,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 48,
|
id: 48,
|
||||||
key: 403,
|
key: 403,
|
||||||
val: new Buffer('97'),
|
val: new Buffer('97')
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
qb.insertBatch('create_test', data, err => {
|
qb.insertBatch('create_test', data, err => {
|
||||||
@ -73,9 +74,9 @@ suite('Dblite adapter tests -', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
Promise Tests
|
// Promise Tests
|
||||||
---------------------------------------------------------------------------*/
|
// ---------------------------------------------------------------------------
|
||||||
promiseTestRunner(qb);
|
promiseTestRunner(qb);
|
||||||
test('Promise - Select with function and argument in WHERE clause', () => {
|
test('Promise - Select with function and argument in WHERE clause', () => {
|
||||||
let promise = qb.select('id')
|
let promise = qb.select('id')
|
||||||
@ -90,16 +91,16 @@ suite('Dblite adapter tests -', () => {
|
|||||||
{
|
{
|
||||||
id: 544,
|
id: 544,
|
||||||
key: 3,
|
key: 3,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 89,
|
id: 89,
|
||||||
key: 34,
|
key: 34,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 48,
|
id: 48,
|
||||||
key: 403,
|
key: 403,
|
||||||
val: new Buffer('97'),
|
val: new Buffer('97')
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
let promise = qb.query(qb.driver.truncate('create_test')).then(
|
let promise = qb.query(qb.driver.truncate('create_test')).then(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Load the test base
|
// Load the test base
|
||||||
@ -42,21 +43,26 @@ suite('Mysql2 adapter tests -', () => {
|
|||||||
return done();
|
return done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
test('Callback - Test Truncate', done => {
|
||||||
|
qb.truncate('create_test', (err, res) => {
|
||||||
|
return done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
test('Callback - Test Insert Batch', done => {
|
test('Callback - Test Insert Batch', done => {
|
||||||
let data = [
|
let data = [
|
||||||
{
|
{
|
||||||
id: 5441,
|
id: 5441,
|
||||||
key: 3,
|
key: 3,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 891,
|
id: 891,
|
||||||
key: 34,
|
key: 34,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 481,
|
id: 481,
|
||||||
key: 403,
|
key: 403,
|
||||||
val: new Buffer('97'),
|
val: new Buffer('97')
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
qb.insertBatch('create_test', data, (err, res) => {
|
qb.insertBatch('create_test', data, (err, res) => {
|
||||||
@ -77,22 +83,25 @@ suite('Mysql2 adapter tests -', () => {
|
|||||||
|
|
||||||
return expect(promise).to.be.fulfilled;
|
return expect(promise).to.be.fulfilled;
|
||||||
});
|
});
|
||||||
|
test('Test Truncate', () => {
|
||||||
|
let promise = qb.truncate('create_test');
|
||||||
|
return expect(promise).to.be.fullfilled;
|
||||||
|
});
|
||||||
test('Test Insert Batch', () => {
|
test('Test Insert Batch', () => {
|
||||||
let data = [
|
let data = [
|
||||||
{
|
{
|
||||||
id: 5442,
|
id: 5442,
|
||||||
key: 4,
|
key: 4,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 892,
|
id: 892,
|
||||||
key: 35,
|
key: 35,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 482,
|
id: 482,
|
||||||
key: 404,
|
key: 404,
|
||||||
val: 97,
|
val: 97
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return expect(qb.insertBatch('create_test', data)).to.be.fulfilled;
|
return expect(qb.insertBatch('create_test', data)).to.be.fulfilled;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Load the test base
|
// Load the test base
|
||||||
@ -32,6 +33,17 @@ suite('Pg adapter tests -', () => {
|
|||||||
return expect(qb2).to.be.ok;
|
return expect(qb2).to.be.ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Test Connection Error', done => {
|
||||||
|
try {
|
||||||
|
reload('../../lib/NodeQuery')({});
|
||||||
|
done(true);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e).to.be.ok;
|
||||||
|
expect(e).is.an('Error');
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Callback Tests
|
// Callback Tests
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@ -52,21 +64,27 @@ suite('Pg adapter tests -', () => {
|
|||||||
return done(err);
|
return done(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
test('Callback - Test Truncate', done => {
|
||||||
|
qb.truncate('create_test', (err, res) => {
|
||||||
|
expect(err).is.not.ok;
|
||||||
|
return done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
test('Callback - Test Insert Batch', done => {
|
test('Callback - Test Insert Batch', done => {
|
||||||
let data = [
|
let data = [
|
||||||
{
|
{
|
||||||
id: 5441,
|
id: 5441,
|
||||||
key: 3,
|
key: 3,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 891,
|
id: 891,
|
||||||
key: 34,
|
key: 34,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 481,
|
id: 481,
|
||||||
key: 403,
|
key: 403,
|
||||||
val: new Buffer('97'),
|
val: new Buffer('97')
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
qb.insertBatch('create_test', data, (err, res) => {
|
qb.insertBatch('create_test', data, (err, res) => {
|
||||||
@ -87,21 +105,25 @@ suite('Pg adapter tests -', () => {
|
|||||||
|
|
||||||
return expect(promise).to.be.fulfilled;
|
return expect(promise).to.be.fulfilled;
|
||||||
});
|
});
|
||||||
|
test('Promise - Test Truncate', () => {
|
||||||
|
let promise = qb.truncate('create_test');
|
||||||
|
return expect(promise).to.be.fulfilled;
|
||||||
|
});
|
||||||
test('Promise - Test Insert Batch', () => {
|
test('Promise - Test Insert Batch', () => {
|
||||||
let data = [
|
let data = [
|
||||||
{
|
{
|
||||||
id: 544,
|
id: 544,
|
||||||
key: 3,
|
key: 3,
|
||||||
val: new Buffer('7'),
|
val: new Buffer('7')
|
||||||
}, {
|
}, {
|
||||||
id: 89,
|
id: 89,
|
||||||
key: 34,
|
key: 34,
|
||||||
val: new Buffer('10 o\'clock'),
|
val: new Buffer('10 o\'clock')
|
||||||
}, {
|
}, {
|
||||||
id: 48,
|
id: 48,
|
||||||
key: 403,
|
key: 403,
|
||||||
val: new Buffer('97'),
|
val: new Buffer('97')
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
let promise = qb.insertBatch('create_test', data);
|
let promise = qb.insertBatch('create_test', data);
|
||||||
|
@ -12,5 +12,5 @@ module.exports = {
|
|||||||
expect: chai.expect,
|
expect: chai.expect,
|
||||||
tests: require('./base/tests'),
|
tests: require('./base/tests'),
|
||||||
testRunner: require('./base/adapterCallbackTestRunner'),
|
testRunner: require('./base/adapterCallbackTestRunner'),
|
||||||
promiseTestRunner: require('./base/adapterPromiseTestRunner'),
|
promiseTestRunner: require('./base/adapterPromiseTestRunner')
|
||||||
};
|
};
|
@ -1,6 +1,6 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// jscs:disable
|
|
||||||
// Load the test base
|
// Load the test base
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
const chaiAsPromised = require('chai-as-promised');
|
const chaiAsPromised = require('chai-as-promised');
|
||||||
@ -10,8 +10,8 @@ const expect = chai.expect;
|
|||||||
const reload = require('require-reload')(require);
|
const reload = require('require-reload')(require);
|
||||||
let tests = reload('../base/tests');
|
let tests = reload('../base/tests');
|
||||||
|
|
||||||
let helpers = reload('../../lib/helpers'),
|
const helpers = reload('../../lib/helpers');
|
||||||
State = reload('../../lib/State');
|
const State = reload('../../lib/State');
|
||||||
|
|
||||||
module.exports = function testRunner (qb, callback) {
|
module.exports = function testRunner (qb, callback) {
|
||||||
Object.keys(tests).forEach(suiteName => {
|
Object.keys(tests).forEach(suiteName => {
|
||||||
@ -19,22 +19,21 @@ module.exports = function testRunner(qb, callback) {
|
|||||||
let currentSuite = tests[suiteName];
|
let currentSuite = tests[suiteName];
|
||||||
Object.keys(currentSuite).forEach(testDesc => {
|
Object.keys(currentSuite).forEach(testDesc => {
|
||||||
test(`Callback - ${testDesc}`, done => {
|
test(`Callback - ${testDesc}`, done => {
|
||||||
let methodObj = currentSuite[testDesc];
|
const methodObj = currentSuite[testDesc];
|
||||||
let methodNames = Object.keys(methodObj);
|
const methodNames = Object.keys(methodObj);
|
||||||
let lastMethodIndex = methodNames[methodNames.length - 1];
|
const lastMethodIndex = methodNames[methodNames.length - 1];
|
||||||
|
|
||||||
methodObj[lastMethodIndex].push((err, rows) => callback(err, rows, done));
|
methodObj[lastMethodIndex].push((err, rows) => callback(err, rows, done));
|
||||||
|
|
||||||
methodNames.forEach(name => {
|
methodNames.forEach(name => {
|
||||||
let args = methodObj[name],
|
const args = methodObj[name];
|
||||||
method = qb[name];
|
const method = qb[name];
|
||||||
|
|
||||||
if (args[0] === 'multiple') {
|
if (args[0] === 'multiple') {
|
||||||
args.shift();
|
args.shift();
|
||||||
args.forEach(argSet => {
|
args.forEach(argSet => {
|
||||||
method.apply(qb, argSet);
|
method.apply(qb, argSet);
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
method.apply(qb, args);
|
method.apply(qb, args);
|
||||||
}
|
}
|
||||||
@ -57,7 +56,7 @@ module.exports = function testRunner(qb, callback) {
|
|||||||
qb.insert('create_test', {
|
qb.insert('create_test', {
|
||||||
id: 587,
|
id: 587,
|
||||||
key: 1,
|
key: 1,
|
||||||
val: new Buffer('2'),
|
val: new Buffer('2')
|
||||||
}, (err, rows) => {
|
}, (err, rows) => {
|
||||||
return callback(err, rows, done);
|
return callback(err, rows, done);
|
||||||
});
|
});
|
||||||
@ -67,7 +66,7 @@ module.exports = function testRunner(qb, callback) {
|
|||||||
.update('create_test', {
|
.update('create_test', {
|
||||||
id: 7,
|
id: 7,
|
||||||
key: 'gogle',
|
key: 'gogle',
|
||||||
val: new Buffer('non-word'),
|
val: new Buffer('non-word')
|
||||||
}, (err, rows) => {
|
}, (err, rows) => {
|
||||||
return callback(err, rows, done);
|
return callback(err, rows, done);
|
||||||
});
|
});
|
||||||
@ -76,7 +75,7 @@ module.exports = function testRunner(qb, callback) {
|
|||||||
let object = {
|
let object = {
|
||||||
id: 22,
|
id: 22,
|
||||||
key: 'gogle',
|
key: 'gogle',
|
||||||
val: new Buffer('non-word'),
|
val: new Buffer('non-word')
|
||||||
};
|
};
|
||||||
|
|
||||||
qb.set(object)
|
qb.set(object)
|
||||||
@ -108,7 +107,7 @@ module.exports = function testRunner(qb, callback) {
|
|||||||
test('Callback - Delete multiple where values', done => {
|
test('Callback - Delete multiple where values', done => {
|
||||||
qb.delete('create_test', {
|
qb.delete('create_test', {
|
||||||
id: 5,
|
id: 5,
|
||||||
key: 'gogle',
|
key: 'gogle'
|
||||||
}, (err, rows) => {
|
}, (err, rows) => {
|
||||||
return callback(err, rows, done);
|
return callback(err, rows, done);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// jscs:disable
|
|
||||||
// Load the test base
|
// Load the test base
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
const chaiAsPromised = require('chai-as-promised');
|
const chaiAsPromised = require('chai-as-promised');
|
||||||
@ -8,10 +8,7 @@ chai.use(chaiAsPromised);
|
|||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
const reload = require('require-reload')(require);
|
const reload = require('require-reload')(require);
|
||||||
let tests = reload('../base/tests');
|
const tests = reload('../base/tests');
|
||||||
|
|
||||||
let helpers = reload('../../lib/helpers'),
|
|
||||||
State = reload('../../lib/State');
|
|
||||||
|
|
||||||
module.exports = function promiseTestRunner (qb) {
|
module.exports = function promiseTestRunner (qb) {
|
||||||
Object.keys(tests).forEach(suiteName => {
|
Object.keys(tests).forEach(suiteName => {
|
||||||
@ -19,21 +16,19 @@ module.exports = function promiseTestRunner(qb) {
|
|||||||
let currentSuite = tests[suiteName];
|
let currentSuite = tests[suiteName];
|
||||||
Object.keys(currentSuite).forEach(testDesc => {
|
Object.keys(currentSuite).forEach(testDesc => {
|
||||||
test(`Promise - ${testDesc}`, () => {
|
test(`Promise - ${testDesc}`, () => {
|
||||||
let methodObj = currentSuite[testDesc];
|
const methodObj = currentSuite[testDesc];
|
||||||
let methodNames = Object.keys(methodObj);
|
const methodNames = Object.keys(methodObj);
|
||||||
let lastMethodIndex = methodNames[methodNames.length - 1];
|
|
||||||
let results = [];
|
let results = [];
|
||||||
|
|
||||||
methodNames.forEach(name => {
|
methodNames.forEach(name => {
|
||||||
let args = methodObj[name],
|
const args = methodObj[name];
|
||||||
method = qb[name];
|
const method = qb[name];
|
||||||
|
|
||||||
if (args[0] === 'multiple') {
|
if (args[0] === 'multiple') {
|
||||||
args.shift();
|
args.shift();
|
||||||
args.forEach(argSet => {
|
args.forEach(argSet => {
|
||||||
results.push(method.apply(qb, argSet));
|
results.push(method.apply(qb, argSet));
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
results.push(method.apply(qb, args));
|
results.push(method.apply(qb, args));
|
||||||
}
|
}
|
||||||
@ -63,7 +58,7 @@ module.exports = function promiseTestRunner(qb) {
|
|||||||
let promise = qb.insert('create_test', {
|
let promise = qb.insert('create_test', {
|
||||||
id: 587,
|
id: 587,
|
||||||
key: 1,
|
key: 1,
|
||||||
val: new Buffer('2'),
|
val: new Buffer('2')
|
||||||
});
|
});
|
||||||
|
|
||||||
return expect(promise).to.be.fulfilled;
|
return expect(promise).to.be.fulfilled;
|
||||||
@ -73,7 +68,7 @@ module.exports = function promiseTestRunner(qb) {
|
|||||||
.update('create_test', {
|
.update('create_test', {
|
||||||
id: 7,
|
id: 7,
|
||||||
key: 'gogle',
|
key: 'gogle',
|
||||||
val: new Buffer('non-word'),
|
val: new Buffer('non-word')
|
||||||
});
|
});
|
||||||
|
|
||||||
return expect(promise).to.be.fulfilled;
|
return expect(promise).to.be.fulfilled;
|
||||||
@ -82,7 +77,7 @@ module.exports = function promiseTestRunner(qb) {
|
|||||||
let object = {
|
let object = {
|
||||||
id: 22,
|
id: 22,
|
||||||
key: 'gogle',
|
key: 'gogle',
|
||||||
val: new Buffer('non-word'),
|
val: new Buffer('non-word')
|
||||||
};
|
};
|
||||||
|
|
||||||
let promise = qb.set(object)
|
let promise = qb.set(object)
|
||||||
@ -113,7 +108,7 @@ module.exports = function promiseTestRunner(qb) {
|
|||||||
test('Promise - Delete multiple where values', () => {
|
test('Promise - Delete multiple where values', () => {
|
||||||
let promise = qb.delete('create_test', {
|
let promise = qb.delete('create_test', {
|
||||||
id: 5,
|
id: 5,
|
||||||
key: 'gogle',
|
key: 'gogle'
|
||||||
});
|
});
|
||||||
|
|
||||||
return expect(promise).to.be.fulfilled;
|
return expect(promise).to.be.fulfilled;
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// jscs:disable
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'Get tests -': {
|
'Get tests -': {
|
||||||
'Get with function': {
|
'Get with function': {
|
||||||
select: ['id, COUNT(id) as count'],
|
select: ['id, COUNT(id) as count'],
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
groupBy: ['id'],
|
groupBy: ['id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Basic select all get': {
|
'Basic select all get': {
|
||||||
get: ['create_test'],
|
get: ['create_test']
|
||||||
},
|
},
|
||||||
'Basic select all with from': {
|
'Basic select all with from': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Get with limit': {
|
'Get with limit': {
|
||||||
get: ['create_test', 2],
|
get: ['create_test', 2]
|
||||||
},
|
},
|
||||||
'Get with limit and offset': {
|
'Get with limit and offset': {
|
||||||
get: ['create_test', 2, 1],
|
get: ['create_test', 2, 1]
|
||||||
},
|
},
|
||||||
'Get with having': {
|
'Get with having': {
|
||||||
select: ['id'],
|
select: ['id'],
|
||||||
@ -30,9 +29,9 @@ module.exports = {
|
|||||||
'multiple',
|
'multiple',
|
||||||
[{'id >': 1}],
|
[{'id >': 1}],
|
||||||
['id !=', 3],
|
['id !=', 3],
|
||||||
['id', 900],
|
['id', 900]
|
||||||
],
|
],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Get with orHaving': {
|
'Get with orHaving': {
|
||||||
select: ['id'],
|
select: ['id'],
|
||||||
@ -40,8 +39,8 @@ module.exports = {
|
|||||||
groupBy: ['id'],
|
groupBy: ['id'],
|
||||||
having: [{'id >': 1}],
|
having: [{'id >': 1}],
|
||||||
orHaving: ['id !=', 3],
|
orHaving: ['id !=', 3],
|
||||||
get: [],
|
get: []
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
'Select tests -': {
|
'Select tests -': {
|
||||||
'Select where get': {
|
'Select where get': {
|
||||||
@ -49,94 +48,94 @@ module.exports = {
|
|||||||
where: [
|
where: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['id >', 1],
|
['id >', 1],
|
||||||
['id <', 900],
|
['id <', 900]
|
||||||
],
|
],
|
||||||
get: ['create_test', 2, 1],
|
get: ['create_test', 2, 1]
|
||||||
},
|
},
|
||||||
'Select where get 2': {
|
'Select where get 2': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
where: ['id !=', 1],
|
where: ['id !=', 1],
|
||||||
get: ['create_test', 2, 1],
|
get: ['create_test', 2, 1]
|
||||||
},
|
},
|
||||||
'Multi Order By': {
|
'Multi Order By': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
orderBy: ['id, key'],
|
orderBy: ['id, key'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select get': {
|
'Select get': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
get: ['create_test', 2, 1],
|
get: ['create_test', 2, 1]
|
||||||
},
|
},
|
||||||
'Select from get': {
|
'Select from get': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
where: ['id >', 1],
|
where: ['id >', 1],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select from limit get': {
|
'Select from limit get': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
where: ['id >', 1],
|
where: ['id >', 1],
|
||||||
limit: [3],
|
limit: [3],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select where IS NOT NULL': {
|
'Select where IS NOT NULL': {
|
||||||
select: ['id', 'key as k', 'val'],
|
select: ['id', 'key as k', 'val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
whereIsNotNull: ['id'],
|
whereIsNotNull: ['id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select where IS NULL': {
|
'Select where IS NULL': {
|
||||||
select: ['id', 'key as k', 'val'],
|
select: ['id', 'key as k', 'val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
whereIsNull: ['id'],
|
whereIsNull: ['id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select where OR IS NOT NULL': {
|
'Select where OR IS NOT NULL': {
|
||||||
select: ['id', 'key as k', 'val'],
|
select: ['id', 'key as k', 'val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
whereIsNull: ['id'],
|
whereIsNull: ['id'],
|
||||||
orWhereIsNotNull: ['id'],
|
orWhereIsNotNull: ['id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select where OR IS NULL': {
|
'Select where OR IS NULL': {
|
||||||
select: ['id', 'key as k', 'val'],
|
select: ['id', 'key as k', 'val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
where: ['id', 3],
|
where: ['id', 3],
|
||||||
orWhereIsNull: ['id'],
|
orWhereIsNull: ['id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Select with string where value': {
|
'Select with string where value': {
|
||||||
select: ['id', 'key as k', 'val'],
|
select: ['id', 'key as k', 'val'],
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
where: ['id > 3'],
|
where: ['id > 3'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
'Where in tests -': {
|
'Where in tests -': {
|
||||||
'Where in': {
|
'Where in': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
whereIn: ['id', [0, 6, 56, 563, 341]],
|
whereIn: ['id', [0, 6, 56, 563, 341]],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Or Where in': {
|
'Or Where in': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
where: ['key', 'false'],
|
where: ['key', 'false'],
|
||||||
orWhereIn: ['id', [0, 6, 56, 563, 341]],
|
orWhereIn: ['id', [0, 6, 56, 563, 341]],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Where Not in': {
|
'Where Not in': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
where: ['key', 'false'],
|
where: ['key', 'false'],
|
||||||
whereNotIn: ['id', [0, 6, 56, 563, 341]],
|
whereNotIn: ['id', [0, 6, 56, 563, 341]],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Or Where Not in': {
|
'Or Where Not in': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
where: ['key', 'false'],
|
where: ['key', 'false'],
|
||||||
orWhereNotIn: ['id', [0, 6, 56, 563, 341]],
|
orWhereNotIn: ['id', [0, 6, 56, 563, 341]],
|
||||||
get: [],
|
get: []
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
'Query modifier tests -': {
|
'Query modifier tests -': {
|
||||||
'Order By': {
|
'Order By': {
|
||||||
@ -145,15 +144,15 @@ module.exports = {
|
|||||||
where: [
|
where: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['id >', 0],
|
['id >', 0],
|
||||||
['id <', 9000],
|
['id <', 9000]
|
||||||
],
|
],
|
||||||
orderBy: [
|
orderBy: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['id', 'DESC'],
|
['id', 'DESC'],
|
||||||
['k', 'ASC'],
|
['k', 'ASC']
|
||||||
],
|
],
|
||||||
limit: [5, 2],
|
limit: [5, 2],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Group By': {
|
'Group By': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
@ -161,20 +160,20 @@ module.exports = {
|
|||||||
where: [
|
where: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['id >', 0],
|
['id >', 0],
|
||||||
['id <', 9000],
|
['id <', 9000]
|
||||||
],
|
],
|
||||||
groupBy: [
|
groupBy: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['k'],
|
['k'],
|
||||||
[['id', 'val']],
|
[['id', 'val']]
|
||||||
],
|
],
|
||||||
orderBy: [
|
orderBy: [
|
||||||
'multiple',
|
'multiple',
|
||||||
['id', 'DESC'],
|
['id', 'DESC'],
|
||||||
['k', 'ASC'],
|
['k', 'ASC']
|
||||||
],
|
],
|
||||||
limit: [5, 2],
|
limit: [5, 2],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Or Where': {
|
'Or Where': {
|
||||||
select: ['id, key as k, val'],
|
select: ['id, key as k, val'],
|
||||||
@ -182,55 +181,55 @@ module.exports = {
|
|||||||
where: [' id ', 1],
|
where: [' id ', 1],
|
||||||
orWhere: ['key > ', 0],
|
orWhere: ['key > ', 0],
|
||||||
limit: [2, 1],
|
limit: [2, 1],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
Like: {
|
Like: {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og'],
|
like: ['key', 'og'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Or Like': {
|
'Or Like': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og'],
|
like: ['key', 'og'],
|
||||||
orLike: ['key', 'val'],
|
orLike: ['key', 'val'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Not Like': {
|
'Not Like': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og', 'before'],
|
like: ['key', 'og', 'before'],
|
||||||
notLike: ['key', 'val'],
|
notLike: ['key', 'val'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Or Not Like': {
|
'Or Not Like': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og', 'before'],
|
like: ['key', 'og', 'before'],
|
||||||
orNotLike: ['key', 'val'],
|
orNotLike: ['key', 'val'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Like Before': {
|
'Like Before': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og', 'before'],
|
like: ['key', 'og', 'before'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Like After': {
|
'Like After': {
|
||||||
from: ['create_test'],
|
from: ['create_test'],
|
||||||
like: ['key', 'og', 'after'],
|
like: ['key', 'og', 'after'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Basic Join': {
|
'Basic Join': {
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
join: ['create_join cj', 'cj.id=ct.id'],
|
join: ['create_join cj', 'cj.id=ct.id'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Left Join': {
|
'Left Join': {
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
join: ['create_join cj', 'cj.id=ct.id', 'left'],
|
join: ['create_join cj', 'cj.id=ct.id', 'left'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Inner Join': {
|
'Inner Join': {
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
join: ['create_join cj', 'cj.id=ct.id', 'inner'],
|
join: ['create_join cj', 'cj.id=ct.id', 'inner'],
|
||||||
get: [],
|
get: []
|
||||||
},
|
},
|
||||||
'Join with multiple where values': {
|
'Join with multiple where values': {
|
||||||
from: ['create_test ct'],
|
from: ['create_test ct'],
|
||||||
@ -238,10 +237,10 @@ module.exports = {
|
|||||||
where: [
|
where: [
|
||||||
{
|
{
|
||||||
'ct.id < ': 3,
|
'ct.id < ': 3,
|
||||||
'ct.key ': 'foo',
|
'ct.key ': 'foo'
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
get: [],
|
get: []
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
@ -1,10 +1,11 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let expect = require('chai').expect,
|
const expect = require('chai').expect;
|
||||||
reload = require('require-reload')(require),
|
const reload = require('require-reload')(require);
|
||||||
glob = require('glob'),
|
const glob = require('glob');
|
||||||
nodeQuery = reload('../lib/NodeQuery')(),
|
const nodeQuery = reload('../lib/NodeQuery')();
|
||||||
Adapter = reload('../lib/Adapter');
|
const Adapter = reload('../lib/Adapter');
|
||||||
|
|
||||||
suite('Base tests -', () => {
|
suite('Base tests -', () => {
|
||||||
suite('Sanity check', () => {
|
suite('Sanity check', () => {
|
||||||
@ -31,7 +32,7 @@ suite('Base tests -', () => {
|
|||||||
test('Invalid driver type', () => {
|
test('Invalid driver type', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
reload('../lib/NodeQuery')({
|
reload('../lib/NodeQuery')({
|
||||||
driver: 'Foo',
|
driver: 'Foo'
|
||||||
});
|
});
|
||||||
}).to.throw(Error, 'Selected driver (Foo) does not exist!');
|
}).to.throw(Error, 'Selected driver (Foo) does not exist!');
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let chai = require('chai'),
|
const chai = require('chai');
|
||||||
assert = chai.assert,
|
const assert = chai.assert;
|
||||||
expect = chai.expect,
|
const expect = chai.expect;
|
||||||
should = chai.should();
|
|
||||||
|
|
||||||
let helpers = require('../lib/helpers');
|
let helpers = require('../lib/helpers');
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ suite('Helper Module Tests -', () => {
|
|||||||
'Function',
|
'Function',
|
||||||
'RegExp',
|
'RegExp',
|
||||||
'NaN',
|
'NaN',
|
||||||
'Infinite',
|
'Infinite'
|
||||||
];
|
];
|
||||||
|
|
||||||
types.forEach(type => {
|
types.forEach(type => {
|
||||||
@ -48,7 +48,7 @@ suite('Helper Module Tests -', () => {
|
|||||||
let trueCases = {
|
let trueCases = {
|
||||||
'Strings are scalar': 'foo',
|
'Strings are scalar': 'foo',
|
||||||
'Booleans are scalar': true,
|
'Booleans are scalar': true,
|
||||||
'Numbers are scalar': 545,
|
'Numbers are scalar': 545
|
||||||
};
|
};
|
||||||
Object.keys(trueCases).forEach(desc => {
|
Object.keys(trueCases).forEach(desc => {
|
||||||
test(desc, () => {
|
test(desc, () => {
|
||||||
@ -58,7 +58,7 @@ suite('Helper Module Tests -', () => {
|
|||||||
|
|
||||||
let falseCases = {
|
let falseCases = {
|
||||||
'Arrays are not scalar': [],
|
'Arrays are not scalar': [],
|
||||||
'Objects are not scalar': [],
|
'Objects are not scalar': []
|
||||||
};
|
};
|
||||||
Object.keys(falseCases).forEach(desc => {
|
Object.keys(falseCases).forEach(desc => {
|
||||||
test(desc, () => {
|
test(desc, () => {
|
||||||
@ -95,14 +95,14 @@ suite('Helper Module Tests -', () => {
|
|||||||
suite('arrayPluck -', () => {
|
suite('arrayPluck -', () => {
|
||||||
let orig = [
|
let orig = [
|
||||||
{
|
{
|
||||||
foo: 1,
|
foo: 1
|
||||||
}, {
|
}, {
|
||||||
foo: 2,
|
foo: 2,
|
||||||
bar: 10,
|
bar: 10
|
||||||
}, {
|
}, {
|
||||||
foo: 3,
|
foo: 3,
|
||||||
bar: 15,
|
bar: 15
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
test('Finding members in all objects', () => {
|
test('Finding members in all objects', () => {
|
||||||
@ -121,11 +121,11 @@ suite('Helper Module Tests -', () => {
|
|||||||
let cases = [
|
let cases = [
|
||||||
{
|
{
|
||||||
'Dollar sign is not in any of the array items': /\$/,
|
'Dollar sign is not in any of the array items': /\$/,
|
||||||
'None of the numbers in the array match /5/': /5/,
|
'None of the numbers in the array match /5/': /5/
|
||||||
}, {
|
}, {
|
||||||
'\' string \' matches /^ ?string/': /^ ?string/,
|
'\' string \' matches /^ ?string/': /^ ?string/,
|
||||||
'\'apple\' matches /APPLE/i': /APPLE/i,
|
'\'apple\' matches /APPLE/i': /APPLE/i
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
[0, 1].forEach(i => {
|
[0, 1].forEach(i => {
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
'use strict';
|
'use strict';
|
||||||
let expect = require('chai').expect;
|
const expect = require('chai').expect;
|
||||||
|
|
||||||
// Use the base driver as a mock for testing
|
// Use the base driver as a mock for testing
|
||||||
let getArgs = require('getargs');
|
const getArgs = require('getargs');
|
||||||
let helpers = require('../lib/helpers');
|
const helpers = require('../lib/helpers');
|
||||||
let driver = require('../lib/Driver');
|
const driver = require('../lib/Driver');
|
||||||
|
|
||||||
let P = require('../lib/QueryParser');
|
const P = require('../lib/QueryParser');
|
||||||
let parser = new P(driver);
|
let parser = new P(driver);
|
||||||
|
|
||||||
let State = require('../lib/State');
|
const State = require('../lib/State');
|
||||||
|
|
||||||
// Simulate query builder state
|
// Simulate query builder state
|
||||||
let state = new State();
|
let state = new State();
|
||||||
@ -86,7 +87,7 @@ suite('Query Parser Tests', () => {
|
|||||||
});
|
});
|
||||||
test('Has function key/val object', () => {
|
test('Has function key/val object', () => {
|
||||||
whereMock({
|
whereMock({
|
||||||
'time <': 'SUM(FOO(BAR(\'x\')))',
|
'time <': 'SUM(FOO(BAR(\'x\')))'
|
||||||
});
|
});
|
||||||
parser.parseWhere(driver, state);
|
parser.parseWhere(driver, state);
|
||||||
expect(state.whereMap)
|
expect(state.whereMap)
|
||||||
@ -94,7 +95,7 @@ suite('Query Parser Tests', () => {
|
|||||||
});
|
});
|
||||||
test('Has literal value', () => {
|
test('Has literal value', () => {
|
||||||
whereMock({
|
whereMock({
|
||||||
foo: 3,
|
foo: 3
|
||||||
});
|
});
|
||||||
parser.parseWhere(driver, state);
|
parser.parseWhere(driver, state);
|
||||||
expect(state.whereMap)
|
expect(state.whereMap)
|
||||||
@ -105,7 +106,7 @@ suite('Query Parser Tests', () => {
|
|||||||
test('Has multiple literal values', () => {
|
test('Has multiple literal values', () => {
|
||||||
whereMock({
|
whereMock({
|
||||||
foo: 3,
|
foo: 3,
|
||||||
bar: 5,
|
bar: 5
|
||||||
});
|
});
|
||||||
parser.parseWhere(driver, state);
|
parser.parseWhere(driver, state);
|
||||||
expect(state.whereMap)
|
expect(state.whereMap)
|
||||||
@ -119,20 +120,20 @@ suite('Query Parser Tests', () => {
|
|||||||
{
|
{
|
||||||
desc: 'Simple equals condition',
|
desc: 'Simple equals condition',
|
||||||
join: 'table1.field1=table2.field2',
|
join: 'table1.field1=table2.field2',
|
||||||
expected: ['table1.field1', '=', 'table2.field2'],
|
expected: ['table1.field1', '=', 'table2.field2']
|
||||||
}, {
|
}, {
|
||||||
desc: 'Db.table.field condition',
|
desc: 'Db.table.field condition',
|
||||||
join: 'db1.table1.field1!=db2.table2.field2',
|
join: 'db1.table1.field1!=db2.table2.field2',
|
||||||
expected: ['db1.table1.field1', '!=', 'db2.table2.field2'],
|
expected: ['db1.table1.field1', '!=', 'db2.table2.field2']
|
||||||
}, {
|
}, {
|
||||||
desc: 'Underscore in identifier',
|
desc: 'Underscore in identifier',
|
||||||
join: 'table_1.field1 = tab_le2.field_2',
|
join: 'table_1.field1 = tab_le2.field_2',
|
||||||
expected: ['table_1.field1', '=', 'tab_le2.field_2'],
|
expected: ['table_1.field1', '=', 'tab_le2.field_2']
|
||||||
}, {
|
}, {
|
||||||
desc: 'Function in condition',
|
desc: 'Function in condition',
|
||||||
join: 'table1.field1 > SUM(3+6)',
|
join: 'table1.field1 > SUM(3+6)',
|
||||||
expected: ['table1.field1', '>', 'SUM(3+6)'],
|
expected: ['table1.field1', '>', 'SUM(3+6)']
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
data.forEach(datum => {
|
data.forEach(datum => {
|
||||||
@ -147,20 +148,20 @@ suite('Query Parser Tests', () => {
|
|||||||
{
|
{
|
||||||
desc: 'Simple equals condition',
|
desc: 'Simple equals condition',
|
||||||
clause: 'table1.field1=table2.field2',
|
clause: 'table1.field1=table2.field2',
|
||||||
expected: '"table1"."field1" = "table2"."field2"',
|
expected: '"table1"."field1" = "table2"."field2"'
|
||||||
}, {
|
}, {
|
||||||
desc: 'Db.table.field condition',
|
desc: 'Db.table.field condition',
|
||||||
clause: 'db1.table1.field1!=db2.table2.field2',
|
clause: 'db1.table1.field1!=db2.table2.field2',
|
||||||
expected: '"db1"."table1"."field1" != "db2"."table2"."field2"',
|
expected: '"db1"."table1"."field1" != "db2"."table2"."field2"'
|
||||||
}, {
|
}, {
|
||||||
desc: 'Underscore in identifier',
|
desc: 'Underscore in identifier',
|
||||||
clause: 'table_1.field1 = tab_le2.field_2',
|
clause: 'table_1.field1 = tab_le2.field_2',
|
||||||
expected: '"table_1"."field1" = "tab_le2"."field_2"',
|
expected: '"table_1"."field1" = "tab_le2"."field_2"'
|
||||||
}, {
|
}, {
|
||||||
desc: 'Function in condition',
|
desc: 'Function in condition',
|
||||||
clause: 'table1.field1 > SUM(3+6)',
|
clause: 'table1.field1 > SUM(3+6)',
|
||||||
expected: '"table1"."field1" > SUM(3+6)',
|
expected: '"table1"."field1" > SUM(3+6)'
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
data.forEach(datum => {
|
data.forEach(datum => {
|
||||||
|
Loading…
Reference in New Issue
Block a user