-
-
- .type(o)
-
-
- Get the type of the variable passed
-
-
-
-
-
-
- type(o)
-
- Get the type of the variable passed
-
- Parameters
-
- mixed
o
:
@@ -822,6 +649,34 @@ in the passed array
+
+
+ constructor(Driver, driver)
+
+
+ Parameters
+
+ - Driver
+ :
+
+
The driver object for the database in use
+
+
+
+ - driver
+ :
+
+
+
+
+
+ Returns
+ void
+
+
+
+
+
delete(table, [where], callback)
@@ -853,11 +708,10 @@ in the passed array
Returns
-
- :
+ void
+
- void
-
+
@@ -867,11 +721,32 @@ in the passed array
Closes the database connection for the current adapter
Returns
-
- :
+ void
+
- void
+
+
+
+
+
+ filterMatches(array)
+
+ Filter matched patterns
+ Parameters
+
+ Array
array
+ :
+
+
+
+
+
+ Returns
+ Array
or
+
+
+
@@ -891,11 +766,10 @@ in the passed array
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -936,19 +810,12 @@ in the passed array
Returns
-
- :
+ void
+
- void
-
+
-
getCompiledDelete(table, [reset])
@@ -1036,11 +903,10 @@ in the passed array
Returns
-
- :
+ String
+
- String
-
+
@@ -1074,19 +940,6 @@ in the passed array
-
-
- getQuery
-
- Return an existing query builder instance
-
- Returns
- queryBuilder
-
-
-
-
-
groupBy(field)
@@ -1103,11 +956,10 @@ in the passed array
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1117,11 +969,10 @@ in the passed array
Ends a logical grouping started with one of the groupStart methods
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1131,11 +982,10 @@ in the passed array
Adds an open paren to the current query for logical grouping
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1186,66 +1036,7 @@ If there are no matches, return null
Returns
-
- :
-
- this
-
-
-
-
-
- helpers(str)
-
-
- Parameters
-
-
-
-
- init(drivername, driverType, connObject, [connLib])
-
- Create a query builder object
-
- Parameters
-
- String
drivername
- :
-
- The name of the database type, eg. mysql or pg
-
-
-
- - driverType
- :
-
-
-
-
- Object
connObject
- :
-
- A connection object from the database library you are connecting with
-
-
-
- [String
]
connLib
- :
-
- The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as drivername
-
-
-
-
- Returns
- queryBuilder
+ QueryBuilder
@@ -1282,11 +1073,10 @@ If there are no matches, return null
Returns
-
- :
+ void
+
- void
-
+
@@ -1320,11 +1110,10 @@ If there are no matches, return null
Returns
-
- :
+ void
+
- void
-
+
Examples
query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
@@ -1361,11 +1150,10 @@ If there are no matches, return null
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1400,11 +1188,10 @@ If there are no matches, return null
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1431,11 +1218,10 @@ If there are no matches, return null
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1470,11 +1256,10 @@ If there are no matches, return null
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1485,11 +1270,10 @@ If there are no matches, return null
prefixed with 'OR'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1516,11 +1300,10 @@ prefixed with 'OR'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1555,11 +1338,10 @@ prefixed with 'OR'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1570,11 +1352,10 @@ prefixed with 'OR'
prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1609,11 +1390,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1640,11 +1420,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1671,11 +1450,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1694,11 +1472,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1717,11 +1494,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1748,11 +1524,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1780,11 +1555,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1817,7 +1591,7 @@ prefixed with 'OR NOT'
Parameters
- Object
driver
+ Driver
driver
:
@@ -1845,11 +1619,10 @@ prefixed with 'OR NOT'
Reset the object state for a new query
Returns
-
- :
+ void
+
- void
-
+
@@ -1869,11 +1642,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1900,11 +1672,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -1938,11 +1709,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ void
+
- void
-
+
@@ -1969,11 +1739,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -2000,11 +1769,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -2023,11 +1791,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -2047,11 +1814,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
@@ -2078,11 +1844,10 @@ prefixed with 'OR NOT'
Returns
-
- :
+ QueryBuilder
+
- this
-
+
diff --git a/gulpfile.js b/gulpfile.js
index 6e118ce..4011e1f 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,30 +1,123 @@
-var gulp = require('gulp'),
+var babel = require('gulp-babel'),
+ concat = require('gulp-concat'),
documentation = require('gulp-documentation'),
+ eslint = require('gulp-eslint'),
+ gulp = require('gulp'),
+ istanbul = require('gulp-babel-istanbul'),
nodeunit_runner = require('gulp-nodeunit-runner'),
- istanbul = require('gulp-istanbul');
+ sloc = require('gulp-sloc'),
+ sourcemaps = require('gulp-sourcemaps');
-gulp.task('default', ['docs', 'test']);
+gulp.task('transpile', function() {
+ return gulp.src('src/**/*.js')
+ .pipe(sourcemaps.init())
+ .pipe(babel({
+ presets: ['es2015'],
+ plugins: ['transform-es2015-modules-commonjs']
+ }))
+ .pipe(sourcemaps.write('.'))
+ .pipe(gulp.dest('lib'));
+});
-gulp.task('docs', function() {
- gulp.src('./lib/node-query.js')
+gulp.task('lint', function() {
+ return gulp.src('src/**/*.js')
+ .pipe(eslint({
+ "env": {
+ "node": true,
+ "es6": true
+ },
+ "ecmaFeatures": {
+ "arrowFunctions": true,
+ "blockBindings": true,
+ "classes": true,
+ "defaultParams": true,
+ "destructuring": true,
+ "forOf": true,
+ "modules": true
+ },
+ "rules": {
+ "radix": [2],
+ "no-with": [2],
+ "no-eval": [2],
+ "no-unreachable": [2],
+ "no-irregular-whitespace": [1],
+ "no-new-wrappers": [2],
+ "curly" : [2, "multi-line"],
+ "no-implied-eval": [2],
+ "no-invalid-this": [2],
+ "constructor-super": [2],
+ "no-dupe-class-members": [2],
+ "no-this-before-super": [2],
+ "prefer-arrow-callback": [1],
+ "no-var": [1],
+ "valid-jsdoc": [1]
+ }
+ }))
+ .pipe(eslint.format())
+ .pipe(eslint.failAfterError());
+});
+
+gulp.task('lint-tests', ['lint'], function() {
+ return gulp.src('tests/**/*.js')
+ .pipe(eslint({
+ "env": {
+ "node": true
+ },
+ "rules": {
+ "radix": [2],
+ "no-with": [2],
+ "no-eval": [2],
+ "no-unreachable": [1],
+ "no-irregular-whitespace": [1],
+ "curly" : [2, "multi-line"],
+ "no-implied-eval": [2],
+ "no-invalid-this": [2],
+ "no-dupe-class-members": [2],
+ "block-scoped-var": [2]
+ }
+ }))
+ .pipe(eslint.format())
+ .pipe(eslint.failAfterError());
+});
+
+gulp.task('sloc', ['transpile'], function() {
+ gulp.src(['src/**/*.js'])
+ .pipe(sloc());
+ gulp.src(['lib/**/*.js'])
+ .pipe(sloc());
+})
+
+gulp.task('docs', ['transpile'], function() {
+ gulp.src('./src/QueryBuilder.js')
.pipe(documentation({format: 'html'}))
.pipe(gulp.dest('docs'));
- gulp.src('./lib/node-query.js')
+ /*gulp.src('./lib/QueryBuilder.js')
.pipe(documentation({format: 'md'}))
- .pipe(gulp.dest('api-docs'));
+ .pipe(gulp.dest('api-docs'));*/
});
-gulp.task('pre-test', function() {
+gulp.task('nodeunit', ['transpile', 'lint-tests'], function() {
+ return gulp.src(['tests/**/*_test.js'])
+ .pipe(nodeunit_runner());
+});
+
+gulp.task('fast-test', ['transpile', 'lint-tests'], function() {
+ return gulp.src(['tests/**/*_test.js'])
+ .pipe(nodeunit_runner());
+});
+
+gulp.task('test', ['transpile', 'lint-tests'], function(cb) {
return gulp.src(['lib/**/*.js'])
.pipe(istanbul())
- .pipe(istanbul.hookRequire());
+ .pipe(istanbul.hookRequire())
+ .on('finish', function () {
+ gulp.src(['tests/**/*_test.js'])
+ .pipe(nodeunit_runner())
+ .pipe(istanbul.writeReports({
+ dir: './coverage',
+ reporters: ['lcov', 'lcovonly', 'html', 'text']
+ }));
+ });
});
-gulp.task('test', ['pre-test'], function() {
- return gulp.src(['tests/**/*_test.js'])
- .pipe(nodeunit_runner())
- .pipe(istanbul.writeReports({
- dir: './coverage',
- reporters: ['lcov', 'lcovonly', 'html', 'text']
- }));
-});
\ No newline at end of file
+gulp.task('default', ['lint', 'sloc', 'docs', 'test']);
\ No newline at end of file
diff --git a/lib/Adapter.js b/lib/Adapter.js
new file mode 100755
index 0000000..bd29e2a
--- /dev/null
+++ b/lib/Adapter.js
@@ -0,0 +1,42 @@
+'use strict'
+
+/** @module Adapter */
+;
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+module.exports = (function () {
+ /**
+ * Invoke an adapter
+ *
+ * @param {Object} instance - The connection objec
+ * @return {void}
+ */
+
+ function Adapter(instance) {
+ _classCallCheck(this, Adapter);
+
+ this.instance = instance;
+ }
+
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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}
+ */
+
+ _createClass(Adapter, [{
+ key: "execute",
+ value: function execute() /*sql, params, callback*/{
+ throw new Error("Correct adapter not defined for query execution");
+ }
+ }]);
+
+ return Adapter;
+})();
+//# sourceMappingURL=Adapter.js.map
diff --git a/lib/Adapter.js.map b/lib/Adapter.js.map
new file mode 100644
index 0000000..06bc225
--- /dev/null
+++ b/lib/Adapter.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Adapter.js"],"names":[],"mappings":"AAAA;;;AAAY,CAAC;;;;;;AAGb,MAAM,CAAC,OAAO;;;;;;;;AAOb,UAPsB,OAAO,CAOjB,QAAQ,EAAE;wBAPA,OAAO;;AAQ5B,MAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;EACzB;;;;;;;;;;AAAA;cATqB,OAAO;;qDAmBM;AAClC,SAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;GACnE;;;QArBqB,OAAO;IAsB7B,CAAA","file":"Adapter.js","sourcesContent":["'use strict';\n\n/** @module Adapter */\nmodule.exports = class Adapter {\n\t/**\n\t * Invoke an adapter\n\t *\n\t * @param {Object} instance - The connection objec\n\t * @return {void}\n\t */\n\tconstructor(instance) {\n\t\tthis.instance = instance;\n\t}\n\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return {void}\n\t */\n\texecute(/*sql, params, callback*/) {\n\t\tthrow new Error(\"Correct adapter not defined for query execution\");\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/DriverBase.js b/lib/DriverBase.js
new file mode 100755
index 0000000..11ddacf
--- /dev/null
+++ b/lib/DriverBase.js
@@ -0,0 +1,157 @@
+'use strict';
+
+var _helpers = require('./helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Base Database Driver
+ *
+ * @module driver
+ */
+var d = {
+ identifierStartChar: '"',
+ identifierEndChar: '"',
+ tablePrefix: null,
+ hasTruncate: true,
+
+ /**
+ * Low level function for naive quoting of strings
+ * @param {String} str
+ * @return {String}
+ * @private
+ */
+ _quote: function _quote(str) {
+ return _helpers2.default.isString(str) && !(str.startsWith(d.identifierStartChar) || str.endsWith(d.identifierEndChar)) ? d.identifierStartChar + str + d.identifierEndChar : str;
+ },
+
+ /**
+ * Set the limit clause
+ * @param {String} sql
+ * @param {Number} limit
+ * @param {Number|null} offset
+ * @return {String}
+ */
+ limit: function limit(sql, _limit, offset) {
+ sql += " LIMIT " + _limit;
+
+ if (_helpers2.default.isNumber(offset)) {
+ sql += " OFFSET " + offset;
+ }
+
+ return sql;
+ },
+
+ /**
+ * Quote database table name, and set prefix
+ *
+ * @param {String} table
+ * @return {String}
+ */
+ quoteTable: function quoteTable(table) {
+ // Quote after prefix
+ return d.quoteIdentifiers(table);
+ },
+
+ /**
+ * Use the driver's escape character to quote identifiers
+ *
+ * @param {String|Array}
+ * @return {String|Array}
+ */
+ quoteIdentifiers: function quoteIdentifiers(str) {
+ var hiers, raw;
+ var pattern = new RegExp(d.identifierStartChar + '(' + '([a-zA-Z0-9_]+)' + '(\((.*?)\))' + ')' + d.identifierEndChar, 'ig');
+
+ // Recurse for arrays of identifiiers
+ if (Array.isArray(str)) {
+ return str.map(d.quoteIdentifiers);
+ }
+
+ // Handle commas
+ if (str.includes(',')) {
+ var parts = str.split(',').map(_helpers2.default.stringTrim);
+ str = parts.map(d.quoteIdentifiers).join(',');
+ }
+
+ // Split identifiers by period
+ hiers = str.split('.').map(d._quote);
+ raw = hiers.join('.');
+
+ // Fix functions
+ if (raw.includes('(') && raw.includes(')')) {
+ var funcs = pattern.exec(raw);
+
+ // Unquote the function
+ raw = raw.replace(funcs[0], funcs[1]);
+
+ // Quote the identifiers inside of the parens
+ var inParens = funcs[3].substring(1, funcs[3].length - 1);
+ raw = raw.replace(inParens, d.quoteIdentifiers(inParens));
+ }
+
+ return raw;
+ },
+
+ /**
+ * SQL to truncate the passed table
+ *
+ * @param {String} table
+ * @return {String} - sql
+ */
+ truncate: function truncate(table) {
+ var sql = d.hasTruncate ? 'TRUNCATE ' : 'DELETE FROM ';
+
+ sql += d.quoteTable(table);
+
+ return sql;
+ },
+
+ /**
+ * 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
+ * @return {String}
+ */
+ insertBatch: function insertBatch(table, data) {
+ var vals = [],
+ fields = Object.keys(data[0]),
+ sql = "",
+ params = [],
+ paramString = "",
+ paramList = [];
+
+ // Get the data values to insert, so they can
+ // be parameterized
+ data.forEach(function (obj) {
+ Object.keys(obj).forEach(function (key) {
+ vals.push(obj[key]);
+ });
+ });
+
+ // Get the field names from the keys of the first
+ // object inserted
+ table = d.quoteTable(table);
+
+ sql += "INSERT INTO " + table + " (" + d.quoteIdentifiers(fields).join(",") + ") VALUES ";
+
+ // Create placeholder groups
+ params = Array(fields.length).fill('?');
+ paramString = "(" + params.join(',') + ")";
+ paramList = Array(data.length).fill(paramString);
+
+ sql += paramList.join(',');
+
+ return {
+ sql: sql,
+ values: vals
+ };
+ }
+
+};
+
+module.exports = d;
+//# sourceMappingURL=DriverBase.js.map
diff --git a/lib/DriverBase.js.map b/lib/DriverBase.js.map
new file mode 100644
index 0000000..fdbcf48
--- /dev/null
+++ b/lib/DriverBase.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["DriverBase.js"],"names":[],"mappings":"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","file":"DriverBase.js","sourcesContent":["'use strict';\n\nimport helpers from './helpers'\n\n/**\n * Base Database Driver\n *\n * @module driver\n */\nvar d = {\n\tidentifierStartChar: '\"',\n\tidentifierEndChar: '\"',\n\ttablePrefix: null,\n\thasTruncate: true,\n\n\t/**\n\t * Low level function for naive quoting of strings\n\n\t * @param {String} str\n\t * @return {String}\n\t * @private\n\t */\n\t_quote: function(str) {\n\t\treturn (helpers.isString(str) && ! (str.startsWith(d.identifierStartChar) || str.endsWith(d.identifierEndChar)))\n\t\t\t? d.identifierStartChar + str + d.identifierEndChar\n\t\t\t: str;\n\t},\n\n\t/**\n\t * Set the limit clause\n\n\t * @param {String} sql\n\t * @param {Number} limit\n\t * @param {Number|null} offset\n\t * @return {String}\n\t */\n\tlimit: function(sql, limit, offset) {\n\t\tsql += \" LIMIT \" + limit;\n\n\t\tif (helpers.isNumber(offset))\n\t\t{\n\t\t\tsql += \" OFFSET \" + offset;\n\t\t}\n\n\t\treturn sql;\n\t},\n\n\t/**\n\t * Quote database table name, and set prefix\n\t *\n\t * @param {String} table\n\t * @return {String}\n\t */\n\tquoteTable: function(table) {\n\t\t// Quote after prefix\n\t\treturn d.quoteIdentifiers(table);\n\t},\n\n\t/**\n\t * Use the driver's escape character to quote identifiers\n\t *\n\t * @param {String|Array}\n\t * @return {String|Array}\n\t */\n\tquoteIdentifiers: function(str) {\n\t\tvar hiers, raw;\n\t\tvar pattern = new RegExp(d.identifierStartChar + '(' + '([a-zA-Z0-9_]+)' + '(\\((.*?)\\))' + ')' + d.identifierEndChar, 'ig');\n\n\t\t// Recurse for arrays of identifiiers\n\t\tif (Array.isArray(str))\n\t\t{\n\t\t\treturn str.map(d.quoteIdentifiers);\n\t\t}\n\n\t\t// Handle commas\n\t\tif (str.includes(','))\n\t\t{\n\t\t\tvar parts = str.split(',').map(helpers.stringTrim);\n\t\t\tstr = parts.map(d.quoteIdentifiers).join(',');\n\t\t}\n\n\t\t// Split identifiers by period\n\t\thiers = str.split('.').map(d._quote);\n\t\traw = hiers.join('.');\n\n\t\t// Fix functions\n\t\tif (raw.includes('(') && raw.includes(')'))\n\t\t{\n\t\t\tvar funcs = pattern.exec(raw);\n\n\t\t\t// Unquote the function\n\t\t\traw = raw.replace(funcs[0], funcs[1]);\n\n\t\t\t// Quote the identifiers inside of the parens\n\t\t\tvar inParens = funcs[3].substring(1, funcs[3].length -1);\n\t\t\traw = raw.replace(inParens, d.quoteIdentifiers(inParens));\n\t\t}\n\n\t\treturn raw;\n\t},\n\n\t/**\n\t * SQL to truncate the passed table\n\t *\n\t * @param {String} table\n\t * @return {String} - sql\n\t */\n\ttruncate: function(table) {\n\t\tvar sql = (d.hasTruncate)\n\t\t\t? 'TRUNCATE '\n\t\t\t: 'DELETE FROM ';\n\n\t\tsql += d.quoteTable(table);\n\n\t\treturn sql;\n\t},\n\n\t/**\n\t * SQL to insert a group of rows\n\t *\n\t * @param {String} table - The table to insert to\n\t * @param {Array} [data] - The array of object containing data to insert\n\t * @return {String}\n\t */\n\tinsertBatch: function(table, data) {\n\t\tvar vals = [],\n\t\t\tfields = Object.keys(data[0]),\n\t\t\tsql = \"\",\n\t\t\tparams = [],\n\t\t\tparamString = \"\",\n\t\t\tparamList = [];\n\n\t\t// Get the data values to insert, so they can\n\t\t// be parameterized\n\t\tdata.forEach(function(obj) {\n\t\t\tObject.keys(obj).forEach(function(key) {\n\t\t\t\tvals.push(obj[key]);\n\t\t\t});\n\t\t});\n\n\t\t// Get the field names from the keys of the first\n\t\t// object inserted\n\t\ttable = d.quoteTable(table);\n\n\t\tsql += \"INSERT INTO \" + table + \" (\"\n\t\t\t+ d.quoteIdentifiers(fields).join(\",\")\n\t\t\t+ \") VALUES \";\n\n\t\t// Create placeholder groups\n\t\tparams = Array(fields.length).fill('?');\n\t\tparamString = \"(\" + params.join(',') + \")\";\n\t\tparamList = Array(data.length).fill(paramString);\n\n\t\tsql += paramList.join(',');\n\n\t\treturn {\n\t\t\tsql: sql,\n\t\t\tvalues: vals\n\t\t};\n\t}\n\n};\n\nmodule.exports = d;"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/DriverClass.js b/lib/DriverClass.js
new file mode 100644
index 0000000..3029d7a
--- /dev/null
+++ b/lib/DriverClass.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var _DriverBase = require('./DriverBase');
+
+var _DriverBase2 = _interopRequireDefault(_DriverBase);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+module.exports = function DriverClass() {
+ var _this = this;
+
+ var properties = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+
+ _classCallCheck(this, DriverClass);
+
+ Object.keys(_DriverBase2.default).forEach(function (key) {
+ _this[key] = Object.keys(properties).indexOf(key) !== -1 ? properties[key] : _DriverBase2.default[key];
+ });
+};
+//# sourceMappingURL=DriverClass.js.map
diff --git a/lib/DriverClass.js.map b/lib/DriverClass.js.map
new file mode 100644
index 0000000..278b095
--- /dev/null
+++ b/lib/DriverClass.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["DriverClass.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;AAIb,MAAM,CAAC,OAAO,GACb,SADsB,WAAW,GACJ;;;KAAjB,UAAU,yDAAG,EAAE;;uBADL,WAAW;;AAEhC,OAAM,CAAC,IAAI,sBAAY,CAAC,OAAO,CAAC,UAAC,GAAG,EAAK;AACxC,QAAK,GAAG,CAAC,GAAG,AAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GACrD,UAAU,CAAC,GAAG,CAAC,GACf,qBAAW,GAAG,CAAC,CAAC;EACnB,CAAC,CAAC;CACH,AACD,CAAA","file":"DriverClass.js","sourcesContent":["'use strict';\n\nimport driverBase from './DriverBase';\n\nmodule.exports = class DriverClass {\n\tconstructor(properties = {}) {\n\t\tObject.keys(driverBase).forEach((key) => {\n\t\t\tthis[key] = (Object.keys(properties).indexOf(key) !== -1)\n\t\t\t\t? properties[key]\n\t\t\t\t: driverBase[key];\n\t\t});\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/NodeQuery.js b/lib/NodeQuery.js
new file mode 100755
index 0000000..2531bd4
--- /dev/null
+++ b/lib/NodeQuery.js
@@ -0,0 +1,103 @@
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _fs = require('fs');
+
+var _fs2 = _interopRequireDefault(_fs);
+
+var _helpers = require('./helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+var _QueryBuilder = require('./QueryBuilder');
+
+var _QueryBuilder2 = _interopRequireDefault(_QueryBuilder);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var instance = null;
+
+/**
+ * @module NodeQuery
+ */
+
+var NodeQuery = (function () {
+
+ /**
+ * Constructor
+ */
+
+ function NodeQuery() {
+ _classCallCheck(this, NodeQuery);
+
+ this.instance = null;
+ }
+
+ /**
+ * Create a query builder object
+ *
+ * @memberOf NodeQuery
+ * @param {String} drivername - 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
+ * @return {QueryBuilder}
+ */
+
+ _createClass(NodeQuery, [{
+ key: 'init',
+ value: function init(driverType, connObject, connLib) {
+ connLib = connLib || driverType;
+
+ var paths = {
+ driver: __dirname + '/drivers/' + _helpers2.default.upperCaseFirst(driverType),
+ adapter: __dirname + '/adapters/' + connLib
+ };
+
+ /*Object.keys(paths).forEach((type) => {
+ if ( ! fs.existsSync(paths[type]))
+ {
+ console.log(paths[type]);
+ throw new Error(
+ `Selected ${type} (` +
+ helpers.upperCaseFirst(driverType) +
+ `) does not exist!`
+ );
+ }
+ });*/
+
+ var driver = require(paths.driver);
+ var $adapter = require(paths.adapter);
+ var adapter = new $adapter(connObject);
+
+ this.instance = new _QueryBuilder2.default(driver, adapter);
+
+ return this.instance;
+ }
+ }, {
+ key: 'getQuery',
+
+ /**
+ * Return an existing query builder instance
+ *
+ * @memberOf NodeQuery
+ * @return {QueryBuilder}
+ */
+ value: function getQuery() {
+ if (!this.instance) {
+ throw new Error("No Query Builder instance to return");
+ }
+
+ return this.instance;
+ }
+ }]);
+
+ return NodeQuery;
+})();
+
+;
+
+module.exports = new NodeQuery();
+//# sourceMappingURL=NodeQuery.js.map
diff --git a/lib/NodeQuery.js.map b/lib/NodeQuery.js.map
new file mode 100644
index 0000000..00d5f09
--- /dev/null
+++ b/lib/NodeQuery.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["NodeQuery.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;AAEb,IAAI,QAAQ,GAAG,IAAI,CAAC;;;;;;IAQd,SAAS;;;;;;AAKd,UALK,SAAS,GAKA;wBALT,SAAS;;AAMb,MAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;EACrB;;;;;;;;;;;AAAA;cAPI,SAAS;;uBAkBT,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE;AACrC,UAAO,GAAG,OAAO,IAAI,UAAU,CAAC;;AAEhC,OAAI,KAAK,GAAG;AACX,UAAM,EAAE,AAAG,SAAS,iBAAc,kBAAQ,cAAc,CAAC,UAAU,CAAC;AACpE,WAAO,EAAK,SAAS,kBAAa,OAAO,AAAE;IAC3C;;;;;;;;;;;;;;AAAC,AAcF,OAAI,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACnC,OAAI,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACtC,OAAI,OAAO,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC;;AAEvC,OAAI,CAAC,QAAQ,GAAG,2BAAiB,MAAM,EAAE,OAAO,CAAC,CAAC;;AAElD,UAAO,IAAI,CAAC,QAAQ,CAAC;GACrB;;;;;;;;;;6BAQU;AACV,OAAK,CAAE,IAAI,CAAC,QAAQ,EAAE;AACrB,UAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACvD;;AAED,UAAO,IAAI,CAAC,QAAQ,CAAC;GACrB;;;QA3DI,SAAS;;;AA6Dd,CAAC;;AAEF,MAAM,CAAC,OAAO,GAAG,IAAI,SAAS,EAAE,CAAC","file":"NodeQuery.js","sourcesContent":["\"use strict\";\n\nlet instance = null;\nimport fs from 'fs';\nimport helpers from './helpers';\nimport QueryBuilder from './QueryBuilder';\n\n/**\n * @module NodeQuery\n */\nclass NodeQuery {\n\n\t/**\n\t * Constructor\n\t */\n\tconstructor() {\n\t\tthis.instance = null;\n\t}\n\n\t/**\n\t * Create a query builder object\n\t *\n\t * @memberOf NodeQuery\n\t * @param {String} drivername - The name of the database type, eg. mysql or pg\n\t * @param {Object} connObject - A connection object from the database library you are connecting with\n\t * @param {String} [connLib] - The name of the db connection library you are using, eg. mysql or mysql2. Optional if the same as drivername\n\t * @return {QueryBuilder}\n\t */\n\tinit(driverType, connObject, connLib) {\n\t\tconnLib = connLib || driverType;\n\n\t\tlet paths = {\n\t\t\tdriver: `${__dirname}/drivers/` + helpers.upperCaseFirst(driverType),\n\t\t\tadapter: `${__dirname}/adapters/${connLib}`\n\t\t};\n\n\t\t/*Object.keys(paths).forEach((type) => {\n\t\t\tif ( ! fs.existsSync(paths[type]))\n\t\t\t{\n\t\t\t\tconsole.log(paths[type]);\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Selected ${type} (` +\n\t\t\t\t\thelpers.upperCaseFirst(driverType) +\n\t\t\t\t\t`) does not exist!`\n\t\t\t\t);\n\t\t\t}\n\t\t});*/\n\n\t\tlet driver = require(paths.driver);\n\t\tlet $adapter = require(paths.adapter);\n\t\tlet adapter = new $adapter(connObject);\n\n\t\tthis.instance = new QueryBuilder(driver, adapter);\n\n\t\treturn this.instance;\n\t};\n\n\t/**\n\t * Return an existing query builder instance\n\t *\n\t * @memberOf NodeQuery\n\t * @return {QueryBuilder}\n\t */\n\tgetQuery() {\n\t\tif ( ! this.instance) {\n\t\t\tthrow new Error(\"No Query Builder instance to return\");\n\t\t}\n\n\t\treturn this.instance;\n\t};\n\n};\n\nmodule.exports = new NodeQuery();"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/QueryBuilder.js b/lib/QueryBuilder.js
new file mode 100755
index 0000000..3efc825
--- /dev/null
+++ b/lib/QueryBuilder.js
@@ -0,0 +1,1063 @@
+'use strict'
+
+/** @module QueryBuilder */
+;
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _getargs = require('getargs');
+
+var _getargs2 = _interopRequireDefault(_getargs);
+
+var _helpers = require('./helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+var _State = require('./State');
+
+var _State2 = _interopRequireDefault(_State);
+
+var _QueryParser = require('./QueryParser');
+
+var _QueryParser2 = _interopRequireDefault(_QueryParser);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+module.exports = (function () {
+ /*
+ * SQL generation object
+ *
+ * @param {driver} - The syntax driver for the database
+ * @param {adapter} - The database module adapter for running queries
+ * @returns {QueryBuilder}
+ * @constructor
+ */
+
+ function QueryBuilder(driver, adapter) {
+ _classCallCheck(this, QueryBuilder);
+
+ this.driver = driver;
+ this.adapter = adapter;
+ this.parser = new _QueryParser2.default(this.driver);
+ this.state = new _State2.default();
+ }
+
+ /**
+ * Complete the sql building based on the type provided
+ *
+ * @param {String} type
+ * @param {String} table
+ * @private
+ * @return {String}
+ */
+
+ _createClass(QueryBuilder, [{
+ key: '_compile',
+ value: function _compile(type, table) {
+ var _this = this;
+
+ // Put together the basic query
+ var sql = this._compileType(type, table);
+
+ // Set each subClause
+ ['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(function (clause) {
+ var param = _this.state[clause];
+
+ if (!_helpers2.default.isScalar(param)) {
+ Object.keys(param).forEach(function (part) {
+ sql += param[part].conjunction + param[part].string;
+ });
+ } else {
+ sql += param;
+ }
+ });
+
+ // Append the limit, if it exists
+ if (_helpers2.default.isNumber(this.state.limit)) {
+ sql = this.driver.limit(sql, this.state.limit, this.state.offset);
+ }
+
+ return sql;
+ }
+ }, {
+ key: '_compileType',
+ value: function _compileType(type, table) {
+ var sql = '';
+
+ switch (type) {
+ case "insert":
+ var params = Array(this.state.setArrayKeys.length).fill('?');
+
+ sql = 'INSERT INTO ' + table + ' (';
+ sql += this.state.setArrayKeys.join(',');
+ sql += ") VALUES (";
+ sql += params.join(',') + ')';
+ break;
+
+ case "update":
+ sql = 'UPDATE ' + table + ' SET ' + this.state.setString;
+ break;
+
+ case "delete":
+ sql = 'DELETE FROM ' + table;
+ break;
+
+ default:
+ sql = 'SELECT * FROM ' + this.state.fromString;
+
+ // Set the select string
+ if (this.state.selectString.length > 0) {
+ // Replace the star with the selected fields
+ sql = sql.replace('*', this.state.selectString);
+ }
+ break;
+ }
+
+ return sql;
+ }
+ }, {
+ key: '_like',
+ value: function _like(field, val, pos, like, conj) {
+ field = this.driver.quoteIdentifiers(field);
+
+ like = field + ' ' + like + ' ?';
+
+ if (pos == 'before') {
+ val = '%' + val;
+ } else if (pos == 'after') {
+ val = val + '%';
+ } else {
+ val = '%' + val + '%';
+ }
+
+ conj = this.state.queryMap.length < 1 ? ' WHERE ' : ' ' + conj + ' ';
+ this._appendMap(conj, like, 'like');
+
+ this.state.whereValues.push(val);
+ }
+
+ /**
+ * Append a clause to the query map
+ *
+ * @param {String} conjunction
+ * @param {String} string
+ * @param {String} type
+ * @return {void}
+ */
+
+ }, {
+ key: '_appendMap',
+ value: function _appendMap(conjunction, string, type) {
+ this.state.queryMap.push({
+ type: type,
+ conjunction: conjunction,
+ string: string
+ });
+ }
+
+ /**
+ * Handle key/value pairs in an object the same way as individual arguments,
+ * when appending to state
+ *
+ * @private
+ */
+
+ }, {
+ key: '_mixedSet',
+ value: function _mixedSet() /* $letName, $valType, $key, [$val] */{
+ var _this2 = this;
+
+ var args = (0, _getargs2.default)('$letName:string, $valType:string, $key:object|string|number, [$val]', arguments);
+
+ var obj = {};
+
+ if (_helpers2.default.isScalar(args.$key) && !_helpers2.default.isUndefined(args.$val)) {
+ // Convert key/val pair to a simple object
+ obj[args.$key] = args.$val;
+ } else if (_helpers2.default.isScalar(args.$key) && _helpers2.default.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(function (k) {
+ // If a single value for the return
+ if (['key', 'value'].indexOf(args.$valType) !== -1) {
+ var pushVal = args.$valType === 'key' ? k : obj[k];
+ _this2.state[args.$letName].push(pushVal);
+ } else {
+ _this2.state[args.$letName][k] = obj[k];
+ }
+ });
+
+ return this.state[args.$letName];
+ }
+ }, {
+ key: '_whereMixedSet',
+ value: function _whereMixedSet() /*key, val*/{
+ var args = (0, _getargs2.default)('key:string|object, [val]', arguments);
+
+ this.state.whereMap = [];
+ this.state.rawWhereValues = [];
+
+ this._mixedSet('whereMap', 'both', args.key, args.val);
+ this._mixedSet('rawWhereValues', 'value', args.key, args.val);
+ }
+ }, {
+ key: '_fixConjunction',
+ value: function _fixConjunction(conj) {
+ var lastItem = this.state.queryMap[this.state.queryMap.length - 1];
+ var conjunctionList = _helpers2.default.arrayPluck(this.state.queryMap, 'conjunction');
+
+ if (this.state.queryMap.length === 0 || !_helpers2.default.regexInArray(conjunctionList, /^ ?WHERE/i)) {
+ conj = " WHERE ";
+ } else if (lastItem.type === 'groupStart') {
+ conj = '';
+ } else {
+ conj = ' ' + conj + ' ';
+ }
+
+ return conj;
+ }
+ }, {
+ key: '_where',
+ value: function _where(key, val, defaultConj) {
+ var _this3 = this;
+
+ // Normalize key and value and insert into this.state.whereMap
+ this._whereMixedSet(key, val);
+
+ // Parse the where condition to account for operators,
+ // functions, identifiers, and literal values
+ this.state = this.parser.parseWhere(this.driver, this.state);
+
+ this.state.whereMap.forEach(function (clause) {
+ var conj = _this3._fixConjunction(defaultConj);
+ _this3._appendMap(conj, clause, 'where');
+ });
+
+ this.state.whereMap = {};
+ }
+ }, {
+ key: '_whereNull',
+ value: function _whereNull(field, stmt, conj) {
+ field = this.driver.quoteIdentifiers(field);
+ var item = field + ' ' + stmt;
+
+ this._appendMap(this._fixConjunction(conj), item, 'whereNull');
+ }
+ }, {
+ key: '_having',
+ value: function _having() /*key, val, conj*/{
+ var _this4 = this;
+
+ var args = (0, _getargs2.default)('key:string|object, [val]:string|number, [conj]:string', arguments);
+ args.conj = args.conj || 'AND';
+ args.val = args.val || null;
+
+ // Normalize key/val and put in state.whereMap
+ this._whereMixedSet(args.key, args.val);
+
+ // Parse the having condition to account for operators,
+ // functions, identifiers, and literal values
+ this.state = this.parser.parseWhere(this.driver, this.state);
+
+ this.state.whereMap.forEach(function (clause) {
+ // Put in the having map
+ _this4.state.havingMap.push({
+ conjunction: _this4.state.havingMap.length > 0 ? ' ' + args.conj + ' ' : ' HAVING ',
+ string: clause
+ });
+ });
+
+ // Clear the where Map
+ this.state.whereMap = {};
+ }
+ }, {
+ key: '_whereIn',
+ value: function _whereIn() /*key, val, inClause, conj*/{
+ var _this5 = this;
+
+ var args = (0, _getargs2.default)('key:string, val:array, inClause:string, conj:string', arguments);
+
+ args.key = this.driver.quoteIdentifiers(args.key);
+ var params = new Array(args.val.length);
+ params.fill('?');
+
+ args.val.forEach(function (value) {
+ _this5.state.whereValues.push(value);
+ });
+
+ args.conj = this.state.queryMap.length > 0 ? " " + args.conj + " " : ' WHERE ';
+ var str = args.key + " " + args.inClause + " (" + params.join(',') + ") ";
+
+ this._appendMap(args.conj, str, 'whereIn');
+ }
+ }, {
+ key: '_run',
+ value: function _run(type, table, callback, sql, vals) {
+
+ if (!sql) {
+ sql = this._compile(type, table);
+ }
+
+ if (!vals) {
+ vals = this.state.values.concat(this.state.whereValues);
+ }
+
+ //console.log(this.state);
+ //console.log(sql);
+ //console.log(vals);
+ //console.log(callback);
+ //console.log('------------------------');
+
+ // Reset the state so another query can be built
+ this._resetState();
+
+ // Pass the sql and values to the adapter to run on the database
+ this.adapter.execute(sql, vals, callback);
+ }
+ }, {
+ key: '_getCompile',
+ value: function _getCompile(type, table, reset) {
+ reset = reset || false;
+
+ var sql = this._compile(type, table);
+
+ if (reset) this._resetState();
+
+ return sql;
+ }
+ }, {
+ key: '_resetState',
+ value: function _resetState() {
+ this.state = new _State2.default();
+ }
+
+ // ----------------------------------------------------------------------------
+ // ! Miscellaneous Methods
+ // ----------------------------------------------------------------------------
+
+ /**
+ * Reset the object state for a new query
+ *
+ * @memberOf QueryBuilder
+ * @return {void}
+ */
+
+ }, {
+ key: 'resetQuery',
+ value: function resetQuery() {
+ this._resetState();
+ }
+
+ /**
+ * Returns the current class state for testing or other purposes
+ *
+ * @private
+ * @return {Object}
+ */
+
+ }, {
+ key: 'getState',
+ value: function getState() {
+ return this.state;
+ }
+
+ /**
+ * Closes the database connection for the current adapter
+ *
+ * @return {void}
+ */
+
+ }, {
+ key: 'end',
+ value: function end() {
+ this.adapter.close();
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Query Builder Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Specify rows to select in the query
+ *
+ * @memberOf QueryBuilder
+ * @param {String|Array} fields - The fields to select from the current table
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'select',
+ value: function select(fields) {
+
+ // Split/trim fields by comma
+ fields = Array.isArray(fields) ? fields : fields.split(",").map(_helpers2.default.stringTrim);
+
+ // Split on 'As'
+ fields.forEach(function (field, index) {
+ if (field.match(/as/i)) {
+ fields[index] = field.split(/ as /i).map(_helpers2.default.stringTrim);
+ }
+ });
+
+ var safeArray = this.driver.quoteIdentifiers(fields);
+
+ // Join the strings back together
+ safeArray.forEach(function (field, index) {
+ if (Array.isArray(field)) {
+ safeArray[index] = safeArray[index].join(' AS ');
+ }
+ });
+
+ this.state.selectString += safeArray.join(', ');
+
+ return this;
+ }
+
+ /**
+ * Specify the database table to select from
+ *
+ * @param {String} tableName - The table to use for the current query
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'from',
+ value: function from(tableName) {
+ // Split identifiers on spaces
+ var identArray = tableName.trim().split(' ').map(_helpers2.default.stringTrim);
+
+ // Quote/prefix identifiers
+ identArray[0] = this.driver.quoteTable(identArray[0]);
+ identArray = this.driver.quoteIdentifiers(identArray);
+
+ // Put it back together
+ this.state.fromString = identArray.join(' ');
+
+ return this;
+ }
+
+ /**
+ * Add a 'like/ and like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'like',
+ value: function like(field, val, pos) {
+ this._like(field, val, pos, ' LIKE ', 'AND');
+ return this;
+ }
+
+ /**
+ * Add a 'not like/ and not like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'notLike',
+ value: function notLike(field, val, pos) {
+ this._like(field, val, pos, ' NOT LIKE ', 'AND');
+ return this;
+ }
+
+ /**
+ * Add an 'or like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orLike',
+ value: function orLike(field, val, pos) {
+ this._like(field, val, pos, ' LIKE ', 'OR');
+ return this;
+ }
+
+ /**
+ * Add an 'or not like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orNotLike',
+ value: function orNotLike(field, val, pos) {
+ this._like(field, val, pos, ' NOT LIKE ', 'OR');
+ return this;
+ }
+
+ /**
+ * Add a 'having' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'having',
+ value: function having() /*key, [val]*/{
+ var args = (0, _getargs2.default)('key:string|object, [val]:string|number', arguments);
+
+ this._having(args.key, args.val, 'AND');
+ return this;
+ }
+
+ /**
+ * Add an 'or having' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orHaving',
+ value: function orHaving() /*key, [val]*/{
+ var args = (0, _getargs2.default)('key:string|object, [val]:string|number', arguments);
+
+ this._having(args.key, args.val, 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'where',
+ value: function where(key, val) {
+ this._where(key, val, 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orWhere',
+ value: function orWhere(key, val) {
+ this._where(key, val, 'OR');
+ return this;
+ }
+
+ /**
+ * Select a field that is Null
+ *
+ * @param {String} field - The name of the field that has a NULL value
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'whereIsNull',
+ value: function whereIsNull(field) {
+ this._whereNull(field, 'IS NULL', 'AND');
+ return this;
+ }
+
+ /**
+ * Specify that a field IS NOT NULL
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'whereIsNotNull',
+ value: function whereIsNotNull(field) {
+ this._whereNull(field, 'IS NOT NULL', 'AND');
+ return this;
+ }
+
+ /**
+ * Field is null prefixed with 'OR'
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orWhereIsNull',
+ value: function orWhereIsNull(field) {
+ this._whereNull(field, 'IS NULL', 'OR');
+ return this;
+ }
+
+ /**
+ * Field is not null prefixed with 'OR'
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orWhereIsNotNull',
+ value: function orWhereIsNotNull(field) {
+ this._whereNull(field, 'IS NOT NULL', 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'whereIn',
+ value: function whereIn(key, val) {
+ this._whereIn(key, val, 'IN', 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orWhereIn',
+ value: function orWhereIn(key, val) {
+ this._whereIn(key, val, 'IN', 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where not in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'whereNotIn',
+ value: function whereNotIn(key, val) {
+ this._whereIn(key, val, 'NOT IN', 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where not in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orWhereNotIn',
+ value: function orWhereNotIn(key, val) {
+ this._whereIn(key, val, 'NOT IN', 'OR');
+ return this;
+ }
+
+ /**
+ * Set values for insertion or updating
+ *
+ * @param {String|Object} key - The key or object to use
+ * @param {String} [val] - The value if using a scalar key
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'set',
+ value: function set() /* $key, [$val] */{
+ var args = (0, _getargs2.default)('$key, [$val]', arguments);
+
+ // Set the appropriate state variables
+ this._mixedSet('setArrayKeys', 'key', args.$key, args.$val);
+ this._mixedSet('values', 'value', args.$key, args.$val);
+
+ // Use the keys of the array to make the insert/update string
+ // and escape the field names
+ this.state.setArrayKeys = this.state.setArrayKeys.map(this.driver._quote);
+
+ // Generate the "set" string
+ this.state.setString = this.state.setArrayKeys.join('=?,');
+ this.state.setString += '=?';
+
+ return this;
+ }
+
+ /**
+ * Add a join clause to the query
+ *
+ * @param {String} table - The table you are joining
+ * @param {String} cond - The join condition.
+ * @param {String} [type='inner'] - The type of join, which defaults to inner
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'join',
+ value: function join(table, cond, type) {
+ type = type || "inner";
+
+ // Prefix/quote table name
+ table = table.split(' ').map(_helpers2.default.stringTrim);
+ table[0] = this.driver.quoteTable(table[0]);
+ table = table.map(this.driver.quoteIdentifiers);
+ table = table.join(' ');
+
+ // Parse out the join condition
+ var parsedCondition = this.parser.compileJoin(cond);
+ var condition = table + ' ON ' + parsedCondition;
+
+ // Append the join condition to the query map
+ this._appendMap("\n" + type.toUpperCase() + ' JOIN ', condition, 'join');
+
+ return this;
+ }
+
+ /**
+ * Group the results by the selected field(s)
+ *
+ * @param {String|Array} field
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'groupBy',
+ value: function groupBy(field) {
+ if (!_helpers2.default.isScalar(field)) {
+ var newGroupArray = field.map(this.driver.quoteIdentifiers);
+ this.state.groupArray = this.state.groupArray.concat(newGroupArray);
+ } else {
+ this.state.groupArray.push(this.driver.quoteIdentifiers(field));
+ }
+
+ this.state.groupString = ' GROUP BY ' + this.state.groupArray.join(',');
+
+ return this;
+ }
+
+ /**
+ * Order the results by the selected field(s)
+ *
+ * @param {String} field - The field(s) to order by
+ * @param {String} [type='ASC'] - The order direction, ASC or DESC
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orderBy',
+ value: function orderBy(field, type) {
+ var _this6 = this;
+
+ type = type || 'ASC';
+
+ // Set the fields for later manipulation
+ field = this.driver.quoteIdentifiers(field);
+
+ this.state.orderArray[field] = type;
+
+ var orderClauses = [];
+
+ // Flatten key/val pairs into an array of space-separated pairs
+ Object.keys(this.state.orderArray).forEach(function (key) {
+ orderClauses.push(key + ' ' + _this6.state.orderArray[key].toUpperCase());
+ });
+
+ // Set the final string
+ this.state.orderString = ' ORDER BY ' + orderClauses.join(', ');
+
+ return this;
+ }
+
+ /**
+ * Put a limit on the query
+ *
+ * @param {Number} limit - The maximum number of rows to fetch
+ * @param {Number} [offset] - The row number to start from
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'limit',
+ value: function limit(_limit, offset) {
+ this.state.limit = _limit;
+ this.state.offset = offset || null;
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping
+ *
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'groupStart',
+ value: function groupStart() {
+ var conj = this.state.queryMap.length < 1 ? ' WHERE ' : ' AND ';
+ this._appendMap(conj, '(', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping,
+ * prefixed with 'OR'
+ *
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orGroupStart',
+ value: function orGroupStart() {
+ this._appendMap('', ' OR (', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping,
+ * prefixed with 'OR NOT'
+ *
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'orNotGroupStart',
+ value: function orNotGroupStart() {
+ this._appendMap('', ' OR NOT (', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Ends a logical grouping started with one of the groupStart methods
+ *
+ * @return {QueryBuilder}
+ */
+
+ }, {
+ key: 'groupEnd',
+ value: function groupEnd() {
+ this._appendMap('', ')', 'groupEnd');
+
+ return this;
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Result Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the results of the compiled query
+ *
+ * @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}
+ */
+
+ }, {
+ key: 'get',
+ value: function get() /* [table], [limit], [offset], callback */{
+ var args = (0, _getargs2.default)('[table]:string, [limit]:number, [offset]:number, callback:function', arguments);
+
+ if (args.table) {
+ this.from(args.table);
+ }
+
+ if (args.limit) {
+ this.limit(args.limit, args.offset);
+ }
+
+ // Run the query
+ this._run('get', args.table, args.callback);
+ }
+
+ /**
+ * Run the generated insert query
+ *
+ * @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}
+ */
+
+ }, {
+ key: 'insert',
+ value: function insert() /* table, data, callback */{
+ var args = (0, _getargs2.default)('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);
+ }
+
+ /**
+ * Insert multiple sets of rows at a time
+ *
+ * @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
+ * @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
+ * @return {void}
+ */
+
+ }, {
+ key: 'insertBatch',
+ value: function insertBatch() /* table, data, callback */{
+ var args = (0, _getargs2.default)('table:string, data:array, callback:function', arguments);
+ var batch = this.driver.insertBatch(args.table, args.data);
+
+ // Run the query
+ this._run('', '', args.callback, batch.sql, batch.values);
+ }
+
+ /**
+ * Run the generated update query
+ *
+ * @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}
+ */
+
+ }, {
+ key: 'update',
+ value: function update() /*table, data, callback*/{
+ var args = (0, _getargs2.default)('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);
+ }
+
+ /**
+ * Run the generated delete query
+ *
+ * @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}
+ */
+
+ }, {
+ key: 'delete',
+ value: function _delete() /*table, [where], callback*/{
+ var args = (0, _getargs2.default)('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);
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Methods returning SQL
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return generated select query SQL
+ *
+ * @param {String} [table] - the name of the table to retrieve from
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+
+ }, {
+ key: 'getCompiledSelect',
+ value: function getCompiledSelect() /*table, reset*/{
+ var args = (0, _getargs2.default)('[table]:string, [reset]:boolean', arguments);
+ if (args.table) {
+ this.from(args.table);
+ }
+
+ return this._getCompile('get', args.table, args.reset);
+ }
+
+ /**
+ * Return generated insert query SQL
+ *
+ * @param {String} table - the name of the table to insert into
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+
+ }, {
+ key: 'getCompiledInsert',
+ value: function getCompiledInsert(table, reset) {
+ return this._getCompile('insert', this.driver.quoteTable(table), reset);
+ }
+
+ /**
+ * Return generated update query SQL
+ *
+ * @param {String} table - the name of the table to update
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+
+ }, {
+ key: 'getCompiledUpdate',
+ value: function getCompiledUpdate(table, reset) {
+ return this._getCompile('update', this.driver.quoteTable(table), reset);
+ }
+
+ /**
+ * Return generated delete query SQL
+ *
+ * @param {String} table - the name of the table to delete from
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+
+ }, {
+ key: 'getCompiledDelete',
+ value: function getCompiledDelete(table, reset) {
+ return this._getCompile('delete', this.driver.quoteTable(table), reset);
+ }
+ }]);
+
+ return QueryBuilder;
+})();
+//# sourceMappingURL=QueryBuilder.js.map
diff --git a/lib/QueryBuilder.js.map b/lib/QueryBuilder.js.map
new file mode 100644
index 0000000..b9903ee
--- /dev/null
+++ b/lib/QueryBuilder.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["QueryBuilder.js"],"names":[],"mappings":"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","file":"QueryBuilder.js","sourcesContent":["'use strict';\n\n/** @module QueryBuilder */\nimport getArgs from 'getargs';\nimport helpers from './helpers';\nimport State from './State';\nimport QueryParser from './QueryParser';\n\nmodule.exports = class QueryBuilder {\n\t/*\n\t * SQL generation object\n\t *\n\t * @param {driver} - The syntax driver for the database\n\t * @param {adapter} - The database module adapter for running queries\n\t * @returns {QueryBuilder}\n\t * @constructor\n\t */\n\tconstructor(driver, adapter) {\n\t\tthis.driver = driver;\n\t\tthis.adapter = adapter;\n\t\tthis.parser = new QueryParser(this.driver);\n\t\tthis.state = new State();\n\t}\n\n\t/**\n\t * Complete the sql building based on the type provided\n\t *\n\t * @param {String} type\n\t * @param {String} table\n\t * @private\n\t * @return {String}\n\t */\n\t_compile(type, table) {\n\t\t// Put together the basic query\n\t\tlet sql = this._compileType(type, table);\n\n\t\t// Set each subClause\n\t\t['queryMap', 'groupString', 'orderString', 'havingMap'].forEach((clause) => {\n\t\t\tlet param = this.state[clause];\n\n\t\t\tif ( ! helpers.isScalar(param))\n\t\t\t{\n\t\t\t\tObject.keys(param).forEach((part) => {\n\t\t\t\t\tsql += param[part].conjunction + param[part].string;\n\t\t\t\t});\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsql += param;\n\t\t\t}\n\t\t});\n\n\t\t// Append the limit, if it exists\n\t\tif (helpers.isNumber(this.state.limit))\n\t\t{\n\t\t\tsql = this.driver.limit(sql, this.state.limit, this.state.offset);\n\t\t}\n\n\t\treturn sql;\n\t}\n\n\t_compileType(type, table) {\n\t\tlet sql = '';\n\n\t\tswitch(type) {\n\t\t\tcase \"insert\":\n\t\t\t\tlet params = Array(this.state.setArrayKeys.length).fill('?');\n\n\t\t\t\tsql = `INSERT INTO ${table} (`;\n\t\t\t\tsql += this.state.setArrayKeys.join(',');\n\t\t\t\tsql += \") VALUES (\";\n\t\t\t\tsql += params.join(',') + ')';\n\t\t\tbreak;\n\n\t\t\tcase \"update\":\n\t\t\t\tsql = `UPDATE ${table} SET ${this.state.setString}`;\n\t\t\tbreak;\n\n\t\t\tcase \"delete\":\n\t\t\t\tsql = `DELETE FROM ${table}`;\n\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tsql = `SELECT * FROM ${this.state.fromString}`;\n\n\t\t\t\t// Set the select string\n\t\t\t\tif (this.state.selectString.length > 0)\n\t\t\t\t{\n\t\t\t\t\t// Replace the star with the selected fields\n\t\t\t\t\tsql = sql.replace('*', this.state.selectString);\n\t\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\treturn sql;\n\t}\n\n\t_like(field, val, pos, like, conj) {\n\t\tfield = this.driver.quoteIdentifiers(field);\n\n\t\tlike = `${field} ${like} ?`;\n\n\t\tif (pos == 'before')\n\t\t{\n\t\t\tval = `%${val}`;\n\t\t}\n\t\telse if (pos == 'after')\n\t\t{\n\t\t\tval = `${val}%`;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tval = `%${val}%`;\n\t\t}\n\n\t\tconj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;\n\t\tthis._appendMap(conj, like, 'like');\n\n\t\tthis.state.whereValues.push(val);\n\t}\n\n\t/**\n\t * Append a clause to the query map\n\t *\n\t * @param {String} conjunction\n\t * @param {String} string\n\t * @param {String} type\n\t * @return {void}\n\t */\n\t_appendMap(conjunction, string, type) {\n\t\tthis.state.queryMap.push({\n\t\t\ttype: type,\n\t\t\tconjunction: conjunction,\n\t\t\tstring: string\n\t\t});\n\t}\n\n\t/**\n\t * Handle key/value pairs in an object the same way as individual arguments,\n\t * when appending to state\n\t *\n\t * @private\n\t */\n\t_mixedSet(/* $letName, $valType, $key, [$val] */) {\n\t\tlet args = getArgs('$letName:string, $valType:string, $key:object|string|number, [$val]', arguments);\n\n\t\tlet obj = {};\n\n\n\t\tif (helpers.isScalar(args.$key) && !helpers.isUndefined(args.$val))\n\t\t{\n\t\t\t// Convert key/val pair to a simple object\n\t\t\tobj[args.$key] = args.$val;\n\t\t}\n\t\telse if (helpers.isScalar(args.$key) && helpers.isUndefined(args.$val))\n\t\t{\n\t\t\t// If just a string for the key, and no value, create a simple object with duplicate key/val\n\t\t\tobj[args.$key] = args.$key;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tobj = args.$key;\n\t\t}\n\n\t\tObject.keys(obj).forEach((k) => {\n\t\t\t// If a single value for the return\n\t\t\tif (['key','value'].indexOf(args.$valType) !== -1)\n\t\t\t{\n\t\t\t\tlet pushVal = (args.$valType === 'key') ? k : obj[k];\n\t\t\t\tthis.state[args.$letName].push(pushVal);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthis.state[args.$letName][k] = obj[k];\n\t\t\t}\n\t\t});\n\n\n\t\treturn this.state[args.$letName];\n\t}\n\n\t_whereMixedSet(/*key, val*/) {\n\t\tlet args = getArgs('key:string|object, [val]', arguments);\n\n\t\tthis.state.whereMap = [];\n\t\tthis.state.rawWhereValues = [];\n\n\t\tthis._mixedSet('whereMap', 'both', args.key, args.val);\n\t\tthis._mixedSet('rawWhereValues', 'value', args.key, args.val);\n\t}\n\n\t_fixConjunction(conj) {\n\t\tlet lastItem = this.state.queryMap[this.state.queryMap.length - 1];\n\t\tlet conjunctionList = helpers.arrayPluck(this.state.queryMap, 'conjunction');\n\n\t\tif (this.state.queryMap.length === 0 || ( ! helpers.regexInArray(conjunctionList, /^ ?WHERE/i)))\n\t\t{\n\t\t\tconj = \" WHERE \";\n\t\t}\n\t\telse if (lastItem.type === 'groupStart')\n\t\t{\n\t\t\tconj = '';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tconj = ' ' + conj + ' ';\n\t\t}\n\n\t\treturn conj;\n\t}\n\n\t_where(key, val, defaultConj) {\n\t\t// Normalize key and value and insert into this.state.whereMap\n\t\tthis._whereMixedSet(key, val);\n\n\t\t// Parse the where condition to account for operators,\n\t\t// functions, identifiers, and literal values\n\t\tthis.state = this.parser.parseWhere(this.driver, this.state);\n\n\t\tthis.state.whereMap.forEach((clause) => {\n\t\t\tlet conj = this._fixConjunction(defaultConj);\n\t\t\tthis._appendMap(conj, clause, 'where');\n\t\t});\n\n\t\tthis.state.whereMap = {};\n\t}\n\n\t_whereNull(field, stmt, conj) {\n\t\tfield = this.driver.quoteIdentifiers(field);\n\t\tlet item = field + ' ' + stmt;\n\n\t\tthis._appendMap(this._fixConjunction(conj), item, 'whereNull');\n\t}\n\n\t_having(/*key, val, conj*/) {\n\t\tlet args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments);\n\t\targs.conj = args.conj || 'AND';\n\t\targs.val = args.val || null;\n\n\t\t// Normalize key/val and put in state.whereMap\n\t\tthis._whereMixedSet(args.key, args.val);\n\n\t\t// Parse the having condition to account for operators,\n\t\t// functions, identifiers, and literal values\n\t\tthis.state = this.parser.parseWhere(this.driver, this.state);\n\n\t\tthis.state.whereMap.forEach((clause) => {\n\t\t\t// Put in the having map\n\t\t\tthis.state.havingMap.push({\n\t\t\t\tconjunction: (this.state.havingMap.length > 0) ? ` ${args.conj} ` : ' HAVING ',\n\t\t\t\tstring: clause\n\t\t\t});\n\t\t});\n\n\t\t// Clear the where Map\n\t\tthis.state.whereMap = {};\n\t}\n\t_whereIn(/*key, val, inClause, conj*/) {\n\t\tlet args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);\n\n\t\targs.key = this.driver.quoteIdentifiers(args.key);\n\t\tlet params = new Array(args.val.length);\n\t\tparams.fill('?');\n\n\t\targs.val.forEach((value) => {\n\t\t\tthis.state.whereValues.push(value);\n\t\t});\n\n\t\targs.conj = (this.state.queryMap.length > 0) ? \" \" + args.conj + \" \" : ' WHERE ';\n\t\tlet str = args.key + \" \" + args.inClause + \" (\" + params.join(',') + \") \";\n\n\t\tthis._appendMap(args.conj, str, 'whereIn');\n\t}\n\n\t_run(type, table, callback, sql, vals) {\n\n\t\tif ( ! sql)\n\t\t{\n\t\t\tsql = this._compile(type, table);\n\t\t}\n\n\t\tif ( ! vals)\n\t\t{\n\t\t\tvals = this.state.values.concat(this.state.whereValues);\n\t\t}\n\n//console.log(this.state);\n//console.log(sql);\n//console.log(vals);\n//console.log(callback);\n//console.log('------------------------');\n\n\t\t// Reset the state so another query can be built\n\t\tthis._resetState();\n\n\t\t// Pass the sql and values to the adapter to run on the database\n\t\tthis.adapter.execute(sql, vals, callback);\n\n\t}\n\n\t_getCompile(type, table, reset) {\n\t\treset = reset || false;\n\n\t\tlet sql = this._compile(type, table);\n\n\t\tif (reset) this._resetState();\n\n\t\treturn sql;\n\t}\n\n\t_resetState() {\n\t\tthis.state = new State();\n\t}\n\n\t// ----------------------------------------------------------------------------\n\t// ! Miscellaneous Methods\n\t// ----------------------------------------------------------------------------\n\n\t/**\n\t * Reset the object state for a new query\n\t *\n\t * @memberOf QueryBuilder\n\t * @return {void}\n\t */\n\tresetQuery() {\n\t\tthis._resetState();\n\t}\n\n\t/**\n\t * Returns the current class state for testing or other purposes\n\t *\n\t * @private\n\t * @return {Object}\n\t */\n\tgetState() {\n\t\treturn this.state;\n\t}\n\n\t/**\n\t * Closes the database connection for the current adapter\n\t *\n\t * @return {void}\n\t */\n\tend() {\n\t\tthis.adapter.close();\n\t}\n\n\t// ------------------------------------------------------------------------\n\t// ! Query Builder Methods\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Specify rows to select in the query\n\t *\n\t * @memberOf QueryBuilder\n\t * @param {String|Array} fields - The fields to select from the current table\n\t * @return {QueryBuilder}\n\t */\n\tselect(fields) {\n\n\t\t// Split/trim fields by comma\n\t\tfields = (Array.isArray(fields))\n\t\t\t? fields\n\t\t\t: fields.split(\",\").map(helpers.stringTrim);\n\n\t\t// Split on 'As'\n\t\tfields.forEach((field, index) => {\n\t\t\tif (field.match(/as/i))\n\t\t\t{\n\t\t\t\tfields[index] = field.split(/ as /i).map(helpers.stringTrim);\n\t\t\t}\n\t\t});\n\n\t\tlet safeArray = this.driver.quoteIdentifiers(fields);\n\n\t\t// Join the strings back together\n\t\tsafeArray.forEach((field, index) => {\n\t\t\tif (Array.isArray(field))\n\t\t\t{\n\t\t\t\tsafeArray[index] = safeArray[index].join(' AS ');\n\t\t\t}\n\t\t});\n\n\t\tthis.state.selectString += safeArray.join(', ');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Specify the database table to select from\n\t *\n\t * @param {String} tableName - The table to use for the current query\n\t * @return {QueryBuilder}\n\t */\n\tfrom(tableName) {\n\t\t// Split identifiers on spaces\n\t\tlet identArray = tableName.trim().split(' ').map(helpers.stringTrim);\n\n\t\t// Quote/prefix identifiers\n\t\tidentArray[0] = this.driver.quoteTable(identArray[0]);\n\t\tidentArray = this.driver.quoteIdentifiers(identArray);\n\n\t\t// Put it back together\n\t\tthis.state.fromString = identArray.join(' ');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a 'like/ and like' clause to the query\n\t *\n\t * @param {String} field - The name of the field to compare to\n\t * @param {String} val - The value to compare to\n\t * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both\n\t * @return {QueryBuilder}\n\t */\n\tlike(field, val, pos) {\n\t\tthis._like(field, val, pos, ' LIKE ', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a 'not like/ and not like' clause to the query\n\t *\n\t * @param {String} field - The name of the field to compare to\n\t * @param {String} val - The value to compare to\n\t * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both\n\t * @return {QueryBuilder}\n\t */\n\tnotLike(field, val, pos) {\n\t\tthis._like(field, val, pos, ' NOT LIKE ', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an 'or like' clause to the query\n\t *\n\t * @param {String} field - The name of the field to compare to\n\t * @param {String} val - The value to compare to\n\t * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both\n\t * @return {QueryBuilder}\n\t */\n\torLike(field, val, pos) {\n\t\tthis._like(field, val, pos, ' LIKE ', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an 'or not like' clause to the query\n\t *\n\t * @param {String} field - The name of the field to compare to\n\t * @param {String} val - The value to compare to\n\t * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both\n\t * @return {QueryBuilder}\n\t */\n\torNotLike(field, val, pos) {\n\t\tthis._like(field, val, pos, ' NOT LIKE ', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a 'having' clause\n\t *\n\t * @param {String|Object} key - The name of the field and the comparision operator, or an object\n\t * @param {String|Number} [val] - The value to compare if the value of key is a string\n\t * @return {QueryBuilder}\n\t */\n\thaving(/*key, [val]*/) {\n\t\tlet args = getArgs('key:string|object, [val]:string|number', arguments);\n\n\t\tthis._having(args.key, args.val, 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add an 'or having' clause\n\t *\n\t * @param {String|Object} key - The name of the field and the comparision operator, or an object\n\t * @param {String|Number} [val] - The value to compare if the value of key is a string\n\t * @return {QueryBuilder}\n\t */\n\torHaving(/*key, [val]*/) {\n\t\tlet args = getArgs('key:string|object, [val]:string|number', arguments);\n\n\t\tthis._having(args.key, args.val, 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'where' clause\n\t *\n\t * @param {String|Object} key - The name of the field and the comparision operator, or an object\n\t * @param {String|Number} [val] - The value to compare if the value of key is a string\n\t * @return {QueryBuilder}\n\t */\n\twhere(key, val) {\n\t\tthis._where(key, val, 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'or where' clause\n\t *\n\t * @param {String|Object} key - The name of the field and the comparision operator, or an object\n\t * @param {String|Number} [val] - The value to compare if the value of key is a string\n\t * @return {QueryBuilder}\n\t */\n\torWhere(key, val) {\n\t\tthis._where(key, val, 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Select a field that is Null\n\t *\n\t * @param {String} field - The name of the field that has a NULL value\n\t * @return {QueryBuilder}\n\t */\n\twhereIsNull(field) {\n\t\tthis._whereNull(field, 'IS NULL', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Specify that a field IS NOT NULL\n\t *\n\t * @param {String} field\n\t * @return {QueryBuilder}\n\t */\n\twhereIsNotNull(field) {\n\t\tthis._whereNull(field, 'IS NOT NULL', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Field is null prefixed with 'OR'\n\t *\n\t * @param {String} field\n\t * @return {QueryBuilder}\n\t */\n\torWhereIsNull(field) {\n\t\tthis._whereNull(field, 'IS NULL', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Field is not null prefixed with 'OR'\n\t *\n\t * @param {String} field\n\t * @return {QueryBuilder}\n\t */\n\torWhereIsNotNull(field) {\n\t\tthis._whereNull(field, 'IS NOT NULL', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'where in' clause\n\t *\n\t * @param {String} key - the field to search\n\t * @param {Array} val - the array of items to search in\n\t * @return {QueryBuilder}\n\t */\n\twhereIn(key, val) {\n\t\tthis._whereIn(key, val, 'IN', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'or where in' clause\n\t *\n\t * @param {String} key - the field to search\n\t * @param {Array} val - the array of items to search in\n\t * @return {QueryBuilder}\n\t */\n\torWhereIn(key, val) {\n\t\tthis._whereIn(key, val, 'IN', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'where not in' clause\n\t *\n\t * @param {String} key - the field to search\n\t * @param {Array} val - the array of items to search in\n\t * @return {QueryBuilder}\n\t */\n\twhereNotIn(key, val) {\n\t\tthis._whereIn(key, val, 'NOT IN', 'AND');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set a 'or where not in' clause\n\t *\n\t * @param {String} key - the field to search\n\t * @param {Array} val - the array of items to search in\n\t * @return {QueryBuilder}\n\t */\n\torWhereNotIn(key, val) {\n\t\tthis._whereIn(key, val, 'NOT IN', 'OR');\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set values for insertion or updating\n\t *\n\t * @param {String|Object} key - The key or object to use\n\t * @param {String} [val] - The value if using a scalar key\n\t * @return {QueryBuilder}\n\t */\n\tset(/* $key, [$val] */) {\n\t\tlet args = getArgs('$key, [$val]', arguments);\n\n\t\t// Set the appropriate state variables\n\t\tthis._mixedSet('setArrayKeys', 'key', args.$key, args.$val);\n\t\tthis._mixedSet('values', 'value', args.$key, args.$val);\n\n\t\t// Use the keys of the array to make the insert/update string\n\t\t// and escape the field names\n\t\tthis.state.setArrayKeys = this.state.setArrayKeys.map(this.driver._quote);\n\n\t\t// Generate the \"set\" string\n\t\tthis.state.setString = this.state.setArrayKeys.join('=?,');\n\t\tthis.state.setString += '=?';\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a join clause to the query\n\t *\n\t * @param {String} table - The table you are joining\n\t * @param {String} cond - The join condition.\n\t * @param {String} [type='inner'] - The type of join, which defaults to inner\n\t * @return {QueryBuilder}\n\t */\n\tjoin(table, cond, type) {\n\t\ttype = type || \"inner\";\n\n\t\t// Prefix/quote table name\n\t\ttable = table.split(' ').map(helpers.stringTrim);\n\t\ttable[0] = this.driver.quoteTable(table[0]);\n\t\ttable = table.map(this.driver.quoteIdentifiers);\n\t\ttable = table.join(' ');\n\n\t\t// Parse out the join condition\n\t\tlet parsedCondition = this.parser.compileJoin(cond);\n\t\tlet condition = table + ' ON ' + parsedCondition;\n\n\t\t// Append the join condition to the query map\n\t\tthis._appendMap(\"\\n\" + type.toUpperCase() + ' JOIN ', condition, 'join');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Group the results by the selected field(s)\n\t *\n\t * @param {String|Array} field\n\t * @return {QueryBuilder}\n\t */\n\tgroupBy(field) {\n\t\tif ( ! helpers.isScalar(field))\n\t\t{\n\t\t\tlet newGroupArray = field.map(this.driver.quoteIdentifiers);\n\t\t\tthis.state.groupArray = this.state.groupArray.concat(newGroupArray);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthis.state.groupArray.push(this.driver.quoteIdentifiers(field));\n\t\t}\n\n\t\tthis.state.groupString = ' GROUP BY ' + this.state.groupArray.join(',');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Order the results by the selected field(s)\n\t *\n\t * @param {String} field - The field(s) to order by\n\t * @param {String} [type='ASC'] - The order direction, ASC or DESC\n\t * @return {QueryBuilder}\n\t */\n\torderBy(field, type) {\n\t\ttype = type || 'ASC';\n\n\t\t// Set the fields for later manipulation\n\t\tfield = this.driver.quoteIdentifiers(field);\n\n\t\tthis.state.orderArray[field] = type;\n\n\t\tlet orderClauses = [];\n\n\t\t// Flatten key/val pairs into an array of space-separated pairs\n\t\tObject.keys(this.state.orderArray).forEach((key) => {\n\t\t\torderClauses.push(key + ' ' + this.state.orderArray[key].toUpperCase());\n\t\t});\n\n\t\t// Set the final string\n\t\tthis.state.orderString = ' ORDER BY ' + orderClauses.join(', ');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Put a limit on the query\n\t *\n\t * @param {Number} limit - The maximum number of rows to fetch\n\t * @param {Number} [offset] - The row number to start from\n\t * @return {QueryBuilder}\n\t */\n\tlimit(limit, offset) {\n\t\tthis.state.limit = limit;\n\t\tthis.state.offset = offset || null;\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds an open paren to the current query for logical grouping\n\t *\n\t * @return {QueryBuilder}\n\t */\n\tgroupStart() {\n\t\tlet conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';\n\t\tthis._appendMap(conj, '(', 'groupStart');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds an open paren to the current query for logical grouping,\n\t * prefixed with 'OR'\n\t *\n\t * @return {QueryBuilder}\n\t */\n\torGroupStart() {\n\t\tthis._appendMap('', ' OR (', 'groupStart');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds an open paren to the current query for logical grouping,\n\t * prefixed with 'OR NOT'\n\t *\n\t * @return {QueryBuilder}\n\t */\n\torNotGroupStart() {\n\t\tthis._appendMap('', ' OR NOT (', 'groupStart');\n\n\t\treturn this;\n\t}\n\n\t/**\n\t * Ends a logical grouping started with one of the groupStart methods\n\t *\n\t * @return {QueryBuilder}\n\t */\n\tgroupEnd() {\n\t\tthis._appendMap('', ')', 'groupEnd');\n\n\t\treturn this;\n\t}\n\n\t// ------------------------------------------------------------------------\n\t// ! Result Methods\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get the results of the compiled query\n\t *\n\t * @param {String} [table] - The table to select from\n\t * @param {Number} [limit] - A limit for the query\n\t * @param {Number} [offset] - An offset for the query\n\t * @param {Function} callback - A callback for receiving the result\n\t * @return {void}\n\t */\n\tget(/* [table], [limit], [offset], callback */) {\n\t\tlet args = getArgs('[table]:string, [limit]:number, [offset]:number, callback:function', arguments);\n\n\t\tif (args.table) {\n\t\t\tthis.from(args.table);\n\t\t}\n\n\t\tif (args.limit) {\n\t\t\tthis.limit(args.limit, args.offset);\n\t\t}\n\n\t\t// Run the query\n\t\tthis._run('get', args.table, args.callback);\n\t}\n\n\t/**\n\t * Run the generated insert query\n\t *\n\t * @param {String} table - The table to insert into\n\t * @param {Object} [data] - Data to insert, if not already added with the 'set' method\n\t * @param {Function} callback - Callback for handling response from the database\n\t * @return {void}\n\t */\n\tinsert(/* table, data, callback */) {\n\t\tlet args = getArgs('table:string, [data]:object, callback:function', arguments);\n\n\t\tif (args.data) {\n\t\t\tthis.set(args.data);\n\t\t}\n\n\t\t// Run the query\n\t\tthis._run('insert', this.driver.quoteTable(args.table), args.callback);\n\t}\n\n\t/**\n\t * Insert multiple sets of rows at a time\n\t *\n\t * @param {String} table - The table to insert into\n\t * @param {Array} data - The array of objects containing data rows to insert\n\t * @param {Function} callback - Callback for handling database response\n\t * @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);\n\t * @return {void}\n\t */\n\tinsertBatch(/* table, data, callback */) {\n\t\tlet args = getArgs('table:string, data:array, callback:function', arguments);\n\t\tlet batch = this.driver.insertBatch(args.table, args.data);\n\n\t\t// Run the query\n\t\tthis._run('', '', args.callback, batch.sql, batch.values);\n\t}\n\n\t/**\n\t * Run the generated update query\n\t *\n\t * @param {String} table - The table to insert into\n\t * @param {Object} [data] - Data to insert, if not already added with the 'set' method\n\t * @param {Function} callback - Callback for handling response from the database\n\t * @return {void}\n\t */\n\tupdate(/*table, data, callback*/) {\n\t\tlet args = getArgs('table:string, [data]:object, callback:function', arguments);\n\n\t\tif (args.data) {\n\t\t\tthis.set(args.data);\n\t\t}\n\n\t\t// Run the query\n\t\tthis._run('update', this.driver.quoteTable(args.table), args.callback);\n\t}\n\n\t/**\n\t * Run the generated delete query\n\t *\n\t * @param {String} table - The table to insert into\n\t * @param {Object} [where] - Where clause for delete statement\n\t * @param {Function} callback - Callback for handling response from the database\n\t * @return {void}\n\t */\n\tdelete(/*table, [where], callback*/) {\n\t\tlet args = getArgs('table:string, [where]:object, callback:function', arguments);\n\n\t\tif (args.where)\n\t\t{\n\t\t\tthis.where(args.where);\n\t\t}\n\n\t\t// Run the query\n\t\tthis._run('delete', this.driver.quoteTable(args.table), args.callback);\n\t}\n\n\t// ------------------------------------------------------------------------\n\t// ! Methods returning SQL\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Return generated select query SQL\n\t *\n\t * @param {String} [table] - the name of the table to retrieve from\n\t * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built\n\t * @return {String}\n\t */\n\tgetCompiledSelect(/*table, reset*/) {\n\t\tlet args = getArgs('[table]:string, [reset]:boolean', arguments);\n\t\tif (args.table)\n\t\t{\n\t\t\tthis.from(args.table);\n\t\t}\n\n\t\treturn this._getCompile('get', args.table, args.reset);\n\t}\n\n\t/**\n\t * Return generated insert query SQL\n\t *\n\t * @param {String} table - the name of the table to insert into\n\t * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built\n\t * @return {String}\n\t */\n\tgetCompiledInsert(table, reset) {\n\t\treturn this._getCompile('insert', this.driver.quoteTable(table), reset);\n\t}\n\n\t/**\n\t * Return generated update query SQL\n\t *\n\t * @param {String} table - the name of the table to update\n\t * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built\n\t * @return {String}\n\t */\n\tgetCompiledUpdate(table, reset) {\n\t\treturn this._getCompile('update', this.driver.quoteTable(table), reset);\n\t}\n\n\t/**\n\t * Return generated delete query SQL\n\t *\n\t * @param {String} table - the name of the table to delete from\n\t * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built\n\t * @return {String}\n\t */\n\tgetCompiledDelete(table, reset) {\n\t\treturn this._getCompile('delete', this.driver.quoteTable(table), reset);\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/QueryParser.js b/lib/QueryParser.js
new file mode 100644
index 0000000..13bd592
--- /dev/null
+++ b/lib/QueryParser.js
@@ -0,0 +1,278 @@
+'use strict';
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _helpers = require('./helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+// --------------------------------------------------------------------------
+
+/**
+ * @constructor
+ * @param {Driver} - The driver object for the database in use
+ * @module query-parser
+ */
+module.exports = (function () {
+ /**
+ * @constructor
+ * @param {Driver} - The driver object for the database in use
+ * @return {void}
+ */
+
+ function QueryParser(driver) {
+ _classCallCheck(this, QueryParser);
+
+ this.driver = driver;
+
+ var matchPatterns = {
+ 'function': /([a-z0-9_]+\((.*)\))/i,
+ operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
+ literal: /([0-9]+)|'(.*?)'|true|false/ig
+ };
+
+ // Full pattern for identifiers
+ // Making sure that literals and functions aren't matched
+ matchPatterns.identifier = new RegExp('(' + '(?!' + matchPatterns['function'].source + '|' + matchPatterns.literal.source + ')' + '([a-z_\-]+[0-9]*\\.?)' + ')+', 'ig');
+
+ // Full pattern for determining ordering of the pieces
+ matchPatterns.joinCombined = new RegExp(matchPatterns['function'].source + "+|" + matchPatterns.literal.source + '+|' + matchPatterns.identifier.source + '|(' + matchPatterns.operator.source + ')+', 'ig');
+
+ this.matchPatterns = matchPatterns;
+ this.identifierBlacklist = ['true', 'false', 'null'];
+ }
+
+ /**
+ * Filter matched patterns
+ *
+ * @param {Array} array
+ * @return {Array|null}
+ */
+
+ _createClass(QueryParser, [{
+ key: 'filterMatches',
+ value: function filterMatches(array) {
+ var output = [];
+
+ // Return non-array matches
+ if (_helpers2.default.isNull(array)) return null;
+ if (_helpers2.default.isScalar(array) || _helpers2.default.isUndefined(array)) return output;
+
+ array.forEach(function (item) {
+ output.push(item);
+ });
+ return output;
+ }
+
+ /**
+ * Check if the string contains an operator, and if so, return the operator(s).
+ * If there are no matches, return null
+ *
+ * @param {String} string - the string to check
+ * @return {Array|null}
+ */
+
+ }, {
+ key: 'hasOperator',
+ value: function hasOperator(string) {
+ return this.filterMatches(string.match(this.matchPatterns.operator));
+ }
+
+ /**
+ * Tokenize the sql into parts for additional processing
+ *
+ * @param {String} sql
+ * @return {Object}
+ */
+
+ }, {
+ key: 'parseJoin',
+ value: function parseJoin(sql) {
+ var _this = this;
+
+ var matches = {};
+ var output = {
+ functions: [],
+ identifiers: [],
+ operators: [],
+ literals: []
+ };
+
+ // Get clause components
+ matches.functions = sql.match(new RegExp(this.matchPatterns['function'].source, 'ig'));
+ matches.identifiers = sql.match(this.matchPatterns.identifier);
+ matches.operators = sql.match(this.matchPatterns.operator);
+ matches.literals = sql.match(this.matchPatterns.literal);
+
+ // Get everything at once for ordering
+ matches.combined = sql.match(this.matchPatterns.joinCombined);
+
+ // Flatten the matches to increase relevance
+ Object.keys(matches).forEach(function (key) {
+ output[key] = _this.filterMatches(matches[key]);
+ });
+
+ return output;
+ }
+
+ /**
+ * Return the output of the parsing of the join condition
+ *
+ * @param {String} condition - The join condition to evalate
+ * @return {String} - The parsed/escaped join condition
+ */
+
+ }, {
+ key: 'compileJoin',
+ value: function compileJoin(condition) {
+ var _this2 = this;
+
+ var parts = this.parseJoin(condition);
+ var count = parts.identifiers.length;
+ var i = undefined;
+
+ // Quote the identifiers
+ parts.combined.forEach(function (part, i) {
+ if (parts.identifiers.indexOf(part) !== -1 && !_helpers2.default.isNumber(part)) {
+ parts.combined[i] = _this2.driver.quoteIdentifiers(part);
+ }
+ });
+
+ return parts.combined.join(' ');
+ }
+
+ /**
+ * Parse a where clause to separate functions from values
+ *
+ * @param {Driver} driver
+ * @param {State} state
+ * @return {String} - The parsed/escaped where condition
+ */
+
+ }, {
+ key: 'parseWhere',
+ value: function parseWhere(driver, state) {
+ var _this3 = this;
+
+ var whereMap = state.whereMap;
+ var whereValues = state.rawWhereValues;
+
+ var outputMap = [];
+ var outputValues = [];
+
+ Object.keys(whereMap).forEach(function (key) {
+ // Combine fields, operators, functions and values into a full clause
+ // to have a common starting flow
+ var fullClause = '';
+
+ // Add an explicit = sign where one is inferred
+ if (!_this3.hasOperator(key)) {
+ fullClause = key + ' = ' + whereMap[key];
+ } else if (whereMap[key] === key) {
+ fullClause = key;
+ } else {
+ fullClause = key + ' ' + whereMap[key];
+ }
+
+ // Separate the clause into separate pieces
+ var parts = _this3.parseJoin(fullClause);
+
+ // Filter explicit literals from lists of matches
+ if (whereValues.indexOf(whereMap[key]) !== -1) {
+ var value = whereMap[key];
+ var identIndex = _helpers2.default.isArray(parts.identifiers) ? parts.identifiers.indexOf(value) : -1;
+ var litIndex = _helpers2.default.isArray(parts.literals) ? parts.literals.indexOf(value) : -1;
+ var combIndex = _helpers2.default.isArray(parts.combined) ? parts.combined.indexOf(value) : -1;
+ var funcIndex = _helpers2.default.isArray(parts.functions) ? parts.functions.indexOf(value) : -1;
+ var inOutputArray = outputValues.indexOf(value) !== -1;
+
+ // Remove the identifier in question,
+ // and add to the output values array
+ if (identIndex !== -1) {
+ parts.identifiers.splice(identIndex, 1);
+
+ if (!inOutputArray) {
+ outputValues.push(value);
+ inOutputArray = true;
+ }
+ }
+
+ // Remove the value from the literals list
+ // so it is not added twice
+ if (litIndex !== -1) {
+ parts.literals.splice(litIndex, 1);
+
+ if (!inOutputArray) {
+ outputValues.push(value);
+ inOutputArray = true;
+ }
+ }
+
+ // Remove the value from the combined list
+ // and replace it with a placeholder
+ if (combIndex !== -1) {
+ // Make sure to skip functions when replacing values
+ if (funcIndex === -1) {
+ parts.combined[combIndex] = '?';
+
+ if (!inOutputArray) {
+ outputValues.push(value);
+ inOutputArray = true;
+ }
+ }
+ }
+ }
+
+ // Filter false positive identifiers
+ parts.identifiers = parts.identifiers || [];
+ parts.identifiers = parts.identifiers.filter(function (item) {
+ var isInCombinedMatches = parts.combined.indexOf(item) !== -1;
+ var isNotInBlackList = _this3.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
+
+ return isInCombinedMatches && isNotInBlackList;
+ }, _this3);
+
+ // Quote identifiers
+ if (_helpers2.default.isArray(parts.identifiers)) {
+ parts.identifiers.forEach(function (ident) {
+ var index = parts.combined.indexOf(ident);
+ if (index !== -1) {
+ parts.combined[index] = driver.quoteIdentifiers(ident);
+ }
+ });
+ }
+
+ // Replace each literal with a placeholder in the map
+ // and add the literal to the values,
+ // This should only apply to literal values that are not
+ // explicitly mapped to values, but have to be parsed from
+ // a where condition,
+ if (_helpers2.default.isArray(parts.literals)) {
+ parts.literals.forEach(function (lit) {
+ var litIndex = parts.combined.indexOf(lit);
+
+ if (litIndex !== -1) {
+ parts.combined[litIndex] = _helpers2.default.isArray(parts.operators) ? '?' : '= ?';
+ outputValues.push(lit);
+ }
+ });
+ }
+
+ outputMap.push(parts.combined.join(' '));
+ });
+
+ state.rawWhereValues = [];
+ state.whereValues = state.whereValues.concat(outputValues);
+ state.whereMap = outputMap;
+
+ return state;
+ }
+ }]);
+
+ return QueryParser;
+})();
+//# sourceMappingURL=QueryParser.js.map
diff --git a/lib/QueryParser.js.map b/lib/QueryParser.js.map
new file mode 100644
index 0000000..5a11709
--- /dev/null
+++ b/lib/QueryParser.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["QueryParser.js"],"names":[],"mappings":"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","file":"QueryParser.js","sourcesContent":["'use strict';\n\nimport helpers from './helpers';\n\n\n// --------------------------------------------------------------------------\n\n/**\n * @constructor\n * @param {Driver} - The driver object for the database in use\n * @module query-parser\n */\nmodule.exports = class QueryParser {\n\t/**\n\t * @constructor\n\t * @param {Driver} - The driver object for the database in use\n\t * @return {void}\n\t */\n\tconstructor(driver) {\n\t\tthis.driver = driver;\n\n\t\tlet matchPatterns = {\n\t\t\t'function': /([a-z0-9_]+\\((.*)\\))/i,\n\t\t\toperator: /\\!=?|\\=|\\+|&&?|~|\\|\\|?|\\^|\\/|<>|>=?|<=?|\\-|%|OR|AND|NOT|XOR/ig,\n\t\t\tliteral: /([0-9]+)|'(.*?)'|true|false/ig\n\t\t};\n\n\t\t// Full pattern for identifiers\n\t\t// Making sure that literals and functions aren't matched\n\t\tmatchPatterns.identifier = new RegExp(\n\t\t\t'('\n\t\t\t\t+ '(?!'\n\t\t\t\t\t+ matchPatterns['function'].source + '|'\n\t\t\t\t\t+ matchPatterns.literal.source\n\t\t\t\t+ ')'\n\t\t\t\t+ '([a-z_\\-]+[0-9]*\\\\.?)'\n\t\t\t+ ')+'\n\t\t, 'ig');\n\n\t\t// Full pattern for determining ordering of the pieces\n\t\tmatchPatterns.joinCombined = new RegExp(\n\t\t\tmatchPatterns['function'].source + \"+|\"\n\t\t\t+ matchPatterns.literal.source + '+|'\n\t\t\t+ matchPatterns.identifier.source\n\t\t\t+ '|(' + matchPatterns.operator.source + ')+'\n\t\t, 'ig');\n\n\t\tthis.matchPatterns = matchPatterns;\n\t\tthis.identifierBlacklist = ['true','false','null'];\n\t}\n\n\t/**\n\t * Filter matched patterns\n\t *\n\t * @param {Array} array\n\t * @return {Array|null}\n\t */\n\tfilterMatches(array) {\n\t\tlet output = [];\n\n\t\t// Return non-array matches\n\t\tif (helpers.isNull(array)) return null;\n\t\tif (helpers.isScalar(array) || helpers.isUndefined(array)) return output;\n\n\t\tarray.forEach((item) => {\n\t\t\toutput.push(item);\n\t\t});\n\t\treturn output;\n\t}\n\n\t/**\n\t * Check if the string contains an operator, and if so, return the operator(s).\n\t * If there are no matches, return null\n\t *\n\t * @param {String} string - the string to check\n\t * @return {Array|null}\n\t */\n\thasOperator(string) {\n\t\treturn this.filterMatches(string.match(this.matchPatterns.operator));\n\t}\n\n\t/**\n\t * Tokenize the sql into parts for additional processing\n\t *\n\t * @param {String} sql\n\t * @return {Object}\n\t */\n\tparseJoin(sql) {\n\t\tlet matches = {};\n\t\tlet output = {\n\t\t\tfunctions: [],\n\t\t\tidentifiers: [],\n\t\t\toperators: [],\n\t\t\tliterals: []\n\t\t};\n\n\t\t// Get clause components\n\t\tmatches.functions = sql.match(new RegExp(this.matchPatterns['function'].source, 'ig'));\n\t\tmatches.identifiers = sql.match(this.matchPatterns.identifier);\n\t\tmatches.operators = sql.match(this.matchPatterns.operator);\n\t\tmatches.literals = sql.match(this.matchPatterns.literal);\n\n\t\t// Get everything at once for ordering\n\t\tmatches.combined = sql.match(this.matchPatterns.joinCombined);\n\n\t\t// Flatten the matches to increase relevance\n\t\tObject.keys(matches).forEach((key) => {\n\t\t\toutput[key] = this.filterMatches(matches[key]);\n\t\t});\n\n\t\treturn output;\n\t}\n\n\t/**\n\t * Return the output of the parsing of the join condition\n\t *\n\t * @param {String} condition - The join condition to evalate\n\t * @return {String} - The parsed/escaped join condition\n\t */\n\tcompileJoin(condition) {\n\t\tlet parts = this.parseJoin(condition);\n\t\tlet count = parts.identifiers.length;\n\t\tlet i;\n\n\t\t// Quote the identifiers\n\t\tparts.combined.forEach((part, i) => {\n\t\t\tif (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part))\n\t\t\t{\n\t\t\t\tparts.combined[i] = this.driver.quoteIdentifiers(part);\n\t\t\t}\n\t\t});\n\n\t\treturn parts.combined.join(' ');\n\t}\n\n\t/**\n\t * Parse a where clause to separate functions from values\n\t *\n\t * @param {Driver} driver\n\t * @param {State} state\n\t * @return {String} - The parsed/escaped where condition\n\t */\n\tparseWhere(driver, state) {\n\t\tlet whereMap = state.whereMap;\n\t\tlet\twhereValues = state.rawWhereValues;\n\n\t\tlet outputMap = [];\n\t\tlet outputValues = [];\n\n\t\tObject.keys(whereMap).forEach((key) => {\n\t\t\t// Combine fields, operators, functions and values into a full clause\n\t\t\t// to have a common starting flow\n\t\t\tlet fullClause = '';\n\n\t\t\t// Add an explicit = sign where one is inferred\n\t\t\tif ( ! this.hasOperator(key))\n\t\t\t{\n\t\t\t\tfullClause = key + ' = ' + whereMap[key];\n\t\t\t}\n\t\t\telse if (whereMap[key] === key)\n\t\t\t{\n\t\t\t\tfullClause = key;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfullClause = key + ' ' + whereMap[key];\n\t\t\t}\n\n\t\t\t// Separate the clause into separate pieces\n\t\t\tlet parts = this.parseJoin(fullClause);\n\n\t\t\t// Filter explicit literals from lists of matches\n\t\t\tif (whereValues.indexOf(whereMap[key]) !== -1)\n\t\t\t{\n\t\t\t\tlet value = whereMap[key];\n\t\t\t\tlet identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;\n\t\t\t\tlet litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;\n\t\t\t\tlet combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;\n\t\t\t\tlet funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;\n\t\t\t\tlet inOutputArray = outputValues.indexOf(value) !== -1;\n\n\t\t\t\t// Remove the identifier in question,\n\t\t\t\t// and add to the output values array\n\t\t\t\tif (identIndex !== -1)\n\t\t\t\t{\n\t\t\t\t\tparts.identifiers.splice(identIndex, 1);\n\n\t\t\t\t\tif ( ! inOutputArray)\n\t\t\t\t\t{\n\t\t\t\t\t\toutputValues.push(value);\n\t\t\t\t\t\tinOutputArray = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove the value from the literals list\n\t\t\t\t// so it is not added twice\n\t\t\t\tif (litIndex !== -1)\n\t\t\t\t{\n\t\t\t\t\tparts.literals.splice(litIndex, 1);\n\n\t\t\t\t\tif ( ! inOutputArray)\n\t\t\t\t\t{\n\t\t\t\t\t\toutputValues.push(value);\n\t\t\t\t\t\tinOutputArray = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Remove the value from the combined list\n\t\t\t\t// and replace it with a placeholder\n\t\t\t\tif (combIndex !== -1)\n\t\t\t\t{\n\t\t\t\t\t// Make sure to skip functions when replacing values\n\t\t\t\t\tif (funcIndex === -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tparts.combined[combIndex] = '?';\n\n\t\t\t\t\t\tif ( ! inOutputArray)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toutputValues.push(value);\n\t\t\t\t\t\t\tinOutputArray = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Filter false positive identifiers\n\t\t\tparts.identifiers = parts.identifiers || [];\n\t\t\tparts.identifiers = parts.identifiers.filter((item) => {\n\t\t\t\tlet isInCombinedMatches = parts.combined.indexOf(item) !== -1;\n\t\t\t\tlet isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;\n\n\t\t\t\treturn isInCombinedMatches && isNotInBlackList;\n\t\t\t}, this);\n\n\t\t\t// Quote identifiers\n\t\t\tif (helpers.isArray(parts.identifiers))\n\t\t\t{\n\t\t\t\tparts.identifiers.forEach((ident) => {\n\t\t\t\t\tlet index = parts.combined.indexOf(ident);\n\t\t\t\t\tif (index !== -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tparts.combined[index] = driver.quoteIdentifiers(ident);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Replace each literal with a placeholder in the map\n\t\t\t// and add the literal to the values,\n\t\t\t// This should only apply to literal values that are not\n\t\t\t// explicitly mapped to values, but have to be parsed from\n\t\t\t// a where condition,\n\t\t\tif (helpers.isArray(parts.literals))\n\t\t\t{\n\t\t\t\tparts.literals.forEach((lit) => {\n\t\t\t\t\tlet litIndex = parts.combined.indexOf(lit);\n\n\t\t\t\t\tif (litIndex !== -1)\n\t\t\t\t\t{\n\t\t\t\t\t\tparts.combined[litIndex] = (helpers.isArray(parts.operators)) ? '?' : '= ?';\n\t\t\t\t\t\toutputValues.push(lit);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\toutputMap.push(parts.combined.join(' '));\n\t\t});\n\n\t\tstate.rawWhereValues = [];\n\t\tstate.whereValues = state.whereValues.concat(outputValues);\n\t\tstate.whereMap = outputMap;\n\n\t\treturn state;\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/State.js b/lib/State.js
new file mode 100644
index 0000000..f290f7d
--- /dev/null
+++ b/lib/State.js
@@ -0,0 +1,34 @@
+'use strict'
+
+/** @module State */
+;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+module.exports = function State() {
+ _classCallCheck(this, State);
+
+ // Arrays/maps
+ this.queryMap = [];
+ this.values = [];
+ this.whereValues = [];
+ this.setArrayKeys = [];
+ this.orderArray = [];
+ this.groupArray = [];
+ this.havingMap = [];
+ this.whereMap = [];
+ this.rawWhereValues = [];
+
+ // Partials
+ this.selectString = '';
+ this.fromString = '';
+ this.setString = '';
+ this.orderString = '';
+ this.groupString = '';
+
+ // Other various values
+ this.limit = null;
+ this.offset = null;
+};
+// End of module State
+//# sourceMappingURL=State.js.map
diff --git a/lib/State.js.map b/lib/State.js.map
new file mode 100644
index 0000000..25d0f9b
--- /dev/null
+++ b/lib/State.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["State.js"],"names":[],"mappings":"AAAA;;;AAAY,CAAC;;;;AAGb,MAAM,CAAC,OAAO,GACb,SADsB,KAAK,GACb;uBADQ,KAAK;;;AAG1B,KAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;AACnB,KAAI,CAAC,MAAM,GAAG,EAAE,CAAC;AACjB,KAAI,CAAC,WAAW,GAAG,EAAE,CAAC;AACtB,KAAI,CAAC,YAAY,GAAG,EAAE,CAAC;AACvB,KAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACrB,KAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACrB,KAAI,CAAC,SAAS,GAAG,EAAE,CAAC;AACpB,KAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;AACnB,KAAI,CAAC,cAAc,GAAG,EAAE;;;AAAC,AAGzB,KAAI,CAAC,YAAY,GAAG,EAAE,CAAC;AACvB,KAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AACrB,KAAI,CAAC,SAAS,GAAG,EAAE,CAAC;AACpB,KAAI,CAAC,WAAW,GAAG,EAAE,CAAC;AACtB,KAAI,CAAC,WAAW,GAAG,EAAE;;;AAAC,AAGtB,KAAI,CAAC,KAAK,GAAG,IAAI,CAAC;AAClB,KAAI,CAAC,MAAM,GAAG,IAAI,CAAC;CACnB,AACD;;AAAA","file":"State.js","sourcesContent":["'use strict';\n\n/** @module State */\nmodule.exports = class State {\n\tconstructor() {\n\t\t// Arrays/maps\n\t\tthis.queryMap = [];\n\t\tthis.values = [];\n\t\tthis.whereValues = [];\n\t\tthis.setArrayKeys = [];\n\t\tthis.orderArray = [];\n\t\tthis.groupArray = [];\n\t\tthis.havingMap = [];\n\t\tthis.whereMap = [];\n\t\tthis.rawWhereValues = [];\n\n\t\t// Partials\n\t\tthis.selectString = '';\n\t\tthis.fromString = '';\n\t\tthis.setString = '';\n\t\tthis.orderString = '';\n\t\tthis.groupString = '';\n\n\t\t// Other various values\n\t\tthis.limit = null;\n\t\tthis.offset = null;\n\t}\n}\n// End of module State"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/adapters/dblite.js b/lib/adapters/dblite.js
index 5a77f23..3640241 100644
--- a/lib/adapters/dblite.js
+++ b/lib/adapters/dblite.js
@@ -1,29 +1,50 @@
'use strict';
-var adapter = require('../adapter'),
- getArgs = require('getargs');
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _Adapter2 = require('../Adapter');
+
+var _Adapter3 = _interopRequireDefault(_Adapter2);
+
+var _getargs = require('getargs');
+
+var _getargs2 = _interopRequireDefault(_getargs);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/** @module adapters/dblite */
-var Dblite = function(instance) {
+module.exports = (function (_Adapter) {
+ _inherits(dblite, _Adapter);
- // That 'new' keyword is annoying
- if ( ! (this instanceof Dblite)) return new Dblite(instance);
+ function dblite() {
+ _classCallCheck(this, dblite);
- /**
- * Run the sql query as a prepared statement
- *
- * @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
- */
- adapter.execute = function(/*sql, params, callback*/) {
- var args = getArgs('sql:string, [params]:array, callback:function', arguments);
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(dblite).apply(this, arguments));
+ }
- instance.query(args.sql, args.params, args.callback);
- };
+ _createClass(dblite, [{
+ key: 'execute',
- return adapter;
-}
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ value: function execute() /*sql, params, callback*/{
+ var args = (0, _getargs2.default)('sql:string, [params]:array, callback:function', arguments);
+ this.instance.query(args.sql, args.params, args.callback);
+ }
+ }]);
-module.exports = Dblite;
\ No newline at end of file
+ return dblite;
+})(_Adapter3.default);
+//# sourceMappingURL=dblite.js.map
diff --git a/lib/adapters/dblite.js.map b/lib/adapters/dblite.js.map
new file mode 100644
index 0000000..9579bdd
--- /dev/null
+++ b/lib/adapters/dblite.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["dblite.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;AAMb,MAAM,CAAC,OAAO;WAAS,MAAM;;UAAN,MAAM;wBAAN,MAAM;;gEAAN,MAAM;;;cAAN,MAAM;;;;;;;;;;;qDASO;AAClC,OAAI,IAAI,GAAG,uBAAQ,+CAA+C,EAAE,SAAS,CAAC,CAAC;AAC/E,OAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;GAC1D;;;QAZqB,MAAM;qBAa5B,CAAA","file":"adapters/dblite.js","sourcesContent":["'use strict';\n\nimport Adapter from '../Adapter';\nimport getArgs from 'getargs';\n\n/** @module adapters/dblite */\nmodule.exports = class dblite extends Adapter {\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return void\n\t */\n\texecute(/*sql, params, callback*/) {\n\t\tlet args = getArgs('sql:string, [params]:array, callback:function', arguments);\n\t\tthis.instance.query(args.sql, args.params, args.callback);\n\t};\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/adapters/mysql.js b/lib/adapters/mysql.js
index 55135a6..9e934ab 100644
--- a/lib/adapters/mysql.js
+++ b/lib/adapters/mysql.js
@@ -1,27 +1,45 @@
'use strict';
-var adapter = require('../adapter.js');
-var conn;
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _Adapter2 = require('../Adapter');
+
+var _Adapter3 = _interopRequireDefault(_Adapter2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/** @module adapters/mysql */
-var MySQL = function(instance) {
+module.exports = (function (_Adapter) {
+ _inherits(mysql, _Adapter);
- // That 'new' keyword is annoying
- if ( ! (this instanceof MySQL)) return new MySQL(instance);
+ function mysql() {
+ _classCallCheck(this, mysql);
- /**
- * Run the sql query as a prepared statement
- *
- * @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
- */
- adapter.execute = function(sql, params, callback) {
- instance.query.apply(instance, arguments);
- };
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql).apply(this, arguments));
+ }
- return adapter;
-};
+ _createClass(mysql, [{
+ key: 'execute',
-module.exports = MySQL;
\ No newline at end of file
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ value: function execute(sql, params, callback) {
+ this.instance.query.apply(instance, arguments);
+ }
+ }]);
+
+ return mysql;
+})(_Adapter3.default);
+//# sourceMappingURL=mysql.js.map
diff --git a/lib/adapters/mysql.js.map b/lib/adapters/mysql.js.map
new file mode 100644
index 0000000..4d83827
--- /dev/null
+++ b/lib/adapters/mysql.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["mysql.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;AAKb,MAAM,CAAC,OAAO;WAAS,KAAK;;UAAL,KAAK;wBAAL,KAAK;;gEAAL,KAAK;;;cAAL,KAAK;;;;;;;;;;;0BASnB,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE;AAC9B,OAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;GAC/C;;;QAXqB,KAAK;qBAY3B,CAAA","file":"adapters/mysql.js","sourcesContent":["'use strict';\n\nimport Adapter from '../Adapter';\n\n/** @module adapters/mysql */\nmodule.exports = class mysql extends Adapter {\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return void\n\t */\n\texecute(sql, params, callback) {\n\t\tthis.instance.query.apply(instance, arguments);\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/adapters/mysql2.js b/lib/adapters/mysql2.js
index 051c310..ed73744 100644
--- a/lib/adapters/mysql2.js
+++ b/lib/adapters/mysql2.js
@@ -1,26 +1,45 @@
'use strict';
-var adapter = require('../adapter.js');
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _Adapter2 = require('../Adapter');
+
+var _Adapter3 = _interopRequireDefault(_Adapter2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/** @module adapters/mysql2 */
-var MySQL2 = function(instance) {
+module.exports = (function (_Adapter) {
+ _inherits(mysql2, _Adapter);
- // That 'new' keyword is annoying
- if ( ! (this instanceof MySQL2)) return new MySQL2(instance);
+ function mysql2() {
+ _classCallCheck(this, mysql2);
- /**
- * Run the sql query as a prepared statement
- *
- * @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
- */
- adapter.execute = function(sql, params, callback) {
- instance.execute.apply(instance, arguments);
- };
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql2).apply(this, arguments));
+ }
- return adapter;
-}
+ _createClass(mysql2, [{
+ key: 'execute',
-module.exports = MySQL2;
\ No newline at end of file
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ value: function execute(sql, params, callback) {
+ this.instance.execute.apply(this.instance, arguments);
+ }
+ }]);
+
+ return mysql2;
+})(_Adapter3.default);
+//# sourceMappingURL=mysql2.js.map
diff --git a/lib/adapters/mysql2.js.map b/lib/adapters/mysql2.js.map
new file mode 100644
index 0000000..7be47b9
--- /dev/null
+++ b/lib/adapters/mysql2.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["mysql2.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;AAKb,MAAM,CAAC,OAAO;WAAS,MAAM;;UAAN,MAAM;wBAAN,MAAM;;gEAAN,MAAM;;;cAAN,MAAM;;;;;;;;;;;0BASpB,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE;AAC9B,OAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;GACtD;;;QAXqB,MAAM;qBAY5B,CAAA","file":"adapters/mysql2.js","sourcesContent":["'use strict';\n\nimport Adapter from '../Adapter';\n\n/** @module adapters/mysql2 */\nmodule.exports = class mysql2 extends Adapter {\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return void\n\t */\n\texecute(sql, params, callback) {\n\t\tthis.instance.execute.apply(this.instance, arguments);\n\t};\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/adapters/node-firebird.js b/lib/adapters/node-firebird.js
index bd02b38..a8a2ff5 100644
--- a/lib/adapters/node-firebird.js
+++ b/lib/adapters/node-firebird.js
@@ -1,29 +1,50 @@
'use strict';
-var adapter = require('../adapter'),
- getArgs = require('getargs');
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _Adapter2 = require('../Adapter');
+
+var _Adapter3 = _interopRequireDefault(_Adapter2);
+
+var _getargs = require('getargs');
+
+var _getargs2 = _interopRequireDefault(_getargs);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/** @module adapters/node-firebird */
-var NodeFirebird = function(instance) {
+module.exports = (function (_Adapter) {
+ _inherits(nodefirebird, _Adapter);
- // That 'new' keyword is annoying
- if ( ! (this instanceof NodeFirebird)) return new NodeFirebird(instance);
+ function nodefirebird() {
+ _classCallCheck(this, nodefirebird);
- /**
- * Run the sql query as a prepared statement
- *
- * @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
- */
- adapter.execute = function(sql, params, callback) {
- var args = getArgs('sql:string, [params], callback:function', arguments);
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(nodefirebird).apply(this, arguments));
+ }
- instance.execute(args.sql, args.params, args.callback);
- };
+ _createClass(nodefirebird, [{
+ key: 'execute',
- return adapter;
-}
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ value: function execute() /*sql, params, callback*/{
+ var args = (0, _getargs2.default)('sql:string, [params], callback:function', arguments);
+ this.instance.execute(args.sql, args.params, args.callback);
+ }
+ }]);
-module.exports = NodeFirebird;
\ No newline at end of file
+ return nodefirebird;
+})(_Adapter3.default);
+//# sourceMappingURL=node-firebird.js.map
diff --git a/lib/adapters/node-firebird.js.map b/lib/adapters/node-firebird.js.map
new file mode 100644
index 0000000..b29163d
--- /dev/null
+++ b/lib/adapters/node-firebird.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["node-firebird.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;AAMb,MAAM,CAAC,OAAO;WAAS,YAAY;;UAAZ,YAAY;wBAAZ,YAAY;;gEAAZ,YAAY;;;cAAZ,YAAY;;;;;;;;;;;qDASC;AAClC,OAAI,IAAI,GAAG,uBAAQ,yCAAyC,EAAE,SAAS,CAAC,CAAC;AACzE,OAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;GAC5D;;;QAZqB,YAAY;qBAalC,CAAA","file":"adapters/node-firebird.js","sourcesContent":["'use strict';\n\nimport Adapter from '../Adapter';\nimport getArgs from 'getargs';\n\n/** @module adapters/node-firebird */\nmodule.exports = class nodefirebird extends Adapter {\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return void\n\t */\n\texecute(/*sql, params, callback*/) {\n\t\tlet args = getArgs('sql:string, [params], callback:function', arguments);\n\t\tthis.instance.execute(args.sql, args.params, args.callback);\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/adapters/pg.js b/lib/adapters/pg.js
index 0d4d164..05a211e 100644
--- a/lib/adapters/pg.js
+++ b/lib/adapters/pg.js
@@ -1,36 +1,58 @@
'use strict';
-var adapter = require('../adapter'),
- getArgs = require('getargs');
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _Adapter2 = require('../Adapter');
+
+var _Adapter3 = _interopRequireDefault(_Adapter2);
+
+var _getargs = require('getargs');
+
+var _getargs2 = _interopRequireDefault(_getargs);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/** @module adapters/pg */
-var Pg = function(instance) {
+module.exports = (function (_Adapter) {
+ _inherits(pg, _Adapter);
- // That 'new' keyword is annoying
- if ( ! (this instanceof Pg)) return new Pg(instance);
+ function pg() {
+ _classCallCheck(this, pg);
- /**
- * Run the sql query as a prepared statement
- *
- * @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
- */
- adapter.execute = function(/*sql, params, callback*/) {
- var args = getArgs('sql:string, [params]:array, callback:function', arguments);
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(pg).apply(this, arguments));
+ }
- // Replace question marks with numbered placeholders, because this adapter is different...
- var count = 0;
- args.sql = args.sql.replace(/\?/g, function() {
- count++;
- return '$' + count;
- });
+ _createClass(pg, [{
+ key: 'execute',
- instance.query(args.sql, args.params, args.callback);
- };
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ value: function execute() /*sql, params, callback*/{
+ var args = (0, _getargs2.default)('sql:string, [params]:array, callback:function', arguments);
- return adapter;
-}
+ // Replace question marks with numbered placeholders, because this adapter is different...
+ var count = 0;
+ args.sql = args.sql.replace(/\?/g, function () {
+ count++;
+ return '$' + count;
+ });
-module.exports = Pg;
\ No newline at end of file
+ this.instance.query(args.sql, args.params, args.callback);
+ }
+ }]);
+
+ return pg;
+})(_Adapter3.default);
+//# sourceMappingURL=pg.js.map
diff --git a/lib/adapters/pg.js.map b/lib/adapters/pg.js.map
new file mode 100644
index 0000000..fa33d5f
--- /dev/null
+++ b/lib/adapters/pg.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["pg.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;AAMb,MAAM,CAAC,OAAO;WAAS,EAAE;;UAAF,EAAE;wBAAF,EAAE;;gEAAF,EAAE;;;cAAF,EAAE;;;;;;;;;;;qDASW;AAClC,OAAI,IAAI,GAAG,uBAAQ,+CAA+C,EAAE,SAAS,CAAC;;;AAAC,AAG/E,OAAI,KAAK,GAAG,CAAC,CAAC;AACd,OAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,YAAM;AACxC,SAAK,EAAE,CAAC;AACR,WAAO,GAAG,GAAG,KAAK,CAAC;IACnB,CAAC,CAAC;;AAEH,OAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;GAC1D;;;QApBqB,EAAE;qBAqBxB,CAAA","file":"adapters/pg.js","sourcesContent":["'use strict';\n\nimport Adapter from '../Adapter';\nimport getArgs from 'getargs';\n\n/** @module adapters/pg */\nmodule.exports = class pg extends Adapter {\n\t/**\n\t * Run the sql query as a prepared statement\n\t *\n\t * @param {String} sql - The sql with placeholders\n\t * @param {Array} params - The values to insert into the query\n\t * @param {Function} callback - Callback to run when a response is recieved\n\t * @return void\n\t */\n\texecute(/*sql, params, callback*/) {\n\t\tlet args = getArgs('sql:string, [params]:array, callback:function', arguments);\n\n\t\t// Replace question marks with numbered placeholders, because this adapter is different...\n\t\tlet count = 0;\n\t\targs.sql = args.sql.replace(/\\?/g, () => {\n\t\t\tcount++;\n\t\t\treturn '$' + count;\n\t\t});\n\n\t\tthis.instance.query(args.sql, args.params, args.callback);\n\t}\n}"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/drivers/Firebird.js b/lib/drivers/Firebird.js
new file mode 100644
index 0000000..8b9143f
--- /dev/null
+++ b/lib/drivers/Firebird.js
@@ -0,0 +1,78 @@
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _helpers = require('../helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+var _DriverClass = require('../DriverClass');
+
+var _DriverClass2 = _interopRequireDefault(_DriverClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * Driver for Firebird databases
+ *
+ * @module drivers/firebird
+ */
+
+var Firebird = (function (_Driver) {
+ _inherits(Firebird, _Driver);
+
+ function Firebird() {
+ _classCallCheck(this, Firebird);
+
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(Firebird).call(this, {
+ hasTruncate: false
+ }));
+ }
+
+ /**
+ * Generate a limit clause for firebird, which uses the syntax closest to the SQL standard
+ *
+ * @param {String} sql
+ * @param {Number} limit
+ * @param {Number} offset
+ * @return {String}
+ */
+
+ _createClass(Firebird, [{
+ key: 'limit',
+ value: function limit(origSql, _limit, offset) {
+ var sql = 'FIRST ' + _limit;
+
+ if (_helpers2.default.isNumber(offset)) {
+ sql += ' SKIP ' + offset;
+ }
+
+ return origSql.replace(/SELECT/i, "SELECT " + sql);
+ }
+
+ /**
+ * 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
+ * @return {String}
+ */
+
+ }, {
+ key: 'insertBatch',
+ value: function insertBatch() {
+ throw new Error("Not Implemented");
+ }
+ }]);
+
+ return Firebird;
+})(_DriverClass2.default);
+
+module.exports = new Firebird();
+//# sourceMappingURL=Firebird.js.map
diff --git a/lib/drivers/Firebird.js.map b/lib/drivers/Firebird.js.map
new file mode 100644
index 0000000..51e756b
--- /dev/null
+++ b/lib/drivers/Firebird.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Firebird.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;IAUP,QAAQ;WAAR,QAAQ;;AACb,UADK,QAAQ,GACC;wBADT,QAAQ;;gEAAR,QAAQ,aAEN;AACL,cAAW,EAAE,KAAK;GAClB;EACD;;;;;;;;;;AAAA;cALI,QAAQ;;wBAeP,OAAO,EAAE,MAAK,EAAE,MAAM,EAAE;AAC7B,OAAI,GAAG,eAAa,MAAK,AAAE,CAAC;;AAE5B,OAAI,kBAAQ,QAAQ,CAAC,MAAM,CAAC,EAC5B;AACC,OAAG,gBAAc,MAAM,AAAE,CAAC;IAC1B;;AAED,UAAO,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,CAAC;GACnD;;;;;;;;;;;;gCASa;AACb,SAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;GACnC;;;QAnCI,QAAQ;;;AAsCd,MAAM,CAAC,OAAO,GAAG,IAAI,QAAQ,EAAE,CAAC","file":"drivers/Firebird.js","sourcesContent":["\"use strict\";\n\nimport helpers from '../helpers';\nimport Driver from '../DriverClass';\n\n/**\n * Driver for Firebird databases\n *\n * @module drivers/firebird\n */\nclass Firebird extends Driver {\n\tconstructor() {\n\t\tsuper({\n\t\t\thasTruncate: false\n\t\t});\n\t}\n\n\t/**\n\t * Generate a limit clause for firebird, which uses the syntax closest to the SQL standard\n\t *\n\t * @param {String} sql\n\t * @param {Number} limit\n\t * @param {Number} offset\n\t * @return {String}\n\t */\n\tlimit(origSql, limit, offset) {\n\t\tlet sql = `FIRST ${limit}`;\n\n\t\tif (helpers.isNumber(offset))\n\t\t{\n\t\t\tsql += ` SKIP ${offset}`;\n\t\t}\n\n\t\treturn origSql.replace(/SELECT/i, \"SELECT \" + sql);\n\t}\n\n\t/**\n\t * SQL to insert a group of rows\n\t *\n\t * @param {String} table - The table to insert to\n\t * @param {Array} [data] - The array of object containing data to insert\n\t * @return {String}\n\t */\n\tinsertBatch() {\n\t\tthrow new Error(\"Not Implemented\");\n\t}\n}\n\nmodule.exports = new Firebird();"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/drivers/Mysql.js b/lib/drivers/Mysql.js
new file mode 100755
index 0000000..a52450e
--- /dev/null
+++ b/lib/drivers/Mysql.js
@@ -0,0 +1,54 @@
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _helpers = require('../helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+var _DriverClass = require('../DriverClass');
+
+var _DriverClass2 = _interopRequireDefault(_DriverClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * Driver for MySQL databases
+ *
+ * @module drivers/mysql
+ */
+
+var Mysql = (function (_Driver) {
+ _inherits(Mysql, _Driver);
+
+ function Mysql() {
+ _classCallCheck(this, Mysql);
+
+ return _possibleConstructorReturn(this, Object.getPrototypeOf(Mysql).call(this, {
+ identifierStartChar: '`',
+ identifierEndChar: '`'
+ }));
+ }
+
+ _createClass(Mysql, [{
+ key: 'limit',
+ value: function limit(sql, _limit, offset) {
+ if (!_helpers2.default.isNumber(offset)) {
+ return sql += ' LIMIT ' + _limit;
+ }
+
+ return sql += ' LIMIT ' + offset + ', ' + _limit;
+ }
+ }]);
+
+ return Mysql;
+})(_DriverClass2.default);
+
+module.exports = new Mysql();
+//# sourceMappingURL=Mysql.js.map
diff --git a/lib/drivers/Mysql.js.map b/lib/drivers/Mysql.js.map
new file mode 100644
index 0000000..0db23ec
--- /dev/null
+++ b/lib/drivers/Mysql.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Mysql.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;IAUP,KAAK;WAAL,KAAK;;AACV,UADK,KAAK,GACI;wBADT,KAAK;;gEAAL,KAAK,aAEH;AACL,sBAAmB,EAAE,GAAG;AACxB,oBAAiB,EAAE,GAAG;GACtB;EACD;;cANI,KAAK;;wBAQJ,GAAG,EAAE,MAAK,EAAE,MAAM,EAAE;AACzB,OAAK,CAAE,kBAAQ,QAAQ,CAAC,MAAM,CAAC,EAC/B;AACC,WAAO,GAAG,gBAAc,MAAK,AAAE,CAAC;IAChC;;AAED,UAAO,GAAG,gBAAc,MAAM,UAAK,MAAK,AAAE,CAAC;GAC3C;;;QAfI,KAAK;;;AAkBX,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,EAAE,CAAC","file":"drivers/Mysql.js","sourcesContent":["\"use strict\";\n\nimport helpers from '../helpers';\nimport Driver from '../DriverClass';\n\n/**\n * Driver for MySQL databases\n *\n * @module drivers/mysql\n */\nclass Mysql extends Driver {\n\tconstructor() {\n\t\tsuper({\n\t\t\tidentifierStartChar: '`',\n\t\t\tidentifierEndChar: '`'\n\t\t});\n\t}\n\n\tlimit(sql, limit, offset) {\n\t\tif ( ! helpers.isNumber(offset))\n\t\t{\n\t\t\treturn sql += ` LIMIT ${limit}`;\n\t\t}\n\n\t\treturn sql += ` LIMIT ${offset}, ${limit}`;\n\t}\n}\n\nmodule.exports = new Mysql();"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/drivers/Pg.js b/lib/drivers/Pg.js
new file mode 100755
index 0000000..2de962c
--- /dev/null
+++ b/lib/drivers/Pg.js
@@ -0,0 +1,15 @@
+"use strict";
+
+var _DriverClass = require("../DriverClass");
+
+var _DriverClass2 = _interopRequireDefault(_DriverClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Driver for PostgreSQL databases
+ *
+ * @module drivers/pg
+ */
+module.exports = new _DriverClass2.default();
+//# sourceMappingURL=Pg.js.map
diff --git a/lib/drivers/Pg.js.map b/lib/drivers/Pg.js.map
new file mode 100644
index 0000000..4537eb6
--- /dev/null
+++ b/lib/drivers/Pg.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Pg.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;AASb,MAAM,CAAC,OAAO,GAAG,2BAAY,CAAC","file":"drivers/Pg.js","sourcesContent":["\"use strict\";\n\nimport Driver from '../DriverClass';\n\n/**\n * Driver for PostgreSQL databases\n *\n * @module drivers/pg\n */\nmodule.exports = new Driver();"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/drivers/Sqlite.js b/lib/drivers/Sqlite.js
new file mode 100644
index 0000000..c748268
--- /dev/null
+++ b/lib/drivers/Sqlite.js
@@ -0,0 +1,94 @@
+"use strict";
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
+
+var _helpers = require('../helpers');
+
+var _helpers2 = _interopRequireDefault(_helpers);
+
+var _DriverClass = require('../DriverClass');
+
+var _DriverClass2 = _interopRequireDefault(_DriverClass);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+/**
+ * Driver for Sqlite databases
+ *
+ * @module drivers/sqlite
+ */
+
+var Sqlite = (function (_Driver) {
+ _inherits(Sqlite, _Driver);
+
+ function Sqlite() {
+ _classCallCheck(this, Sqlite);
+
+ var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Sqlite).call(this));
+
+ _this.hasTruncate = false;
+ return _this;
+ }
+
+ _createClass(Sqlite, [{
+ key: 'insertBatch',
+ value: function insertBatch(table, data) {
+ var _this2 = this;
+
+ // Get the data values to insert, so they can
+ // be parameterized
+ var sql = "",
+ vals = [],
+ cols = [],
+ fields = [],
+ first = data.shift(),
+ params = [],
+ paramString = "",
+ paramList = [];
+
+ data.forEach(function (obj) {
+ var row = [];
+ Object.keys(obj).forEach(function (key) {
+ row.push(obj[key]);
+ });
+ vals.push(row);
+ });
+
+ sql += "INSERT INTO " + this.quoteTable(table) + "\n";
+
+ // Get the field names from the keys of the first
+ // object to be inserted
+ fields = Object.keys(first);
+ Object.keys(first).forEach(function (key) {
+ cols.push("'" + _this2._quote(first[key]) + "' AS " + _this2.quoteIdentifiers(key));
+ });
+
+ sql += "SELECT " + cols.join(', ') + "\n";
+
+ vals.forEach(function (row_values) {
+ var quoted = row_values.map(function (value) {
+ return String(value).replace("'", "'\'");
+ });
+ sql += "UNION ALL SELECT '" + quoted.join("', '") + "'\n";
+ });
+
+ return {
+ sql: sql,
+ values: null
+ };
+ }
+ }]);
+
+ return Sqlite;
+})(_DriverClass2.default);
+
+;
+
+module.exports = new Sqlite();
+//# sourceMappingURL=Sqlite.js.map
diff --git a/lib/drivers/Sqlite.js.map b/lib/drivers/Sqlite.js.map
new file mode 100644
index 0000000..3306c4d
--- /dev/null
+++ b/lib/drivers/Sqlite.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["Sqlite.js"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;IAUP,MAAM;WAAN,MAAM;;AACX,UADK,MAAM,GACG;wBADT,MAAM;;qEAAN,MAAM;;AAGV,QAAK,WAAW,GAAG,KAAK,CAAC;;EACzB;;cAJI,MAAM;;8BAMC,KAAK,EAAE,IAAI,EAAE;;;;;AAIxB,OAAI,GAAG,GAAG,EAAE;OACX,IAAI,GAAG,EAAE;OACT,IAAI,GAAG,EAAE;OACT,MAAM,GAAG,EAAE;OACX,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE;OACpB,MAAM,GAAG,EAAE;OACX,WAAW,GAAG,EAAE;OAChB,SAAS,GAAG,EAAE,CAAC;;AAGhB,OAAI,CAAC,OAAO,CAAC,UAAC,GAAG,EAAK;AACrB,QAAI,GAAG,GAAG,EAAE,CAAC;AACb,UAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAC,GAAG,EAAK;AACjC,QAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;KACnB,CAAC,CAAC;AACH,QAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC,CAAC;;AAEH,MAAG,IAAI,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI;;;;AAAC,AAItD,SAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,SAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,UAAC,GAAG,EAAK;AACnC,QAAI,CAAC,IAAI,CAAC,GAAG,GAAG,OAAK,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,GAAG,OAAK,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC;;AAEH,MAAG,IAAI,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;;AAE1C,OAAI,CAAC,OAAO,CAAC,UAAC,UAAU,EAAK;AAC5B,QAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,UAAC,KAAK,EAAK;AACtC,YAAO,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;KACzC,CAAC,CAAC;AACH,OAAG,IAAI,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;IAC1D,CAAC,CAAC;;AAEH,UAAO;AACN,OAAG,EAAE,GAAG;AACR,UAAM,EAAE,IAAI;IACZ,CAAC;GACF;;;QAlDI,MAAM;;;AAmDX,CAAC;;AAEF,MAAM,CAAC,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC","file":"drivers/Sqlite.js","sourcesContent":["\"use strict\";\n\nimport helpers from '../helpers';\nimport Driver from '../DriverClass';\n\n/**\n * Driver for Sqlite databases\n *\n * @module drivers/sqlite\n */\nclass Sqlite extends Driver {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.hasTruncate = false;\n\t}\n\n\tinsertBatch(table, data) {\n\n\t\t// Get the data values to insert, so they can\n\t\t// be parameterized\n\t\tlet sql = \"\",\n\t\t\tvals = [],\n\t\t\tcols = [],\n\t\t\tfields = [],\n\t\t\tfirst = data.shift(),\n\t\t\tparams = [],\n\t\t\tparamString = \"\",\n\t\t\tparamList = [];\n\n\n\t\tdata.forEach((obj) => {\n\t\t\tlet row = [];\n\t\t\tObject.keys(obj).forEach((key) => {\n\t\t\t\trow.push(obj[key]);\n\t\t\t});\n\t\t\tvals.push(row);\n\t\t});\n\n\t\tsql += \"INSERT INTO \" + this.quoteTable(table) + \"\\n\";\n\n\t\t// Get the field names from the keys of the first\n\t\t// object to be inserted\n\t\tfields = Object.keys(first);\n\t\tObject.keys(first).forEach((key) => {\n\t\t\tcols.push(\"'\" + this._quote(first[key]) + \"' AS \" + this.quoteIdentifiers(key));\n\t\t});\n\n\t\tsql += \"SELECT \" + cols.join(', ') + \"\\n\";\n\n\t\tvals.forEach((row_values) => {\n\t\t\tlet quoted = row_values.map((value) => {\n\t\t\t\treturn String(value).replace(\"'\", \"'\\'\");\n\t\t\t});\n\t\t\tsql += \"UNION ALL SELECT '\" + quoted.join(\"', '\") + \"'\\n\";\n\t\t});\n\n\t\treturn {\n\t\t\tsql: sql,\n\t\t\tvalues: null\n\t\t};\n\t}\n};\n\nmodule.exports = new Sqlite();"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/drivers/mysql.js b/lib/drivers/mysql.js
deleted file mode 100755
index 66663c5..0000000
--- a/lib/drivers/mysql.js
+++ /dev/null
@@ -1,31 +0,0 @@
-"use strict";
-
-/**
- * Driver for MySQL databases
- *
- * @module drivers/mysql
- */
-module.exports = (function() {
- delete require.cache[require.resolve('../driver')];
- var driver = require('../driver');
- var driver = require('../driver'),
- helpers = require('../helpers');
-
- driver.identifierStartChar = '`';
- driver.identifierEndChar = '`';
-
- /**
- * Override default limit method because mysql likes to be different
- */
- driver.limit = function(sql, limit, offset) {
- if ( ! helpers.isNumber(offset))
- {
- return sql += " LIMIT " + limit;
- }
-
- return sql += " LIMIT " + offset + "," + limit;
- };
-
- return driver;
-
-}());
\ No newline at end of file
diff --git a/lib/drivers/pg.js b/lib/drivers/pg.js
deleted file mode 100755
index f2a3956..0000000
--- a/lib/drivers/pg.js
+++ /dev/null
@@ -1,13 +0,0 @@
-"use strict";
-
-/**
- * Driver for PostgreSQL databases
- *
- * @module drivers/pg
- */
-module.exports = (function() {
- delete require.cache[require.resolve('../driver')];
- var driver = require('../driver');
-
- return driver;
-}());
\ No newline at end of file
diff --git a/lib/drivers/sqlite.js b/lib/drivers/sqlite.js
deleted file mode 100644
index 1725df9..0000000
--- a/lib/drivers/sqlite.js
+++ /dev/null
@@ -1,71 +0,0 @@
-"use strict";
-
-/**
- * Driver for Sqlite databases
- *
- * @module drivers/sqlite
- */
-module.exports = (function() {
- delete require.cache[require.resolve('../driver')];
- var driver = require('../driver'),
- helpers = require('../helpers');
-
- // Sqlite doesn't have a truncate command
- driver.hasTruncate = false;
-
- /**
- * SQL to insert a group of rows
- * Override default to have better compatibility
- *
- * @param {String} table - The table to insert to
- * @param {Array} [data] - The array of object containing data to insert
- * @return {String}
- */
- driver.insertBatch = function(table, data) {
-
- // Get the data values to insert, so they can
- // be parameterized
- var sql = "",
- vals = [],
- cols = [],
- fields = [],
- first = data.shift(),
- params = [],
- paramString = "",
- paramList = [];
-
-
- data.forEach(function(obj) {
- var row = [];
- Object.keys(obj).forEach(function(key) {
- row.push(obj[key]);
- });
- vals.push(row);
- });
-
- sql += "INSERT INTO " + driver.quoteTable(table) + "\n";
-
- // Get the field names from the keys of the first
- // object to be inserted
- fields = Object.keys(first);
- Object.keys(first).forEach(function(key) {
- cols.push("'" + driver._quote(first[key]) + "' AS " + driver.quoteIdentifiers(key));
- });
-
- sql += "SELECT " + cols.join(', ') + "\n";
-
- vals.forEach(function(row_values) {
- var quoted = row_values.map(function(value) {
- return String(value).replace("'", "'\'");
- });
- sql += "UNION ALL SELECT '" + quoted.join("', '") + "'\n";
- });
-
- return {
- sql: sql,
- values: null
- };
- }
-
- return driver;
-}());
\ No newline at end of file
diff --git a/lib/helpers.js b/lib/helpers.js
index 3432849..d5aefd3 100755
--- a/lib/helpers.js
+++ b/lib/helpers.js
@@ -1,68 +1,66 @@
-"use strict";
+"use strict"
-require('es6-shim');
-/** @module helpers */
+//require('es6-shim');
-/** @alias module:helpers */
-var h = {
+;
+var helpers = {
/**
- * Wrap String.prototype.trim in a way that is easily mappable
- *
- * @param {String} str - The string to trim
- * @return {String} - The trimmed string
- */
- stringTrim: function(str) {
+ * Wrap String.prototype.trim in a way that is easily mappable
+ *
+ * @param {String} str - The string to trim
+ * @return {String} - The trimmed string
+ */
+ stringTrim: function stringTrim(str) {
return str.trim();
},
/**
- * Get the type of the variable passed
- *
- * @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
- * @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
- * @param {mixed} o
- * @return {String}
- */
- type: function (o) {
- var type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
+ * Get the type of the variable passed
+ *
+ * @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
+ * @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
+ * @param {mixed} o
+ * @return {String}
+ */
+ type: function type(o) {
+ var type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
- // handle NaN and Infinity
- if (type === 'number') {
- if (isNaN(o)) {
- return 'nan';
- }
- if (!isFinite(o)) {
- return 'infinity';
- }
- }
+ // handle NaN and Infinity
+ if (type === 'number') {
+ if (isNaN(o)) {
+ return 'nan';
+ }
+ if (!isFinite(o)) {
+ return 'infinity';
+ }
+ }
- return type;
+ return type;
},
/**
- * Determine whether an object is scalar
- *
- * @param {mixed} obj
- * @return {bool}
- */
- isScalar: function(obj) {
+ * Determine whether an object is scalar
+ *
+ * @param {mixed} obj
+ * @return {bool}
+ */
+ isScalar: function isScalar(obj) {
var scalar = ['string', 'number', 'boolean'];
- return scalar.indexOf(h.type(obj)) !== -1;
+ return scalar.indexOf(helpers.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) {
+ * 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 arrayPluck(arr, key) {
var output = [];
// Empty case
if (arr.length === 0) return output;
- arr.forEach(function(obj) {
- if ( ! h.isUndefined(obj[key]))
- {
+ arr.forEach(function (obj) {
+ if (!helpers.isUndefined(obj[key])) {
output.push(obj[key]);
}
});
@@ -70,51 +68,62 @@ var h = {
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) {
+ * 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 regexInArray(arr, pattern) {
// Empty case(s)
- if ( ! h.isArray(arr)) return false;
+ if (!helpers.isArray(arr)) return false;
if (arr.length === 0) return false;
- var i, l = arr.length;
+ var i = undefined,
+ l = arr.length;
- for(i=0; i< l; i++)
- {
+ for (i = 0; i < l; i++) {
// Short circuit if any items match
if (pattern.test(arr[i])) return true;
}
return false;
+ },
+ /**
+ * Make the first letter of the string uppercase
+ *
+ * @param {String} str
+ * @return {String}
+ */
+ upperCaseFirst: function upperCaseFirst(str) {
+ str += '';
+ var first = str.charAt(0).toUpperCase();
+ return first + str.substr(1);
}
};
// Define an 'is' method for each type
-var types = ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp','NaN','Infinite'];
+var types = ['Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp', 'NaN', 'Infinite'];
types.forEach(function (t) {
/**
- * Determine whether a variable is of the type specified in the
- * function name, eg isNumber
- *
- * Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
- *
- * @name is[type]
- * @param {mixed} o
- * @return {Boolean}
- */
- h['is' + t] = function (o) {
- if (t.toLowerCase() === 'infinite')
- {
- t = 'infinity';
- }
+ * Determine whether a variable is of the type specified in the
+ * function name, eg isNumber
+ *
+ * Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
+ *
+ * @name is[type]
+ * @param {mixed} o
+ * @return {Boolean}
+ */
+ helpers['is' + t] = function (o) {
+ if (t.toLowerCase() === 'infinite') {
+ t = 'infinity';
+ }
- return h.type(o) === t.toLowerCase();
- };
+ return helpers.type(o) === t.toLowerCase();
+ };
});
-module.exports = h;
\ No newline at end of file
+module.exports = helpers;
+//# sourceMappingURL=helpers.js.map
diff --git a/lib/helpers.js.map b/lib/helpers.js.map
new file mode 100644
index 0000000..567c6aa
--- /dev/null
+++ b/lib/helpers.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["helpers.js"],"names":[],"mappings":"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","file":"helpers.js","sourcesContent":["\"use strict\";\n\n//require('es6-shim');\n\nlet helpers = {\n\t/**\n\t * Wrap String.prototype.trim in a way that is easily mappable\n\t *\n\t * @param {String} str - The string to trim\n\t * @return {String} - The trimmed string\n\t */\n\tstringTrim: (str) => str.trim(),\n\t/**\n\t * Get the type of the variable passed\n\t *\n\t * @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/\n\t * @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/\n\t * @param {mixed} o\n\t * @return {String}\n\t */\n\ttype: (o) => {\n\t let type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();\n\n\t // handle NaN and Infinity\n\t if (type === 'number') {\n\t if (isNaN(o)) {\n\t return 'nan';\n\t }\n\t if (!isFinite(o)) {\n\t return 'infinity';\n\t }\n\t }\n\n\t return type;\n\t},\n\t/**\n\t * Determine whether an object is scalar\n\t *\n\t * @param {mixed} obj\n\t * @return {bool}\n\t */\n\tisScalar: (obj) => {\n\t\tlet scalar = ['string', 'number', 'boolean'];\n\t\treturn scalar.indexOf(helpers.type(obj)) !== -1;\n\t},\n\t/**\n\t * Get a list of values with a common key from an array of objects\n\t *\n\t * @param {Array} arr - The array of objects to search\n\t * @param {String} key - The key of the object to get\n\t * @return {Array}\n\t */\n\tarrayPluck: (arr, key) => {\n\t\tlet output = [];\n\n\t\t// Empty case\n\t\tif (arr.length === 0) return output;\n\n\t\tarr.forEach((obj) => {\n\t\t\tif ( ! helpers.isUndefined(obj[key]))\n\t\t\t{\n\t\t\t\toutput.push(obj[key]);\n\t\t\t}\n\t\t});\n\n\t\treturn output;\n\t},\n\t/**\n\t * Determine if a value matching the passed regular expression is\n\t * in the passed array\n\t *\n\t * @param {Array} arr - The array to search\n\t * @param {RegExp} pattern - The pattern to match\n\t * @return {Boolean} - If an array item matches the pattern\n\t */\n\tregexInArray: (arr, pattern) => {\n\t\t// Empty case(s)\n\t\tif ( ! helpers.isArray(arr)) return false;\n\t\tif (arr.length === 0) return false;\n\n\t\tlet i, l = arr.length;\n\n\t\tfor(i=0; i< l; i++)\n\t\t{\n\t\t\t// Short circuit if any items match\n\t\t\tif (pattern.test(arr[i])) return true;\n\t\t}\n\n\t\treturn false;\n\t},\n\t/**\n\t * Make the first letter of the string uppercase\n\t *\n\t * @param {String} str\n\t * @return {String}\n\t */\n\tupperCaseFirst: (str) => {\n\t\tstr += '';\n\t\tlet first = str.charAt(0).toUpperCase();\n\t\treturn first + str.substr(1);\n\t}\n};\n\n// Define an 'is' method for each type\nlet types = ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp','NaN','Infinite'];\ntypes.forEach((t) => {\n\t/**\n\t * Determine whether a variable is of the type specified in the\n\t * function name, eg isNumber\n\t *\n\t * Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite\n\t *\n\t * @name is[type]\n\t * @param {mixed} o\n\t * @return {Boolean}\n\t */\n helpers['is' + t] = function (o) {\n\t if (t.toLowerCase() === 'infinite')\n\t {\n\t\t t = 'infinity';\n\t }\n\n return helpers.type(o) === t.toLowerCase();\n };\n});\n\nmodule.exports = helpers;"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/lib/node-query.js b/lib/node-query.js
deleted file mode 100755
index da9146f..0000000
--- a/lib/node-query.js
+++ /dev/null
@@ -1,58 +0,0 @@
-"use strict";
-
-/** @module node-query */
-var NodeQuery = function() {
-
- var instance = null;
-
- /**
- * Create a query builder object
- *
- * @alias module:node-query
- * @param {String} drivername - 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
- * @return {queryBuilder}
- */
- this.init = function (driverType, connObject, connLib) {
- connLib = connLib || driverType;
-
- var fs = require('fs'),
- qb = require('./query-builder');
-
- var paths = {
- driver: __dirname + '/drivers/' + driverType + '.js',
- adapter: __dirname + '/adapters/' + connLib + '.js'
- };
-
- Object.keys(paths).forEach(function(type) {
- if ( ! fs.existsSync(paths[type]))
- {
- console.log(paths[type]);
- throw new Error('Selected ' + type + ' does not exist!');
- }
- });
-
- instance = qb(require(paths.driver), require(paths.adapter)(connObject));
-
- return instance;
- };
-
- /**
- * Return an existing query builder instance
- *
- * @return {queryBuilder}
- */
- this.getQuery = function () {
- if ( ! instance) {
- throw new Error("No Query Builder instance to return");
- }
-
- return instance;
- };
-
-};
-
-
-
-module.exports = new NodeQuery();
\ No newline at end of file
diff --git a/lib/query-builder.js b/lib/query-builder.js
deleted file mode 100755
index 59a8e70..0000000
--- a/lib/query-builder.js
+++ /dev/null
@@ -1,928 +0,0 @@
-'use strict';
-
-/** @module query-builder */
-var getArgs = require('getargs'),
- helpers = require('./helpers'),
- State = require('./state');
-
-/**
- * Variables controlling the sql building
- *
- * @private
- */
-var state = new State();
-
-/*
- * SQL generation object
- *
- * @param {driver} - The syntax driver for the database
- * @param {adapter} - The database module adapter for running queries
- * @constructor
- */
-var QueryBuilder = function(driver, adapter) {
-
- // That 'new' keyword is annoying
- if ( ! (this instanceof QueryBuilder)) return new QueryBuilder(driver, adapter);
-
- var parser = require('./query-parser')(driver);
-
- this.driver = driver;
- this.adapter = adapter;
-
- /**
- * "Private" methods
- *
- * @private
- */
- var _p = {
- /**
- * Complete the sql building based on the type provided
- *
- * @param {String} type
- * @param {String} table
- * @private
- * @return {String}
- */
- compile: function (type, table) {
- // Put together the basic query
- var sql = _p.compileType(type, table);
-
- // Set each subClause
- ['queryMap', 'groupString', 'orderString', 'havingMap'].forEach(function(clause) {
- var param = state[clause];
-
- if ( ! helpers.isScalar(param))
- {
- Object.keys(param).forEach(function(part) {
- sql += param[part].conjunction + param[part].string;
- });
- }
- else
- {
- sql += param;
- }
- });
-
- // Append the limit, if it exists
- if (helpers.isNumber(state.limit))
- {
- sql = driver.limit(sql, state.limit, state.offset);
- }
-
- return sql;
- },
- compileType: function (type, table) {
- var sql = '';
-
- switch(type) {
- case "insert":
- var params = new Array(state.setArrayKeys.length);
- params.fill('?');
-
- sql = "INSERT INTO " + table + " (";
- sql += state.setArrayKeys.join(',');
- sql += ") VALUES (";
- sql += params.join(',') + ')';
- break;
-
- case "update":
- sql = "UPDATE " + table + " SET " + state.setString;
- break;
-
- case "delete":
- sql = "DELETE FROM " + table;
- break;
-
- default:
- sql = "SELECT * FROM " + state.fromString;
-
- // Set the select string
- if (state.selectString.length > 0)
- {
- // Replace the star with the selected fields
- sql = sql.replace('*', state.selectString);
- }
- break;
- }
-
- return sql;
- },
- like: function (field, val, pos, like, conj) {
- field = driver.quoteIdentifiers(field);
-
- like = field + " " + like + " ?";
-
- if (pos == 'before')
- {
- val = "%" + val;
- }
- else if (pos == 'after')
- {
- val = val + "%";
- }
- else
- {
- val = "%" + val + "%";
- }
-
- conj = (state.queryMap.length < 1) ? ' WHERE ' : ' ' + conj + ' ';
- _p.appendMap(conj, like, 'like');
-
- state.whereValues.push(val);
- },
- /**
- * Append a clause to the query map
- *
- * @param {String} conjunction
- * @param {String} string
- * @param {String} type
- * @return void
- */
- appendMap: function(conjunction, string, type) {
- state.queryMap.push({
- type: type,
- conjunction: conjunction,
- string: string
- });
- },
- /**
- * Handle key/value pairs in an object the same way as individual arguments,
- * when appending to state
- *
- * @private
- */
- mixedSet: function(/* $varName, $valType, $key, [$val] */) {
- var args = getArgs('$varName:string, $valType:string, $key:object|string|number, [$val]', arguments);
-
- var 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(function(k) {
- // If a single value for the return
- if (['key','value'].indexOf(args.$valType) !== -1)
- {
- var pushVal = (args.$valType === 'key') ? k : obj[k];
- state[args.$varName].push(pushVal);
- }
- else
- {
- state[args.$varName][k] = obj[k];
- }
- });
-
-
- return state[args.$varName];
- },
- whereMixedSet: function(/*key, val*/) {
- var args = getArgs('key:string|object, [val]', arguments);
-
- state.whereMap = [];
- state.rawWhereValues = [];
-
- _p.mixedSet('whereMap', 'both', args.key, args.val);
- _p.mixedSet('rawWhereValues', '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);
-
- // Parse the where condition to account for operators,
- // functions, identifiers, and literal values
- state = parser.parseWhere(driver, state);
-
- state.whereMap.forEach(function(clause) {
- var conj = _p.fixConjunction(defaultConj);
- _p.appendMap(conj, clause, 'where');
- });
-
- state.whereMap = {};
- },
- whereNull: function(field, stmt, conj) {
- 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';
- args.val = args.val || null;
-
- // Normalize key/val and put in state.whereMap
- _p.whereMixedSet(args.key, args.val);
-
- // Parse the having condition to account for operators,
- // functions, identifiers, and literal values
- state = parser.parseWhere(driver, state);
-
- state.whereMap.forEach(function(clause) {
- // Put in the having map
- state.havingMap.push({
- conjunction: (state.havingMap.length > 0) ? " " + args.conj + " " : ' HAVING ',
- string: clause
- });
- });
-
- // Clear the where Map
- state.whereMap = {};
- },
- whereIn: function(/*key, val, inClause, conj*/) {
- var args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);
-
- args.key = driver.quoteIdentifiers(args.key);
- var params = new Array(args.val.length);
- params.fill('?');
-
- args.val.forEach(function(value) {
- state.whereValues.push(value);
- });
-
- args.conj = (state.queryMap.length > 0) ? " " + args.conj + " " : ' WHERE ';
- var str = args.key + " " + args.inClause + " (" + params.join(',') + ") ";
-
- _p.appendMap(args.conj, str, 'whereIn');
- },
- run: function(type, table, callback, sql, vals) {
-
- if ( ! sql)
- {
- sql = _p.compile(type, table);
- }
-
- if ( ! vals)
- {
- vals = state.values.concat(state.whereValues);
- }
-
-//console.log(state);
-//console.log(sql);
-//console.log(vals);
-//console.log(callback);
-//console.log('------------------------');
-
- // Reset the state so another query can be built
- _p.resetState();
-
- // Pass the sql and values to the adapter to run on the database
- adapter.execute(sql, vals, callback);
-
- },
- getCompile: function(type, table, reset) {
- reset = reset || false;
-
- var sql = _p.compile(type, table);
-
- if (reset) _p.resetState();
-
- return sql;
- },
- resetState: function() {
- state = new State();
- }
- };
-
- // ----------------------------------------------------------------------------
- // ! Miscellaneous Methods
- // ----------------------------------------------------------------------------
-
- /**
- * Reset the object state for a new query
- *
- * @memberOf query-builder
- * @return void
- */
- this.resetQuery = function() {
- _p.resetState();
- };
-
- /**
- * Returns the current class state for testing or other purposes
- *
- * @private
- * @return {Object}
- */
- this.getState = function() {
- return state;
- };
-
- /**
- * Closes the database connection for the current adapter
- *
- * @return void
- */
- this.end = function() {
- adapter.close();
- };
-
- // ------------------------------------------------------------------------
- // ! Query Builder Methods
- // ------------------------------------------------------------------------
-
- /**
- * Specify rows to select in the query
- *
- * @param {String|Array} fields - The fields to select from the current table
- * @return this
- */
- this.select = function(fields) {
-
- // Split/trim fields by comma
- fields = (Array.isArray(fields)) ? fields : fields.split(",").map(helpers.stringTrim);
-
- // Split on 'As'
- fields.forEach(function (field, index) {
- if (field.match(/as/i))
- {
- fields[index] = field.split(/ as /i).map(helpers.stringTrim);
- }
- });
-
- var safeArray = driver.quoteIdentifiers(fields);
-
- // Join the strings back together
- safeArray.forEach(function (field, index) {
- if (Array.isArray(field))
- {
- safeArray[index] = safeArray[index].join(' AS ');
- }
- });
-
- state.selectString += safeArray.join(', ');
-
- return this;
- };
-
- /**
- * Specify the database table to select from
- *
- * @param {String} tableName - The table to use for the current query
- * @return this
- */
- this.from = function(tableName) {
- // Split identifiers on spaces
- var identArray = tableName.trim().split(' ').map(helpers.stringTrim);
-
- // Quote/prefix identifiers
- identArray[0] = driver.quoteTable(identArray[0]);
- identArray = driver.quoteIdentifiers(identArray);
-
- // Put it back together
- state.fromString = identArray.join(' ');
-
- return this;
- };
-
- /**
- * Add a 'like/ and like' clause to the query
- *
- * @param {String} field - The name of the field to compare to
- * @param {String} val - The value to compare to
- * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
- * @return this
- */
- this.like = function(field, val, pos) {
- _p.like(field, val, pos, ' LIKE ', 'AND');
- return this;
- };
-
- /**
- * Add a 'not like/ and not like' clause to the query
- *
- * @param {String} field - The name of the field to compare to
- * @param {String} val - The value to compare to
- * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
- * @return this
- */
- this.notLike = function(field, val, pos) {
- _p.like(field, val, pos, ' NOT LIKE ', 'AND');
- return this;
- };
-
- /**
- * Add an 'or like' clause to the query
- *
- * @param {String} field - The name of the field to compare to
- * @param {String} val - The value to compare to
- * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
- * @return this
- */
- this.orLike = function(field, val, pos) {
- _p.like(field, val, pos, ' LIKE ', 'OR');
- return this;
- };
-
- /**
- * Add an 'or not like' clause to the query
- *
- * @param {String} field - The name of the field to compare to
- * @param {String} val - The value to compare to
- * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
- * @return this
- */
- this.orNotLike = function(field, val, pos) {
- _p.like(field, val, pos, ' NOT LIKE ', 'OR');
- return this;
- };
-
- /**
- * Add a 'having' clause
- *
- * @param {String|Object} key - The name of the field and the comparision operator, or an object
- * @param {String|Number} [val] - The value to compare if the value of key is a string
- * @return this
- */
- this.having = function(/*key, [val]*/) {
- var args = getArgs('key:string|object, [val]:string|number', arguments);
-
- _p.having(args.key, args.val, 'AND');
- return this;
- };
-
- /**
- * Add an 'or having' clause
- *
- * @param {String|Object} key - The name of the field and the comparision operator, or an object
- * @param {String|Number} [val] - The value to compare if the value of key is a string
- * @return this
- */
- this.orHaving = function(/*key, [val]*/) {
- var args = getArgs('key:string|object, [val]:string|number', arguments);
-
- _p.having(args.key, args.val, 'OR');
- return this;
- };
-
- /**
- * Set a 'where' clause
- *
- * @param {String|Object} key - The name of the field and the comparision operator, or an object
- * @param {String|Number} [val] - The value to compare if the value of key is a string
- * @return this
- */
- this.where = function(key, val) {
- _p.where(key, val, 'AND');
- return this;
- };
-
- /**
- * Set a 'or where' clause
- *
- * @param {String|Object} key - The name of the field and the comparision operator, or an object
- * @param {String|Number} [val] - The value to compare if the value of key is a string
- * @return this
- */
- this.orWhere = function(key, val) {
- _p.where(key, val, 'OR');
- 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
- *
- * @param {String} key - the field to search
- * @param {Array} val - the array of items to search in
- * @return this
- */
- this.whereIn = function(key, val) {
- _p.whereIn(key, val, 'IN', 'AND');
- return this;
- };
-
- /**
- * Set a 'or where in' clause
- *
- * @param {String} key - the field to search
- * @param {Array} val - the array of items to search in
- * @return this
- */
- this.orWhereIn = function(key, val) {
- _p.whereIn(key, val, 'IN', 'OR');
- return this;
- };
-
- /**
- * Set a 'where not in' clause
- *
- * @param {String} key - the field to search
- * @param {Array} val - the array of items to search in
- * @return this
- */
- this.whereNotIn = function(key, val) {
- _p.whereIn(key, val, 'NOT IN', 'AND');
- return this;
- };
-
- /**
- * Set a 'or where not in' clause
- *
- * @param {String} key - the field to search
- * @param {Array} val - the array of items to search in
- * @return this
- */
- this.orWhereNotIn = function(key, val) {
- _p.whereIn(key, val, 'NOT IN', 'OR');
- return this;
- };
-
- /**
- * Set values for insertion or updating
- *
- * @param {String|Object} key - The key or object to use
- * @param {String} [val] - The value if using a scalar key
- * @return this
- */
- this.set = function(/* $key, [$val] */) {
- var args = getArgs('$key, [$val]', arguments);
-
- // Set the appropriate state variables
- _p.mixedSet('setArrayKeys', 'key', args.$key, args.$val);
- _p.mixedSet('values', 'value', args.$key, args.$val);
-
- // Use the keys of the array to make the insert/update string
- // and escape the field names
- state.setArrayKeys = state.setArrayKeys.map(driver._quote);
-
- // Generate the "set" string
- state.setString = state.setArrayKeys.join('=?,');
- state.setString += '=?';
-
- return this;
- };
-
- /**
- * Add a join clause to the query
- *
- * @param {String} table - The table you are joining
- * @param {String} cond - The join condition.
- * @param {String} [type='inner'] - The type of join, which defaults to inner
- * @return this
- */
- this.join = function(table, cond, type) {
- type = type || "inner";
-
- // Prefix/quote table name
- var table = table.split(' ').map(helpers.stringTrim);
- table[0] = driver.quoteTable(table[0]);
- table = table.map(driver.quoteIdentifiers);
- table = table.join(' ');
-
- // Parse out the join condition
- var parsedCondition = parser.compileJoin(cond);
- var condition = table + ' ON ' + parsedCondition;
-
- // Append the join condition to the query map
- _p.appendMap("\n" + type.toUpperCase() + ' JOIN ', condition, 'join');
-
- return this;
- };
-
- /**
- * Group the results by the selected field(s)
- *
- * @param {String|Array} field
- * @return this
- */
- this.groupBy = function(field) {
- if ( ! helpers.isScalar(field))
- {
- var newGroupArray = field.map(driver.quoteIdentifiers);
- state.groupArray = state.groupArray.concat(newGroupArray);
- }
- else
- {
- state.groupArray.push(driver.quoteIdentifiers(field));
- }
-
- state.groupString = ' GROUP BY ' + state.groupArray.join(',');
-
- return this;
- };
-
- /**
- * Order the results by the selected field(s)
- *
- * @param {String} field - The field(s) to order by
- * @param {String} [type='ASC'] - The order direction, ASC or DESC
- * @return this
- */
- this.orderBy = function(field, type) {
- type = type || 'ASC';
-
- // Set the fields for later manipulation
- field = driver.quoteIdentifiers(field);
-
- state.orderArray[field] = type;
-
- var orderClauses = [];
-
- // Flatten key/val pairs into an array of space-separated pairs
- Object.keys(state.orderArray).forEach(function(key) {
- orderClauses.push(key + ' ' + state.orderArray[key].toUpperCase());
- });
-
- // Set the final string
- state.orderString = ' ORDER BY ' + orderClauses.join(', ');
-
- return this;
- };
-
- /**
- * Put a limit on the query
- *
- * @param {Number} limit - The maximum number of rows to fetch
- * @param {Number} [offset] - The row number to start from
- * @return this
- */
- this.limit = function(limit, offset) {
- state.limit = limit;
- state.offset = offset || null;
-
- return this;
- };
-
- /**
- * Adds an open paren to the current query for logical grouping
- *
- * @return this
- */
- this.groupStart = function() {
- var conj = (state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
- _p.appendMap(conj, '(', 'groupStart');
-
- return this;
- };
-
- /**
- * Adds an open paren to the current query for logical grouping,
- * prefixed with 'OR'
- *
- * @return this
- */
- this.orGroupStart = function() {
- _p.appendMap('', ' OR (', 'groupStart');
-
- return this;
- };
-
- /**
- * Adds an open paren to the current query for logical grouping,
- * prefixed with 'OR NOT'
- *
- * @return this
- */
- this.orNotGroupStart = function() {
- _p.appendMap('', ' OR NOT (', 'groupStart');
-
- return this;
- };
-
- /**
- * Ends a logical grouping started with one of the groupStart methods
- *
- * @return this
- */
- this.groupEnd = function() {
- _p.appendMap('', ')', 'groupEnd');
-
- return this;
- };
-
- // ------------------------------------------------------------------------
- // ! Result Methods
- // ------------------------------------------------------------------------
-
- /**
- * Get the results of the compiled query
- *
- * @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
- */
- this.get = function(/* [table], [limit], [offset], callback */) {
- var args = getArgs('[table]:string, [limit]:number, [offset]:number, callback:function', arguments);
-
- if (args.table) {
- this.from(args.table);
- }
-
- if (args.limit) {
- this.limit(args.limit, args.offset);
- }
-
- // Run the query
- _p.run('get', args.table, args.callback);
- };
-
- /**
- * Run the generated insert query
- *
- * @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
- */
- this.insert = function(/* table, data, callback */) {
- var args = getArgs('table:string, [data]:object, callback:function', arguments);
-
- if (args.data) {
- this.set(args.data);
- }
-
- // Run the query
- _p.run('insert', driver.quoteTable(args.table), args.callback);
- };
-
- /**
- * Insert multiple sets of rows at a time
- *
- * @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
- * @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
- * @return void
- */
- this.insertBatch = function(/* table, data, callback */) {
- var args = getArgs('table:string, data:array, callback:function', arguments);
- var batch = driver.insertBatch(args.table, args.data);
-
- // Run the query
- _p.run('', '', args.callback, batch.sql, batch.values);
- };
-
- /**
- * Run the generated update query
- *
- * @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
- */
- this.update = function(/*table, data, callback*/) {
- var args = getArgs('table:string, [data]:object, callback:function', arguments);
-
- if (args.data) {
- this.set(args.data);
- }
-
- // Run the query
- _p.run('update', driver.quoteTable(args.table), args.callback);
- };
-
- /**
- * Run the generated delete query
- *
- * @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
- */
- this.delete = function (/*table, [where], callback*/) {
- var args = getArgs('table:string, [where]:object, callback:function', arguments);
-
- if (args.where)
- {
- this.where(args.where);
- }
-
- // Run the query
- _p.run('delete', driver.quoteTable(args.table), args.callback);
- };
-
- // ------------------------------------------------------------------------
- // ! Methods returning SQL
- // ------------------------------------------------------------------------
-
- /**
- * Return generated select query SQL
- *
- * @param {String} [table] - the name of the table to retrieve from
- * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
- * @return String
- */
- this.getCompiledSelect = function(/*table, reset*/) {
- var args = getArgs('[table]:string, [reset]:boolean', arguments);
- if (args.table)
- {
- this.from(args.table);
- }
-
- return _p.getCompile('get', args.table, args.reset);
- };
-
- /**
- * Return generated insert query SQL
- *
- * @param {String} table - the name of the table to insert into
- * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
- * @return {String}
- */
- this.getCompiledInsert = function(table, reset) {
- return _p.getCompile('insert', driver.quoteTable(table), reset);
- };
-
- /**
- * Return generated update query SQL
- *
- * @param {String} table - the name of the table to update
- * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
- * @return {String}
- */
- this.getCompiledUpdate = function(table, reset) {
- return _p.getCompile('update', driver.quoteTable(table), reset);
- };
-
- /**
- * Return generated delete query SQL
- *
- * @param {String} table - the name of the table to delete from
- * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
- * @return {String}
- */
- this.getCompiledDelete = function(table, reset) {
- return _p.getCompile('delete', driver.quoteTable(table), reset);
- };
-
- return this;
-};
-
-module.exports = QueryBuilder;
\ No newline at end of file
diff --git a/lib/state.js b/lib/state.js
deleted file mode 100644
index 549f491..0000000
--- a/lib/state.js
+++ /dev/null
@@ -1,29 +0,0 @@
-'use strict';
-
-/** @module State */
-module.exports = function State() {
- return {
- // Arrays/Maps
- queryMap: [],
- values: [],
- whereValues: [],
- setArrayKeys: [],
- orderArray: [],
- groupArray: [],
- havingMap: [],
- whereMap: {},
- rawWhereValues: [],
-
- // Partials
- selectString: '',
- fromString: '',
- setString: '',
- orderString: '',
- groupString: '',
-
- // Other various values
- limit: null,
- offset: null
- };
-};
-// End of module State
\ No newline at end of file
diff --git a/package.json b/package.json
index 86eb2fb..715dfda 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,10 @@
"mysql2": "^0.15.8",
"node-firebird": "^0.7.0",
"pg": "^4.4.3",
- "es6-shim": ""
+ "es6-shim": "",
+ "babel": "",
+ "babel-preset-es2015": "",
+ "babel-plugin-transform-es2015-modules-commonjs": ""
},
"optionalDependencies": {
"dblite": "*",
@@ -49,14 +52,19 @@
"documentation": "",
"nodeunit": "",
"gulp": "",
+ "gulp-babel": "",
+ "gulp-babel-istanbul": "",
+ "gulp-sourcemaps": "",
+ "gulp-concat": "",
"gulp-documentation": "",
- "gulp-istanbul": "",
"gulp-nodeunit-runner": "",
- "jsdoc": "",
+ "gulp-sloc": "",
+ "gulp-eslint": "",
+ "eslint": "",
"istanbul": ""
},
"license": "MIT",
"scripts": {
- "test": "grunt tests"
+ "test": "gulp nodeunit"
}
}
diff --git a/src/Adapter.js b/src/Adapter.js
new file mode 100755
index 0000000..bb1627d
--- /dev/null
+++ b/src/Adapter.js
@@ -0,0 +1,26 @@
+'use strict';
+
+/** @module Adapter */
+module.exports = class Adapter {
+ /**
+ * Invoke an adapter
+ *
+ * @param {Object} instance - The connection objec
+ * @return {void}
+ */
+ constructor(instance) {
+ this.instance = instance;
+ }
+
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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}
+ */
+ execute(/*sql, params, callback*/) {
+ throw new Error("Correct adapter not defined for query execution");
+ }
+}
\ No newline at end of file
diff --git a/lib/driver.js b/src/DriverBase.js
similarity index 98%
rename from lib/driver.js
rename to src/DriverBase.js
index 4c7a3ee..c4a257e 100755
--- a/lib/driver.js
+++ b/src/DriverBase.js
@@ -1,6 +1,6 @@
'use strict';
-var helpers = require('./helpers');
+import helpers from './helpers'
/**
* Base Database Driver
diff --git a/src/DriverClass.js b/src/DriverClass.js
new file mode 100644
index 0000000..bc80b23
--- /dev/null
+++ b/src/DriverClass.js
@@ -0,0 +1,13 @@
+'use strict';
+
+import driverBase from './DriverBase';
+
+module.exports = class DriverClass {
+ constructor(properties = {}) {
+ Object.keys(driverBase).forEach((key) => {
+ this[key] = (Object.keys(properties).indexOf(key) !== -1)
+ ? properties[key]
+ : driverBase[key];
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/NodeQuery.js b/src/NodeQuery.js
new file mode 100755
index 0000000..fc8abe3
--- /dev/null
+++ b/src/NodeQuery.js
@@ -0,0 +1,74 @@
+"use strict";
+
+let instance = null;
+import fs from 'fs';
+import helpers from './helpers';
+import QueryBuilder from './QueryBuilder';
+
+/**
+ * @module NodeQuery
+ */
+class NodeQuery {
+
+ /**
+ * Constructor
+ */
+ constructor() {
+ this.instance = null;
+ }
+
+ /**
+ * Create a query builder object
+ *
+ * @memberOf NodeQuery
+ * @param {String} drivername - 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
+ * @return {QueryBuilder}
+ */
+ init(driverType, connObject, connLib) {
+ connLib = connLib || driverType;
+
+ let paths = {
+ driver: `${__dirname}/drivers/` + helpers.upperCaseFirst(driverType),
+ adapter: `${__dirname}/adapters/${connLib}`
+ };
+
+ /*Object.keys(paths).forEach((type) => {
+ if ( ! fs.existsSync(paths[type]))
+ {
+ console.log(paths[type]);
+ throw new Error(
+ `Selected ${type} (` +
+ helpers.upperCaseFirst(driverType) +
+ `) does not exist!`
+ );
+ }
+ });*/
+
+ let driver = require(paths.driver);
+ let $adapter = require(paths.adapter);
+ let adapter = new $adapter(connObject);
+
+ this.instance = new QueryBuilder(driver, adapter);
+
+ return this.instance;
+ };
+
+ /**
+ * Return an existing query builder instance
+ *
+ * @memberOf NodeQuery
+ * @return {QueryBuilder}
+ */
+ getQuery() {
+ if ( ! this.instance) {
+ throw new Error("No Query Builder instance to return");
+ }
+
+ return this.instance;
+ };
+
+};
+
+module.exports = new NodeQuery();
\ No newline at end of file
diff --git a/src/QueryBuilder.js b/src/QueryBuilder.js
new file mode 100755
index 0000000..7d4d120
--- /dev/null
+++ b/src/QueryBuilder.js
@@ -0,0 +1,924 @@
+'use strict';
+
+/** @module QueryBuilder */
+import getArgs from 'getargs';
+import helpers from './helpers';
+import State from './State';
+import QueryParser from './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
+ * @returns {QueryBuilder}
+ * @constructor
+ */
+ constructor(driver, adapter) {
+ this.driver = driver;
+ this.adapter = adapter;
+ this.parser = new QueryParser(this.driver);
+ this.state = new State();
+ }
+
+ /**
+ * Complete the sql building based on the type provided
+ *
+ * @param {String} type
+ * @param {String} table
+ * @private
+ * @return {String}
+ */
+ _compile(type, table) {
+ // Put together the basic query
+ let sql = this._compileType(type, table);
+
+ // Set each subClause
+ ['queryMap', 'groupString', 'orderString', 'havingMap'].forEach((clause) => {
+ let param = this.state[clause];
+
+ if ( ! helpers.isScalar(param))
+ {
+ Object.keys(param).forEach((part) => {
+ sql += param[part].conjunction + param[part].string;
+ });
+ }
+ else
+ {
+ sql += param;
+ }
+ });
+
+ // Append the limit, if it exists
+ if (helpers.isNumber(this.state.limit))
+ {
+ sql = this.driver.limit(sql, this.state.limit, this.state.offset);
+ }
+
+ return sql;
+ }
+
+ _compileType(type, table) {
+ let sql = '';
+
+ switch(type) {
+ case "insert":
+ let params = Array(this.state.setArrayKeys.length).fill('?');
+
+ sql = `INSERT INTO ${table} (`;
+ sql += this.state.setArrayKeys.join(',');
+ sql += ") VALUES (";
+ sql += params.join(',') + ')';
+ break;
+
+ case "update":
+ sql = `UPDATE ${table} SET ${this.state.setString}`;
+ break;
+
+ case "delete":
+ sql = `DELETE FROM ${table}`;
+ break;
+
+ default:
+ sql = `SELECT * FROM ${this.state.fromString}`;
+
+ // Set the select string
+ if (this.state.selectString.length > 0)
+ {
+ // Replace the star with the selected fields
+ sql = sql.replace('*', this.state.selectString);
+ }
+ break;
+ }
+
+ return sql;
+ }
+
+ _like(field, val, pos, like, conj) {
+ field = this.driver.quoteIdentifiers(field);
+
+ like = `${field} ${like} ?`;
+
+ if (pos == 'before')
+ {
+ val = `%${val}`;
+ }
+ else if (pos == 'after')
+ {
+ val = `${val}%`;
+ }
+ else
+ {
+ val = `%${val}%`;
+ }
+
+ conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ` ${conj} `;
+ this._appendMap(conj, like, 'like');
+
+ this.state.whereValues.push(val);
+ }
+
+ /**
+ * Append a clause to the query map
+ *
+ * @param {String} conjunction
+ * @param {String} string
+ * @param {String} type
+ * @return {void}
+ */
+ _appendMap(conjunction, string, type) {
+ this.state.queryMap.push({
+ type: type,
+ conjunction: conjunction,
+ string: string
+ });
+ }
+
+ /**
+ * Handle key/value pairs in an object the same way as individual arguments,
+ * when appending to state
+ *
+ * @private
+ */
+ _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];
+ this.state[args.$letName].push(pushVal);
+ }
+ else
+ {
+ this.state[args.$letName][k] = obj[k];
+ }
+ });
+
+
+ return this.state[args.$letName];
+ }
+
+ _whereMixedSet(/*key, val*/) {
+ let args = getArgs('key:string|object, [val]', arguments);
+
+ this.state.whereMap = [];
+ this.state.rawWhereValues = [];
+
+ this._mixedSet('whereMap', 'both', args.key, args.val);
+ this._mixedSet('rawWhereValues', 'value', args.key, args.val);
+ }
+
+ _fixConjunction(conj) {
+ let lastItem = this.state.queryMap[this.state.queryMap.length - 1];
+ let conjunctionList = helpers.arrayPluck(this.state.queryMap, 'conjunction');
+
+ if (this.state.queryMap.length === 0 || ( ! helpers.regexInArray(conjunctionList, /^ ?WHERE/i)))
+ {
+ conj = " WHERE ";
+ }
+ else if (lastItem.type === 'groupStart')
+ {
+ conj = '';
+ }
+ else
+ {
+ conj = ' ' + conj + ' ';
+ }
+
+ return conj;
+ }
+
+ _where(key, val, defaultConj) {
+ // Normalize key and value and insert into this.state.whereMap
+ this._whereMixedSet(key, val);
+
+ // Parse the where condition to account for operators,
+ // functions, identifiers, and literal values
+ this.state = this.parser.parseWhere(this.driver, this.state);
+
+ this.state.whereMap.forEach((clause) => {
+ let conj = this._fixConjunction(defaultConj);
+ this._appendMap(conj, clause, 'where');
+ });
+
+ this.state.whereMap = {};
+ }
+
+ _whereNull(field, stmt, conj) {
+ field = this.driver.quoteIdentifiers(field);
+ let item = field + ' ' + stmt;
+
+ this._appendMap(this._fixConjunction(conj), item, 'whereNull');
+ }
+
+ _having(/*key, val, conj*/) {
+ let args = getArgs('key:string|object, [val]:string|number, [conj]:string', arguments);
+ args.conj = args.conj || 'AND';
+ args.val = args.val || null;
+
+ // Normalize key/val and put in state.whereMap
+ this._whereMixedSet(args.key, args.val);
+
+ // Parse the having condition to account for operators,
+ // functions, identifiers, and literal values
+ this.state = this.parser.parseWhere(this.driver, this.state);
+
+ this.state.whereMap.forEach((clause) => {
+ // Put in the having map
+ this.state.havingMap.push({
+ conjunction: (this.state.havingMap.length > 0) ? ` ${args.conj} ` : ' HAVING ',
+ string: clause
+ });
+ });
+
+ // Clear the where Map
+ this.state.whereMap = {};
+ }
+ _whereIn(/*key, val, inClause, conj*/) {
+ let args = getArgs('key:string, val:array, inClause:string, conj:string', arguments);
+
+ args.key = this.driver.quoteIdentifiers(args.key);
+ let params = new Array(args.val.length);
+ params.fill('?');
+
+ args.val.forEach((value) => {
+ this.state.whereValues.push(value);
+ });
+
+ args.conj = (this.state.queryMap.length > 0) ? " " + args.conj + " " : ' WHERE ';
+ let str = args.key + " " + args.inClause + " (" + params.join(',') + ") ";
+
+ this._appendMap(args.conj, str, 'whereIn');
+ }
+
+ _run(type, table, callback, sql, vals) {
+
+ if ( ! sql)
+ {
+ sql = this._compile(type, table);
+ }
+
+ if ( ! vals)
+ {
+ vals = this.state.values.concat(this.state.whereValues);
+ }
+
+//console.log(this.state);
+//console.log(sql);
+//console.log(vals);
+//console.log(callback);
+//console.log('------------------------');
+
+ // Reset the state so another query can be built
+ this._resetState();
+
+ // Pass the sql and values to the adapter to run on the database
+ this.adapter.execute(sql, vals, callback);
+
+ }
+
+ _getCompile(type, table, reset) {
+ reset = reset || false;
+
+ let sql = this._compile(type, table);
+
+ if (reset) this._resetState();
+
+ return sql;
+ }
+
+ _resetState() {
+ this.state = new State();
+ }
+
+ // ----------------------------------------------------------------------------
+ // ! Miscellaneous Methods
+ // ----------------------------------------------------------------------------
+
+ /**
+ * Reset the object state for a new query
+ *
+ * @memberOf QueryBuilder
+ * @return {void}
+ */
+ resetQuery() {
+ this._resetState();
+ }
+
+ /**
+ * Returns the current class state for testing or other purposes
+ *
+ * @private
+ * @return {Object}
+ */
+ getState() {
+ return this.state;
+ }
+
+ /**
+ * Closes the database connection for the current adapter
+ *
+ * @return {void}
+ */
+ end() {
+ this.adapter.close();
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Query Builder Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Specify rows to select in the query
+ *
+ * @memberOf QueryBuilder
+ * @param {String|Array} fields - The fields to select from the current table
+ * @return {QueryBuilder}
+ */
+ select(fields) {
+
+ // Split/trim fields by comma
+ fields = (Array.isArray(fields))
+ ? fields
+ : fields.split(",").map(helpers.stringTrim);
+
+ // Split on 'As'
+ fields.forEach((field, index) => {
+ if (field.match(/as/i))
+ {
+ fields[index] = field.split(/ as /i).map(helpers.stringTrim);
+ }
+ });
+
+ let safeArray = this.driver.quoteIdentifiers(fields);
+
+ // Join the strings back together
+ safeArray.forEach((field, index) => {
+ if (Array.isArray(field))
+ {
+ safeArray[index] = safeArray[index].join(' AS ');
+ }
+ });
+
+ this.state.selectString += safeArray.join(', ');
+
+ return this;
+ }
+
+ /**
+ * Specify the database table to select from
+ *
+ * @param {String} tableName - The table to use for the current query
+ * @return {QueryBuilder}
+ */
+ from(tableName) {
+ // Split identifiers on spaces
+ let identArray = tableName.trim().split(' ').map(helpers.stringTrim);
+
+ // Quote/prefix identifiers
+ identArray[0] = this.driver.quoteTable(identArray[0]);
+ identArray = this.driver.quoteIdentifiers(identArray);
+
+ // Put it back together
+ this.state.fromString = identArray.join(' ');
+
+ return this;
+ }
+
+ /**
+ * Add a 'like/ and like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+ like(field, val, pos) {
+ this._like(field, val, pos, ' LIKE ', 'AND');
+ return this;
+ }
+
+ /**
+ * Add a 'not like/ and not like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+ notLike(field, val, pos) {
+ this._like(field, val, pos, ' NOT LIKE ', 'AND');
+ return this;
+ }
+
+ /**
+ * Add an 'or like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+ orLike(field, val, pos) {
+ this._like(field, val, pos, ' LIKE ', 'OR');
+ return this;
+ }
+
+ /**
+ * Add an 'or not like' clause to the query
+ *
+ * @param {String} field - The name of the field to compare to
+ * @param {String} val - The value to compare to
+ * @param {String} [pos=both] - The placement of the wildcard character(s): before, after, or both
+ * @return {QueryBuilder}
+ */
+ orNotLike(field, val, pos) {
+ this._like(field, val, pos, ' NOT LIKE ', 'OR');
+ return this;
+ }
+
+ /**
+ * Add a 'having' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+ having(/*key, [val]*/) {
+ let args = getArgs('key:string|object, [val]:string|number', arguments);
+
+ this._having(args.key, args.val, 'AND');
+ return this;
+ }
+
+ /**
+ * Add an 'or having' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+ orHaving(/*key, [val]*/) {
+ let args = getArgs('key:string|object, [val]:string|number', arguments);
+
+ this._having(args.key, args.val, 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+ where(key, val) {
+ this._where(key, val, 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where' clause
+ *
+ * @param {String|Object} key - The name of the field and the comparision operator, or an object
+ * @param {String|Number} [val] - The value to compare if the value of key is a string
+ * @return {QueryBuilder}
+ */
+ orWhere(key, val) {
+ this._where(key, val, 'OR');
+ return this;
+ }
+
+ /**
+ * Select a field that is Null
+ *
+ * @param {String} field - The name of the field that has a NULL value
+ * @return {QueryBuilder}
+ */
+ whereIsNull(field) {
+ this._whereNull(field, 'IS NULL', 'AND');
+ return this;
+ }
+
+ /**
+ * Specify that a field IS NOT NULL
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+ whereIsNotNull(field) {
+ this._whereNull(field, 'IS NOT NULL', 'AND');
+ return this;
+ }
+
+ /**
+ * Field is null prefixed with 'OR'
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+ orWhereIsNull(field) {
+ this._whereNull(field, 'IS NULL', 'OR');
+ return this;
+ }
+
+ /**
+ * Field is not null prefixed with 'OR'
+ *
+ * @param {String} field
+ * @return {QueryBuilder}
+ */
+ orWhereIsNotNull(field) {
+ this._whereNull(field, 'IS NOT NULL', 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+ whereIn(key, val) {
+ this._whereIn(key, val, 'IN', 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+ orWhereIn(key, val) {
+ this._whereIn(key, val, 'IN', 'OR');
+ return this;
+ }
+
+ /**
+ * Set a 'where not in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+ whereNotIn(key, val) {
+ this._whereIn(key, val, 'NOT IN', 'AND');
+ return this;
+ }
+
+ /**
+ * Set a 'or where not in' clause
+ *
+ * @param {String} key - the field to search
+ * @param {Array} val - the array of items to search in
+ * @return {QueryBuilder}
+ */
+ orWhereNotIn(key, val) {
+ this._whereIn(key, val, 'NOT IN', 'OR');
+ return this;
+ }
+
+ /**
+ * Set values for insertion or updating
+ *
+ * @param {String|Object} key - The key or object to use
+ * @param {String} [val] - The value if using a scalar key
+ * @return {QueryBuilder}
+ */
+ set(/* $key, [$val] */) {
+ let args = getArgs('$key, [$val]', arguments);
+
+ // Set the appropriate state variables
+ this._mixedSet('setArrayKeys', 'key', args.$key, args.$val);
+ this._mixedSet('values', 'value', args.$key, args.$val);
+
+ // Use the keys of the array to make the insert/update string
+ // and escape the field names
+ this.state.setArrayKeys = this.state.setArrayKeys.map(this.driver._quote);
+
+ // Generate the "set" string
+ this.state.setString = this.state.setArrayKeys.join('=?,');
+ this.state.setString += '=?';
+
+ return this;
+ }
+
+ /**
+ * Add a join clause to the query
+ *
+ * @param {String} table - The table you are joining
+ * @param {String} cond - The join condition.
+ * @param {String} [type='inner'] - The type of join, which defaults to inner
+ * @return {QueryBuilder}
+ */
+ join(table, cond, type) {
+ type = type || "inner";
+
+ // Prefix/quote table name
+ table = table.split(' ').map(helpers.stringTrim);
+ table[0] = this.driver.quoteTable(table[0]);
+ table = table.map(this.driver.quoteIdentifiers);
+ table = table.join(' ');
+
+ // Parse out the join condition
+ let parsedCondition = this.parser.compileJoin(cond);
+ let condition = table + ' ON ' + parsedCondition;
+
+ // Append the join condition to the query map
+ this._appendMap("\n" + type.toUpperCase() + ' JOIN ', condition, 'join');
+
+ return this;
+ }
+
+ /**
+ * Group the results by the selected field(s)
+ *
+ * @param {String|Array} field
+ * @return {QueryBuilder}
+ */
+ groupBy(field) {
+ if ( ! helpers.isScalar(field))
+ {
+ let newGroupArray = field.map(this.driver.quoteIdentifiers);
+ this.state.groupArray = this.state.groupArray.concat(newGroupArray);
+ }
+ else
+ {
+ this.state.groupArray.push(this.driver.quoteIdentifiers(field));
+ }
+
+ this.state.groupString = ' GROUP BY ' + this.state.groupArray.join(',');
+
+ return this;
+ }
+
+ /**
+ * Order the results by the selected field(s)
+ *
+ * @param {String} field - The field(s) to order by
+ * @param {String} [type='ASC'] - The order direction, ASC or DESC
+ * @return {QueryBuilder}
+ */
+ orderBy(field, type) {
+ type = type || 'ASC';
+
+ // Set the fields for later manipulation
+ field = this.driver.quoteIdentifiers(field);
+
+ this.state.orderArray[field] = type;
+
+ let orderClauses = [];
+
+ // Flatten key/val pairs into an array of space-separated pairs
+ Object.keys(this.state.orderArray).forEach((key) => {
+ orderClauses.push(key + ' ' + this.state.orderArray[key].toUpperCase());
+ });
+
+ // Set the final string
+ this.state.orderString = ' ORDER BY ' + orderClauses.join(', ');
+
+ return this;
+ }
+
+ /**
+ * Put a limit on the query
+ *
+ * @param {Number} limit - The maximum number of rows to fetch
+ * @param {Number} [offset] - The row number to start from
+ * @return {QueryBuilder}
+ */
+ limit(limit, offset) {
+ this.state.limit = limit;
+ this.state.offset = offset || null;
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping
+ *
+ * @return {QueryBuilder}
+ */
+ groupStart() {
+ let conj = (this.state.queryMap.length < 1) ? ' WHERE ' : ' AND ';
+ this._appendMap(conj, '(', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping,
+ * prefixed with 'OR'
+ *
+ * @return {QueryBuilder}
+ */
+ orGroupStart() {
+ this._appendMap('', ' OR (', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Adds an open paren to the current query for logical grouping,
+ * prefixed with 'OR NOT'
+ *
+ * @return {QueryBuilder}
+ */
+ orNotGroupStart() {
+ this._appendMap('', ' OR NOT (', 'groupStart');
+
+ return this;
+ }
+
+ /**
+ * Ends a logical grouping started with one of the groupStart methods
+ *
+ * @return {QueryBuilder}
+ */
+ groupEnd() {
+ this._appendMap('', ')', 'groupEnd');
+
+ return this;
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Result Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the results of the compiled query
+ *
+ * @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}
+ */
+ get(/* [table], [limit], [offset], callback */) {
+ let args = getArgs('[table]:string, [limit]:number, [offset]:number, callback:function', arguments);
+
+ if (args.table) {
+ this.from(args.table);
+ }
+
+ if (args.limit) {
+ this.limit(args.limit, args.offset);
+ }
+
+ // Run the query
+ this._run('get', args.table, args.callback);
+ }
+
+ /**
+ * Run the generated insert query
+ *
+ * @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}
+ */
+ insert(/* table, data, callback */) {
+ 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);
+ }
+
+ /**
+ * Insert multiple sets of rows at a time
+ *
+ * @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
+ * @example query.insertBatch('foo',[{id:1,val:'bar'},{id:2,val:'baz'}], callbackFunction);
+ * @return {void}
+ */
+ insertBatch(/* table, data, callback */) {
+ 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);
+ }
+
+ /**
+ * Run the generated update query
+ *
+ * @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}
+ */
+ update(/*table, data, callback*/) {
+ 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);
+ }
+
+ /**
+ * Run the generated delete query
+ *
+ * @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}
+ */
+ delete(/*table, [where], callback*/) {
+ 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);
+ }
+
+ // ------------------------------------------------------------------------
+ // ! Methods returning SQL
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return generated select query SQL
+ *
+ * @param {String} [table] - the name of the table to retrieve from
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+ getCompiledSelect(/*table, reset*/) {
+ let args = getArgs('[table]:string, [reset]:boolean', arguments);
+ if (args.table)
+ {
+ this.from(args.table);
+ }
+
+ return this._getCompile('get', args.table, args.reset);
+ }
+
+ /**
+ * Return generated insert query SQL
+ *
+ * @param {String} table - the name of the table to insert into
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+ getCompiledInsert(table, reset) {
+ return this._getCompile('insert', this.driver.quoteTable(table), reset);
+ }
+
+ /**
+ * Return generated update query SQL
+ *
+ * @param {String} table - the name of the table to update
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+ getCompiledUpdate(table, reset) {
+ return this._getCompile('update', this.driver.quoteTable(table), reset);
+ }
+
+ /**
+ * Return generated delete query SQL
+ *
+ * @param {String} table - the name of the table to delete from
+ * @param {Boolean} [reset=true] - Whether to reset the query builder so another query can be built
+ * @return {String}
+ */
+ getCompiledDelete(table, reset) {
+ return this._getCompile('delete', this.driver.quoteTable(table), reset);
+ }
+}
\ No newline at end of file
diff --git a/lib/query-parser.js b/src/QueryParser.js
similarity index 51%
rename from lib/query-parser.js
rename to src/QueryParser.js
index 84d33b5..822a3b6 100644
--- a/lib/query-parser.js
+++ b/src/QueryParser.js
@@ -1,48 +1,7 @@
'use strict';
-var helpers = require('./helpers');
+import helpers from './helpers';
-var matchPatterns = {
- 'function': /([a-z0-9_]+\((.*)\))/i,
- operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
- literal: /([0-9]+)|'(.*?)'|true|false/ig
-};
-
-// Full pattern for identifiers
-// Making sure that literals and functions aren't matched
-matchPatterns.identifier = new RegExp(
- '('
- + '(?!'
- + matchPatterns['function'].source + '|'
- + matchPatterns.literal.source
- + ')'
- + '([a-z_\-]+[0-9]*\\.?)'
- + ')+'
-, 'ig');
-
-// Full pattern for determining ordering of the pieces
-matchPatterns.joinCombined = new RegExp(
- matchPatterns['function'].source + "+|"
- + matchPatterns.literal.source + '+|'
- + matchPatterns.identifier.source
- + '|(' + matchPatterns.operator.source + ')+'
-, 'ig');
-
-var identifierBlacklist = ['true','false','null'];
-
-var filterMatches = function(array) {
- var output = [];
-
- // Return non-array matches
- if (helpers.isNull(array)) return null;
- if (helpers.isScalar(array) || helpers.isUndefined(array)) return output;
-
- array.forEach(function(item) {
- output.push(item);
- });
-
- return output;
-};
// --------------------------------------------------------------------------
@@ -51,10 +10,63 @@ var filterMatches = function(array) {
* @param {Driver} - The driver object for the database in use
* @module query-parser
*/
-var QueryParser = function(driver) {
+module.exports = class QueryParser {
+ /**
+ * @constructor
+ * @param {Driver} - The driver object for the database in use
+ * @return {void}
+ */
+ constructor(driver) {
+ this.driver = driver;
- // That 'new' keyword is annoying
- if ( ! (this instanceof QueryParser)) return new QueryParser(driver);
+ let matchPatterns = {
+ 'function': /([a-z0-9_]+\((.*)\))/i,
+ operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
+ literal: /([0-9]+)|'(.*?)'|true|false/ig
+ };
+
+ // Full pattern for identifiers
+ // Making sure that literals and functions aren't matched
+ matchPatterns.identifier = new RegExp(
+ '('
+ + '(?!'
+ + matchPatterns['function'].source + '|'
+ + matchPatterns.literal.source
+ + ')'
+ + '([a-z_\-]+[0-9]*\\.?)'
+ + ')+'
+ , 'ig');
+
+ // Full pattern for determining ordering of the pieces
+ matchPatterns.joinCombined = new RegExp(
+ matchPatterns['function'].source + "+|"
+ + matchPatterns.literal.source + '+|'
+ + matchPatterns.identifier.source
+ + '|(' + matchPatterns.operator.source + ')+'
+ , 'ig');
+
+ this.matchPatterns = matchPatterns;
+ this.identifierBlacklist = ['true','false','null'];
+ }
+
+ /**
+ * Filter matched patterns
+ *
+ * @param {Array} array
+ * @return {Array|null}
+ */
+ filterMatches(array) {
+ let output = [];
+
+ // Return non-array matches
+ if (helpers.isNull(array)) return null;
+ if (helpers.isScalar(array) || helpers.isUndefined(array)) return output;
+
+ array.forEach((item) => {
+ output.push(item);
+ });
+ return output;
+ }
/**
* Check if the string contains an operator, and if so, return the operator(s).
@@ -63,8 +75,8 @@ var QueryParser = function(driver) {
* @param {String} string - the string to check
* @return {Array|null}
*/
- this.hasOperator = function(string) {
- return filterMatches(string.match(matchPatterns.operator));
+ hasOperator(string) {
+ return this.filterMatches(string.match(this.matchPatterns.operator));
}
/**
@@ -73,26 +85,31 @@ var QueryParser = function(driver) {
* @param {String} sql
* @return {Object}
*/
- this.parseJoin = function(sql) {
- var matches = {};
- var output = {};
+ parseJoin(sql) {
+ let matches = {};
+ let output = {
+ functions: [],
+ identifiers: [],
+ operators: [],
+ literals: []
+ };
// Get clause components
- matches.functions = sql.match(new RegExp(matchPatterns['function'].source, 'ig'));
- matches.identifiers = sql.match(matchPatterns.identifier);
- matches.operators = sql.match(matchPatterns.operator);
- matches.literals = sql.match(matchPatterns.literal);
+ matches.functions = sql.match(new RegExp(this.matchPatterns['function'].source, 'ig'));
+ matches.identifiers = sql.match(this.matchPatterns.identifier);
+ matches.operators = sql.match(this.matchPatterns.operator);
+ matches.literals = sql.match(this.matchPatterns.literal);
// Get everything at once for ordering
- matches.combined = sql.match(matchPatterns.joinCombined);
+ matches.combined = sql.match(this.matchPatterns.joinCombined);
// Flatten the matches to increase relevance
- Object.keys(matches).forEach(function(key) {
- output[key] = filterMatches(matches[key]);
+ Object.keys(matches).forEach((key) => {
+ output[key] = this.filterMatches(matches[key]);
});
return output;
- };
+ }
/**
* Return the output of the parsing of the join condition
@@ -100,40 +117,40 @@ var QueryParser = function(driver) {
* @param {String} condition - The join condition to evalate
* @return {String} - The parsed/escaped join condition
*/
- this.compileJoin = function(condition) {
- var parts = this.parseJoin(condition);
- var count = parts.identifiers.length;
- var i;
+ compileJoin(condition) {
+ let parts = this.parseJoin(condition);
+ let count = parts.identifiers.length;
+ let i;
// Quote the identifiers
- parts.combined.forEach(function(part, i) {
+ parts.combined.forEach((part, i) => {
if (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part))
{
- parts.combined[i] = driver.quoteIdentifiers(part);
+ parts.combined[i] = this.driver.quoteIdentifiers(part);
}
});
return parts.combined.join(' ');
- };
+ }
/**
* Parse a where clause to separate functions from values
*
- * @param {Object} driver
+ * @param {Driver} driver
* @param {State} state
* @return {String} - The parsed/escaped where condition
*/
- this.parseWhere = function(driver, state) {
- var whereMap = state.whereMap,
- whereValues = state.rawWhereValues;
+ parseWhere(driver, state) {
+ let whereMap = state.whereMap;
+ let whereValues = state.rawWhereValues;
- var outputMap = [];
- var outputValues = [];
+ let outputMap = [];
+ let outputValues = [];
- Object.keys(whereMap).forEach(function(key) {
+ Object.keys(whereMap).forEach((key) => {
// Combine fields, operators, functions and values into a full clause
// to have a common starting flow
- var fullClause = '';
+ let fullClause = '';
// Add an explicit = sign where one is inferred
if ( ! this.hasOperator(key))
@@ -150,17 +167,17 @@ var QueryParser = function(driver) {
}
// Separate the clause into separate pieces
- var parts = this.parseJoin(fullClause);
+ let parts = this.parseJoin(fullClause);
// Filter explicit literals from lists of matches
if (whereValues.indexOf(whereMap[key]) !== -1)
{
- var value = whereMap[key];
- var identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
- var litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
- var combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
- var funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
- var inOutputArray = outputValues.indexOf(value) !== -1;
+ let value = whereMap[key];
+ let identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
+ let litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
+ let combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
+ let funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
+ let inOutputArray = outputValues.indexOf(value) !== -1;
// Remove the identifier in question,
// and add to the output values array
@@ -207,18 +224,19 @@ var QueryParser = function(driver) {
}
// Filter false positive identifiers
- parts.identifiers = parts.identifiers.filter(function(item) {
- var isInCombinedMatches = parts.combined.indexOf(item) !== -1;
- var isNotInBlackList = identifierBlacklist.indexOf(item.toLowerCase()) === -1;
+ parts.identifiers = parts.identifiers || [];
+ parts.identifiers = parts.identifiers.filter((item) => {
+ let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
+ let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
return isInCombinedMatches && isNotInBlackList;
- });
+ }, this);
// Quote identifiers
if (helpers.isArray(parts.identifiers))
{
- parts.identifiers.forEach(function(ident) {
- var index = parts.combined.indexOf(ident);
+ parts.identifiers.forEach((ident) => {
+ let index = parts.combined.indexOf(ident);
if (index !== -1)
{
parts.combined[index] = driver.quoteIdentifiers(ident);
@@ -233,8 +251,8 @@ var QueryParser = function(driver) {
// a where condition,
if (helpers.isArray(parts.literals))
{
- parts.literals.forEach(function(lit) {
- var litIndex = parts.combined.indexOf(lit);
+ parts.literals.forEach((lit) => {
+ let litIndex = parts.combined.indexOf(lit);
if (litIndex !== -1)
{
@@ -245,14 +263,12 @@ var QueryParser = function(driver) {
}
outputMap.push(parts.combined.join(' '));
- }, this);
+ });
state.rawWhereValues = [];
state.whereValues = state.whereValues.concat(outputValues);
state.whereMap = outputMap;
return state;
- };
-};
-
-module.exports = QueryParser;
\ No newline at end of file
+ }
+}
\ No newline at end of file
diff --git a/src/State.js b/src/State.js
new file mode 100644
index 0000000..1e6a889
--- /dev/null
+++ b/src/State.js
@@ -0,0 +1,29 @@
+'use strict';
+
+/** @module State */
+module.exports = class State {
+ constructor() {
+ // Arrays/maps
+ this.queryMap = [];
+ this.values = [];
+ this.whereValues = [];
+ this.setArrayKeys = [];
+ this.orderArray = [];
+ this.groupArray = [];
+ this.havingMap = [];
+ this.whereMap = [];
+ this.rawWhereValues = [];
+
+ // Partials
+ this.selectString = '';
+ this.fromString = '';
+ this.setString = '';
+ this.orderString = '';
+ this.groupString = '';
+
+ // Other various values
+ this.limit = null;
+ this.offset = null;
+ }
+}
+// End of module State
\ No newline at end of file
diff --git a/src/adapters/dblite.js b/src/adapters/dblite.js
new file mode 100644
index 0000000..337f9fd
--- /dev/null
+++ b/src/adapters/dblite.js
@@ -0,0 +1,20 @@
+'use strict';
+
+import Adapter from '../Adapter';
+import getArgs from 'getargs';
+
+/** @module adapters/dblite */
+module.exports = class dblite extends Adapter {
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ execute(/*sql, params, callback*/) {
+ let args = getArgs('sql:string, [params]:array, callback:function', arguments);
+ this.instance.query(args.sql, args.params, args.callback);
+ };
+}
\ No newline at end of file
diff --git a/lib/adapter.js b/src/adapters/mysql.js
old mode 100755
new mode 100644
similarity index 59%
rename from lib/adapter.js
rename to src/adapters/mysql.js
index 2784ad1..2a07ccb
--- a/lib/adapter.js
+++ b/src/adapters/mysql.js
@@ -1,8 +1,9 @@
'use strict';
-/** @module adapter */
-module.exports = {
+import Adapter from '../Adapter';
+/** @module adapters/mysql */
+module.exports = class mysql extends Adapter {
/**
* Run the sql query as a prepared statement
*
@@ -11,7 +12,7 @@ module.exports = {
* @param {Function} callback - Callback to run when a response is recieved
* @return void
*/
- execute: function(/*sql, params, callback*/) {
- throw new Error("Correct adapter not defined for query execution");
+ execute(sql, params, callback) {
+ this.instance.query.apply(instance, arguments);
}
-};
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/adapters/mysql2.js b/src/adapters/mysql2.js
new file mode 100644
index 0000000..85daf2c
--- /dev/null
+++ b/src/adapters/mysql2.js
@@ -0,0 +1,18 @@
+'use strict';
+
+import Adapter from '../Adapter';
+
+/** @module adapters/mysql2 */
+module.exports = class mysql2 extends Adapter {
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ execute(sql, params, callback) {
+ this.instance.execute.apply(this.instance, arguments);
+ };
+}
\ No newline at end of file
diff --git a/src/adapters/node-firebird.js b/src/adapters/node-firebird.js
new file mode 100644
index 0000000..d60fae4
--- /dev/null
+++ b/src/adapters/node-firebird.js
@@ -0,0 +1,20 @@
+'use strict';
+
+import Adapter from '../Adapter';
+import getArgs from 'getargs';
+
+/** @module adapters/node-firebird */
+module.exports = class nodefirebird extends Adapter {
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ execute(/*sql, params, callback*/) {
+ let args = getArgs('sql:string, [params], callback:function', arguments);
+ this.instance.execute(args.sql, args.params, args.callback);
+ }
+}
\ No newline at end of file
diff --git a/src/adapters/pg.js b/src/adapters/pg.js
new file mode 100644
index 0000000..9ca4bb0
--- /dev/null
+++ b/src/adapters/pg.js
@@ -0,0 +1,28 @@
+'use strict';
+
+import Adapter from '../Adapter';
+import getArgs from 'getargs';
+
+/** @module adapters/pg */
+module.exports = class pg extends Adapter {
+ /**
+ * Run the sql query as a prepared statement
+ *
+ * @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
+ */
+ execute(/*sql, params, callback*/) {
+ let args = getArgs('sql:string, [params]:array, callback:function', arguments);
+
+ // Replace question marks with numbered placeholders, because this adapter is different...
+ let count = 0;
+ args.sql = args.sql.replace(/\?/g, () => {
+ count++;
+ return '$' + count;
+ });
+
+ this.instance.query(args.sql, args.params, args.callback);
+ }
+}
\ No newline at end of file
diff --git a/lib/drivers/firebird.js b/src/drivers/Firebird.js
similarity index 57%
rename from lib/drivers/firebird.js
rename to src/drivers/Firebird.js
index 58abafa..92f7bc4 100644
--- a/lib/drivers/firebird.js
+++ b/src/drivers/Firebird.js
@@ -1,17 +1,19 @@
"use strict";
-var helpers = require('../helpers');
+import helpers from '../helpers';
+import Driver from '../DriverClass';
/**
* Driver for Firebird databases
*
* @module drivers/firebird
*/
-module.exports = (function() {
- delete require.cache[require.resolve('../driver')];
- var driver = require('../driver');
-
- driver.hasTruncate = false;
+class Firebird extends Driver {
+ constructor() {
+ super({
+ hasTruncate: false
+ });
+ }
/**
* Generate a limit clause for firebird, which uses the syntax closest to the SQL standard
@@ -21,16 +23,16 @@ module.exports = (function() {
* @param {Number} offset
* @return {String}
*/
- driver.limit = function(origSql, limit, offset) {
- var sql = 'FIRST ' + limit;
+ limit(origSql, limit, offset) {
+ let sql = `FIRST ${limit}`;
if (helpers.isNumber(offset))
{
- sql += ' SKIP ' + offset;
+ sql += ` SKIP ${offset}`;
}
- return origSql.replace(/SELECT/i, "SELECT " + sql);;
- };
+ return origSql.replace(/SELECT/i, "SELECT " + sql);
+ }
/**
* SQL to insert a group of rows
@@ -39,9 +41,9 @@ module.exports = (function() {
* @param {Array} [data] - The array of object containing data to insert
* @return {String}
*/
- driver.insertBatch = function(table, data) {
+ insertBatch() {
throw new Error("Not Implemented");
- };
+ }
+}
- return driver;
-}());
\ No newline at end of file
+module.exports = new Firebird();
\ No newline at end of file
diff --git a/src/drivers/Mysql.js b/src/drivers/Mysql.js
new file mode 100755
index 0000000..1146231
--- /dev/null
+++ b/src/drivers/Mysql.js
@@ -0,0 +1,29 @@
+"use strict";
+
+import helpers from '../helpers';
+import Driver from '../DriverClass';
+
+/**
+ * Driver for MySQL databases
+ *
+ * @module drivers/mysql
+ */
+class Mysql extends Driver {
+ constructor() {
+ super({
+ identifierStartChar: '`',
+ identifierEndChar: '`'
+ });
+ }
+
+ limit(sql, limit, offset) {
+ if ( ! helpers.isNumber(offset))
+ {
+ return sql += ` LIMIT ${limit}`;
+ }
+
+ return sql += ` LIMIT ${offset}, ${limit}`;
+ }
+}
+
+module.exports = new Mysql();
\ No newline at end of file
diff --git a/src/drivers/Pg.js b/src/drivers/Pg.js
new file mode 100755
index 0000000..43e2fd7
--- /dev/null
+++ b/src/drivers/Pg.js
@@ -0,0 +1,10 @@
+"use strict";
+
+import Driver from '../DriverClass';
+
+/**
+ * Driver for PostgreSQL databases
+ *
+ * @module drivers/pg
+ */
+module.exports = new Driver();
\ No newline at end of file
diff --git a/src/drivers/Sqlite.js b/src/drivers/Sqlite.js
new file mode 100644
index 0000000..0dd7872
--- /dev/null
+++ b/src/drivers/Sqlite.js
@@ -0,0 +1,64 @@
+"use strict";
+
+import helpers from '../helpers';
+import Driver from '../DriverClass';
+
+/**
+ * Driver for Sqlite databases
+ *
+ * @module drivers/sqlite
+ */
+class Sqlite extends Driver {
+ constructor() {
+ super();
+ this.hasTruncate = false;
+ }
+
+ insertBatch(table, data) {
+
+ // Get the data values to insert, so they can
+ // be parameterized
+ let sql = "",
+ vals = [],
+ cols = [],
+ fields = [],
+ first = data.shift(),
+ params = [],
+ paramString = "",
+ paramList = [];
+
+
+ data.forEach((obj) => {
+ let row = [];
+ Object.keys(obj).forEach((key) => {
+ row.push(obj[key]);
+ });
+ vals.push(row);
+ });
+
+ sql += "INSERT INTO " + this.quoteTable(table) + "\n";
+
+ // Get the field names from the keys of the first
+ // object to be inserted
+ fields = Object.keys(first);
+ Object.keys(first).forEach((key) => {
+ cols.push("'" + this._quote(first[key]) + "' AS " + this.quoteIdentifiers(key));
+ });
+
+ sql += "SELECT " + cols.join(', ') + "\n";
+
+ vals.forEach((row_values) => {
+ let quoted = row_values.map((value) => {
+ return String(value).replace("'", "'\'");
+ });
+ sql += "UNION ALL SELECT '" + quoted.join("', '") + "'\n";
+ });
+
+ return {
+ sql: sql,
+ values: null
+ };
+ }
+};
+
+module.exports = new Sqlite();
\ No newline at end of file
diff --git a/src/helpers.js b/src/helpers.js
new file mode 100755
index 0000000..1458e0d
--- /dev/null
+++ b/src/helpers.js
@@ -0,0 +1,127 @@
+"use strict";
+
+//require('es6-shim');
+
+let helpers = {
+ /**
+ * Wrap String.prototype.trim in a way that is easily mappable
+ *
+ * @param {String} str - The string to trim
+ * @return {String} - The trimmed string
+ */
+ stringTrim: (str) => str.trim(),
+ /**
+ * Get the type of the variable passed
+ *
+ * @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
+ * @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
+ * @param {mixed} o
+ * @return {String}
+ */
+ type: (o) => {
+ let type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
+
+ // handle NaN and Infinity
+ if (type === 'number') {
+ if (isNaN(o)) {
+ return 'nan';
+ }
+ if (!isFinite(o)) {
+ return 'infinity';
+ }
+ }
+
+ return type;
+ },
+ /**
+ * Determine whether an object is scalar
+ *
+ * @param {mixed} obj
+ * @return {bool}
+ */
+ isScalar: (obj) => {
+ let scalar = ['string', 'number', 'boolean'];
+ return scalar.indexOf(helpers.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: (arr, key) => {
+ let output = [];
+
+ // Empty case
+ if (arr.length === 0) return output;
+
+ arr.forEach((obj) => {
+ if ( ! helpers.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: (arr, pattern) => {
+ // Empty case(s)
+ if ( ! helpers.isArray(arr)) return false;
+ if (arr.length === 0) return false;
+
+ let i, l = arr.length;
+
+ for(i=0; i< l; i++)
+ {
+ // Short circuit if any items match
+ if (pattern.test(arr[i])) return true;
+ }
+
+ return false;
+ },
+ /**
+ * Make the first letter of the string uppercase
+ *
+ * @param {String} str
+ * @return {String}
+ */
+ upperCaseFirst: (str) => {
+ str += '';
+ let first = str.charAt(0).toUpperCase();
+ return first + str.substr(1);
+ }
+};
+
+// Define an 'is' method for each type
+let types = ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp','NaN','Infinite'];
+types.forEach((t) => {
+ /**
+ * Determine whether a variable is of the type specified in the
+ * function name, eg isNumber
+ *
+ * Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
+ *
+ * @name is[type]
+ * @param {mixed} o
+ * @return {Boolean}
+ */
+ helpers['is' + t] = function (o) {
+ if (t.toLowerCase() === 'infinite')
+ {
+ t = 'infinity';
+ }
+
+ return helpers.type(o) === t.toLowerCase();
+ };
+});
+
+module.exports = helpers;
\ No newline at end of file
diff --git a/tests/adapters/dblite_test.js b/tests/adapters/dblite_test.js
index 8bf0415..6af9260 100644
--- a/tests/adapters/dblite_test.js
+++ b/tests/adapters/dblite_test.js
@@ -18,13 +18,13 @@ try {
// Export an empty testsuite if module not loaded
console.log(e);
console.log("Database adapter dblite not found");
- return {};
+ //return {};
}
if (connection)
{
// Set up the query builder object
- var nodeQuery = require('../../lib/node-query');
+ var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('sqlite', connection, adapterName);
// Set up the sqlite database
diff --git a/tests/adapters/mysql2_test.js b/tests/adapters/mysql2_test.js
index 5db53e1..324071a 100644
--- a/tests/adapters/mysql2_test.js
+++ b/tests/adapters/mysql2_test.js
@@ -16,7 +16,7 @@ var mysql2 = require(adapterName);
var connection = mysql2.createConnection(config.conn);
// Set up the query builder object
-var nodeQuery = require('../../lib/node-query');
+var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('mysql', connection, adapterName);
diff --git a/tests/adapters/mysql_test.js b/tests/adapters/mysql_test.js
index c6d3a32..e46e02e 100644
--- a/tests/adapters/mysql_test.js
+++ b/tests/adapters/mysql_test.js
@@ -16,7 +16,7 @@ var mysql = require(adapterName);
var connection = mysql.createConnection(config.conn);
// Set up the query builder object
-var nodeQuery = require('../../lib/node-query');
+var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('mysql', connection);
// Set up the test base
diff --git a/tests/adapters/node-firebird_test.js b/tests/adapters/node-firebird_test.js
index 7d4f586..d8774c7 100644
--- a/tests/adapters/node-firebird_test.js
+++ b/tests/adapters/node-firebird_test.js
@@ -7,7 +7,7 @@ var testBase = require('../query-builder-base');
var adapterName = 'node-firebird';
var config = require('../config.json')[adapterName];
config.conn.database = __dirname + config.conn.database;
-var nodeQuery = require('../../lib/node-query');
+var nodeQuery = require('../../lib/NodeQuery');
// Skip on TravisCi
if (process.env.CI || process.env.JENKINS_HOME)
diff --git a/tests/adapters/pg_test.js b/tests/adapters/pg_test.js
index 2af084a..e787420 100644
--- a/tests/adapters/pg_test.js
+++ b/tests/adapters/pg_test.js
@@ -21,7 +21,7 @@ connection.connect(function(err) {
});
// Set up the query builder object
-var nodeQuery = require('../../lib/node-query');
+var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('pg', connection);
diff --git a/tests/base_test.js b/tests/base_test.js
index 51d6fa5..8406519 100755
--- a/tests/base_test.js
+++ b/tests/base_test.js
@@ -2,13 +2,13 @@
var modules = {
helpers: require('../lib/helpers'),
- driver: require('../lib/driver'),
- qb: require('../lib/query-builder'),
- 'node-query': require('../lib/node-query'),
- 'state': require('../lib/state'),
- 'drivers/pg': require('../lib/drivers/pg'),
- 'drivers/mysql': require('../lib/drivers/mysql'),
- 'drivers/sqlite': require('../lib/drivers/sqlite'),
+ driver: require('../lib/DriverBase'),
+ qb: require('../lib/QueryBuilder'),
+ 'node-query': require('../lib/NodeQuery'),
+ 'state': require('../lib/State'),
+ 'drivers/pg': require('../lib/drivers/Pg'),
+ 'drivers/mysql': require('../lib/drivers/Mysql'),
+ 'drivers/sqlite': require('../lib/drivers/Sqlite'),
'adapters/mysql': require('../lib/adapters/mysql'),
'adapters/mysql2': require('../lib/adapters/mysql2'),
'adapters/pg': require('../lib/adapters/pg'),
diff --git a/tests/query-builder-base.js b/tests/query-builder-base.js
index 88f1ee3..8349236 100644
--- a/tests/query-builder-base.js
+++ b/tests/query-builder-base.js
@@ -1,7 +1,7 @@
'use strict';
var helpers = require('../lib/helpers');
-var State = require('../lib/state');
+var State = require('../lib/State');
module.exports = (function QueryBuilderTestBase() {
diff --git a/tests/query-parser_test.js b/tests/query-parser_test.js
index a1ccf02..a7fd249 100644
--- a/tests/query-parser_test.js
+++ b/tests/query-parser_test.js
@@ -1,12 +1,14 @@
'use strict';
// Use the base driver as a mock for testing
-delete require.cache[require.resolve('../lib/driver')];
var getArgs = require('getargs');
var helpers = require('../lib/helpers');
-var driver = require('../lib/driver');
-var parser = require('../lib/query-parser')(driver);
-var State = require('../lib/state');
+var driver = require('../lib/DriverBase');
+
+var p = require('../lib/QueryParser');
+var parser = new p(driver);
+
+var State = require('../lib/State');
// Simulate query builder state
var state = new State();
@@ -63,7 +65,7 @@ var whereMock = function() {
// ! Start Tests
// -----------------------------------------------------------------------------
-module.exports = {
+var tests = {
'Has operator tests': {
'Has operator': function(test) {
var matches = parser.hasOperator('foo <> 2');
@@ -171,4 +173,6 @@ module.exports = {
test.done();
}
}
-};
\ No newline at end of file
+};
+
+module.exports = tests;
\ No newline at end of file