Streamline some dependencies, and add tests for query parser
This commit is contained in:
parent
0b9d4bf7c1
commit
7a3c5b7e79
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}());
|
|
@ -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 = {
|
||||||
|
@ -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)
|
||||||
|
@ -29,26 +29,6 @@ var filterMatches = function(array) {
|
|||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
var parseJoin = function(sql) {
|
|
||||||
var matches = {};
|
|
||||||
var output = {};
|
|
||||||
|
|
||||||
// Get clause components
|
|
||||||
matches['function'] = sql.match(matchPatterns['function']);
|
|
||||||
matches.identifiers = sql.match(matchPatterns.identifier);
|
|
||||||
matches.operators = sql.match(matchPatterns.operator);
|
|
||||||
|
|
||||||
// Get everything at once for ordering
|
|
||||||
matches.combined = sql.match(matchPatterns.combined);
|
|
||||||
|
|
||||||
// Flatten the matches to increase relevance
|
|
||||||
Object.keys(matches).forEach(function(key) {
|
|
||||||
output[key] = filterMatches(matches[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,6 +41,32 @@ var QueryParser = function(driver) {
|
|||||||
// That 'new' keyword is annoying
|
// That 'new' keyword is annoying
|
||||||
if ( ! (this instanceof QueryParser)) return new QueryParser(driver);
|
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 output = {};
|
||||||
|
|
||||||
|
// Get clause components
|
||||||
|
matches['function'] = sql.match(matchPatterns['function']);
|
||||||
|
matches.identifiers = sql.match(matchPatterns.identifier);
|
||||||
|
matches.operators = sql.match(matchPatterns.operator);
|
||||||
|
|
||||||
|
// Get everything at once for ordering
|
||||||
|
matches.combined = sql.match(matchPatterns.combined);
|
||||||
|
|
||||||
|
// Flatten the matches to increase relevance
|
||||||
|
Object.keys(matches).forEach(function(key) {
|
||||||
|
output[key] = filterMatches(matches[key]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
52
tests/query-parser_test.js
Normal file
52
tests/query-parser_test.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user