Start of coversion to ES6-style code with transpiling
This commit is contained in:
parent
5f20e0adb4
commit
6a9c67b924
733
docs/index.html
733
docs/index.html
File diff suppressed because it is too large
Load Diff
127
gulpfile.js
127
gulpfile.js
@ -1,30 +1,123 @@
|
|||||||
var gulp = require('gulp'),
|
var babel = require('gulp-babel'),
|
||||||
|
concat = require('gulp-concat'),
|
||||||
documentation = require('gulp-documentation'),
|
documentation = require('gulp-documentation'),
|
||||||
|
eslint = require('gulp-eslint'),
|
||||||
|
gulp = require('gulp'),
|
||||||
|
istanbul = require('gulp-babel-istanbul'),
|
||||||
nodeunit_runner = require('gulp-nodeunit-runner'),
|
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.task('lint', function() {
|
||||||
gulp.src('./lib/node-query.js')
|
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(documentation({format: 'html'}))
|
||||||
.pipe(gulp.dest('docs'));
|
.pipe(gulp.dest('docs'));
|
||||||
gulp.src('./lib/node-query.js')
|
/*gulp.src('./lib/QueryBuilder.js')
|
||||||
.pipe(documentation({format: 'md'}))
|
.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'])
|
return gulp.src(['lib/**/*.js'])
|
||||||
.pipe(istanbul())
|
.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() {
|
gulp.task('default', ['lint', 'sloc', 'docs', 'test']);
|
||||||
return gulp.src(['tests/**/*_test.js'])
|
|
||||||
.pipe(nodeunit_runner())
|
|
||||||
.pipe(istanbul.writeReports({
|
|
||||||
dir: './coverage',
|
|
||||||
reporters: ['lcov', 'lcovonly', 'html', 'text']
|
|
||||||
}));
|
|
||||||
});
|
|
42
lib/Adapter.js
Executable file
42
lib/Adapter.js
Executable file
@ -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
|
1
lib/Adapter.js.map
Normal file
1
lib/Adapter.js.map
Normal file
@ -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/"}
|
157
lib/DriverBase.js
Executable file
157
lib/DriverBase.js
Executable file
@ -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
|
1
lib/DriverBase.js.map
Normal file
1
lib/DriverBase.js.map
Normal file
File diff suppressed because one or more lines are too long
22
lib/DriverClass.js
Normal file
22
lib/DriverClass.js
Normal file
@ -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
|
1
lib/DriverClass.js.map
Normal file
1
lib/DriverClass.js.map
Normal file
@ -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/"}
|
103
lib/NodeQuery.js
Executable file
103
lib/NodeQuery.js
Executable file
@ -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
|
1
lib/NodeQuery.js.map
Normal file
1
lib/NodeQuery.js.map
Normal file
@ -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/"}
|
1063
lib/QueryBuilder.js
Executable file
1063
lib/QueryBuilder.js
Executable file
File diff suppressed because it is too large
Load Diff
1
lib/QueryBuilder.js.map
Normal file
1
lib/QueryBuilder.js.map
Normal file
File diff suppressed because one or more lines are too long
278
lib/QueryParser.js
Normal file
278
lib/QueryParser.js
Normal file
@ -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
|
1
lib/QueryParser.js.map
Normal file
1
lib/QueryParser.js.map
Normal file
File diff suppressed because one or more lines are too long
34
lib/State.js
Normal file
34
lib/State.js
Normal file
@ -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
|
1
lib/State.js.map
Normal file
1
lib/State.js.map
Normal file
@ -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/"}
|
@ -1,29 +1,50 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var adapter = require('../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; }; })();
|
||||||
getArgs = require('getargs');
|
|
||||||
|
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 */
|
/** @module adapters/dblite */
|
||||||
var Dblite = function(instance) {
|
module.exports = (function (_Adapter) {
|
||||||
|
_inherits(dblite, _Adapter);
|
||||||
|
|
||||||
// That 'new' keyword is annoying
|
function dblite() {
|
||||||
if ( ! (this instanceof Dblite)) return new Dblite(instance);
|
_classCallCheck(this, dblite);
|
||||||
|
|
||||||
/**
|
return _possibleConstructorReturn(this, Object.getPrototypeOf(dblite).apply(this, arguments));
|
||||||
* 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);
|
|
||||||
|
|
||||||
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;
|
return dblite;
|
||||||
|
})(_Adapter3.default);
|
||||||
|
//# sourceMappingURL=dblite.js.map
|
||||||
|
1
lib/adapters/dblite.js.map
Normal file
1
lib/adapters/dblite.js.map
Normal file
@ -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/"}
|
@ -1,27 +1,45 @@
|
|||||||
'use strict';
|
'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 conn;
|
|
||||||
|
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 */
|
/** @module adapters/mysql */
|
||||||
var MySQL = function(instance) {
|
module.exports = (function (_Adapter) {
|
||||||
|
_inherits(mysql, _Adapter);
|
||||||
|
|
||||||
// That 'new' keyword is annoying
|
function mysql() {
|
||||||
if ( ! (this instanceof MySQL)) return new MySQL(instance);
|
_classCallCheck(this, mysql);
|
||||||
|
|
||||||
/**
|
return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql).apply(this, arguments));
|
||||||
* 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 adapter;
|
_createClass(mysql, [{
|
||||||
};
|
key: 'execute',
|
||||||
|
|
||||||
module.exports = 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
|
||||||
|
*/
|
||||||
|
value: function execute(sql, params, callback) {
|
||||||
|
this.instance.query.apply(instance, arguments);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return mysql;
|
||||||
|
})(_Adapter3.default);
|
||||||
|
//# sourceMappingURL=mysql.js.map
|
||||||
|
1
lib/adapters/mysql.js.map
Normal file
1
lib/adapters/mysql.js.map
Normal file
@ -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/"}
|
@ -1,26 +1,45 @@
|
|||||||
'use strict';
|
'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 */
|
/** @module adapters/mysql2 */
|
||||||
var MySQL2 = function(instance) {
|
module.exports = (function (_Adapter) {
|
||||||
|
_inherits(mysql2, _Adapter);
|
||||||
|
|
||||||
// That 'new' keyword is annoying
|
function mysql2() {
|
||||||
if ( ! (this instanceof MySQL2)) return new MySQL2(instance);
|
_classCallCheck(this, mysql2);
|
||||||
|
|
||||||
/**
|
return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql2).apply(this, arguments));
|
||||||
* 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 adapter;
|
_createClass(mysql2, [{
|
||||||
}
|
key: 'execute',
|
||||||
|
|
||||||
module.exports = 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
|
||||||
|
*/
|
||||||
|
value: function execute(sql, params, callback) {
|
||||||
|
this.instance.execute.apply(this.instance, arguments);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return mysql2;
|
||||||
|
})(_Adapter3.default);
|
||||||
|
//# sourceMappingURL=mysql2.js.map
|
||||||
|
1
lib/adapters/mysql2.js.map
Normal file
1
lib/adapters/mysql2.js.map
Normal file
@ -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/"}
|
@ -1,29 +1,50 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var adapter = require('../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; }; })();
|
||||||
getArgs = require('getargs');
|
|
||||||
|
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 */
|
/** @module adapters/node-firebird */
|
||||||
var NodeFirebird = function(instance) {
|
module.exports = (function (_Adapter) {
|
||||||
|
_inherits(nodefirebird, _Adapter);
|
||||||
|
|
||||||
// That 'new' keyword is annoying
|
function nodefirebird() {
|
||||||
if ( ! (this instanceof NodeFirebird)) return new NodeFirebird(instance);
|
_classCallCheck(this, nodefirebird);
|
||||||
|
|
||||||
/**
|
return _possibleConstructorReturn(this, Object.getPrototypeOf(nodefirebird).apply(this, arguments));
|
||||||
* 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);
|
|
||||||
|
|
||||||
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;
|
return nodefirebird;
|
||||||
|
})(_Adapter3.default);
|
||||||
|
//# sourceMappingURL=node-firebird.js.map
|
||||||
|
1
lib/adapters/node-firebird.js.map
Normal file
1
lib/adapters/node-firebird.js.map
Normal file
@ -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/"}
|
@ -1,36 +1,58 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var adapter = require('../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; }; })();
|
||||||
getArgs = require('getargs');
|
|
||||||
|
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 */
|
/** @module adapters/pg */
|
||||||
var Pg = function(instance) {
|
module.exports = (function (_Adapter) {
|
||||||
|
_inherits(pg, _Adapter);
|
||||||
|
|
||||||
// That 'new' keyword is annoying
|
function pg() {
|
||||||
if ( ! (this instanceof Pg)) return new Pg(instance);
|
_classCallCheck(this, pg);
|
||||||
|
|
||||||
/**
|
return _possibleConstructorReturn(this, Object.getPrototypeOf(pg).apply(this, arguments));
|
||||||
* 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);
|
|
||||||
|
|
||||||
// Replace question marks with numbered placeholders, because this adapter is different...
|
_createClass(pg, [{
|
||||||
var count = 0;
|
key: 'execute',
|
||||||
args.sql = args.sql.replace(/\?/g, function() {
|
|
||||||
count++;
|
|
||||||
return '$' + count;
|
|
||||||
});
|
|
||||||
|
|
||||||
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;
|
this.instance.query(args.sql, args.params, args.callback);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return pg;
|
||||||
|
})(_Adapter3.default);
|
||||||
|
//# sourceMappingURL=pg.js.map
|
||||||
|
1
lib/adapters/pg.js.map
Normal file
1
lib/adapters/pg.js.map
Normal file
@ -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/"}
|
78
lib/drivers/Firebird.js
Normal file
78
lib/drivers/Firebird.js
Normal file
@ -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
|
1
lib/drivers/Firebird.js.map
Normal file
1
lib/drivers/Firebird.js.map
Normal file
@ -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/"}
|
54
lib/drivers/Mysql.js
Executable file
54
lib/drivers/Mysql.js
Executable file
@ -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
|
1
lib/drivers/Mysql.js.map
Normal file
1
lib/drivers/Mysql.js.map
Normal file
@ -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/"}
|
15
lib/drivers/Pg.js
Executable file
15
lib/drivers/Pg.js
Executable file
@ -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
|
1
lib/drivers/Pg.js.map
Normal file
1
lib/drivers/Pg.js.map
Normal file
@ -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/"}
|
94
lib/drivers/Sqlite.js
Normal file
94
lib/drivers/Sqlite.js
Normal file
@ -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
|
1
lib/drivers/Sqlite.js.map
Normal file
1
lib/drivers/Sqlite.js.map
Normal file
@ -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/"}
|
@ -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;
|
|
||||||
|
|
||||||
}());
|
|
@ -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;
|
|
||||||
}());
|
|
@ -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;
|
|
||||||
}());
|
|
163
lib/helpers.js
163
lib/helpers.js
@ -1,68 +1,66 @@
|
|||||||
"use strict";
|
"use strict"
|
||||||
|
|
||||||
require('es6-shim');
|
//require('es6-shim');
|
||||||
/** @module helpers */
|
|
||||||
|
|
||||||
/** @alias module:helpers */
|
;
|
||||||
var h = {
|
var helpers = {
|
||||||
/**
|
/**
|
||||||
* Wrap String.prototype.trim in a way that is easily mappable
|
* Wrap String.prototype.trim in a way that is easily mappable
|
||||||
*
|
*
|
||||||
* @param {String} str - The string to trim
|
* @param {String} str - The string to trim
|
||||||
* @return {String} - The trimmed string
|
* @return {String} - The trimmed string
|
||||||
*/
|
*/
|
||||||
stringTrim: function(str) {
|
stringTrim: function stringTrim(str) {
|
||||||
return str.trim();
|
return str.trim();
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Get the type of the variable passed
|
* Get the type of the variable passed
|
||||||
*
|
*
|
||||||
* @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
|
* @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
|
||||||
* @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
|
* @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
|
||||||
* @param {mixed} o
|
* @param {mixed} o
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
type: function (o) {
|
type: function type(o) {
|
||||||
var type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
var type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
|
||||||
|
|
||||||
// handle NaN and Infinity
|
// handle NaN and Infinity
|
||||||
if (type === 'number') {
|
if (type === 'number') {
|
||||||
if (isNaN(o)) {
|
if (isNaN(o)) {
|
||||||
return 'nan';
|
return 'nan';
|
||||||
}
|
}
|
||||||
if (!isFinite(o)) {
|
if (!isFinite(o)) {
|
||||||
return 'infinity';
|
return 'infinity';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Determine whether an object is scalar
|
* Determine whether an object is scalar
|
||||||
*
|
*
|
||||||
* @param {mixed} obj
|
* @param {mixed} obj
|
||||||
* @return {bool}
|
* @return {bool}
|
||||||
*/
|
*/
|
||||||
isScalar: function(obj) {
|
isScalar: function isScalar(obj) {
|
||||||
var scalar = ['string', 'number', 'boolean'];
|
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
|
* Get a list of values with a common key from an array of objects
|
||||||
*
|
*
|
||||||
* @param {Array} arr - The array of objects to search
|
* @param {Array} arr - The array of objects to search
|
||||||
* @param {String} key - The key of the object to get
|
* @param {String} key - The key of the object to get
|
||||||
* @return {Array}
|
* @return {Array}
|
||||||
*/
|
*/
|
||||||
arrayPluck: function(arr, key) {
|
arrayPluck: function arrayPluck(arr, key) {
|
||||||
var output = [];
|
var output = [];
|
||||||
|
|
||||||
// Empty case
|
// Empty case
|
||||||
if (arr.length === 0) return output;
|
if (arr.length === 0) return output;
|
||||||
|
|
||||||
arr.forEach(function(obj) {
|
arr.forEach(function (obj) {
|
||||||
if ( ! h.isUndefined(obj[key]))
|
if (!helpers.isUndefined(obj[key])) {
|
||||||
{
|
|
||||||
output.push(obj[key]);
|
output.push(obj[key]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -70,51 +68,62 @@ var h = {
|
|||||||
return output;
|
return output;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Determine if a value matching the passed regular expression is
|
* Determine if a value matching the passed regular expression is
|
||||||
* in the passed array
|
* in the passed array
|
||||||
*
|
*
|
||||||
* @param {Array} arr - The array to search
|
* @param {Array} arr - The array to search
|
||||||
* @param {RegExp} pattern - The pattern to match
|
* @param {RegExp} pattern - The pattern to match
|
||||||
* @return {Boolean} - If an array item matches the pattern
|
* @return {Boolean} - If an array item matches the pattern
|
||||||
*/
|
*/
|
||||||
regexInArray: function(arr, pattern) {
|
regexInArray: function regexInArray(arr, pattern) {
|
||||||
// Empty case(s)
|
// Empty case(s)
|
||||||
if ( ! h.isArray(arr)) return false;
|
if (!helpers.isArray(arr)) return false;
|
||||||
if (arr.length === 0) 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
|
// Short circuit if any items match
|
||||||
if (pattern.test(arr[i])) return true;
|
if (pattern.test(arr[i])) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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
|
// 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) {
|
types.forEach(function (t) {
|
||||||
/**
|
/**
|
||||||
* Determine whether a variable is of the type specified in the
|
* Determine whether a variable is of the type specified in the
|
||||||
* function name, eg isNumber
|
* function name, eg isNumber
|
||||||
*
|
*
|
||||||
* Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
|
* Types available are Null, Undefined, Object, Array, String, Number, Boolean, Function, RegExp, NaN and Infinite
|
||||||
*
|
*
|
||||||
* @name is[type]
|
* @name is[type]
|
||||||
* @param {mixed} o
|
* @param {mixed} o
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
h['is' + t] = function (o) {
|
helpers['is' + t] = function (o) {
|
||||||
if (t.toLowerCase() === 'infinite')
|
if (t.toLowerCase() === 'infinite') {
|
||||||
{
|
t = 'infinity';
|
||||||
t = 'infinity';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return h.type(o) === t.toLowerCase();
|
return helpers.type(o) === t.toLowerCase();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = h;
|
module.exports = helpers;
|
||||||
|
//# sourceMappingURL=helpers.js.map
|
||||||
|
1
lib/helpers.js.map
Normal file
1
lib/helpers.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -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();
|
|
@ -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;
|
|
29
lib/state.js
29
lib/state.js
@ -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
|
|
16
package.json
16
package.json
@ -38,7 +38,10 @@
|
|||||||
"mysql2": "^0.15.8",
|
"mysql2": "^0.15.8",
|
||||||
"node-firebird": "^0.7.0",
|
"node-firebird": "^0.7.0",
|
||||||
"pg": "^4.4.3",
|
"pg": "^4.4.3",
|
||||||
"es6-shim": ""
|
"es6-shim": "",
|
||||||
|
"babel": "",
|
||||||
|
"babel-preset-es2015": "",
|
||||||
|
"babel-plugin-transform-es2015-modules-commonjs": ""
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"dblite": "*",
|
"dblite": "*",
|
||||||
@ -49,14 +52,19 @@
|
|||||||
"documentation": "",
|
"documentation": "",
|
||||||
"nodeunit": "",
|
"nodeunit": "",
|
||||||
"gulp": "",
|
"gulp": "",
|
||||||
|
"gulp-babel": "",
|
||||||
|
"gulp-babel-istanbul": "",
|
||||||
|
"gulp-sourcemaps": "",
|
||||||
|
"gulp-concat": "",
|
||||||
"gulp-documentation": "",
|
"gulp-documentation": "",
|
||||||
"gulp-istanbul": "",
|
|
||||||
"gulp-nodeunit-runner": "",
|
"gulp-nodeunit-runner": "",
|
||||||
"jsdoc": "",
|
"gulp-sloc": "",
|
||||||
|
"gulp-eslint": "",
|
||||||
|
"eslint": "",
|
||||||
"istanbul": ""
|
"istanbul": ""
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "grunt tests"
|
"test": "gulp nodeunit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
src/Adapter.js
Executable file
26
src/Adapter.js
Executable file
@ -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");
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var helpers = require('./helpers');
|
import helpers from './helpers'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base Database Driver
|
* Base Database Driver
|
13
src/DriverClass.js
Normal file
13
src/DriverClass.js
Normal file
@ -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];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
74
src/NodeQuery.js
Executable file
74
src/NodeQuery.js
Executable file
@ -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();
|
924
src/QueryBuilder.js
Executable file
924
src/QueryBuilder.js
Executable file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +1,7 @@
|
|||||||
'use strict';
|
'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
|
* @param {Driver} - The driver object for the database in use
|
||||||
* @module query-parser
|
* @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
|
let matchPatterns = {
|
||||||
if ( ! (this instanceof QueryParser)) return new QueryParser(driver);
|
'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).
|
* 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
|
* @param {String} string - the string to check
|
||||||
* @return {Array|null}
|
* @return {Array|null}
|
||||||
*/
|
*/
|
||||||
this.hasOperator = function(string) {
|
hasOperator(string) {
|
||||||
return filterMatches(string.match(matchPatterns.operator));
|
return this.filterMatches(string.match(this.matchPatterns.operator));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,26 +85,31 @@ var QueryParser = function(driver) {
|
|||||||
* @param {String} sql
|
* @param {String} sql
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
this.parseJoin = function(sql) {
|
parseJoin(sql) {
|
||||||
var matches = {};
|
let matches = {};
|
||||||
var output = {};
|
let output = {
|
||||||
|
functions: [],
|
||||||
|
identifiers: [],
|
||||||
|
operators: [],
|
||||||
|
literals: []
|
||||||
|
};
|
||||||
|
|
||||||
// Get clause components
|
// Get clause components
|
||||||
matches.functions = sql.match(new RegExp(matchPatterns['function'].source, 'ig'));
|
matches.functions = sql.match(new RegExp(this.matchPatterns['function'].source, 'ig'));
|
||||||
matches.identifiers = sql.match(matchPatterns.identifier);
|
matches.identifiers = sql.match(this.matchPatterns.identifier);
|
||||||
matches.operators = sql.match(matchPatterns.operator);
|
matches.operators = sql.match(this.matchPatterns.operator);
|
||||||
matches.literals = sql.match(matchPatterns.literal);
|
matches.literals = sql.match(this.matchPatterns.literal);
|
||||||
|
|
||||||
// Get everything at once for ordering
|
// 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
|
// Flatten the matches to increase relevance
|
||||||
Object.keys(matches).forEach(function(key) {
|
Object.keys(matches).forEach((key) => {
|
||||||
output[key] = filterMatches(matches[key]);
|
output[key] = this.filterMatches(matches[key]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the output of the parsing of the join condition
|
* 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
|
* @param {String} condition - The join condition to evalate
|
||||||
* @return {String} - The parsed/escaped join condition
|
* @return {String} - The parsed/escaped join condition
|
||||||
*/
|
*/
|
||||||
this.compileJoin = function(condition) {
|
compileJoin(condition) {
|
||||||
var parts = this.parseJoin(condition);
|
let parts = this.parseJoin(condition);
|
||||||
var count = parts.identifiers.length;
|
let count = parts.identifiers.length;
|
||||||
var i;
|
let i;
|
||||||
|
|
||||||
// Quote the identifiers
|
// Quote the identifiers
|
||||||
parts.combined.forEach(function(part, i) {
|
parts.combined.forEach((part, i) => {
|
||||||
if (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part))
|
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(' ');
|
return parts.combined.join(' ');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a where clause to separate functions from values
|
* Parse a where clause to separate functions from values
|
||||||
*
|
*
|
||||||
* @param {Object} driver
|
* @param {Driver} driver
|
||||||
* @param {State} state
|
* @param {State} state
|
||||||
* @return {String} - The parsed/escaped where condition
|
* @return {String} - The parsed/escaped where condition
|
||||||
*/
|
*/
|
||||||
this.parseWhere = function(driver, state) {
|
parseWhere(driver, state) {
|
||||||
var whereMap = state.whereMap,
|
let whereMap = state.whereMap;
|
||||||
whereValues = state.rawWhereValues;
|
let whereValues = state.rawWhereValues;
|
||||||
|
|
||||||
var outputMap = [];
|
let outputMap = [];
|
||||||
var outputValues = [];
|
let outputValues = [];
|
||||||
|
|
||||||
Object.keys(whereMap).forEach(function(key) {
|
Object.keys(whereMap).forEach((key) => {
|
||||||
// Combine fields, operators, functions and values into a full clause
|
// Combine fields, operators, functions and values into a full clause
|
||||||
// to have a common starting flow
|
// to have a common starting flow
|
||||||
var fullClause = '';
|
let fullClause = '';
|
||||||
|
|
||||||
// Add an explicit = sign where one is inferred
|
// Add an explicit = sign where one is inferred
|
||||||
if ( ! this.hasOperator(key))
|
if ( ! this.hasOperator(key))
|
||||||
@ -150,17 +167,17 @@ var QueryParser = function(driver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Separate the clause into separate pieces
|
// Separate the clause into separate pieces
|
||||||
var parts = this.parseJoin(fullClause);
|
let parts = this.parseJoin(fullClause);
|
||||||
|
|
||||||
// Filter explicit literals from lists of matches
|
// Filter explicit literals from lists of matches
|
||||||
if (whereValues.indexOf(whereMap[key]) !== -1)
|
if (whereValues.indexOf(whereMap[key]) !== -1)
|
||||||
{
|
{
|
||||||
var value = whereMap[key];
|
let value = whereMap[key];
|
||||||
var identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
|
let identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
|
||||||
var litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
let litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
|
||||||
var combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
|
let combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
|
||||||
var funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
let funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
|
||||||
var inOutputArray = outputValues.indexOf(value) !== -1;
|
let inOutputArray = outputValues.indexOf(value) !== -1;
|
||||||
|
|
||||||
// Remove the identifier in question,
|
// Remove the identifier in question,
|
||||||
// and add to the output values array
|
// and add to the output values array
|
||||||
@ -207,18 +224,19 @@ var QueryParser = function(driver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter false positive identifiers
|
// Filter false positive identifiers
|
||||||
parts.identifiers = parts.identifiers.filter(function(item) {
|
parts.identifiers = parts.identifiers || [];
|
||||||
var isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
parts.identifiers = parts.identifiers.filter((item) => {
|
||||||
var isNotInBlackList = identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
|
||||||
|
let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
|
||||||
|
|
||||||
return isInCombinedMatches && isNotInBlackList;
|
return isInCombinedMatches && isNotInBlackList;
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
// Quote identifiers
|
// Quote identifiers
|
||||||
if (helpers.isArray(parts.identifiers))
|
if (helpers.isArray(parts.identifiers))
|
||||||
{
|
{
|
||||||
parts.identifiers.forEach(function(ident) {
|
parts.identifiers.forEach((ident) => {
|
||||||
var index = parts.combined.indexOf(ident);
|
let index = parts.combined.indexOf(ident);
|
||||||
if (index !== -1)
|
if (index !== -1)
|
||||||
{
|
{
|
||||||
parts.combined[index] = driver.quoteIdentifiers(ident);
|
parts.combined[index] = driver.quoteIdentifiers(ident);
|
||||||
@ -233,8 +251,8 @@ var QueryParser = function(driver) {
|
|||||||
// a where condition,
|
// a where condition,
|
||||||
if (helpers.isArray(parts.literals))
|
if (helpers.isArray(parts.literals))
|
||||||
{
|
{
|
||||||
parts.literals.forEach(function(lit) {
|
parts.literals.forEach((lit) => {
|
||||||
var litIndex = parts.combined.indexOf(lit);
|
let litIndex = parts.combined.indexOf(lit);
|
||||||
|
|
||||||
if (litIndex !== -1)
|
if (litIndex !== -1)
|
||||||
{
|
{
|
||||||
@ -245,14 +263,12 @@ var QueryParser = function(driver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
outputMap.push(parts.combined.join(' '));
|
outputMap.push(parts.combined.join(' '));
|
||||||
}, this);
|
});
|
||||||
|
|
||||||
state.rawWhereValues = [];
|
state.rawWhereValues = [];
|
||||||
state.whereValues = state.whereValues.concat(outputValues);
|
state.whereValues = state.whereValues.concat(outputValues);
|
||||||
state.whereMap = outputMap;
|
state.whereMap = outputMap;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = QueryParser;
|
|
29
src/State.js
Normal file
29
src/State.js
Normal file
@ -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
|
20
src/adapters/dblite.js
Normal file
20
src/adapters/dblite.js
Normal file
@ -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);
|
||||||
|
};
|
||||||
|
}
|
11
lib/adapter.js → src/adapters/mysql.js
Executable file → Normal file
11
lib/adapter.js → src/adapters/mysql.js
Executable file → Normal file
@ -1,8 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/** @module adapter */
|
import Adapter from '../Adapter';
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
|
/** @module adapters/mysql */
|
||||||
|
module.exports = class mysql extends Adapter {
|
||||||
/**
|
/**
|
||||||
* Run the sql query as a prepared statement
|
* 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
|
* @param {Function} callback - Callback to run when a response is recieved
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
execute: function(/*sql, params, callback*/) {
|
execute(sql, params, callback) {
|
||||||
throw new Error("Correct adapter not defined for query execution");
|
this.instance.query.apply(instance, arguments);
|
||||||
}
|
}
|
||||||
};
|
}
|
18
src/adapters/mysql2.js
Normal file
18
src/adapters/mysql2.js
Normal file
@ -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);
|
||||||
|
};
|
||||||
|
}
|
20
src/adapters/node-firebird.js
Normal file
20
src/adapters/node-firebird.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
28
src/adapters/pg.js
Normal file
28
src/adapters/pg.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,19 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var helpers = require('../helpers');
|
import helpers from '../helpers';
|
||||||
|
import Driver from '../DriverClass';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Driver for Firebird databases
|
* Driver for Firebird databases
|
||||||
*
|
*
|
||||||
* @module drivers/firebird
|
* @module drivers/firebird
|
||||||
*/
|
*/
|
||||||
module.exports = (function() {
|
class Firebird extends Driver {
|
||||||
delete require.cache[require.resolve('../driver')];
|
constructor() {
|
||||||
var driver = require('../driver');
|
super({
|
||||||
|
hasTruncate: false
|
||||||
driver.hasTruncate = false;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a limit clause for firebird, which uses the syntax closest to the SQL standard
|
* 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
|
* @param {Number} offset
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
driver.limit = function(origSql, limit, offset) {
|
limit(origSql, limit, offset) {
|
||||||
var sql = 'FIRST ' + limit;
|
let sql = `FIRST ${limit}`;
|
||||||
|
|
||||||
if (helpers.isNumber(offset))
|
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
|
* 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
|
* @param {Array} [data] - The array of object containing data to insert
|
||||||
* @return {String}
|
* @return {String}
|
||||||
*/
|
*/
|
||||||
driver.insertBatch = function(table, data) {
|
insertBatch() {
|
||||||
throw new Error("Not Implemented");
|
throw new Error("Not Implemented");
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return driver;
|
module.exports = new Firebird();
|
||||||
}());
|
|
29
src/drivers/Mysql.js
Executable file
29
src/drivers/Mysql.js
Executable file
@ -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();
|
10
src/drivers/Pg.js
Executable file
10
src/drivers/Pg.js
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import Driver from '../DriverClass';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Driver for PostgreSQL databases
|
||||||
|
*
|
||||||
|
* @module drivers/pg
|
||||||
|
*/
|
||||||
|
module.exports = new Driver();
|
64
src/drivers/Sqlite.js
Normal file
64
src/drivers/Sqlite.js
Normal file
@ -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();
|
127
src/helpers.js
Executable file
127
src/helpers.js
Executable file
@ -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;
|
@ -18,13 +18,13 @@ try {
|
|||||||
// Export an empty testsuite if module not loaded
|
// Export an empty testsuite if module not loaded
|
||||||
console.log(e);
|
console.log(e);
|
||||||
console.log("Database adapter dblite not found");
|
console.log("Database adapter dblite not found");
|
||||||
return {};
|
//return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection)
|
if (connection)
|
||||||
{
|
{
|
||||||
// Set up the query builder object
|
// Set up the query builder object
|
||||||
var nodeQuery = require('../../lib/node-query');
|
var nodeQuery = require('../../lib/NodeQuery');
|
||||||
var qb = nodeQuery.init('sqlite', connection, adapterName);
|
var qb = nodeQuery.init('sqlite', connection, adapterName);
|
||||||
|
|
||||||
// Set up the sqlite database
|
// Set up the sqlite database
|
||||||
|
@ -16,7 +16,7 @@ var mysql2 = require(adapterName);
|
|||||||
var connection = mysql2.createConnection(config.conn);
|
var connection = mysql2.createConnection(config.conn);
|
||||||
|
|
||||||
// Set up the query builder object
|
// Set up the query builder object
|
||||||
var nodeQuery = require('../../lib/node-query');
|
var nodeQuery = require('../../lib/NodeQuery');
|
||||||
var qb = nodeQuery.init('mysql', connection, adapterName);
|
var qb = nodeQuery.init('mysql', connection, adapterName);
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ var mysql = require(adapterName);
|
|||||||
var connection = mysql.createConnection(config.conn);
|
var connection = mysql.createConnection(config.conn);
|
||||||
|
|
||||||
// Set up the query builder object
|
// Set up the query builder object
|
||||||
var nodeQuery = require('../../lib/node-query');
|
var nodeQuery = require('../../lib/NodeQuery');
|
||||||
var qb = nodeQuery.init('mysql', connection);
|
var qb = nodeQuery.init('mysql', connection);
|
||||||
|
|
||||||
// Set up the test base
|
// Set up the test base
|
||||||
|
@ -7,7 +7,7 @@ var testBase = require('../query-builder-base');
|
|||||||
var adapterName = 'node-firebird';
|
var adapterName = 'node-firebird';
|
||||||
var config = require('../config.json')[adapterName];
|
var config = require('../config.json')[adapterName];
|
||||||
config.conn.database = __dirname + config.conn.database;
|
config.conn.database = __dirname + config.conn.database;
|
||||||
var nodeQuery = require('../../lib/node-query');
|
var nodeQuery = require('../../lib/NodeQuery');
|
||||||
|
|
||||||
// Skip on TravisCi
|
// Skip on TravisCi
|
||||||
if (process.env.CI || process.env.JENKINS_HOME)
|
if (process.env.CI || process.env.JENKINS_HOME)
|
||||||
|
@ -21,7 +21,7 @@ connection.connect(function(err) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set up the query builder object
|
// Set up the query builder object
|
||||||
var nodeQuery = require('../../lib/node-query');
|
var nodeQuery = require('../../lib/NodeQuery');
|
||||||
var qb = nodeQuery.init('pg', connection);
|
var qb = nodeQuery.init('pg', connection);
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
var modules = {
|
var modules = {
|
||||||
helpers: require('../lib/helpers'),
|
helpers: require('../lib/helpers'),
|
||||||
driver: require('../lib/driver'),
|
driver: require('../lib/DriverBase'),
|
||||||
qb: require('../lib/query-builder'),
|
qb: require('../lib/QueryBuilder'),
|
||||||
'node-query': require('../lib/node-query'),
|
'node-query': require('../lib/NodeQuery'),
|
||||||
'state': require('../lib/state'),
|
'state': require('../lib/State'),
|
||||||
'drivers/pg': require('../lib/drivers/pg'),
|
'drivers/pg': require('../lib/drivers/Pg'),
|
||||||
'drivers/mysql': require('../lib/drivers/mysql'),
|
'drivers/mysql': require('../lib/drivers/Mysql'),
|
||||||
'drivers/sqlite': require('../lib/drivers/sqlite'),
|
'drivers/sqlite': require('../lib/drivers/Sqlite'),
|
||||||
'adapters/mysql': require('../lib/adapters/mysql'),
|
'adapters/mysql': require('../lib/adapters/mysql'),
|
||||||
'adapters/mysql2': require('../lib/adapters/mysql2'),
|
'adapters/mysql2': require('../lib/adapters/mysql2'),
|
||||||
'adapters/pg': require('../lib/adapters/pg'),
|
'adapters/pg': require('../lib/adapters/pg'),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var helpers = require('../lib/helpers');
|
var helpers = require('../lib/helpers');
|
||||||
var State = require('../lib/state');
|
var State = require('../lib/State');
|
||||||
|
|
||||||
module.exports = (function QueryBuilderTestBase() {
|
module.exports = (function QueryBuilderTestBase() {
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Use the base driver as a mock for testing
|
// Use the base driver as a mock for testing
|
||||||
delete require.cache[require.resolve('../lib/driver')];
|
|
||||||
var getArgs = require('getargs');
|
var getArgs = require('getargs');
|
||||||
var helpers = require('../lib/helpers');
|
var helpers = require('../lib/helpers');
|
||||||
var driver = require('../lib/driver');
|
var driver = require('../lib/DriverBase');
|
||||||
var parser = require('../lib/query-parser')(driver);
|
|
||||||
var State = require('../lib/state');
|
var p = require('../lib/QueryParser');
|
||||||
|
var parser = new p(driver);
|
||||||
|
|
||||||
|
var State = require('../lib/State');
|
||||||
|
|
||||||
// Simulate query builder state
|
// Simulate query builder state
|
||||||
var state = new State();
|
var state = new State();
|
||||||
@ -63,7 +65,7 @@ var whereMock = function() {
|
|||||||
// ! Start Tests
|
// ! Start Tests
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
module.exports = {
|
var tests = {
|
||||||
'Has operator tests': {
|
'Has operator tests': {
|
||||||
'Has operator': function(test) {
|
'Has operator': function(test) {
|
||||||
var matches = parser.hasOperator('foo <> 2');
|
var matches = parser.hasOperator('foo <> 2');
|
||||||
@ -171,4 +173,6 @@ module.exports = {
|
|||||||
test.done();
|
test.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = tests;
|
Loading…
Reference in New Issue
Block a user