From 1a0ff7ff1507f8cb22105ba262b2925994593b14 Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Tue, 18 Nov 2014 13:42:19 -0500 Subject: [PATCH] Add whereIsNull, whereIsNotNull, orWhereIsNull, orWhereIsNotNull methods --- lib/helpers.js | 6 --- lib/query-builder.js | 88 ++++++++++++++++++++++++++++++------- package.json | 2 +- tests/query-builder-base.js | 30 +++++++++++++ 4 files changed, 102 insertions(+), 24 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index f355470..57e7372 100755 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -86,12 +86,6 @@ var h = { 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; } diff --git a/lib/query-builder.js b/lib/query-builder.js index 1e99a79..bd376c5 100755 --- a/lib/query-builder.js +++ b/lib/query-builder.js @@ -187,6 +187,25 @@ var QueryBuilder = function(driver, adapter) { _p.mixedSet('whereMap', 'both', args.key, args.val); _p.mixedSet('whereValues', 'value', args.key, args.val); }, + fixConjunction: function(conj) { + var lastItem = state.queryMap[state.queryMap.length - 1]; + var conjunctionList = helpers.arrayPluck(state.queryMap, 'conjunction'); + + if (state.queryMap.length === 0 || ( ! helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) + { + conj = " WHERE "; + } + else if (lastItem.type === 'groupStart') + { + conj = ''; + } + else + { + conj = ' ' + conj + ' '; + } + + return conj; + }, where: function(key, val, defaultConj) { // Normalize key and value and insert into state.whereMap _p.whereMixedSet(key, val); @@ -201,24 +220,8 @@ var QueryBuilder = function(driver, adapter) { // Simple key value, or an operator? item += (fieldArray.length === 1 || fieldArray[1] === '') ? '=?' : " " + fieldArray[1] + " ?"; - var firstItem = state.queryMap[0], - lastItem = state.queryMap[state.queryMap.length - 1]; - // Determine the correct conjunction - var conjunctionList = helpers.arrayPluck(state.queryMap, 'conjunction'); - var conj = defaultConj; - if (state.queryMap.length === 0 || ( ! helpers.regexInArray(conjunctionList, /^ ?WHERE/i))) - { - conj = " WHERE "; - } - else if (lastItem.type === 'groupStart') - { - conj = ''; - } - else - { - conj = ' ' + conj + ' '; - } + var conj = _p.fixConjunction(defaultConj); _p.appendMap(conj, item, 'where'); @@ -226,6 +229,13 @@ var QueryBuilder = function(driver, adapter) { state.whereMap = {}; }); }, + whereNull: function(field, stmt, conj) { + conj = conj || 'AND'; + field = driver.quoteIdentifiers(field); + var item = field + ' ' + stmt; + + _p.appendMap(_p.fixConjunction(conj), item, 'whereNull'); + }, having: function(/*key, val, conj*/) { var args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments); args.conj = args.conj || 'AND'; @@ -521,6 +531,50 @@ var QueryBuilder = function(driver, adapter) { return this; }; + /** + * Select a field that is Null + * + * @param {String} field - The name of the field that has a NULL value + * @return this + */ + this.whereIsNull = function(field) { + _p.whereNull(field, 'IS NULL', 'AND'); + return this; + } + + /** + * Specify that a field IS NOT NULL + * + * @param {String} field + * @return this + */ + this.whereIsNotNull = function(field) { + _p.whereNull(field, 'IS NOT NULL', 'AND'); + return this; + } + + /** + * Field is null prefixed with 'OR' + * + * @param {String} field + * @return this + */ + this.orWhereIsNull = function(field) { + _p.whereNull(field, 'IS NULL', 'OR'); + return this; + } + + /** + * Field is not null prefixed with 'OR' + * + * @param {String} field + * @return this + */ + this.orWhereIsNotNull = function(field) { + _p.whereNull(field, 'IS NOT NULL', 'OR'); + return this; + } + /** * Set a 'where in' clause * diff --git a/package.json b/package.json index 0b4366d..09d57eb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ci-node-query", - "version": "1.1.1", + "version": "1.2.0", "description": "A query builder for node based on the one in CodeIgniter", "author": "Timothy J Warren ", "engines": { diff --git a/tests/query-builder-base.js b/tests/query-builder-base.js index a977100..05ee2bd 100644 --- a/tests/query-builder-base.js +++ b/tests/query-builder-base.js @@ -113,6 +113,36 @@ module.exports = (function QueryBuilderTestBase() { .where('id >', 1) .limit(3) .get(base.testCallback.bind(this, test)); + }, + 'Select where IS NOT NULL': function(test) { + test.expect(1); + base.qb.select('id', 'key as k', 'val') + .from('create_test ct') + .whereIsNotNull('id') + .get(base.testCallback.bind(this, test)); + }, + 'Select where IS NULL': function(test) { + test.expect(1); + base.qb.select('id', 'key as k', 'val') + .from('create_test ct') + .whereIsNull('id') + .get(base.testCallback.bind(this, test)); + }, + 'Select where OR IS NOT NULL': function(test) { + test.expect(1); + base.qb.select('id', 'key as k', 'val') + .from('create_test ct') + .whereIsNull('id') + .orWhereIsNotNull('id') + .get(base.testCallback.bind(this, test)); + }, + 'Select where OR IS NULL': function(test) { + test.expect(1); + base.qb.select('id', 'key as k', 'val') + .from('create_test ct') + .where('id', 3) + .orWhereIsNull('id') + .get(base.testCallback.bind(this, test)); } }, // ! Grouping tests