Fix issue with using where method with an object with multiple keys

This commit is contained in:
Timothy Warren 2014-11-05 17:08:56 -05:00
parent 139fdcbac8
commit 5f8c4ad9b0
13 changed files with 183 additions and 40 deletions

View File

@ -46,6 +46,57 @@ var h = {
isScalar: function(obj) { isScalar: function(obj) {
var scalar = ['string', 'number', 'boolean']; var scalar = ['string', 'number', 'boolean'];
return scalar.indexOf(h.type(obj)) !== -1; return scalar.indexOf(h.type(obj)) !== -1;
},
/**
* Get a list of values with a common key from an array of objects
*
* @param {Array} arr - The array of objects to search
* @param {String} key - The key of the object to get
* @return {Array}
*/
arrayPluck: function(arr, key) {
var output = [];
// Empty case
if (arr.length === 0) return output;
arr.forEach(function(obj) {
if ( ! h.isUndefined(obj[key]))
{
output.push(obj[key]);
}
});
return output;
},
/**
* Determine if a value matching the passed regular expression is
* in the passed array
*
* @param {Array} arr - The array to search
* @param {RegExp} pattern - The pattern to match
* @return {Boolean} - If an array item matches the pattern
*/
regexInArray: function(arr, pattern) {
// Empty case(s)
if ( ! h.isArray(arr)) return false;
if (arr.length === 0) return false;
var i, l = arr.length;
for(i=0; i< l; i++)
{
// Recurse for nested arrays
if (Array.isArray(arr[i]))
{
return h.regexInArray(arr[i], pattern);
}
// Short circuit if any items match
if (pattern.test(arr[i])) return true;
}
return false;
} }
}; };

View File

