+
- .type(o)
+ #getCompiledInsert(table, [reset])
-
- Get the type of the variable passed
+
+
Return generated insert query SQL
-
+
-
+
-
- type(o)
+
+ getCompiledInsert(table, [reset])
-
Get the type of the variable passed
+ Return generated insert query SQL
Parameters
- mixed
o
+ String
table
:
-
- Object to type check
+
+
the name of the table to insert into
-
+
+
+ [Boolean
]
reset
+ (default true
)
+ :
+
+
Whether to reset the query builder so another query can be built
+
+
Returns
String
:
-
- Type of the object
+
+
The compiled sql statement
-
+
-
-
+
-
- compileJoin(condition)
-
- Return the output of the parsing of the join condition
-
- Parameters
-
- String
condition
- :
-
- The join condition to evalate
-
-
-
-
- Returns
- String
- :
-
- The parsed/escaped join condition
-
-
-
-
-
- constructor(driver)
-
-
- Parameters
-
- Driver
driver
- :
-
- The driver object for the database in use
-
-
-
-
- Returns
- void
-
-
-
-
-
-
-
- delete(table, [where], callback)
-
- Run the generated delete query
-
- Parameters
-
- String
table
- :
-
- The table to insert into
-
-
-
- [Object
]
where
- :
-
- Where clause for delete statement
-
-
-
- Function
callback
- :
-
- Callback for handling response from the database
-
-
-
-
- Returns
- void
-
-
-
-
-
-
-
- end
-
- Closes the database connection for the current adapter
-
- Returns
- void
-
-
-
-
-
-
-
- filterMatches(array)
-
- Filter matched patterns
-
- Parameters
-
- Array
array
- :
-
- Set of possible matches
-
-
-
-
- Returns
- Array
or
- :
-
- Filtered set of possible matches
-
-
-
-
-
- from(tableName)
-
- Specify the database table to select from
-
- Parameters
-
- String
tableName
- :
-
- The table to use for the current query
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- get([table], [limit], [offset], callback)
-
- Get the results of the compiled query
-
- Parameters
-
- [String
]
table
- :
-
- The table to select from
-
-
-
- [Number
]
limit
- :
-
- A limit for the query
-
-
-
- [Number
]
offset
- :
-
- An offset for the query
-
-
-
- Function
callback
- :
-
- A callback for receiving the result
-
-
-
-
- Returns
- void
-
-
-
-
-
-
-
- getCompiledDelete(table, [reset])
-
- Return generated delete query SQL
-
- Parameters
-
- String
table
- :
-
- the name of the table to delete from
-
-
-
- [Boolean
]
reset
- (default true
)
- :
-
- Whether to reset the query builder so another query can be built
-
-
-
-
- Returns
- String
- :
-
- The compiled sql statement
-
-
-
-
-
- getCompiledInsert(table, [reset])
-
- Return generated insert query SQL
-
- Parameters
-
- String
table
- :
-
- the name of the table to insert into
-
-
-
- [Boolean
]
reset
- (default true
)
- :
-
- Whether to reset the query builder so another query can be built
-
-
-
-
- Returns
- String
- :
-
- The compiled sql statement
-
-
-
-
-
- getCompiledSelect([table], [reset])
-
- Return generated select query SQL
-
- Parameters
-
- [String
]
table
- :
-
- the name of the table to retrieve from
-
-
-
- [Boolean
]
reset
- (default true
)
- :
-
- Whether to reset the query builder so another query can be built
-
-
-
-
- Returns
- String
- :
-
- The compiled sql statement
-
-
-
-
-
- getCompiledUpdate(table, [reset])
-
- Return generated update query SQL
-
- Parameters
-
- String
table
- :
-
- the name of the table to update
-
-
-
- [Boolean
]
reset
- (default true
)
- :
-
- Whether to reset the query builder so another query can be built
-
-
-
-
- Returns
- String
- :
-
- The compiled sql statement
-
-
-
-
-
- groupBy(field)
-
- Group the results by the selected field(s)
-
- Parameters
-
- String
or Array
field
- :
-
- The name of the field to group by
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- groupEnd
-
- Ends a logical grouping started with one of the groupStart methods
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- groupStart
-
- Adds an open paren to the current query for logical grouping
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- hasOperator(string)
-
- Check if the string contains an operator, and if so, return the operator(s).
-If there are no matches, return null
-
- Parameters
-
- String
string
- :
-
- the string to check
-
-
-
-
- Returns
- Array
or
- :
-
- List of operators
-
-
-
-
-
- having(key, [val])
-
- Add a 'having' clause
-
- Parameters
-
- String
or Object
key
- :
-
- The name of the field and the comparision operator, or an object
-
-
-
- [String
or Number
]
val
- :
-
- The value to compare if the value of key is a string
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- insert(table, [data], callback)
-
- Run the generated insert query
-
- Parameters
-
- String
table
- :
-
- The table to insert into
-
-
-
- [Object
]
data
- :
-
- Data to insert, if not already added with the 'set' method
-
-
-
- Function
callback
- :
-
- Callback for handling response from the database
-
-
-
-
- Returns
- void
-
-
-
-
-
-
-
- insertBatch(table, data, callback)
-
- Insert multiple sets of rows at a time
-
- Parameters
-
- String
table
- :
-
- The table to insert into
-
-
-
- Array
data
- :
-
- The array of objects containing data rows to insert
-
-
-
- Function
callback
- :
-
- Callback for handling database response
-
-
-
-
- Returns
- void
-
-
-
-
- Examples
-query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
-
-
-
- join(table, cond, [type])
-
- Add a join clause to the query
-
- Parameters
-
- String
table
- :
-
- The table you are joining
-
-
-
- String
cond
- :
-
- The join condition.
-
-
-
- [String
]
type
- (default 'inner'
)
- :
-
- The type of join, which defaults to inner
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- like(field, val, [pos])
-
- Add a 'like/ and like' clause to the query
-
- Parameters
-
- String
field
- :
-
- The name of the field to compare to
-
-
-
- String
val
- :
-
- The value to compare to
-
-
-
- [String
]
pos
- (default both
)
- :
-
- The placement of the wildcard character(s): before, after, or both
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- limit(limit, [offset])
-
- Put a limit on the query
-
- Parameters
-
- Number
limit
- :
-
- The maximum number of rows to fetch
-
-
-
- [Number
]
offset
- :
-
- The row number to start from
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- notLike(field, val, [pos])
-
- Add a 'not like/ and not like' clause to the query
-
- Parameters
-
- String
field
- :
-
- The name of the field to compare to
-
-
-
- String
val
- :
-
- The value to compare to
-
-
-
- [String
]
pos
- (default both
)
- :
-
- The placement of the wildcard character(s): before, after, or both
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orGroupStart
-
- Adds an open paren to the current query for logical grouping,
+
+
+
+
+
+
+
+
+
+ #insertBatch(table, data, [callback])
+
+
+
Insert multiple sets of rows at a time
+
+
+
+
+
+
+ insertBatch(table, data, [callback])
+
+ Insert multiple sets of rows at a time
+
+ Parameters
+
+ String
table
+ :
+
+
The table to insert into
+
+
+
+ Array
data
+ :
+
+
The array of objects containing data rows to insert
+
+
+
+ [Function
]
callback
+ :
+
+
Callback for handling database response
+
+
+
+
+ Returns
+ void
or Promise
+ :
+
+
If no callback is passed, a promise is returned
+
+
+ Examples
+ query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
+
+
+
+
+
+
+
+
+
+
+
+
+ #orLike(field, val, [pos])
+
+
+
Add an 'or like' clause to the query
-
Parameters
-
- String
or Object
key
- :
-
- The name of the field and the comparision operator, or an object
-
-
-
- [String
or Number
]
val
- :
-
- The value to compare if the value of key is a string
-
-
-
-
-
Returns
-
QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orLike(field, val, [pos])
-
- Add an 'or like' clause to the query
-
- Parameters
-
- String
field
- :
-
- The name of the field to compare to
-
-
-
- String
val
- :
-
- The value to compare to
-
-
-
- [String
]
pos
- (default both
)
- :
-
- The placement of the wildcard character(s): before, after, or both
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orNotGroupStart
-
- Adds an open paren to the current query for logical grouping,
+
+
+
+
+
+ orLike(field, val, [pos])
+
+ Add an 'or like' clause to the query
+
+ Parameters
+
+ String
field
+ :
+
+
The name of the field to compare to
+
+
+
+ String
val
+ :
+
+
The value to compare to
+
+
+
+ [String
]
pos
+ (default both
)
+ :
+
+
The placement of the wildcard character(s): before, after, or both
+
+
+
+
+ Returns
+ QueryBuilder
+ :
+
+
The Query Builder object, for chaining
+
+
+
+
+
+
+
+
+ #orNotGroupStart
+
+
+
Adds an open paren to the current query for logical grouping,
prefixed with 'OR NOT'
-
Returns
-
QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orNotLike(field, val, [pos])
-
- Add an 'or not like' clause to the query
-
- Parameters
-
- String
field
- :
-
- The name of the field to compare to
-
-
-
- String
val
- :
-
- The value to compare to
-
-
-
- [String
]
pos
- (default both
)
- :
-
- The placement of the wildcard character(s): before, after, or both
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orWhere(key, [val])
-
- Set a 'or where' clause
-
- Parameters
-
- String
or Object
key
- :
-
- The name of the field and the comparision operator, or an object
-
-
-
- [String
or Number
]
val
- :
-
- The value to compare if the value of key is a string
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orWhereIn(key, val)
-
- Set a 'or where in' clause
-
- Parameters
-
- String
key
- :
-
- the field to search
-
-
-
- Array
val
- :
-
- the array of items to search in
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orWhereIsNotNull(field)
-
- Field is not null prefixed with 'OR'
-
- Parameters
-
- String
field
- :
-
- The name of the field
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orWhereIsNull(field)
-
- Field is null prefixed with 'OR'
-
- Parameters
-
- String
field
- :
-
- The name of the field
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orWhereNotIn(key, val)
-
- Set a 'or where not in' clause
-
- Parameters
-
- String
key
- :
-
- the field to search
-
-
-
- Array
val
- :
-
- the array of items to search in
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- orderBy(field, [type])
-
- Order the results by the selected field(s)
-
- Parameters
-
- String
field
- :
-
- The field(s) to order by
-
-
-
- [String
]
type
- (default 'ASC'
)
- :
-
- The order direction, ASC or DESC
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- parseJoin(sql)
-
- Tokenize the sql into parts for additional processing
-
- Parameters
-
- String
sql
- :
-
- Join sql to parse
-
-
-
-
- Returns
- Object
- :
-
- Join condition components
-
-
-
-
-
- parseWhere(driver, state)
-
- Parse a where clause to separate functions from values
-
- Parameters
-
- Driver
driver
- :
-
- The current db driver
-
-
-
- State
state
- :
-
- Query Builder state object
-
-
-
-
- Returns
- String
- :
-
- The parsed/escaped where condition
-
-
-
-
-
- resetQuery
-
- Reset the object state for a new query
-
- Returns
- void
-
-
-
-
-
-
-
- select(fields)
-
- Specify rows to select in the query
-
- Parameters
-
- String
or Array
fields
- :
-
- The fields to select from the current table
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- set(key, [val])
-
- Set values for insertion or updating
-
- Parameters
-
- String
or Object
key
- :
-
- The key or object to use
-
-
-
- [String
]
val
- :
-
- The value if using a scalar key
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- update(table, [data], callback)
-
- Run the generated update query
-
- Parameters
-
- String
table
- :
-
- The table to insert into
-
-
-
- [Object
]
data
- :
-
- Data to insert, if not already added with the 'set' method
-
-
-
- Function
callback
- :
-
- Callback for handling response from the database
-
-
-
-
- Returns
- void
-
-
-
-
-
-
-
- where(key, [val])
-
- Set a 'where' clause
-
- Parameters
-
- String
or Object
key
- :
-
- The name of the field and the comparision operator, or an object
-
-
-
- [String
or Number
]
val
- :
-
- The value to compare if the value of key is a string
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- whereIn(key, val)
-
- Set a 'where in' clause
-
- Parameters
-
- String
key
- :
-
- the field to search
-
-
-
- Array
val
- :
-
- the array of items to search in
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- whereIsNotNull(field)
-
- Specify that a field IS NOT NULL
-
- Parameters
-
- String
field
- :
-
- The name so the field that is not to be null
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- whereIsNull(field)
-
- Select a field that is Null
-
- Parameters
-
- String
field
- :
-
- The name of the field that has a NULL value
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
-
-
-
- whereNotIn(key, val)
-
- Set a 'where not in' clause
-
- Parameters
-
- String
key
- :
-
- the field to search
-
-
-
- Array
val
- :
-
- the array of items to search in
-
-
-
-
- Returns
- QueryBuilder
- :
-
- The Query Builder object, for chaining
-
-
+
+
+
+
+
+ orNotGroupStart
+
+ Adds an open paren to the current query for logical grouping,
+ prefixed with 'OR NOT'
+
+ Returns
+ QueryBuilder
+ :
+
+
The Query Builder object, for chaining
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gulpfile.js b/gulpfile.js
index e321cea..23fc1b8 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -54,6 +54,13 @@ const ESLINT_SETTINGS = {
}
};
+const MOCHA_OPTIONS = {
+ ui: 'tdd',
+ bail: true,
+ reporter: 'list',
+ timeout: 10000,
+};
+
gulp.task('lint', () => {
pipe(gulp.src(SRC_FILES), [
eslint(ESLINT_SETTINGS),
@@ -82,22 +89,14 @@ gulp.task('sloc', () => gulp.src(SRC_FILES).pipe(sloc()));
gulp.task('test-sloc', () => gulp.src(TEST_FILES).pipe(sloc()));
gulp.task('docs', () => {
- gulp.src('./lib/QueryBuilder.js')
+ gulp.src(['lib/*.js'])
.pipe(documentation({format: 'html'}))
.pipe(gulp.dest('docs'));
- /*gulp.src('./lib/QueryBuilder.js')
- .pipe(documentation({format: 'md'}))
- .pipe(gulp.dest('api-docs'));*/
});
gulp.task('mocha', ['lint-tests', 'sloc'], () => {
return gulp.src(TEST_FILES)
- .pipe(mocha({
- ui: 'tdd',
- bail: true,
- reporter: 'list',
- timeout: 5000
- }))
+ .pipe(mocha(MOCHA_OPTIONS))
.once('error', () => {
process.exit(1);
})
@@ -112,10 +111,7 @@ gulp.task('test', ['test-sloc', 'lint-tests'], function(cb) {
istanbul.hookRequire()
]).on('finish', () => {
pipe(gulp.src(TEST_FILES), [
- mocha({
- ui: 'tdd',
- bail: true
- }),
+ mocha(MOCHA_OPTIONS),
istanbul.writeReports({
dir: './coverage',
reporters: ['lcov', 'lcovonly', 'html', 'text']
diff --git a/lib/Adapter.js b/lib/Adapter.js
index 3381415..c5a249b 100755
--- a/lib/Adapter.js
+++ b/lib/Adapter.js
@@ -1,12 +1,18 @@
+
'use strict';
-/** @module Adapter */
-module.exports = class Adapter {
+/**
+ * Class that wraps database connection libraries
+ *
+ * @private
+ * @param {Object} instance - The connection object
+ */
+class Adapter {
/**
* Invoke an adapter
*
- * @param {Object} instance - The connection objec
- * @return {void}
+ * @constructor
+ * @param {Object} instance - The connection object
*/
constructor(instance) {
this.instance = instance;
@@ -17,8 +23,8 @@ module.exports = class Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - returns a promise if no callback is passed
*/
execute(/*sql, params, callback*/) {
throw new Error('Correct adapter not defined for query execution');
@@ -31,4 +37,6 @@ module.exports = class Adapter {
close() {
this.instance.end();
}
-};
\ No newline at end of file
+}
+
+module.exports = Adapter;
\ No newline at end of file
diff --git a/lib/Driver.js b/lib/Driver.js
index a6f3e51..3d9b84d 100755
--- a/lib/Driver.js
+++ b/lib/Driver.js
@@ -1,13 +1,13 @@
'use strict';
-let helpers = require('./helpers');
+const helpers = require('./helpers');
/**
* Base Database Driver
*
- * @module driver
+ * @private
*/
-let d = {
+let Driver = {
identifierStartChar: '"',
identifierEndChar: '"',
tablePrefix: null,
@@ -15,14 +15,14 @@ let d = {
/**
* Low level function for naive quoting of strings
-
+ *
* @param {String} str - The sql fragment to quote
* @return {String} - The quoted sql fragment
* @private
*/
_quote(str) {
- return (helpers.isString(str) && ! (str.startsWith(d.identifierStartChar) || str.endsWith(d.identifierEndChar)))
- ? `${d.identifierStartChar}${str}${d.identifierEndChar}`
+ return (helpers.isString(str) && ! (str.startsWith(Driver.identifierStartChar) || str.endsWith(Driver.identifierEndChar)))
+ ? `${Driver.identifierStartChar}${str}${Driver.identifierEndChar}`
: str;
},
@@ -31,7 +31,7 @@ let d = {
* @param {String} sql - SQL statement to modify
* @param {Number} limit - Maximum number of rows to fetch
- * @param {Number|null} offset - Number of rows to skip
+ * @param {Number} [offset] - Number of rows to skip
* @return {String} - Modified SQL statement
*/
limit(sql, limit, offset) {
@@ -53,37 +53,37 @@ let d = {
*/
quoteTable(table) {
// Quote after prefix
- return d.quoteIdentifiers(table);
+ return Driver.quoteIdentifiers(table);
},
/**
* Use the driver's escape character to quote identifiers
*
- * @param {String|String[]} - String or array of strings to quote identifiers
- * @return {String|String[]} - Quoted identifier(s)
+ * @param {String|Array} str - String or array of strings to quote identifiers
+ * @return {String|Array} - Quoted identifier(s)
*/
quoteIdentifiers(str) {
let hiers, raw;
let pattern = new RegExp(
- `${d.identifierStartChar}(`
+ `${Driver.identifierStartChar}(`
+ '([a-zA-Z0-9_]+)' + '(\((.*?)\))'
- + `)${d.identifierEndChar}`, 'ig');
+ + `)${Driver.identifierEndChar}`, 'ig');
// Recurse for arrays of identifiiers
if (Array.isArray(str))
{
- return str.map(d.quoteIdentifiers);
+ return str.map(Driver.quoteIdentifiers);
}
// Handle commas
if (str.includes(','))
{
let parts = str.split(',').map(helpers.stringTrim);
- str = parts.map(d.quoteIdentifiers).join(',');
+ str = parts.map(Driver.quoteIdentifiers).join(',');
}
// Split identifiers by period
- hiers = str.split('.').map(d._quote);
+ hiers = str.split('.').map(Driver._quote);
raw = hiers.join('.');
// Fix functions
@@ -96,30 +96,30 @@ let d = {
// Quote the identifiers inside of the parens
let inParens = funcs[3].substring(1, funcs[3].length - 1);
- raw = raw.replace(inParens, d.quoteIdentifiers(inParens));
+ raw = raw.replace(inParens, Driver.quoteIdentifiers(inParens));
}
return raw;
},
/**
- * SQL to truncate the passed table
+ * Generate SQL to truncate the passed table
*
* @param {String} table - Table to truncate
* @return {String} - Truncation SQL
*/
truncate(table) {
- let sql = (d.hasTruncate)
+ let sql = (Driver.hasTruncate)
? 'TRUNCATE '
: 'DELETE FROM ';
- sql += d.quoteTable(table);
+ sql += Driver.quoteTable(table);
return sql;
},
/**
- * SQL to insert a group of rows
+ * Generate SQL to insert a group of rows
*
* @param {String} table - The table to insert to
* @param {Array} [data] - The array of object containing data to insert
@@ -143,9 +143,9 @@ let d = {
// Get the field names from the keys of the first
// object inserted
- table = d.quoteTable(table);
+ table = Driver.quoteTable(table);
- sql += `INSERT INTO ${table} (${d.quoteIdentifiers(fields).join(',')}) VALUES `;
+ sql += `INSERT INTO ${table} (${Driver.quoteIdentifiers(fields).join(',')}) VALUES `;
// Create placeholder groups
params = Array(fields.length).fill('?');
@@ -161,4 +161,4 @@ let d = {
},
};
-module.exports = d;
\ No newline at end of file
+module.exports = Driver;
\ No newline at end of file
diff --git a/lib/NodeQuery.js b/lib/NodeQuery.js
index 2b3f50a..753956e 100755
--- a/lib/NodeQuery.js
+++ b/lib/NodeQuery.js
@@ -5,14 +5,15 @@ let fs = require('fs'),
QueryBuilder = require('./QueryBuilder');
/**
- * @module NodeQuery
+ * Class for connection management
*/
class NodeQuery {
/**
* Constructor
*
- * @return {void}
+ * @private
+ * @constructor
*/
constructor() {
this.instance = null;
@@ -23,7 +24,7 @@ class NodeQuery {
*
* @param {String} driverType - The name of the database type, eg. mysql or pg
* @param {Object} connObject - A connection object from the database library you are connecting with
- * @param {String} [connLib] - The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as drivername
+ * @param {String} [connLib] - The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as driverType
* @return {QueryBuilder} - The Query Builder object
*/
init(driverType, connObject, connLib) {
diff --git a/lib/QueryBuilder.js b/lib/QueryBuilder.js
index 807f049..f6fe67c 100755
--- a/lib/QueryBuilder.js
+++ b/lib/QueryBuilder.js
@@ -1,23 +1,26 @@
'use strict';
-/** @module QueryBuilder */
let getArgs = require('getargs'),
helpers = require('./helpers'),
State = require('./State'),
QueryParser = require('./QueryParser');
-module.exports = class QueryBuilder {
- /*
- * SQL generation object
- *
- * @param {driver} - The syntax driver for the database
- * @param {adapter} - The database module adapter for running queries
- * @return {QueryBuilder} - The Query Builder object, for chaining
+/**
+ * Main object that builds SQL queries.
+ *
+ * @param {Driver} Driver - The syntax driver for the database
+ * @param {Adapter} Adapter - The database module adapter for running queries
+ */
+class QueryBuilder {
+ /**
+ * @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;
+ constructor(Driver, Adapter) {
+ this.driver = Driver;
+ this.adapter = Adapter;
this.parser = new QueryParser(this.driver);
this.state = new State();
}
@@ -265,8 +268,11 @@ module.exports = class QueryBuilder {
this._resetState();
// Pass the sql and values to the adapter to run on the database
- this.adapter.execute(sql, vals, callback);
-
+ if (callback) {
+ return this.adapter.execute(sql, vals, callback);
+ } else {
+ return this.adapter.execute(sql, vals);
+ }
}
_getCompile(type, table, reset) {
@@ -743,11 +749,11 @@ module.exports = class QueryBuilder {
* @param {String} [table] - The table to select from
* @param {Number} [limit] - A limit for the query
* @param {Number} [offset] - An offset for the query
- * @param {Function} callback - A callback for receiving the result
- * @return {void}
+ * @param {Function} [callback] - A callback for receiving the result
+ * @return {void|Promise} - If no callback is passed, a promise is returned
*/
- get(/* [table], [limit], [offset], callback */) {
- let args = getArgs('[table]:string, [limit]:number, [offset]:number, callback:function', arguments);
+ get(/* [table], [limit], [offset], [callback] */) {
+ let args = getArgs('[table]:string, [limit]:number, [offset]:number, [callback]:function', arguments);
if (args.table) {
this.from(args.table);
@@ -758,7 +764,7 @@ module.exports = class QueryBuilder {
}
// Run the query
- this._run('get', args.table, args.callback);
+ return this._run('get', args.table, args.callback);
}
/**
@@ -766,18 +772,18 @@ module.exports = class QueryBuilder {
*
* @param {String} table - The table to insert into
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
- * @param {Function} callback - Callback for handling response from the database
- * @return {void}
+ * @param {Function} [callback] - Callback for handling response from the database
+ * @return {void|Promise} - If no callback is passed, a promise is returned
*/
insert(/* table, data, callback */) {
- let args = getArgs('table:string, [data]:object, callback:function', arguments);
+ let args = getArgs('table:string, [data]:object, [callback]:function', arguments);
if (args.data) {
this.set(args.data);
}
// Run the query
- this._run('insert', this.driver.quoteTable(args.table), args.callback);
+ return this._run('insert', this.driver.quoteTable(args.table), args.callback);
}
/**
@@ -785,16 +791,16 @@ module.exports = class QueryBuilder {
*
* @param {String} table - The table to insert into
* @param {Array} data - The array of objects containing data rows to insert
- * @param {Function} callback - Callback for handling database response
+ * @param {Function} [callback] - Callback for handling database response
* @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
- * @return {void}
+ * @return {void|Promise} - If no callback is passed, a promise is returned
*/
insertBatch(/* table, data, callback */) {
- let args = getArgs('table:string, data:array, callback:function', arguments);
+ let args = getArgs('table:string, data:array, [callback]:function', arguments);
let batch = this.driver.insertBatch(args.table, args.data);
// Run the query
- this._run('', '', args.callback, batch.sql, batch.values);
+ return this._run('', '', args.callback, batch.sql, batch.values);
}
/**
@@ -802,18 +808,18 @@ module.exports = class QueryBuilder {
*
* @param {String} table - The table to insert into
* @param {Object} [data] - Data to insert, if not already added with the 'set' method
- * @param {Function} callback - Callback for handling response from the database
- * @return {void}
+ * @param {Function} [callback] - Callback for handling response from the database
+ * @return {void|Promise} - If no callback is passed, a promise is returned
*/
update(/*table, data, callback*/) {
- let args = getArgs('table:string, [data]:object, callback:function', arguments);
+ let args = getArgs('table:string, [data]:object, [callback]:function', arguments);
if (args.data) {
this.set(args.data);
}
// Run the query
- this._run('update', this.driver.quoteTable(args.table), args.callback);
+ return this._run('update', this.driver.quoteTable(args.table), args.callback);
}
/**
@@ -821,18 +827,18 @@ module.exports = class QueryBuilder {
*
* @param {String} table - The table to insert into
* @param {Object} [where] - Where clause for delete statement
- * @param {Function} callback - Callback for handling response from the database
- * @return {void}
+ * @param {Function} [callback] - Callback for handling response from the database
+ * @return {void|Promise} - If no callback is passed, a promise is returned
*/
delete(/*table, [where], callback*/) {
- let args = getArgs('table:string, [where]:object, callback:function', arguments);
+ let args = getArgs('table:string, [where]:object, [callback]:function', arguments);
if (args.where) {
this.where(args.where);
}
// Run the query
- this._run('delete', this.driver.quoteTable(args.table), args.callback);
+ return this._run('delete', this.driver.quoteTable(args.table), args.callback);
}
// ------------------------------------------------------------------------
@@ -887,4 +893,6 @@ module.exports = class QueryBuilder {
getCompiledDelete(table, reset) {
return this._getCompile('delete', this.driver.quoteTable(table), reset);
}
-};
\ No newline at end of file
+}
+
+module.exports = QueryBuilder;
\ No newline at end of file
diff --git a/lib/QueryParser.js b/lib/QueryParser.js
index 9ae14ed..461a531 100644
--- a/lib/QueryParser.js
+++ b/lib/QueryParser.js
@@ -4,7 +4,13 @@ let helpers = require('./helpers');
// --------------------------------------------------------------------------
-module.exports = class QueryParser {
+/**
+ * Internal object for parsing query fragments
+ *
+ * @private
+ * @param {Driver} driver - The driver object for the database in use
+ */
+class QueryParser {
/**
* @constructor
*
@@ -237,4 +243,6 @@ module.exports = class QueryParser {
return state;
}
-};
\ No newline at end of file
+}
+
+module.exports = QueryParser;
\ No newline at end of file
diff --git a/lib/State.js b/lib/State.js
index edb2385..66cae2b 100644
--- a/lib/State.js
+++ b/lib/State.js
@@ -1,7 +1,10 @@
'use strict';
-/** @module State */
-module.exports = class State {
+/**
+ * Class for objects containing the query builder state
+ * @private
+ */
+class State {
constructor() {
// Arrays/maps
this.queryMap = [];
@@ -25,6 +28,8 @@ module.exports = class State {
this.limit = null;
this.offset = null;
}
-};
+}
+
+module.exports = State;
// End of module State
\ No newline at end of file
diff --git a/lib/adapters/dblite.js b/lib/adapters/dblite.js
index 371844e..76f325d 100644
--- a/lib/adapters/dblite.js
+++ b/lib/adapters/dblite.js
@@ -1,7 +1,8 @@
'use strict';
let Adapter = require('../Adapter'),
- getArgs = require('getargs');
+ getArgs = require('getargs'),
+ Promise = require('bluebird');
module.exports = class dblite extends Adapter {
/**
@@ -9,16 +10,23 @@ module.exports = class dblite extends Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - Returns a promise if no callback is provided
*/
execute(/*sql, params, callback*/) {
- let args = getArgs('sql:string, [params]:array, callback:function', arguments);
- this.instance.query(args.sql, args.params, args.callback);
+ let args = getArgs('sql:string, [params]:array, [callback]:function', arguments);
+ let instance = Promise.promisifyAll(this.instance);
+
+ if (! args.callback) {
+ return instance.queryAsync(args.sql, args.params);
+ }
+
+ return this.instance.query(args.sql, args.params, args.callback);
}
/**
* Close the current database connection
+
* @return {void}
*/
close() {
diff --git a/lib/adapters/mysql.js b/lib/adapters/mysql.js
index 9f0c1e2..6624618 100644
--- a/lib/adapters/mysql.js
+++ b/lib/adapters/mysql.js
@@ -1,7 +1,8 @@
'use strict';
let Adapter = require('../Adapter'),
- getArgs = require('getargs');
+ getArgs = require('getargs'),
+ Promise = require('bluebird');
module.exports = class mysql extends Adapter {
/**
@@ -9,11 +10,17 @@ module.exports = class mysql extends Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - Returns a promise if no callback is provided
*/
execute(sql, params, callback) {
- let args = getArgs('sql:string, [params], callback:function', arguments);
+ let args = getArgs('sql:string, [params], [callback]:function', arguments);
+ let instance = Promise.promisifyAll(this.instance);
+
+ if (! args.callback) {
+ return instance.queryAsync(args.sql, args.params);
+ }
+
return this.instance.query(args.sql, args.params, args.callback);
}
};
\ No newline at end of file
diff --git a/lib/adapters/mysql2.js b/lib/adapters/mysql2.js
index 3b1d8f8..fc76a19 100644
--- a/lib/adapters/mysql2.js
+++ b/lib/adapters/mysql2.js
@@ -1,7 +1,8 @@
'use strict';
let Adapter = require('../Adapter'),
- getArgs = require('getargs');
+ getArgs = require('getargs'),
+ Promise = require('bluebird');
module.exports = class mysql2 extends Adapter {
/**
@@ -9,11 +10,17 @@ module.exports = class mysql2 extends Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - Returns a promise if no callback is provided
*/
execute(/*sql, params, callback*/) {
- let args = getArgs('sql:string, [params], callback:function', arguments);
+ let args = getArgs('sql:string, [params], [callback]:function', arguments);
+ let instance = Promise.promisifyAll(this.instance);
+
+ if (! args.callback) {
+ return instance.executeAsync(args.sql, args.params);
+ }
+
return this.instance.execute(args.sql, args.params, args.callback);
}
};
\ No newline at end of file
diff --git a/lib/adapters/node-firebird.js b/lib/adapters/node-firebird.js
index e06d812..67e06fd 100644
--- a/lib/adapters/node-firebird.js
+++ b/lib/adapters/node-firebird.js
@@ -1,7 +1,8 @@
'use strict';
let Adapter = require('../Adapter'),
- getArgs = require('getargs');
+ getArgs = require('getargs'),
+ Promise = require('bluebird');
module.exports = class nodefirebird extends Adapter {
/**
@@ -9,11 +10,25 @@ module.exports = class nodefirebird extends Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - Returns a promise if no callback is provided
*/
execute(/*sql, params, callback*/) {
- let args = getArgs('sql:string, [params], callback:function', arguments);
- return this.instance.execute(args.sql, args.params, args.callback);
+ let args = getArgs('sql:string, [params], [callback]:function', arguments);
+ let instance = Promise.promisifyAll(this.instance);
+
+ if (! args.callback) {
+ return instance.queryAsync(args.sql, args.params);
+ }
+
+ return this.instance.query(args.sql, args.params, args.callback);
+ }
+
+ /**
+ * Close the current database connection
+ * @return {void}
+ */
+ close() {
+ this.instance.detach();
}
};
\ No newline at end of file
diff --git a/lib/adapters/pg.js b/lib/adapters/pg.js
index 65fb543..704f37e 100644
--- a/lib/adapters/pg.js
+++ b/lib/adapters/pg.js
@@ -1,7 +1,8 @@
'use strict';
let Adapter = require('../Adapter'),
- getArgs = require('getargs');
+ getArgs = require('getargs'),
+ Promise = require('bluebird');
module.exports = class pg extends Adapter {
/**
@@ -9,11 +10,12 @@ module.exports = class pg extends Adapter {
*
* @param {String} sql - The sql with placeholders
* @param {Array} params - The values to insert into the query
- * @param {Function} callback - Callback to run when a response is recieved
- * @return {void}
+ * @param {Function} [callback] - Callback to run when a response is recieved
+ * @return {void|Promise} - Returns a promise if no callback is provided
*/
execute(/*sql, params, callback*/) {
- let args = getArgs('sql:string, [params]:array, callback:function', arguments);
+ let args = getArgs('sql:string, [params]:array, [callback]:function', arguments);
+ let instance = Promise.promisifyAll(this.instance);
// Replace question marks with numbered placeholders, because this adapter is different...
let count = 0;
@@ -22,6 +24,10 @@ module.exports = class pg extends Adapter {
return `$${count}`;
});
- this.instance.query(args.sql, args.params, args.callback);
+ if (! args.callback) {
+ return instance.queryAsync(args.sql, args.params);
+ }
+
+ return this.instance.query(args.sql, args.params, args.callback);
}
};
\ No newline at end of file
diff --git a/lib/helpers.js b/lib/helpers.js
index 3280079..f59bf8d 100755
--- a/lib/helpers.js
+++ b/lib/helpers.js
@@ -1,5 +1,10 @@
'use strict';
+/**
+ * Various internal helper functions
+ *
+ * @private
+ */
let helpers = {
/**
* Wrap String.prototype.trim in a way that is easily mappable
@@ -124,9 +129,9 @@ types.forEach(t => {
*
* Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
*
- * @name is[type]
- * @param {mixed} o
- * @return {Boolean}
+ * @private
+ * @param {mixed} o - The object to check its type
+ * @return {Boolean} - If the type matches
*/
helpers[`is${t}`] = function(o) {
if (t.toLowerCase() === 'infinite') {
diff --git a/package.json b/package.json
index e1ef6a4..482e483 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,14 @@
{
"name": "ci-node-query",
- "version": "3.0.1",
+ "version": "3.1.0",
"description": "A query builder for node based on the one in CodeIgniter",
"author": "Timothy J Warren
",
"engines": {
"node": ">=4.0.0"
},
+ "files": [
+ "lib/"
+ ],
"contributors": [
{
"name": "Timothy J Warren",
@@ -33,36 +36,34 @@
},
"main": "lib/NodeQuery.js",
"dependencies": {
- "getargs": "",
- "mysql": "^2.9.0",
- "mysql2": "^0.15.8",
- "node-firebird": "^0.7.0",
- "pg": "^4.4.3",
- "require-reload": "*"
- },
- "optionalDependencies": {
- "dblite": "*",
- "node-firebird": "*",
- "pg": "*"
+ "bluebird": "^3.1.4",
+ "dblite": "~0.7.6",
+ "getargs": "~0.0.8",
+ "mysql": "~2.10.2",
+ "mysql2": "~0.15.8",
+ "node-firebird": "~0.7.2",
+ "pg": "~4.4.3",
+ "require-reload": "~0.2.2"
},
"devDependencies": {
- "chai": "",
+ "chai": "~3.4.1",
+ "chai-as-promised": "^5.2.0",
"documentation": "",
- "eslint": "",
- "glob": "^6.0.1",
- "gulp": "",
- "gulp-documentation": "^2.1.0",
- "gulp-eslint": "",
+ "eslint": "~1.10.3",
+ "glob": "~6.0.4",
+ "gulp": "~3.9.0",
+ "gulp-documentation": "~2.1.0",
+ "gulp-eslint": "~1.1.1",
"gulp-istanbul": "^0.10.3",
"gulp-jscs": "^3.0.2",
"gulp-mocha": "^2.2.0",
"gulp-pipe": "^1.0.4",
- "gulp-sloc": "",
- "istanbul": "",
+ "gulp-sloc": "~1.0.4",
+ "istanbul": "~0.4.2",
"mocha": ""
},
"license": "MIT",
"scripts": {
"test": "gulp test"
}
-}
+}
\ No newline at end of file
diff --git a/test/adapters/adapterTestBase.js b/test/adapters/adapterTestBase.js
deleted file mode 100644
index aad4aa4..0000000
--- a/test/adapters/adapterTestBase.js
+++ /dev/null
@@ -1,479 +0,0 @@
-'use strict';
-
-module.exports.tests = {
- 'Get tests': {
- 'Get with function': {
- select: ['id, COUNT(id) as count'],
- from: ['create_test'],
- groupBy: ['id'],
- get: [],
- },
- 'Basic select all get': {
- get: ['create_test'],
- },
- 'Basic select all with from': {
- from: ['create_test'],
- get: [],
- },
- 'Get with limit': {
- get: ['create_test', 2],
- },
- 'Get with limit and offset': {
- get: ['create_test', 2, 1],
- },
- 'Get with having': {
- select: ['id'],
- from: ['create_test'],
- groupBy: ['id'],
- having: [
- 'multiple',
- [{'id >': 1}],
- ['id !=', 3],
- ['id', 900],
- ],
- get: [],
- },
- 'Get with orHaving': {
- select: ['id'],
- from: ['create_test'],
- groupBy: ['id'],
- having: [{'id >': 1}],
- orHaving: ['id !=', 3],
- get: [],
- },
- },
- 'Select tests': {
- 'Select where get': {
- select: [['id', 'key as k', 'val']],
- where: [
- 'multiple',
- ['id >', 1],
- ['id <', 900],
- ],
- get: ['create_test', 2, 1],
- },
- 'Select where get 2': {
- select: ['id, key as k, val'],
- where: ['id !=', 1],
- get: ['create_test', 2, 1],
- },
- 'Multi Order By': {
- from: ['create_test'],
- orderBy: ['id, key'],
- get: [],
- },
- 'Select get': {
- select: ['id, key as k, val'],
- get: ['create_test', 2, 1],
- },
- 'Select from get': {
- select: ['id, key as k, val'],
- from: ['create_test ct'],
- where: ['id >', 1],
- get: [],
- },
- 'Select from limit get': {
- select: ['id, key as k, val'],
- from: ['create_test ct'],
- where: ['id >', 1],
- limit: [3],
- get: [],
- },
- 'Select where IS NOT NULL': {
- select: ['id', 'key as k', 'val'],
- from: ['create_test ct'],
- whereIsNotNull: ['id'],
- get: [],
- },
- 'Select where IS NULL': {
- select: ['id', 'key as k', 'val'],
- from: ['create_test ct'],
- whereIsNull: ['id'],
- get: [],
- },
- 'Select where OR IS NOT NULL': {
- select: ['id', 'key as k', 'val'],
- from: ['create_test ct'],
- whereIsNull: ['id'],
- orWhereIsNotNull: ['id'],
- get: [],
- },
- 'Select where OR IS NULL': {
- select: ['id', 'key as k', 'val'],
- from: ['create_test ct'],
- where: ['id', 3],
- orWhereIsNull: ['id'],
- get: [],
- },
- 'Select with string where value': {
- select: ['id', 'key as k', 'val'],
- from: ['create_test ct'],
- where: ['id > 3'],
- get: [],
- },
- 'Select with function and argument in WHERE clause': {
- select: ['id'],
- from: ['create_test ct'],
- where: ['id', 'CEILING(SQRT(88))'],
- get: [],
- },
- },
- 'Where in tests': {
- 'Where in': {
- from: ['create_test'],
- whereIn: ['id', [0, 6, 56, 563, 341]],
- get: [],
- },
- 'Or Where in': {
- from: ['create_test'],
- where: ['key', 'false'],
- orWhereIn: ['id', [0, 6, 56, 563, 341]],
- get: [],
- },
- 'Where Not in': {
- from: ['create_test'],
- where: ['key', 'false'],
- whereNotIn: ['id', [0, 6, 56, 563, 341]],
- get: [],
- },
- 'Or Where Not in': {
- from: ['create_test'],
- where: ['key', 'false'],
- orWhereNotIn: ['id', [0, 6, 56, 563, 341]],
- get: [],
- },
- },
- 'Query modifier tests': {
- 'Order By': {
- select: ['id, key as k, val'],
- from: ['create_test'],
- where: [
- 'multiple',
- ['id >', 0],
- ['id <', 9000],
- ],
- orderBy: [
- 'multiple',
- ['id', 'DESC'],
- ['k', 'ASC'],
- ],
- limit: [5, 2],
- get: [],
- },
- 'Group By': {
- select: ['id, key as k, val'],
- from: ['create_test'],
- where: [
- 'multiple',
- ['id >', 0],
- ['id <', 9000],
- ],
- groupBy: [
- 'multiple',
- ['k'],
- [['id', 'val']],
- ],
- orderBy: [
- 'multiple',
- ['id', 'DESC'],
- ['k', 'ASC'],
- ],
- limit: [5, 2],
- get: [],
- },
- 'Or Where': {
- select: ['id, key as k, val'],
- from: ['create_test'],
- where: [' id ', 1],
- orWhere: ['key > ', 0],
- limit: [2, 1],
- get: [],
- },
- Like: {
- from: ['create_test'],
- like: ['key', 'og'],
- get: [],
- },
- 'Or Like': {
- from: ['create_test'],
- like: ['key', 'og'],
- orLike: ['key', 'val'],
- get: [],
- },
- 'Not Like': {
- from: ['create_test'],
- like: ['key', 'og', 'before'],
- notLike: ['key', 'val'],
- get: [],
- },
- 'Or Not Like': {
- from: ['create_test'],
- like: ['key', 'og', 'before'],
- orNotLike: ['key', 'val'],
- get: [],
- },
- 'Like Before': {
- from: ['create_test'],
- like: ['key', 'og', 'before'],
- get: [],
- },
- 'Like After': {
- from: ['create_test'],
- like: ['key', 'og', 'after'],
- get: [],
- },
- 'Basic Join': {
- from: ['create_test ct'],
- join: ['create_join cj', 'cj.id=ct.id'],
- get: [],
- },
- 'Left Join': {
- from: ['create_test ct'],
- join: ['create_join cj', 'cj.id=ct.id', 'left'],
- get: [],
- },
- 'Inner Join': {
- from: ['create_test ct'],
- join: ['create_join cj', 'cj.id=ct.id', 'inner'],
- get: [],
- },
- 'Join with multiple where values': {
- from: ['create_test ct'],
- join: ['create_join cj', 'cj.id=ct.id', 'inner'],
- where: [
- {
- 'ct.id < ': 3,
- 'ct.key ': 'foo',
- },
- ],
- get: [],
- },
- },
-};
-
-let expect = require('chai').expect,
- helpers = require('../../lib/helpers'),
- State = require('../../lib/State');
-
-module.exports.runner = (tests, qb, callback) => {
- Object.keys(tests).forEach(suiteName => {
- suite(suiteName, () => {
- let currentSuite = tests[suiteName];
- Object.keys(currentSuite).forEach(testDesc => {
- test(testDesc, done => {
- let methodObj = currentSuite[testDesc];
- let methodNames = Object.keys(methodObj);
- let lastMethodIndex = methodNames[methodNames.length - 1];
-
- methodObj[lastMethodIndex].push((err, rows) => {
- callback(err, done);
- });
-
- methodNames.forEach(name => {
- let args = methodObj[name],
- method = qb[name];
-
- if (args[0] === 'multiple') {
- args.shift();
- args.forEach(argSet => {
- method.apply(qb, argSet);
- });
-
- } else {
- method.apply(qb, args);
- }
- });
- });
- });
- });
- });
- suite('DB update tests', () => {
- setup(done => {
- let sql = qb.driver.truncate('create_test');
- qb.adapter.execute(sql, (err, res) => {
- done();
- });
- });
- test('Test Insert', done => {
- qb.set('id', 98)
- .set('key', '84')
- .set('val', new Buffer('120'))
- .insert('create_test', (err, rows) => {
- return callback(err, done);
- });
- });
- test('Test Insert Object', done => {
- qb.insert('create_test', {
- id: 587,
- key: 1,
- val: new Buffer('2'),
- }, (err, rows) => {
- return callback(err, done);
- });
- });
- test('Test Update', done => {
- qb.where('id', 7)
- .update('create_test', {
- id: 7,
- key: 'gogle',
- val: new Buffer('non-word'),
- }, (err, rows) => {
- return callback(err, done);
- });
- });
- test('Test set Array Update', done => {
- let object = {
- id: 22,
- key: 'gogle',
- val: new Buffer('non-word'),
- };
-
- qb.set(object)
- .where('id', 22)
- .update('create_test', (err, rows) => {
- return callback(err, done);
- });
- });
- test('Test where set update', done => {
- qb.where('id', 36)
- .set('id', 36)
- .set('key', 'gogle')
- .set('val', new Buffer('non-word'))
- .update('create_test', (err, rows) => {
- return callback(err, done);
- });
- });
- test('Test delete', done => {
- qb.delete('create_test', {id: 5}, (err, rows) => {
- return callback(err, done);
- });
- });
- test('Delete with where', done => {
- qb.where('id', 5)
- .delete('create_test', (err, rows) => {
- return callback(err, done);
- });
- });
- test('Delete multiple where values', done => {
- qb.delete('create_test', {
- id: 5,
- key: 'gogle',
- }, (err, rows) => {
- return callback(err, done);
- });
- });
- });
- suite('Grouping tests', () => {
- test('Using grouping method', done => {
- qb.select('id, key as k, val')
- .from('create_test')
- .groupStart()
- .where('id >', 1)
- .where('id <', 900)
- .groupEnd()
- .limit(2, 1)
- .get((err, rows) => {
- return callback(err, done);
- });
- });
- test('Using where first grouping', done => {
- qb.select('id, key as k, val')
- .from('create_test')
- .where('id !=', 5)
- .groupStart()
- .where('id >', 1)
- .where('id <', 900)
- .groupEnd()
- .limit(2, 1)
- .get((err, rows) => {
- return callback(err, done);
- });
- });
- test('Using or grouping method', done => {
- qb.select('id, key as k, val')
- .from('create_test')
- .groupStart()
- .where('id >', 1)
- .where('id <', 900)
- .groupEnd()
- .orGroupStart()
- .where('id', 0)
- .groupEnd()
- .limit(2, 1)
- .get((err, rows) => {
- return callback(err, done);
- });
- });
- test('Using or not grouping method', done => {
- qb.select('id, key as k, val')
- .from('create_test')
- .groupStart()
- .where('id >', 1)
- .where('id <', 900)
- .groupEnd()
- .orNotGroupStart()
- .where('id', 0)
- .groupEnd()
- .limit(2, 1)
- .get((err, rows) => {
- return callback(err, done);
- });
- });
- });
- suite('Get compiled tests', () => {
- test('select', () => {
- let sql = qb.select('id')
- .from('create_test')
- .getCompiledSelect(true);
-
- expect(helpers.isString(sql)).to.be.true;
- });
- test('select from', () => {
- let sql = qb.select('id')
- .getCompiledSelect('create_test', true);
-
- expect(helpers.isString(sql)).to.be.true;
- });
- test('insert', () => {
- let sql = qb.set('id', 3)
- .getCompiledInsert('create_test');
-
- expect(helpers.isString(sql)).to.be.true;
- });
- test('update', () => {
- let sql = qb.set('id', 3)
- .where('id', 5)
- .getCompiledUpdate('create_test');
-
- expect(helpers.isString(sql)).to.be.true;
- });
- test('delete', () => {
- let sql = qb.where('id', 5)
- .getCompiledDelete('create_test');
-
- expect(helpers.isString(sql)).to.be.true;
- });
- });
- suite('Misc tests', () => {
- test('Get State', () => {
- qb.select('foo')
- .from('bar')
- .where('baz', 'foobar');
-
- let state = new State();
-
- expect(JSON.stringify(state)).to.not.be.deep.equal(qb.getState());
- });
- test('Reset State', () => {
- qb.select('foo')
- .from('bar')
- .where('baz', 'foobar');
-
- qb.resetQuery();
-
- let state = new State();
-
- expect(qb.getState()).to.be.deep.equal(state);
- });
- });
-};
\ No newline at end of file
diff --git a/test/adapters/dblite_test.js b/test/adapters/dblite_test.js
index 1d56bd1..d96a387 100644
--- a/test/adapters/dblite_test.js
+++ b/test/adapters/dblite_test.js
@@ -1,11 +1,14 @@
'use strict';
// Load the test base
-let reload = require('require-reload')(require);
-let getArgs = require('getargs');
-let expect = require('chai').expect;
-let tests = reload('./adapterTestBase').tests;
-let testRunner = reload('./adapterTestBase').runner;
+const reload = require('require-reload')(require);
+reload.emptyCache();
+const testBase = reload('../base');
+const expect = testBase.expect,
+ promiseTestRunner = testBase.promiseTestRunner,
+ testRunner = testBase.testRunner;
+
+let tests = reload('../base/tests');
// Load the test config file
let adapterName = 'dblite';
@@ -25,53 +28,73 @@ if (connection) {
let nodeQuery = require('../../lib/NodeQuery');
let qb = nodeQuery.init('sqlite', connection, adapterName);
- // Add a test for this adapter
- tests['Select tests']['Select with function and argument in WHERE clause'] = {
- select: ['id'],
- from: ['create_test'],
- where: ['id', 'ABS(-88)'],
- get: [],
- };
-
- suite('Dblite adapter tests', () => {
- suiteSetup(() => {
+ suite('Dblite adapter tests -', () => {
+ suiteSetup(done => {
// Set up the sqlite database
let sql = 'CREATE TABLE IF NOT EXISTS "create_test" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);' +
'CREATE TABLE IF NOT EXISTS "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);';
- connection.query(sql);
+ connection.query(sql, () => {
+ return done();
+ });
});
- testRunner(tests, qb, (err, done) => {
+ test('nodeQuery.getQuery = nodeQuery.init', () => {
+ expect(nodeQuery.getQuery())
+ .to.be.deep.equal(qb);
+ });
+
+ /*---------------------------------------------------------------------------
+ Callback Tests
+ ---------------------------------------------------------------------------*/
+
+ testRunner(qb, (err, done) => {
expect(err).is.not.ok;
done();
});
- suite('Adapter-specific tests', () => {
- test('nodeQuery.getQuery = nodeQuery.init', () => {
- expect(nodeQuery.getQuery())
- .to.be.deep.equal(qb);
- });
- test('Test Insert Batch', done => {
- let data = [
- {
- id: 544,
- key: 3,
- val: new Buffer('7'),
- }, {
- id: 89,
- key: 34,
- val: new Buffer('10 o\'clock'),
- }, {
- id: 48,
- key: 403,
- val: new Buffer('97'),
- },
- ];
-
- qb.insertBatch('create_test', data, (err, rows) => {
+ test('Callback - Select with function and argument in WHERE clause', done => {
+ qb.select('id')
+ .from('create_test')
+ .where('id', 'ABS(-88)')
+ .get((err, rows) => {
expect(err).is.not.ok;
return done();
});
+ });
+ test('Callback - Test Insert Batch', done => {
+ let data = [
+ {
+ id: 544,
+ key: 3,
+ val: new Buffer('7'),
+ }, {
+ id: 89,
+ key: 34,
+ val: new Buffer('10 o\'clock'),
+ }, {
+ id: 48,
+ key: 403,
+ val: new Buffer('97'),
+ },
+ ];
+
+ qb.insertBatch('create_test', data, (err, rows) => {
+ expect(err).is.not.ok;
+ return done();
});
});
+
+ /*---------------------------------------------------------------------------
+ Promise Tests
+ ---------------------------------------------------------------------------*/
+ promiseTestRunner(qb);
+ test('Promise - Select with function and argument in WHERE clause', () => {
+ let promise = qb.select('id')
+ .from('create_test')
+ .where('id', 'ABS(-88)')
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+
suiteTeardown(() => {
qb.end();
});
diff --git a/test/adapters/mysql-base.js b/test/adapters/mysql-base.js
new file mode 100644
index 0000000..3f9bd06
--- /dev/null
+++ b/test/adapters/mysql-base.js
@@ -0,0 +1,64 @@
+'use strict';
+
+module.exports = function mysqlBase(qb, nodeQuery, expect, testRunner, promiseTestRunner) {
+ test('nodeQuery.getQuery = nodeQuery.init', () => {
+ expect(nodeQuery.getQuery())
+ .to.be.deep.equal(qb);
+ });
+
+ /*---------------------------------------------------------------------------
+ Callback Tests
+ ---------------------------------------------------------------------------*/
+ testRunner(qb, (err, done) => {
+ expect(err).is.not.ok;
+ done();
+ });
+ test('Callback - Select with function and argument in WHERE clause', done => {
+ qb.select('id')
+ .from('create_test')
+ .where('id', 'CEILING(SQRT(88))')
+ .get((err, rows) => {
+ expect(err).is.not.ok;
+ return done();
+ });
+ });
+ test('Test Insert Batch', done => {
+ let data = [
+ {
+ id: 544,
+ key: 3,
+ val: new Buffer('7'),
+ }, {
+ id: 89,
+ key: 34,
+ val: new Buffer('10 o\'clock'),
+ }, {
+ id: 48,
+ key: 403,
+ val: new Buffer('97'),
+ },
+ ];
+
+ qb.insertBatch('create_test', data, (err, rows) => {
+ expect(err).is.not.ok;
+ return done();
+ });
+ });
+
+ /*---------------------------------------------------------------------------
+ Promise Tests
+ ---------------------------------------------------------------------------*/
+ promiseTestRunner(qb);
+ test('Promise - Select with function and argument in WHERE clause', () => {
+ let promise = qb.select('id')
+ .from('create_test')
+ .where('id', 'CEILING(SQRT(88))')
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+
+ suiteTeardown(() => {
+ qb.end();
+ });
+};
\ No newline at end of file
diff --git a/test/adapters/mysql2_test.js b/test/adapters/mysql2_test.js
index 965f3c0..8314700 100644
--- a/test/adapters/mysql2_test.js
+++ b/test/adapters/mysql2_test.js
@@ -1,14 +1,16 @@
'use strict';
-let configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
+const configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load the test base
-let reload = require('require-reload')(require);
+const reload = require('require-reload')(require);
reload.emptyCache();
+const testBase = reload('../base');
+const expect = testBase.expect,
+ promiseTestRunner = testBase.promiseTestRunner,
+ testRunner = testBase.testRunner;
+
let getArgs = reload('getargs');
-let expect = reload('chai').expect;
-let tests = reload('./adapterTestBase').tests;
-let testRunner = reload('./adapterTestBase').runner;
// Load the test config file
let adapterName = 'mysql2';
@@ -22,40 +24,6 @@ let connection = mysql2.createConnection(config.conn);
let nodeQuery = reload('../../lib/NodeQuery');
let qb = nodeQuery.init('mysql', connection, adapterName);
-suite('Mysql2 adapter tests', () => {
- testRunner(tests, qb, (err, done) => {
- expect(err).is.not.ok;
- done();
- });
- suite('Adapter-specific tests', () => {
- test('nodeQuery.getQuery = nodeQuery.init', () => {
- expect(nodeQuery.getQuery())
- .to.be.deep.equal(qb);
- });
- test('Test Insert Batch', done => {
- let data = [
- {
- id: 544,
- key: 3,
- val: new Buffer('7'),
- }, {
- id: 89,
- key: 34,
- val: new Buffer('10 o\'clock'),
- }, {
- id: 48,
- key: 403,
- val: new Buffer('97'),
- },
- ];
-
- qb.insertBatch('create_test', data, (err, rows) => {
- expect(err).is.not.ok;
- return done();
- });
- });
- });
- suiteTeardown(() => {
- qb.end();
- });
+suite('Mysql2 adapter tests -', () => {
+ require('./mysql-base')(qb, nodeQuery, expect, testRunner, promiseTestRunner);
});
\ No newline at end of file
diff --git a/test/adapters/mysql_test.js b/test/adapters/mysql_test.js
index adb2811..05d047c 100644
--- a/test/adapters/mysql_test.js
+++ b/test/adapters/mysql_test.js
@@ -1,14 +1,16 @@
'use strict';
-let configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
+const configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load the test base
-let reload = require('require-reload')(require);
+const reload = require('require-reload')(require);
reload.emptyCache();
+const testBase = reload('../base');
+const expect = testBase.expect,
+ promiseTestRunner = testBase.promiseTestRunner,
+ testRunner = testBase.testRunner;
+
let getArgs = reload('getargs');
-let expect = reload('chai').expect;
-let tests = reload('./adapterTestBase').tests;
-let testRunner = reload('./adapterTestBase').runner;
// Load the test config file
let adapterName = 'mysql';
@@ -22,40 +24,6 @@ let connection = mysql.createConnection(config.conn);
let nodeQuery = reload('../../lib/NodeQuery');
let qb = nodeQuery.init('mysql', connection);
-suite('Mysql adapter tests', () => {
- testRunner(tests, qb, (err, done) => {
- expect(err).is.not.ok;
- done();
- });
- suite('Adapter-specific tests', () => {
- test('nodeQuery.getQuery = nodeQuery.init', () => {
- expect(nodeQuery.getQuery())
- .to.be.deep.equal(qb);
- });
- test('Test Insert Batch', done => {
- let data = [
- {
- id: 544,
- key: 3,
- val: new Buffer('7'),
- }, {
- id: 89,
- key: 34,
- val: new Buffer('10 o\'clock'),
- }, {
- id: 48,
- key: 403,
- val: new Buffer('97'),
- },
- ];
-
- qb.insertBatch('create_test', data, (err, rows) => {
- expect(err).is.not.ok;
- return done();
- });
- });
- });
- suiteTeardown(() => {
- qb.end();
- });
+suite('Mysql adapter tests -', () => {
+ require('./mysql-base')(qb, nodeQuery, expect, testRunner, promiseTestRunner);
});
\ No newline at end of file
diff --git a/test/adapters/node-firebird.js b/test/adapters/node-firebird.js
new file mode 100644
index 0000000..8eda1e6
--- /dev/null
+++ b/test/adapters/node-firebird.js
@@ -0,0 +1,51 @@
+'use strict';
+
+// Load the test base
+const path = require('path');
+const reload = require('require-reload')(require);
+const testBase = reload('../base');
+const expect = reload('chai').expect;
+const testRunner = testBase.testRunner;
+const promiseTestRunner = testBase.promiseTestRunner;
+
+// Load the test config file
+let adapterName = 'node-firebird';
+let Firebird = reload(adapterName);
+const config = reload('../config.json')[adapterName];
+config.conn.database = path.join(__dirname, config.conn.database);
+let nodeQuery = reload('../../lib/NodeQuery');
+
+let qb = null;
+
+// Skip on TravisCi
+if (process.env.CI || process.env.JENKINS_HOME) {
+ return;
+}
+
+suite('Firebird adapter tests -', () => {
+ // Set up the query builder object
+ suiteSetup('Database connection', connected => {
+ Firebird.attach(config.conn, (err, db) => {
+ qb = nodeQuery.init('firebird', db, adapterName);
+ return connected(err);
+ });
+ });
+ testRunner(qb, (err, done) => {
+ expect(err).is.not.ok;
+ done();
+ });
+ suite('Adapter-specific tests', () => {
+ test('nodeQuery.getQuery = nodeQuery.init', () => {
+ expect(nodeQuery.getQuery())
+ .to.be.deep.equal(qb);
+ });
+ test('insertBatch throws error', () => {
+ expect(() => {
+ qb.driver.insertBatch('create_test', []);
+ }).to.throw(Error, "Not Implemented");
+ });
+ });
+ suiteTeardown(() => {
+ qb.end();
+ });
+});
\ No newline at end of file
diff --git a/test/adapters/node-firebird_test.js b/test/adapters/node-firebird_test.js
deleted file mode 100644
index 983d864..0000000
--- a/test/adapters/node-firebird_test.js
+++ /dev/null
@@ -1,46 +0,0 @@
-'use strict';
-
-// Load the test base
-let reload = require('require-reload')(require);
-let expect = reload('chai').expect;
-let tests = reload('./adapterTestBase').tests;
-let testRunner = reload('./adapterTestBase').runner;
-
-// Load the test config file
-let adapterName = 'node-firebird';
-let Firebird = reload(adapterName);
-let config = reload('../config.json')[adapterName];
-config.conn.database = __dirname + config.conn.database;
-let nodeQuery = reload('../../lib/NodeQuery');
-
-// Skip on TravisCi
-if (process.env.CI || process.env.JENKINS_HOME)
-{
- return;
-}
-
-suite('Firebird adapter tests', () => {
- Firebird.attach(config.conn, (err, db) => {
- // Set up the query builder object
- let qb = nodeQuery.init('firebird', db, adapterName);
-
- testRunner(tests, qb, (err, done) => {
- expect(err).is.not.ok;
- done();
- });
- suite('Adapter-specific tests', () => {
- test('nodeQuery.getQuery = nodeQuery.init', () => {
- expect(nodeQuery.getQuery())
- .to.be.deep.equal(qb);
- });
- test('insertBatch throws error', () => {
- expect(() => {
- qb.driver.insertBatch('create_test', []);
- }).to.throw(Error, "Not Implemented");
- });
- });
- suiteTeardown(() => {
- db.detach();
- });
- });
-});
\ No newline at end of file
diff --git a/test/adapters/pg_test.js b/test/adapters/pg_test.js
index 4d53d1b..c515871 100644
--- a/test/adapters/pg_test.js
+++ b/test/adapters/pg_test.js
@@ -3,10 +3,12 @@
let configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load the test base
-let reload = require('require-reload')(require);
-let expect = reload('chai').expect;
-let tests = reload('./adapterTestBase').tests;
-let testRunner = reload('./adapterTestBase').runner;
+const reload = require('require-reload')(require);
+reload.emptyCache();
+const testBase = reload('../base');
+const expect = testBase.expect,
+ promiseTestRunner = testBase.promiseTestRunner,
+ testRunner = testBase.testRunner;
// Load the test config file
let adapterName = 'pg';
@@ -25,40 +27,59 @@ connection.connect(err => {
let nodeQuery = reload('../../lib/NodeQuery');
let qb = nodeQuery.init('pg', connection);
-suite('Pg adapter tests', () => {
- testRunner(tests, qb, (err, done) => {
+suite('Pg adapter tests -', () => {
+ test('nodeQuery.getQuery = nodeQuery.init', () => {
+ expect(nodeQuery.getQuery())
+ .to.be.deep.equal(qb);
+ });
+
+ /*---------------------------------------------------------------------------
+ Callback Tests
+ ---------------------------------------------------------------------------*/
+ testRunner(qb, (err, done) => {
expect(err).is.not.ok;
done();
});
- suite('Adapter-specific tests', () => {
- test('nodeQuery.getQuery = nodeQuery.init', () => {
- expect(nodeQuery.getQuery())
- .to.be.deep.equal(qb);
- });
- test('Test Insert Batch', done => {
- let data = [
- {
- id: 544,
- key: 3,
- val: new Buffer('7'),
- }, {
- id: 89,
- key: 34,
- val: new Buffer('10 o\'clock'),
- }, {
- id: 48,
- key: 403,
- val: new Buffer('97'),
- },
- ];
-
- qb.insertBatch('create_test', data, (err, rows) => {
+ test('Callback - Select with function and argument in WHERE clause', done => {
+ qb.select('id')
+ .from('create_test')
+ .where('id', 'CEILING(SQRT(88))')
+ .get((err, rows) => {
expect(err).is.not.ok;
return done();
});
- });
});
- suiteTeardown(() => {
- qb.end();
+
+ /*---------------------------------------------------------------------------
+ Promise Tests
+ ---------------------------------------------------------------------------*/
+ promiseTestRunner(qb);
+ test('Promise - Select with function and argument in WHERE clause', () => {
+ let promise = qb.select('id')
+ .from('create_test')
+ .where('id', 'CEILING(SQRT(88))')
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test Insert Batch', () => {
+ let data = [
+ {
+ id: 544,
+ key: 3,
+ val: new Buffer('7'),
+ }, {
+ id: 89,
+ key: 34,
+ val: new Buffer('10 o\'clock'),
+ }, {
+ id: 48,
+ key: 403,
+ val: new Buffer('97'),
+ },
+ ];
+
+ let promise = qb.insertBatch('create_test', data);
+ return expect(promise).to.be.fulfilled;
});
});
\ No newline at end of file
diff --git a/test/base.js b/test/base.js
new file mode 100644
index 0000000..af0c5bb
--- /dev/null
+++ b/test/base.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const chai = require('chai');
+const chaiAsPromised = require('chai-as-promised');
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+module.exports = {
+ expect: expect,
+ tests: require('./base/tests'),
+ testRunner: require('./base/adapterCallbackTestRunner'),
+ promiseTestRunner: require('./base/adapterPromiseTestRunner'),
+};
\ No newline at end of file
diff --git a/test/base/adapterCallbackTestRunner.js b/test/base/adapterCallbackTestRunner.js
new file mode 100644
index 0000000..ce874fa
--- /dev/null
+++ b/test/base/adapterCallbackTestRunner.js
@@ -0,0 +1,236 @@
+'use strict';
+
+// Load the test base
+const chai = require('chai');
+const chaiAsPromised = require('chai-as-promised');
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+const reload = require('require-reload')(require);
+let tests = reload('../base/tests');
+
+let helpers = reload('../../lib/helpers'),
+ State = reload('../../lib/State');
+
+module.exports = function testRunner(qb, callback) {
+ Object.keys(tests).forEach(suiteName => {
+ suite(suiteName, () => {
+ let currentSuite = tests[suiteName];
+ Object.keys(currentSuite).forEach(testDesc => {
+ test(`Callback - ${testDesc}`, done => {
+ let methodObj = currentSuite[testDesc];
+ let methodNames = Object.keys(methodObj);
+ let lastMethodIndex = methodNames[methodNames.length - 1];
+
+ methodObj[lastMethodIndex].push((err, rows) => {
+ callback(err, done);
+ });
+
+ methodNames.forEach(name => {
+ let args = methodObj[name],
+ method = qb[name];
+
+ if (args[0] === 'multiple') {
+ args.shift();
+ args.forEach(argSet => {
+ method.apply(qb, argSet);
+ });
+
+ } else {
+ method.apply(qb, args);
+ }
+ });
+ });
+ });
+ });
+ });
+ suite('DB update tests -', () => {
+ setup(done => {
+ let sql = qb.driver.truncate('create_test');
+ qb.adapter.execute(sql, (err, res) => {
+ done();
+ });
+ });
+ test('Callback - Test Insert', done => {
+ qb.set('id', 98)
+ .set('key', '84')
+ .set('val', new Buffer('120'))
+ .insert('create_test', (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Test Insert Object', done => {
+ qb.insert('create_test', {
+ id: 587,
+ key: 1,
+ val: new Buffer('2'),
+ }, (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Test Update', done => {
+ qb.where('id', 7)
+ .update('create_test', {
+ id: 7,
+ key: 'gogle',
+ val: new Buffer('non-word'),
+ }, (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Test set Array Update', done => {
+ let object = {
+ id: 22,
+ key: 'gogle',
+ val: new Buffer('non-word'),
+ };
+
+ qb.set(object)
+ .where('id', 22)
+ .update('create_test', (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Test where set update', done => {
+ qb.where('id', 36)
+ .set('id', 36)
+ .set('key', 'gogle')
+ .set('val', new Buffer('non-word'))
+ .update('create_test', (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Test delete', done => {
+ qb.delete('create_test', {id: 5}, (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Delete with where', done => {
+ qb.where('id', 5)
+ .delete('create_test', (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Delete multiple where values', done => {
+ qb.delete('create_test', {
+ id: 5,
+ key: 'gogle',
+ }, (err, rows) => {
+ return callback(err, done);
+ });
+ });
+ });
+ suite('Grouping tests -', () => {
+ test('Callback - Using grouping method', done => {
+ qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .limit(2, 1)
+ .get((err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Using where first grouping', done => {
+ qb.select('id, key as k, val')
+ .from('create_test')
+ .where('id !=', 5)
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .limit(2, 1)
+ .get((err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Using or grouping method', done => {
+ qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .orGroupStart()
+ .where('id', 0)
+ .groupEnd()
+ .limit(2, 1)
+ .get((err, rows) => {
+ return callback(err, done);
+ });
+ });
+ test('Callback - Using or not grouping method', done => {
+ qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .orNotGroupStart()
+ .where('id', 0)
+ .groupEnd()
+ .limit(2, 1)
+ .get((err, rows) => {
+ return callback(err, done);
+ });
+ });
+ });
+ suite('Get compiled tests -', () => {
+ test('select', () => {
+ let sql = qb.select('id')
+ .from('create_test')
+ .getCompiledSelect(true);
+
+ expect(helpers.isString(sql)).to.be.true;
+ });
+ test('select from', () => {
+ let sql = qb.select('id')
+ .getCompiledSelect('create_test', true);
+
+ expect(helpers.isString(sql)).to.be.true;
+ });
+ test('insert', () => {
+ let sql = qb.set('id', 3)
+ .getCompiledInsert('create_test');
+
+ expect(helpers.isString(sql)).to.be.true;
+ });
+ test('update', () => {
+ let sql = qb.set('id', 3)
+ .where('id', 5)
+ .getCompiledUpdate('create_test');
+
+ expect(helpers.isString(sql)).to.be.true;
+ });
+ test('delete', () => {
+ let sql = qb.where('id', 5)
+ .getCompiledDelete('create_test');
+
+ expect(helpers.isString(sql)).to.be.true;
+ });
+ });
+ suite('Misc tests -', () => {
+ test('Get State', () => {
+ qb.select('foo')
+ .from('bar')
+ .where('baz', 'foobar');
+
+ let state = new State();
+
+ expect(JSON.stringify(state)).to.not.be.deep.equal(qb.getState());
+ });
+ test('Reset State', () => {
+ qb.select('foo')
+ .from('bar')
+ .where('baz', 'foobar');
+
+ qb.resetQuery();
+
+ let state = new State();
+
+ expect(qb.getState()).to.be.deep.equal(state);
+ });
+ });
+};
\ No newline at end of file
diff --git a/test/base/adapterPromiseTestRunner.js b/test/base/adapterPromiseTestRunner.js
new file mode 100644
index 0000000..0dbf97d
--- /dev/null
+++ b/test/base/adapterPromiseTestRunner.js
@@ -0,0 +1,181 @@
+'use strict';
+
+// Load the test base
+const chai = require('chai');
+const chaiAsPromised = require('chai-as-promised');
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+const reload = require('require-reload')(require);
+let tests = reload('../base/tests');
+
+let helpers = reload('../../lib/helpers'),
+ State = reload('../../lib/State');
+
+module.exports = function promiseTestRunner(qb) {
+ Object.keys(tests).forEach(suiteName => {
+ suite(suiteName, () => {
+ let currentSuite = tests[suiteName];
+ Object.keys(currentSuite).forEach(testDesc => {
+ test(`Promise - ${testDesc}`, () => {
+ let methodObj = currentSuite[testDesc];
+ let methodNames = Object.keys(methodObj);
+ let lastMethodIndex = methodNames[methodNames.length - 1];
+ let results = [];
+
+ methodNames.forEach(name => {
+ let args = methodObj[name],
+ method = qb[name];
+
+ if (args[0] === 'multiple') {
+ args.shift();
+ args.forEach(argSet => {
+ results.push(method.apply(qb, argSet));
+ });
+
+ } else {
+ results.push(method.apply(qb, args));
+ }
+ });
+
+ let promise = results.pop();
+ expect(promise).to.be.fulfilled;
+ });
+ });
+ });
+ });
+ suite('DB update tests -', () => {
+ suiteSetup(done => {
+ let sql = qb.driver.truncate('create_test');
+ qb.adapter.execute(sql).then(res => {
+ return done();
+ }).catch(err => {
+ return done(err);
+ });
+ });
+ test('Promise - Test Insert', () => {
+ let promise = qb.set('id', 98)
+ .set('key', '84')
+ .set('val', new Buffer('120'))
+ .insert('create_test');
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test Insert Object', () => {
+ let promise = qb.insert('create_test', {
+ id: 587,
+ key: 1,
+ val: new Buffer('2'),
+ });
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test Update', () => {
+ let promise = qb.where('id', 7)
+ .update('create_test', {
+ id: 7,
+ key: 'gogle',
+ val: new Buffer('non-word'),
+ });
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test set Array Update', () => {
+ let object = {
+ id: 22,
+ key: 'gogle',
+ val: new Buffer('non-word'),
+ };
+
+ let promise = qb.set(object)
+ .where('id', 22)
+ .update('create_test');
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test where set update', () => {
+ let promise = qb.where('id', 36)
+ .set('id', 36)
+ .set('key', 'gogle')
+ .set('val', new Buffer('non-word'))
+ .update('create_test');
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Test delete', () => {
+ let promise = qb.delete('create_test', {id: 5});
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Delete with where', () => {
+ let promise = qb.where('id', 5)
+ .delete('create_test');
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Delete multiple where values', () => {
+ let promise = qb.delete('create_test', {
+ id: 5,
+ key: 'gogle',
+ });
+
+ expect(promise).to.be.fulfilled;
+ });
+ });
+ suite('Grouping tests -', () => {
+ test('Promise - Using grouping method', () => {
+ let promise = qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .limit(2, 1)
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Using where first grouping', () => {
+ let promise = qb.select('id, key as k, val')
+ .from('create_test')
+ .where('id !=', 5)
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .limit(2, 1)
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Using or grouping method', () => {
+ let promise = qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .orGroupStart()
+ .where('id', 0)
+ .groupEnd()
+ .limit(2, 1)
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+ test('Promise - Using or not grouping method', () => {
+ let promise = qb.select('id, key as k, val')
+ .from('create_test')
+ .groupStart()
+ .where('id >', 1)
+ .where('id <', 900)
+ .groupEnd()
+ .orNotGroupStart()
+ .where('id', 0)
+ .groupEnd()
+ .limit(2, 1)
+ .get();
+
+ expect(promise).to.be.fulfilled;
+ });
+ });
+};
\ No newline at end of file
diff --git a/test/base/tests.js b/test/base/tests.js
new file mode 100644
index 0000000..6c43bf1
--- /dev/null
+++ b/test/base/tests.js
@@ -0,0 +1,246 @@
+'use strict';
+
+module.exports = {
+ 'Get tests -': {
+ 'Get with function': {
+ select: ['id, COUNT(id) as count'],
+ from: ['create_test'],
+ groupBy: ['id'],
+ get: [],
+ },
+ 'Basic select all get': {
+ get: ['create_test'],
+ },
+ 'Basic select all with from': {
+ from: ['create_test'],
+ get: [],
+ },
+ 'Get with limit': {
+ get: ['create_test', 2],
+ },
+ 'Get with limit and offset': {
+ get: ['create_test', 2, 1],
+ },
+ 'Get with having': {
+ select: ['id'],
+ from: ['create_test'],
+ groupBy: ['id'],
+ having: [
+ 'multiple',
+ [{'id >': 1}],
+ ['id !=', 3],
+ ['id', 900],
+ ],
+ get: [],
+ },
+ 'Get with orHaving': {
+ select: ['id'],
+ from: ['create_test'],
+ groupBy: ['id'],
+ having: [{'id >': 1}],
+ orHaving: ['id !=', 3],
+ get: [],
+ },
+ },
+ 'Select tests -': {
+ 'Select where get': {
+ select: [['id', 'key as k', 'val']],
+ where: [
+ 'multiple',
+ ['id >', 1],
+ ['id <', 900],
+ ],
+ get: ['create_test', 2, 1],
+ },
+ 'Select where get 2': {
+ select: ['id, key as k, val'],
+ where: ['id !=', 1],
+ get: ['create_test', 2, 1],
+ },
+ 'Multi Order By': {
+ from: ['create_test'],
+ orderBy: ['id, key'],
+ get: [],
+ },
+ 'Select get': {
+ select: ['id, key as k, val'],
+ get: ['create_test', 2, 1],
+ },
+ 'Select from get': {
+ select: ['id, key as k, val'],
+ from: ['create_test ct'],
+ where: ['id >', 1],
+ get: [],
+ },
+ 'Select from limit get': {
+ select: ['id, key as k, val'],
+ from: ['create_test ct'],
+ where: ['id >', 1],
+ limit: [3],
+ get: [],
+ },
+ 'Select where IS NOT NULL': {
+ select: ['id', 'key as k', 'val'],
+ from: ['create_test ct'],
+ whereIsNotNull: ['id'],
+ get: [],
+ },
+ 'Select where IS NULL': {
+ select: ['id', 'key as k', 'val'],
+ from: ['create_test ct'],
+ whereIsNull: ['id'],
+ get: [],
+ },
+ 'Select where OR IS NOT NULL': {
+ select: ['id', 'key as k', 'val'],
+ from: ['create_test ct'],
+ whereIsNull: ['id'],
+ orWhereIsNotNull: ['id'],
+ get: [],
+ },
+ 'Select where OR IS NULL': {
+ select: ['id', 'key as k', 'val'],
+ from: ['create_test ct'],
+ where: ['id', 3],
+ orWhereIsNull: ['id'],
+ get: [],
+ },
+ 'Select with string where value': {
+ select: ['id', 'key as k', 'val'],
+ from: ['create_test ct'],
+ where: ['id > 3'],
+ get: [],
+ },
+ },
+ 'Where in tests -': {
+ 'Where in': {
+ from: ['create_test'],
+ whereIn: ['id', [0, 6, 56, 563, 341]],
+ get: [],
+ },
+ 'Or Where in': {
+ from: ['create_test'],
+ where: ['key', 'false'],
+ orWhereIn: ['id', [0, 6, 56, 563, 341]],
+ get: [],
+ },
+ 'Where Not in': {
+ from: ['create_test'],
+ where: ['key', 'false'],
+ whereNotIn: ['id', [0, 6, 56, 563, 341]],
+ get: [],
+ },
+ 'Or Where Not in': {
+ from: ['create_test'],
+ where: ['key', 'false'],
+ orWhereNotIn: ['id', [0, 6, 56, 563, 341]],
+ get: [],
+ },
+ },
+ 'Query modifier tests -': {
+ 'Order By': {
+ select: ['id, key as k, val'],
+ from: ['create_test'],
+ where: [
+ 'multiple',
+ ['id >', 0],
+ ['id <', 9000],
+ ],
+ orderBy: [
+ 'multiple',
+ ['id', 'DESC'],
+ ['k', 'ASC'],
+ ],
+ limit: [5, 2],
+ get: [],
+ },
+ 'Group By': {
+ select: ['id, key as k, val'],
+ from: ['create_test'],
+ where: [
+ 'multiple',
+ ['id >', 0],
+ ['id <', 9000],
+ ],
+ groupBy: [
+ 'multiple',
+ ['k'],
+ [['id', 'val']],
+ ],
+ orderBy: [
+ 'multiple',
+ ['id', 'DESC'],
+ ['k', 'ASC'],
+ ],
+ limit: [5, 2],
+ get: [],
+ },
+ 'Or Where': {
+ select: ['id, key as k, val'],
+ from: ['create_test'],
+ where: [' id ', 1],
+ orWhere: ['key > ', 0],
+ limit: [2, 1],
+ get: [],
+ },
+ Like: {
+ from: ['create_test'],
+ like: ['key', 'og'],
+ get: [],
+ },
+ 'Or Like': {
+ from: ['create_test'],
+ like: ['key', 'og'],
+ orLike: ['key', 'val'],
+ get: [],
+ },
+ 'Not Like': {
+ from: ['create_test'],
+ like: ['key', 'og', 'before'],
+ notLike: ['key', 'val'],
+ get: [],
+ },
+ 'Or Not Like': {
+ from: ['create_test'],
+ like: ['key', 'og', 'before'],
+ orNotLike: ['key', 'val'],
+ get: [],
+ },
+ 'Like Before': {
+ from: ['create_test'],
+ like: ['key', 'og', 'before'],
+ get: [],
+ },
+ 'Like After': {
+ from: ['create_test'],
+ like: ['key', 'og', 'after'],
+ get: [],
+ },
+ 'Basic Join': {
+ from: ['create_test ct'],
+ join: ['create_join cj', 'cj.id=ct.id'],
+ get: [],
+ },
+ 'Left Join': {
+ from: ['create_test ct'],
+ join: ['create_join cj', 'cj.id=ct.id', 'left'],
+ get: [],
+ },
+ 'Inner Join': {
+ from: ['create_test ct'],
+ join: ['create_join cj', 'cj.id=ct.id', 'inner'],
+ get: [],
+ },
+ 'Join with multiple where values': {
+ from: ['create_test ct'],
+ join: ['create_join cj', 'cj.id=ct.id', 'inner'],
+ where: [
+ {
+ 'ct.id < ': 3,
+ 'ct.key ': 'foo',
+ },
+ ],
+ get: [],
+ },
+ },
+};
\ No newline at end of file
diff --git a/test/base_test.js b/test/base_test.js
index fbec2c2..81a4ac1 100644
--- a/test/base_test.js
+++ b/test/base_test.js
@@ -6,7 +6,7 @@ let expect = require('chai').expect,
nodeQuery = reload('../lib/NodeQuery'),
Adapter = reload('../lib/Adapter');
-suite('Base tests', () => {
+suite('Base tests -', () => {
suite('Sanity check', () => {
let files = glob.sync(`${__dirname}/../lib/**/*.js`);
files.forEach(mod => {
diff --git a/test/helpers_test.js b/test/helpers_test.js
index 8f84b8f..ae60d5f 100644
--- a/test/helpers_test.js
+++ b/test/helpers_test.js
@@ -7,8 +7,8 @@ let chai = require('chai'),
let helpers = require('../lib/helpers');
-suite('Helper Module Tests', () => {
- suite('Type-checking methods', () => {
+suite('Helper Module Tests -', () => {
+ suite('Type-checking methods -', () => {
suite('Object wrappers are listed as their native type', () => {
test('Boolean Wrapper returns \'boolean\' not \'object\'', () => {
let item = Boolean(true);
@@ -23,7 +23,7 @@ suite('Helper Module Tests', () => {
expect(helpers.type(item)).to.deep.equal('string');
});
});
- suite('is..Method methods exist', () => {
+ suite('is..Method methods exist -', () => {
let types = [
'Null',
'Undefined',
@@ -44,7 +44,7 @@ suite('Helper Module Tests', () => {
});
});
});
- suite('isScalar', () => {
+ suite('isScalar -', () => {
let trueCases = {
'Strings are scalar': 'foo',
'Booleans are scalar': true,
@@ -66,7 +66,7 @@ suite('Helper Module Tests', () => {
});
});
});
- suite('isInfinity', () => {
+ suite('isInfinity -', () => {
test('The type of 1/0 is infinity', () => {
expect(helpers.type(1 / 0)).to.equal('infinity');
});
@@ -74,7 +74,7 @@ suite('Helper Module Tests', () => {
expect(helpers.isInfinite(1 / 0)).to.be.true;
});
});
- suite('isNaN', () => {
+ suite('isNaN -', () => {
test('The type of 0 / 0 is NaN', () => {
expect(helpers.type(0 / 0)).to.equal('nan');
});
@@ -83,8 +83,8 @@ suite('Helper Module Tests', () => {
});
});
});
- suite('Other helper methods', () => {
- suite('stringTrim', () => {
+ suite('Other helper methods -', () => {
+ suite('stringTrim -', () => {
test('stringTrim method works as expected', () => {
let orig = [' x y ', 'z ', ' q'];
let ret = ['x y', 'z', 'q'];
@@ -92,7 +92,7 @@ suite('Helper Module Tests', () => {
expect(orig.map(helpers.stringTrim)).to.be.deep.equal(ret);
});
});
- suite('arrayPluck', () => {
+ suite('arrayPluck -', () => {
let orig = [
{
foo: 1,
@@ -115,7 +115,7 @@ suite('Helper Module Tests', () => {
expect(helpers.arrayPluck([], 'apple')).to.be.deep.equal([]);
});
});
- suite('regexInArray', () => {
+ suite('regexInArray -', () => {
let orig = ['apple', ' string ', 6, 4, 7];
let cases = [
diff --git a/test/mocha.opts b/test/mocha.opts
index db5f715..31bf1aa 100644
--- a/test/mocha.opts
+++ b/test/mocha.opts
@@ -1,7 +1,9 @@
--ui tdd
--bail
--recursive
---reporter dot
---slow 100
---timeout 5000
---check-leaks
\ No newline at end of file
+--reporter list
+--slow 200
+--timeout 10000
+--check-leaks
+--growl
+test/**/*_test.js
\ No newline at end of file
diff --git a/test/query-parser_test.js b/test/query-parser_test.js
index e61f6d1..8475cab 100644
--- a/test/query-parser_test.js
+++ b/test/query-parser_test.js
@@ -1,172 +1,172 @@
-'use strict';
-let expect = require('chai').expect;
-
-// Use the base driver as a mock for testing
-let getArgs = require('getargs');
-let helpers = require('../lib/helpers');
-let driver = require('../lib/Driver');
-
-let P = require('../lib/QueryParser');
-let parser = new P(driver);
-
-let State = require('../lib/State');
-
-// Simulate query builder state
-let state = new State();
-
-let mixedSet = function mixedSet(/* $letName, $valType, $key, [$val] */) {
- let args = getArgs('$letName:string, $valType:string, $key:object|string|number, [$val]', 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];
- state[args.$letName].push(pushVal);
- } else {
- state[args.$letName][k] = obj[k];
- }
- });
-
- return state[args.$letName];
-};
-
-let whereMock = function() {
- let args = getArgs('key:string|object, [val]', arguments);
-
- state.whereMap = [];
- state.whereValues = [];
-
- mixedSet('rawWhereValues', 'value', args.key, args.val);
- mixedSet('whereMap', 'both', args.key, args.val);
-};
-
-// -----------------------------------------------------------------------------
-// ! Start Tests
-// -----------------------------------------------------------------------------
-
-suite('Query Parser Tests', () => {
- suite('Has operator tests', () => {
- test('Has operator', () => {
- let matches = parser.hasOperator('foo <> 2');
- expect(matches).to.be.deep.equal(['<>']);
- });
- test('Has no operator', () => {
- let matches = parser.hasOperator('foo');
- expect(matches).to.be.null;
- });
- });
- suite('Where parser tests', () => {
- setup(() => {
- state = new State();
- });
- test('Has function full string', () => {
- whereMock('time < SUM(FOO(BAR()))');
- parser.parseWhere(driver, state);
- expect(state.whereMap)
- .to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
- });
- test('Has function key/val', () => {
- whereMock('time <', 'SUM(FOO(BAR()))');
- parser.parseWhere(driver, state);
- expect(state.whereMap)
- .to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
- });
- test('Has function key/val object', () => {
- whereMock({
- 'time <': 'SUM(FOO(BAR(\'x\')))',
- });
- parser.parseWhere(driver, state);
- expect(state.whereMap)
- .to.be.deep.equal(['"time" < SUM(FOO(BAR(\'x\')))']);
- });
- test('Has literal value', () => {
- whereMock({
- foo: 3,
- });
- parser.parseWhere(driver, state);
- expect(state.whereMap)
- .to.be.deep.equal(['"foo" = ?']);
- expect(state.whereValues)
- .to.be.deep.equal(['3']);
- });
- test('Has multiple literal values', () => {
- whereMock({
- foo: 3,
- bar: 5,
- });
- parser.parseWhere(driver, state);
- expect(state.whereMap)
- .to.be.deep.equal(['"foo" = ?', '"bar" = ?']);
- expect(state.whereValues)
- .to.be.deep.equal(['3', '5']);
- });
- });
- suite('Parse join tests', () => {
- let data = [
- {
- desc: 'Simple equals condition',
- join: 'table1.field1=table2.field2',
- expected: ['table1.field1', '=', 'table2.field2'],
- }, {
- desc: 'Db.table.field condition',
- join: 'db1.table1.field1!=db2.table2.field2',
- expected: ['db1.table1.field1', '!=', 'db2.table2.field2'],
- }, {
- desc: 'Underscore in identifier',
- join: 'table_1.field1 = tab_le2.field_2',
- expected: ['table_1.field1', '=', 'tab_le2.field_2'],
- }, {
- desc: 'Function in condition',
- join: 'table1.field1 > SUM(3+6)',
- expected: ['table1.field1', '>', 'SUM(3+6)'],
- },
- ];
-
- data.forEach(datum => {
- test(datum.desc, () => {
- let matches = parser.parseJoin(datum.join);
- expect(matches.combined).to.be.deep.equal(datum.expected);
- });
- });
- });
- suite('Compile join tests', () => {
- let data = [
- {
- desc: 'Simple equals condition',
- clause: 'table1.field1=table2.field2',
- expected: '"table1"."field1" = "table2"."field2"',
- }, {
- desc: 'Db.table.field condition',
- clause: 'db1.table1.field1!=db2.table2.field2',
- expected: '"db1"."table1"."field1" != "db2"."table2"."field2"',
- }, {
- desc: 'Underscore in identifier',
- clause: 'table_1.field1 = tab_le2.field_2',
- expected: '"table_1"."field1" = "tab_le2"."field_2"',
- }, {
- desc: 'Function in condition',
- clause: 'table1.field1 > SUM(3+6)',
- expected: '"table1"."field1" > SUM(3+6)',
- },
- ];
-
- data.forEach(datum => {
- test(datum.desc, () => {
- let join = parser.compileJoin(datum.clause);
- expect(join).to.be.deep.equal(datum.expected);
- });
- });
- });
+'use strict';
+let expect = require('chai').expect;
+
+// Use the base driver as a mock for testing
+let getArgs = require('getargs');
+let helpers = require('../lib/helpers');
+let driver = require('../lib/Driver');
+
+let P = require('../lib/QueryParser');
+let parser = new P(driver);
+
+let State = require('../lib/State');
+
+// Simulate query builder state
+let state = new State();
+
+let mixedSet = function mixedSet(/* $letName, $valType, $key, [$val] */) {
+ let args = getArgs('$letName:string, $valType:string, $key:object|string|number, [$val]', 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];
+ state[args.$letName].push(pushVal);
+ } else {
+ state[args.$letName][k] = obj[k];
+ }
+ });
+
+ return state[args.$letName];
+};
+
+let whereMock = function() {
+ let args = getArgs('key:string|object, [val]', arguments);
+
+ state.whereMap = [];
+ state.whereValues = [];
+
+ mixedSet('rawWhereValues', 'value', args.key, args.val);
+ mixedSet('whereMap', 'both', args.key, args.val);
+};
+
+// -----------------------------------------------------------------------------
+// ! Start Tests
+// -----------------------------------------------------------------------------
+
+suite('Query Parser Tests', () => {
+ suite('Has operator tests', () => {
+ test('Has operator', () => {
+ let matches = parser.hasOperator('foo <> 2');
+ expect(matches).to.be.deep.equal(['<>']);
+ });
+ test('Has no operator', () => {
+ let matches = parser.hasOperator('foo');
+ expect(matches).to.be.null;
+ });
+ });
+ suite('Where parser tests', () => {
+ setup(() => {
+ state = new State();
+ });
+ test('Has function full string', () => {
+ whereMock('time < SUM(FOO(BAR()))');
+ parser.parseWhere(driver, state);
+ expect(state.whereMap)
+ .to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
+ });
+ test('Has function key/val', () => {
+ whereMock('time <', 'SUM(FOO(BAR()))');
+ parser.parseWhere(driver, state);
+ expect(state.whereMap)
+ .to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
+ });
+ test('Has function key/val object', () => {
+ whereMock({
+ 'time <': 'SUM(FOO(BAR(\'x\')))',
+ });
+ parser.parseWhere(driver, state);
+ expect(state.whereMap)
+ .to.be.deep.equal(['"time" < SUM(FOO(BAR(\'x\')))']);
+ });
+ test('Has literal value', () => {
+ whereMock({
+ foo: 3,
+ });
+ parser.parseWhere(driver, state);
+ expect(state.whereMap)
+ .to.be.deep.equal(['"foo" = ?']);
+ expect(state.whereValues)
+ .to.be.deep.equal(['3']);
+ });
+ test('Has multiple literal values', () => {
+ whereMock({
+ foo: 3,
+ bar: 5,
+ });
+ parser.parseWhere(driver, state);
+ expect(state.whereMap)
+ .to.be.deep.equal(['"foo" = ?', '"bar" = ?']);
+ expect(state.whereValues)
+ .to.be.deep.equal(['3', '5']);
+ });
+ });
+ suite('Parse join tests', () => {
+ let data = [
+ {
+ desc: 'Simple equals condition',
+ join: 'table1.field1=table2.field2',
+ expected: ['table1.field1', '=', 'table2.field2'],
+ }, {
+ desc: 'Db.table.field condition',
+ join: 'db1.table1.field1!=db2.table2.field2',
+ expected: ['db1.table1.field1', '!=', 'db2.table2.field2'],
+ }, {
+ desc: 'Underscore in identifier',
+ join: 'table_1.field1 = tab_le2.field_2',
+ expected: ['table_1.field1', '=', 'tab_le2.field_2'],
+ }, {
+ desc: 'Function in condition',
+ join: 'table1.field1 > SUM(3+6)',
+ expected: ['table1.field1', '>', 'SUM(3+6)'],
+ },
+ ];
+
+ data.forEach(datum => {
+ test(datum.desc, () => {
+ let matches = parser.parseJoin(datum.join);
+ expect(matches.combined).to.be.deep.equal(datum.expected);
+ });
+ });
+ });
+ suite('Compile join tests', () => {
+ let data = [
+ {
+ desc: 'Simple equals condition',
+ clause: 'table1.field1=table2.field2',
+ expected: '"table1"."field1" = "table2"."field2"',
+ }, {
+ desc: 'Db.table.field condition',
+ clause: 'db1.table1.field1!=db2.table2.field2',
+ expected: '"db1"."table1"."field1" != "db2"."table2"."field2"',
+ }, {
+ desc: 'Underscore in identifier',
+ clause: 'table_1.field1 = tab_le2.field_2',
+ expected: '"table_1"."field1" = "tab_le2"."field_2"',
+ }, {
+ desc: 'Function in condition',
+ clause: 'table1.field1 > SUM(3+6)',
+ expected: '"table1"."field1" > SUM(3+6)',
+ },
+ ];
+
+ data.forEach(datum => {
+ test(datum.desc, () => {
+ let join = parser.compileJoin(datum.clause);
+ expect(join).to.be.deep.equal(datum.expected);
+ });
+ });
+ });
});
\ No newline at end of file