Streamline some dependencies, and add tests for query parser

This commit is contained in:
Timothy Warren 2014-10-28 14:40:03 -04:00
parent 0b9d4bf7c1
commit 7a3c5b7e79
9 changed files with 88 additions and 110 deletions

View File

@ -1,78 +0,0 @@
/**
* Polyfills for very handy methods that are standardized, but not fully implemented in Javascript engines
*/
module.exports = (function() {
if (!Array.prototype.fill) {
Array.prototype.fill = function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value;
k++;
}
// Step 13.
return O;
};
}
if ( !String.prototype.contains ) {
String.prototype.contains = function() {
return String.prototype.indexOf.apply( this, arguments ) !== -1;
};
}
if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
enumerable: false,
configurable: false,
writable: false,
value: function (searchString, position) {
position = position || 0;
return this.lastIndexOf(searchString, position) === position;
}
});
}
if (!String.prototype.endsWith) {
Object.defineProperty(String.prototype, 'endsWith', {
value: function (searchString, position) {
var subjectString = this.toString();
if (position === undefined || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
}
});
}
}());

View File

@ -1,8 +1,7 @@
"use strict"; "use strict";
/** @module helpers */ /** @module helpers */
require('es6-shim');
require('./es6-polyfill');
/** @alias module:helpers */ /** @alias module:helpers */
var h = { var h = {

View File

@ -792,13 +792,12 @@ var QueryBuilder = function(driver, adapter) {
/** /**
* Run the generated delete query * Run the generated delete query
* *
* @method delete
* @param {String} table - The table to insert into * @param {String} table - The table to insert into
* @param {Object} [where] - Where clause for delete statement * @param {Object} [where] - Where clause for delete statement
* @param {Function} callback - Callback for handling response from the database * @param {Function} callback - Callback for handling response from the database
* @return void * @return void
*/ */
this['delete'] = function (/*table, [where], callback*/) { this.delete = function (/*table, [where], callback*/) {
var args = getArgs('table:string, [where], callback:function', arguments); var args = getArgs('table:string, [where], callback:function', arguments);
if (args.where) if (args.where)

View File

@ -29,7 +29,25 @@ var filterMatches = function(array) {
return output; return output;
}; };
var parseJoin = function(sql) { // --------------------------------------------------------------------------
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @module query-parser
*/
var QueryParser = function(driver) {
// That 'new' keyword is annoying
if ( ! (this instanceof QueryParser)) return new QueryParser(driver);
/**
* Tokenize the sql into parts for additional processing
*
* @param {String} sql
* @return {Object}
*/
this.parseJoin = function(sql) {
var matches = {}; var matches = {};
var output = {}; var output = {};
@ -47,19 +65,7 @@ var parseJoin = function(sql) {
}); });
return output; return output;
}; };
// --------------------------------------------------------------------------
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @module query-parser
*/
var QueryParser = function(driver) {
// That 'new' keyword is annoying
if ( ! (this instanceof QueryParser)) return new QueryParser(driver);
/** /**
* Return the output of the parsing of the join condition * Return the output of the parsing of the join condition
@ -68,7 +74,7 @@ var QueryParser = function(driver) {
* @return {String} - The parsed/escaped join condition * @return {String} - The parsed/escaped join condition
*/ */
this.compileJoin = function(condition) { this.compileJoin = function(condition) {
var parts = parseJoin(condition); var parts = this.parseJoin(condition);
var count = parts.identifiers.length; var count = parts.identifiers.length;
var i; var i;

View File

@ -1,6 +1,6 @@
{ {
"name": "ci-node-query", "name": "ci-node-query",
"version": "0.0.2", "version": "0.0.3",
"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": {
@ -15,11 +15,11 @@
}, },
"main": "lib/node-query.js", "main": "lib/node-query.js",
"dependencies": { "dependencies": {
"async": "^0.9.0", "getargs": "",
"getargs": "" "es6-shim":""
}, },
"bundledDependencies": [ "bundledDependencies": [
"async","getargs" "es6-shim","getargs"
], ],
"devDependencies": { "devDependencies": {
"grunt": "^0.4.5", "grunt": "^0.4.5",

View File

@ -26,7 +26,7 @@ testBase._setUp(qb, function(test, err, rows) {
throw new Error(err); throw new Error(err);
} }
test.ok(rows, 'Valid result for generated query'); test.ok(rows, 'mysql2: Valid result for generated query');
test.done(); test.done();
}); });

View File

@ -26,7 +26,7 @@ testBase._setUp(qb, function(test, err, rows) {
throw new Error(err); throw new Error(err);
} }
test.ok(rows, 'Valid result for generated query'); test.ok(rows, 'mysql: Valid result for generated query');
test.done(); test.done();
}); });

View File

@ -32,7 +32,7 @@ testBase._setUp(qb, function(test, err, result) {
console.error('SQL syntax error', err); console.error('SQL syntax error', err);
} }
test.ok(result, 'Valid result for generated query'); test.ok(result, 'pg: Valid result for generated query');
test.done(); test.done();
}); });

View File

@ -0,0 +1,52 @@
'use strict';
// Use the base driver as a mock for testing
var driver = require('../lib/driver');
var parser = require('../lib/query-parser')(driver);
module.exports = {
'Parse join tests' : {
'Simple equals condition': function(test) {
var matches = parser.parseJoin('table1.field1=table2.field2');
test.deepEqual(['table1.field1','=','table2.field2'], matches.combined);
test.done();
},
'Db.table.field condition': function(test) {
var matches = parser.parseJoin('db1.table1.field1!=db2.table2.field2');
test.deepEqual(['db1.table1.field1','!=', 'db2.table2.field2'], matches.combined);
test.done();
},
'Underscore in identifier': function(test) {
var matches = parser.parseJoin('table_1.field1 = tab_le2.field_2');
test.deepEqual(['table_1.field1', '=', 'tab_le2.field_2'], matches.combined);
test.done();
},
'Function in condition': function(test) {
var matches = parser.parseJoin('table1.field1 > SUM(3+6)');
test.deepEqual(['table1.field1', '>', 'SUM(3+6)'], matches.combined);
test.done();
}
},
'Compile join tests': {
'Simple equals condition': function(test) {
var join = parser.compileJoin('table1.field1=table2.field2');
test.deepEqual('"table1"."field1"="table2"."field2"', join);
test.done();
},
'Db.table.field condition': function(test) {
var join = parser.compileJoin('db1.table1.field1!=db2.table2.field2');
test.deepEqual('"db1"."table1"."field1"!="db2"."table2"."field2"', join);
test.done();
},
'Underscore in identifier': function(test) {
var join = parser.compileJoin('table_1.field1 = tab_le2.field_2');
test.deepEqual('"table_1"."field1"="tab_le2"."field_2"', join);
test.done();
},
'Function in condition': function(test) {
var join = parser.compileJoin('table1.field1 > SUM(3+6)');
test.deepEqual('"table1"."field1">SUM(3+6)', join);
test.done();
}
}
};