@ -1,11 +1,11 @@
"use strict"; "use strict";
/** @module node-query */ /** @module node-query */
var nodeQuery = {}; var NodeQuery = function() {
var instance = null; var instance = null;
/** /**
* Create a query builder object * Create a query builder object
* *
* @alias module:node-query * @alias module:node-query
@ -14,7 +14,7 @@ var instance = null;
* @param {String} connLib - The name of the db connection library you are using, eg. mysql or mysql2 * @param {String} connLib - The name of the db connection library you are using, eg. mysql or mysql2
* @return {queryBuilder} * @return {queryBuilder}
*/ */
nodeQuery.init = function (driverType, connObject, connLib) { this.init = function (driverType, connObject, connLib) {
var fs = require('fs'), var fs = require('fs'),
qb = require('./query-builder'); qb = require('./query-builder');
@ -34,19 +34,23 @@ nodeQuery.init = function (driverType, connObject, connLib) {
instance = qb(require(paths.driver), require(paths.adapter)(connObject)); instance = qb(require(paths.driver), require(paths.adapter)(connObject));
return instance; return instance;
}; };
/** /**
* Return an existing query builder instance * Return an existing query builder instance
* *
* @return {queryBuilder} * @return {queryBuilder}
*/ */
nodeQuery.getQuery = function () { this.getQuery = function () {
if ( ! instance) { if ( ! instance) {
throw new Error("No Query Builder instance to return"); throw new Error("No Query Builder instance to return");
} }
return instance; return instance;
};
}; };
module.exports = nodeQuery;
module.exports = new NodeQuery();

View File

@ -205,8 +205,9 @@ var QueryBuilder = function(driver, adapter) {
lastItem = state.queryMap[state.queryMap.length - 1]; lastItem = state.queryMap[state.queryMap.length - 1];
// Determine the correct conjunction // Determine the correct conjunction
var conjunctionList = helpers.arrayPluck(state.queryMap, 'conjunction');
var conj = defaultConj; var conj = defaultConj;
if (state.queryMap.length === 0 || firstItem.conjunction.contains('JOIN')) if (state.queryMap.length === 0 || ( ! helpers.regexInArray(conjunctionList, /^ ?WHERE/i)))
{ {
conj = " WHERE "; conj = " WHERE ";
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "ci-node-query", "name": "ci-node-query",
"version": "1.1.0", "version": "1.1.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": {

View File

@ -48,6 +48,12 @@ if (connection)
test.done(); test.done();
}); });
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["dblite adapter with query builder"] = function(test) { tests["dblite adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);
test.ok(testBase.qb); test.ok(testBase.qb);

View File

@ -30,6 +30,12 @@ testBase._setUp(qb, function(test, err, rows) {
test.done(); test.done();
}); });
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
// Export the final test object // Export the final test object
tests["mysql2 adapter with query builder"] = function(test) { tests["mysql2 adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);

View File

@ -30,6 +30,12 @@ testBase._setUp(qb, function(test, err, rows) {
test.done(); test.done();
}); });
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["mysql adapter with query builder"] = function(test) { tests["mysql adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);
test.ok(testBase.qb); test.ok(testBase.qb);

View File

@ -70,6 +70,12 @@ try {
test.done(); test.done();
}; };
testBase.tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
testBase.tests["firebird adapter with query builder"] = function(test) { testBase.tests["firebird adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);
test.ok(testBase.qb); test.ok(testBase.qb);

View File

@ -35,6 +35,11 @@ testBase._setUp(qb, function(test, err, result) {
test.done(); test.done();
}); });
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["pg adapter with query builder"] = function(test) { tests["pg adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);

View File

@ -51,6 +51,12 @@ if (connection)
test.done(); test.done();
}); });
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["sqlite3 adapter with query builder"] = function(test) { tests["sqlite3 adapter with query builder"] = function(test) {
test.expect(1); test.expect(1);
test.ok(testBase.qb); test.ok(testBase.qb);

View File

@ -24,10 +24,17 @@ module.exports = {
test.done(); test.done();
}, },
'NodeQuery.getQuery with no instance': function(test) {
test.expect(1);
test.throws(function() {
nodeQuery.getQuery();
}, Error, "No query builder instance if none created");
test.done();
},
'Invalid driver type': function(test) { 'Invalid driver type': function(test) {
test.expect(1); test.expect(1);
test.throws(function() { test.throws(function() {
modules['node-query'].init('foo', {}, 'bar'); nodeQuery.init('foo', {}, 'bar');
}, Error, "Bad driver throws exception"); }, Error, "Bad driver throws exception");
test.done(); test.done();
} }

View File

@ -37,11 +37,46 @@ var helperTests = {
test.done(); test.done();
}, },
'stringTrim': function(test) { 'stringTrim': function(test) {
test.expect(1);
var orig = [' x y ', 'z ', ' q']; var orig = [' x y ', 'z ', ' q'];
var ret = ['x y', 'z', 'q']; var ret = ['x y', 'z', 'q'];
test.deepEqual(ret, orig.map(helpers.stringTrim)); test.deepEqual(ret, orig.map(helpers.stringTrim));
test.done();
},
'arrayPluck': function(test) {
test.expect(3);
var orig = [{
foo: 1
},{
foo: 2,
bar: 10
},{
foo: 3,
bar: 15
}];
test.deepEqual([1,2,3], helpers.arrayPluck(orig, 'foo'), 'Finding members in all objects');
test.deepEqual([10,15], helpers.arrayPluck(orig, 'bar'), 'Some members are missing in some objects');
// Empty case
test.deepEqual([], helpers.arrayPluck([], 'apple'));
test.done();
},
'regexInArray': function(test) {
var orig = ['apple', ' string ', 6, 4, 7];
test.expect(4);
test.equal(false, helpers.regexInArray(orig, /\$/), 'Dollar sign is not in any of the array items');
test.equal(true, helpers.regexInArray(orig, /^ ?string/), "' string ' matches /^ ?string/");
test.equal(true, helpers.regexInArray(orig, /APPLE/i), "'apple' matches /APPLE/i");
test.equal(false, helpers.regexInArray(orig, /5/), 'None of the numbers in the array match /5/');
test.done(); test.done();
} }
}; };

View File

@ -290,6 +290,16 @@ module.exports = (function QueryBuilderTestBase() {
base.qb.from('create_test ct') base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id', 'inner') .join('create_join cj', 'cj.id=ct.id', 'inner')
.get(base.testCallback.bind(this, test)); .get(base.testCallback.bind(this, test));
},
'Join with multiple where values': function(test) {
test.expect(1);
base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id', 'inner')
.where({
'ct.id <': 3,
'ct.key': 'foo'
})
.get(base.testCallback.bind(this, test));
} }
}, },
// ! DB Update test // ! DB Update test