Remove transpiling, drop node < 4, start moving tests to mocha/chai

This commit is contained in:
Timothy Warren 2015-12-03 20:43:42 -05:00
parent 6a9c67b924
commit 6b0be21782
74 changed files with 2116 additions and 5311 deletions

View File

@ -4,11 +4,10 @@ sudo: false
node_js:
- "iojs"
- "node"
- "5.1"
- "5.0"
- "4.1"
- "4.0"
- "0.12"
- "0.11"
- "0.10"
before_script:
- npm install -g gulp
@ -18,4 +17,8 @@ before_script:
- mysql -v -uroot test < ./tests/sql/mysql.sql
- psql test postgres -f ./tests/sql/pgsql.sql
script: gulp
script: gulp
matrix:
allow_failures:
- node_js: iojs

View File

@ -31,16 +31,6 @@
class='block bold'>
State
</a>
<a
href='#State'
class='block bold'>
State
</a>
<a
href='#_appendMap'
class='block bold'>
_appendMap
</a>
<a
href='#helpers'
class='block bold'>
@ -313,62 +303,6 @@
</h2>
</section>
</div><div class='py1'><section class='py2 clearfix'>
<h2 id='State' class='mt0'>
State<span class='gray'>(Driver, driver)</span>
</h2>
<h4>Parameters</h4>
<ul class='suppress-p-margin'>
<li> <strong>Driver</strong>
:
<span class='force-inline'>
<p>The driver object for the database in use</p>
</span>
</li>
<li> <strong>driver</strong>
:
<span class='force-inline'>
</span>
</li>
</ul>
</section>
</div><div class='py1'><section class='py2 clearfix'>
<h2 id='_appendMap' class='mt0'>
_appendMap<span class='gray'>(conjunction, string, type)</span>
</h2>
<p>Append a clause to the query map</p>
<h4>Parameters</h4>
<ul class='suppress-p-margin'>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>conjunction</strong>
:
<span class='force-inline'>
</span>
</li>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>string</strong>
:
<span class='force-inline'>
</span>
</li>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>type</strong>
:
<span class='force-inline'>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code>void</code></code>
<span class='force-inline'>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
<h2 id='helpers' class='mt0'>
helpers<span class='gray'>(o)</span>
@ -429,9 +363,10 @@ function name, eg isNumber</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code></code>
:
<span class='force-inline'>
<p>The new array of plucked values</p>
</span>
</section>
</div>
@ -458,15 +393,17 @@ function name, eg isNumber</p>
<li><code>mixed</code> <strong>obj</strong>
:
<span class='force-inline'>
<p>Object to test</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code>bool</code></code>
:
<span class='force-inline'>
<p>Is object scalar</p>
</span>
</section>
</div>
@ -576,15 +513,17 @@ in the passed array</p>
<li><code>mixed</code> <strong>o</strong>
:
<span class='force-inline'>
<p>Object to type check</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>Type of the object</p>
</span>
</section>
</div>
@ -611,15 +550,17 @@ in the passed array</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>str</strong>
:
<span class='force-inline'>
<p>The string to modify</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>The modified string</p>
</span>
</section>
</div>
@ -651,22 +592,16 @@ in the passed array</p>
</section>
</div><div class='py1'><section class='py2 clearfix'>
<h2 id='constructor' class='mt0'>
constructor<span class='gray'>(Driver, driver)</span>
constructor<span class='gray'>(driver)</span>
</h2>
<h4>Parameters</h4>
<ul class='suppress-p-margin'>
<li> <strong>Driver</strong>
<li><code>Driver</code> <strong>driver</strong>
:
<span class='force-inline'>
<p>The driver object for the database in use</p>
</span>
</li>
<li> <strong>driver</strong>
:
<span class='force-inline'>
</span>
</li>
</ul>
@ -738,15 +673,17 @@ in the passed array</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code> <strong>array</strong>
:
<span class='force-inline'>
<p>Set of possible matches</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code> or </code>
:
<span class='force-inline'>
<p>Filtered set of possible matches</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -767,9 +704,10 @@ in the passed array</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -842,9 +780,10 @@ in the passed array</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>The compiled sql statement</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -873,9 +812,10 @@ in the passed array</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>The compiled sql statement</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -904,9 +844,10 @@ in the passed array</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>The compiled sql statement</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -935,9 +876,10 @@ in the passed array</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code></code>
:
<span class='force-inline'>
<p>The compiled sql statement</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -951,15 +893,17 @@ in the passed array</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> or <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code> <strong>field</strong>
:
<span class='force-inline'>
<p>The name of the field to group by</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -970,9 +914,10 @@ in the passed array</p>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -983,9 +928,10 @@ in the passed array</p>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1007,9 +953,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code> or </code>
:
<span class='force-inline'>
<p>List of operators</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1037,9 +984,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1151,9 +1099,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1189,9 +1138,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1219,9 +1169,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1257,9 +1208,10 @@ If there are no matches, return null</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1271,9 +1223,10 @@ prefixed with &apos;OR&apos;</p>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1301,9 +1254,10 @@ prefixed with &apos;OR&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1339,9 +1293,10 @@ prefixed with &apos;OR&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1353,9 +1308,10 @@ prefixed with &apos;OR NOT&apos;</p>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1391,9 +1347,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1421,9 +1378,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1451,9 +1409,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1467,15 +1426,17 @@ prefixed with &apos;OR NOT&apos;</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>field</strong>
:
<span class='force-inline'>
<p>The name of the field</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1489,15 +1450,17 @@ prefixed with &apos;OR NOT&apos;</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>field</strong>
:
<span class='force-inline'>
<p>The name of the field</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1525,9 +1488,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1556,9 +1520,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1572,15 +1537,17 @@ prefixed with &apos;OR NOT&apos;</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>sql</strong>
:
<span class='force-inline'>
<p>Join sql to parse</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object</a></code></code>
:
<span class='force-inline'>
<p>Join condition components</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1594,13 +1561,15 @@ prefixed with &apos;OR NOT&apos;</p>
<li><code>Driver</code> <strong>driver</strong>
:
<span class='force-inline'>
<p>The current db driver</p>
</span>
</li>
<li><code><a href="#State">State</a></code> <strong>state</strong>
:
<span class='force-inline'>
<p>Query Builder state object</p>
</span>
</li>
</ul>
@ -1643,9 +1612,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1673,9 +1643,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1740,9 +1711,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1770,9 +1742,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1786,15 +1759,17 @@ prefixed with &apos;OR NOT&apos;</p>
<li><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code> <strong>field</strong>
:
<span class='force-inline'>
<p>The name so the field that is not to be null</p>
</span>
</li>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1815,9 +1790,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div><div class='py1'><section class='py2 clearfix'>
@ -1845,9 +1821,10 @@ prefixed with &apos;OR NOT&apos;</p>
</ul>
<h4>Returns</h4>
<code><code><a href="#QueryBuilder">QueryBuilder</a></code></code>
:
<span class='force-inline'>
<p>The Query Builder object, for chaining</p>
</span>
</section>
</div>

View File

@ -1,94 +1,72 @@
var babel = require('gulp-babel'),
concat = require('gulp-concat'),
documentation = require('gulp-documentation'),
'use strict';
const documentation = require('gulp-documentation'),
eslint = require('gulp-eslint'),
gulp = require('gulp'),
istanbul = require('gulp-babel-istanbul'),
nodeunit_runner = require('gulp-nodeunit-runner'),
sloc = require('gulp-sloc'),
sourcemaps = require('gulp-sourcemaps');
istanbul = require('gulp-istanbul'),
mocha = require('gulp-mocha'),
pipe = require('gulp-pipe'),
sloc = require('gulp-sloc');
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'));
const SRC_FILES = ['lib/**/*.js'];
const TEST_FILES = ['test/**/*_test.js'];
const ESLINT_SETTINGS = {
"env": {
"node": true,
"es6": true
},
"rules": {
"arrow-parens": [2, "as-needed"],
"no-console": [1],
"no-constant-condition": [1],
"no-extra-semi": [1],
"no-func-assign": [1],
"no-unexpected-multiline" : [2],
"radix": [2],
"no-with": [2],
"no-eval": [2],
"no-unreachable": [1],
"no-irregular-whitespace": [1],
"no-new-wrappers": [2],
"no-new-func": [2],
"curly" : [2, "multi-line"],
"no-implied-eval": [2],
"no-invalid-this": [2],
"constructor-super": [2],
"no-dupe-args": [2],
"no-dupe-keys": [2],
"no-dupe-class-members": [2],
"no-this-before-super": [2],
"prefer-arrow-callback": [1],
"no-var": [2],
"valid-jsdoc": [1],
"strict": [2, "global"],
"callback-return": [1]
}
};
gulp.task('lint', () => {
return pipe(gulp.src(SRC_FILES), [
eslint(ESLINT_SETTINGS),
eslint.format(),
eslint.failAfterError()
]);
});
gulp.task('lint', function() {
return gulp.src('src/**/*.js')
.pipe(eslint({
"env": {
"node": true,
"es6": true
},
"ecmaFeatures": {
"arrowFunctions": true,
"blockBindings": true,
"classes": true,
"defaultParams": true,
"destructuring": true,
"forOf": true,
"modules": true
},
"rules": {
"radix": [2],
"no-with": [2],
"no-eval": [2],
"no-unreachable": [2],
"no-irregular-whitespace": [1],
"no-new-wrappers": [2],
"curly" : [2, "multi-line"],
"no-implied-eval": [2],
"no-invalid-this": [2],
"constructor-super": [2],
"no-dupe-class-members": [2],
"no-this-before-super": [2],
"prefer-arrow-callback": [1],
"no-var": [1],
"valid-jsdoc": [1]
}
}))
.pipe(eslint.format())
.pipe(eslint.failAfterError());
gulp.task('lint-tests', ['lint'], () => {
return pipe(gulp.src(TEST_FILES), [
eslint(ESLINT_SETTINGS),
eslint.format(),
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', () => gulp.src(SRC_FILES).pipe(sloc()));
gulp.task('test-sloc', () => gulp.src(TEST_FILES).pipe(sloc()));
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')
gulp.task('docs', () => {
gulp.src('./lib/QueryBuilder.js')
.pipe(documentation({format: 'html'}))
.pipe(gulp.dest('docs'));
/*gulp.src('./lib/QueryBuilder.js')
@ -96,28 +74,32 @@ gulp.task('docs', ['transpile'], function() {
.pipe(gulp.dest('api-docs'));*/
});
gulp.task('nodeunit', ['transpile', 'lint-tests'], function() {
return gulp.src(['tests/**/*_test.js'])
.pipe(nodeunit_runner());
gulp.task('mocha', ['lint-tests', 'sloc'], () => {
return gulp.src(TEST_FILES)
.pipe(mocha({
ui: 'tdd',
bail: true,
//reporter: 'dot',
//reporter: 'landing',
}));
});
gulp.task('fast-test', ['transpile', 'lint-tests'], function() {
return gulp.src(['tests/**/*_test.js'])
.pipe(nodeunit_runner());
});
gulp.task('test', ['transpile', 'lint-tests'], function(cb) {
return gulp.src(['lib/**/*.js'])
.pipe(istanbul())
.pipe(istanbul.hookRequire())
.on('finish', function () {
gulp.src(['tests/**/*_test.js'])
.pipe(nodeunit_runner())
.pipe(istanbul.writeReports({
dir: './coverage',
reporters: ['lcov', 'lcovonly', 'html', 'text']
}));
});
gulp.task('test', ['test-sloc', 'lint-tests'], function(cb) {
return pipe(gulp.src(SRC_FILES), [
istanbul(),
istanbul.hookRequire()
]).on('finish', () => {
pipe(gulp.src(TEST_FILES), [
mocha({
ui: 'tdd',
bail: true
}),
istanbul.writeReports({
dir: './coverage',
reporters: ['lcov', 'lcovonly', 'html', 'text']
})
]);
});
});
gulp.task('default', ['lint', 'sloc', 'docs', 'test']);

View File

@ -1,42 +1,26 @@
'use strict'
'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 () {
module.exports = class Adapter {
/**
* Invoke an adapter
*
* @param {Object} instance - The connection objec
* @return {void}
*/
function Adapter(instance) {
_classCallCheck(this, 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}
*/
_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
* 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");
}
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,78 +1,84 @@
'use strict';
var _helpers = require('./helpers');
var _helpers2 = _interopRequireDefault(_helpers);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let helpers = require('./helpers');
/**
* Base Database Driver
*
* @module driver
*/
var d = {
let 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;
* Low level function for naive quoting of strings
* @param {String} str - The sql fragment to quote
* @return {String} - The quoted sql fragment
* @private
*/
_quote: function(str) {
return (helpers.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;
* Set the limit clause
if (_helpers2.default.isNumber(offset)) {
sql += " OFFSET " + offset;
* @param {String} sql - SQL statement to modify
* @param {Number} limit - Maximum number of rows to fetch
* @param {Number|null} offset - Number of rows to skip
* @return {String} - Modified SQL statement
*/
limit: function(sql, limit, offset) {
sql += ` LIMIT ${limit}`;
if (helpers.isNumber(offset))
{
sql += ` OFFSET ${offset}`;
}
return sql;
},
/**
* Quote database table name, and set prefix
*
* @param {String} table
* @return {String}
*/
quoteTable: function quoteTable(table) {
* Quote database table name, and set prefix
*
* @param {String} table - Table name to quote
* @return {String} - Quoted table name
*/
quoteTable: function(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');
* Use the driver's escape character to quote identifiers
*
* @param {String|String[]} - String or array of strings to quote identifiers
* @return {String|String[]} - Quoted identifier(s)
*/
quoteIdentifiers: function(str) {
let hiers, raw;
let pattern = new RegExp(
`${d.identifierStartChar}(`
+ '([a-zA-Z0-9_]+)' + '(\((.*?)\))'
+ `)${d.identifierEndChar}`, 'ig');
// Recurse for arrays of identifiiers
if (Array.isArray(str)) {
if (Array.isArray(str))
{
return str.map(d.quoteIdentifiers);
}
// Handle commas
if (str.includes(',')) {
var parts = str.split(',').map(_helpers2.default.stringTrim);
if (str.includes(','))
{
let parts = str.split(',').map(helpers.stringTrim);
str = parts.map(d.quoteIdentifiers).join(',');
}
@ -81,14 +87,15 @@ var d = {
raw = hiers.join('.');
// Fix functions
if (raw.includes('(') && raw.includes(')')) {
var funcs = pattern.exec(raw);
if (raw.includes('(') && raw.includes(')'))
{
let 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);
let inParens = funcs[3].substring(1, funcs[3].length -1);
raw = raw.replace(inParens, d.quoteIdentifiers(inParens));
}
@ -96,13 +103,15 @@ var d = {
},
/**
* SQL to truncate the passed table
*
* @param {String} table
* @return {String} - sql
*/
truncate: function truncate(table) {
var sql = d.hasTruncate ? 'TRUNCATE ' : 'DELETE FROM ';
* SQL to truncate the passed table
*
* @param {String} table - Table to truncate
* @return {String} - Truncation SQL
*/
truncate: function(table) {
let sql = (d.hasTruncate)
? 'TRUNCATE '
: 'DELETE FROM ';
sql += d.quoteTable(table);
@ -110,24 +119,24 @@ var d = {
},
/**
* 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 = [];
* 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} - Query and data to insert
*/
insertBatch: function(table, data) {
let 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) {
data.forEach(obj => {
Object.keys(obj).forEach(key => {
vals.push(obj[key]);
});
});
@ -136,7 +145,9 @@ var d = {
// object inserted
table = d.quoteTable(table);
sql += "INSERT INTO " + table + " (" + d.quoteIdentifiers(fields).join(",") + ") VALUES ";
sql += `INSERT INTO ${table} (`
+ d.quoteIdentifiers(fields).join(",")
+ ") VALUES ";
// Create placeholder groups
params = Array(fields.length).fill('?');
@ -153,5 +164,4 @@ var d = {
};
module.exports = d;
//# sourceMappingURL=DriverBase.js.map
module.exports = d;

File diff suppressed because one or more lines are too long

View File

@ -1,22 +1,18 @@
'use strict';
var _DriverBase = require('./DriverBase');
let driverBase = require('./DriverBase'),
getArgs = require('getargs');
var _DriverBase2 = _interopRequireDefault(_DriverBase);
module.exports = class DriverClass {
constructor(/* properties:object */) {
let args = getArgs('[properties]:object', arguments);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
args.properties = args.properties || {};
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
Object.keys(driverBase).forEach(key => {
this[key] = (Object.keys(args.properties).indexOf(key) !== -1)
? args.properties[key]
: driverBase[key];
});
}
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,103 +1,74 @@
"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;
let instance = null;
let fs = require('fs'),
helpers = require('./helpers'),
QueryBuilder = require('./QueryBuilder');
/**
* @module NodeQuery
*/
var NodeQuery = (function () {
class NodeQuery {
/**
* Constructor
*/
function NodeQuery() {
_classCallCheck(this, NodeQuery);
* Constructor
*
* @return {void}
*/
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}
*/
* Create a query builder object
*
* @memberOf NodeQuery
* @param {String} driverType - 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} - The Query Builder object
*/
init(driverType, connObject, connLib) {
connLib = connLib || driverType;
_createClass(NodeQuery, [{
key: 'init',
value: function init(driverType, connObject, connLib) {
connLib = connLib || driverType;
let paths = {
driver: `${__dirname}/drivers/` + helpers.upperCaseFirst(driverType),
adapter: `${__dirname}/adapters/${connLib}`
};
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");
Object.keys(paths).forEach(type => {
if ( ! fs.existsSync(paths[type]))
{
throw new Error(
`Selected ${type} (` +
helpers.upperCaseFirst(driverType) +
`) does not exist!`
);
}
});
return this.instance;
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
*
* @return {QueryBuilder} - The Query Builder object
*/
getQuery() {
if ( ! this.instance) {
throw new Error("No Query Builder instance to return");
}
}]);
return NodeQuery;
})();
return this.instance;
}
;
}
module.exports = new NodeQuery();
//# sourceMappingURL=NodeQuery.js.map
module.exports = new NodeQuery();

View File

@ -1 +0,0 @@
{"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/"}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,35 +1,20 @@
'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"); } }
let helpers = require('./helpers');
// --------------------------------------------------------------------------
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @module query-parser
*/
module.exports = (function () {
module.exports = class QueryParser {
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @return {void}
*/
function QueryParser(driver) {
_classCallCheck(this, QueryParser);
* @constructor
*
* @param {Driver} driver - The driver object for the database in use
* @return {void}
*/
constructor(driver) {
this.driver = driver;
var matchPatterns = {
let matchPatterns = {
'function': /([a-z0-9_]+\((.*)\))/i,
operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
literal: /([0-9]+)|'(.*?)'|true|false/ig
@ -37,242 +22,248 @@ module.exports = (function () {
// 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');
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');
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'];
this.identifierBlacklist = ['true','false','null'];
}
/**
* Filter matched patterns
*
* @param {Array} array
* @return {Array|null}
*/
* Filter matched patterns
*
* @param {Array} array - Set of possible matches
* @return {Array|null} - Filtered set of possible matches
*/
filterMatches(array) {
let output = [];
_createClass(QueryParser, [{
key: 'filterMatches',
value: function filterMatches(array) {
var output = [];
// Return non-array matches
if (helpers.isNull(array)) return null;
if (helpers.isScalar(array) || helpers.isUndefined(array)) return 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(item => {
output.push(item);
});
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} - List of operators
*/
hasOperator(string) {
return this.filterMatches(string.match(this.matchPatterns.operator));
}
/**
* 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}
*/
/**
* Tokenize the sql into parts for additional processing
*
* @param {String} sql - Join sql to parse
* @return {Object} - Join condition components
*/
parseJoin(sql) {
let matches = {};
let output = {
functions: [],
identifiers: [],
operators: [],
literals: []
};
}, {
key: 'hasOperator',
value: function hasOperator(string) {
return this.filterMatches(string.match(this.matchPatterns.operator));
}
// 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);
/**
* Tokenize the sql into parts for additional processing
*
* @param {String} sql
* @return {Object}
*/
// Get everything at once for ordering
matches.combined = sql.match(this.matchPatterns.joinCombined);
}, {
key: 'parseJoin',
value: function parseJoin(sql) {
var _this = this;
// Flatten the matches to increase relevance
Object.keys(matches).forEach(key => {
output[key] = this.filterMatches(matches[key]);
});
var matches = {};
var output = {
functions: [],
identifiers: [],
operators: [],
literals: []
};
return output;
}
// 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);
/**
* 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
*/
compileJoin(condition) {
let parts = this.parseJoin(condition);
let count = parts.identifiers.length;
let i;
// Get everything at once for ordering
matches.combined = sql.match(this.matchPatterns.joinCombined);
// Quote the identifiers
parts.combined.forEach((part, i) => {
if (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part))
{
parts.combined[i] = this.driver.quoteIdentifiers(part);
}
});
// Flatten the matches to increase relevance
Object.keys(matches).forEach(function (key) {
output[key] = _this.filterMatches(matches[key]);
});
return parts.combined.join(' ');
}
return output;
}
/**
* Parse a where clause to separate functions from values
*
* @param {Driver} driver - The current db driver
* @param {State} state - Query Builder state object
* @return {String} - The parsed/escaped where condition
*/
parseWhere(driver, state) {
let whereMap = state.whereMap;
let whereValues = state.rawWhereValues;
/**
* 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
*/
let outputMap = [];
let outputValues = [];
}, {
key: 'compileJoin',
value: function compileJoin(condition) {
var _this2 = this;
Object.keys(whereMap).forEach(key => {
// Combine fields, operators, functions and values into a full clause
// to have a common starting flow
let fullClause = '';
var parts = this.parseJoin(condition);
var count = parts.identifiers.length;
var i = undefined;
// Add an explicit = sign where one is inferred
if ( ! this.hasOperator(key))
{
fullClause = key + ' = ' + whereMap[key];
}
else if (whereMap[key] === key)
{
fullClause = key;
}
else
{
fullClause = key + ' ' + whereMap[key];
}
// 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);
}
});
// Separate the clause into separate pieces
let parts = this.parseJoin(fullClause);
return parts.combined.join(' ');
}
// Filter explicit literals from lists of matches
if (whereValues.indexOf(whereMap[key]) !== -1)
{
let value = whereMap[key];
let identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
let litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
let combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
let funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
let inOutputArray = outputValues.indexOf(value) !== -1;
/**
* Parse a where clause to separate functions from values
*
* @param {Driver} driver
* @param {State} state
* @return {String} - The parsed/escaped where condition
*/
// Remove the identifier in question,
// and add to the output values array
if (identIndex !== -1)
{
parts.identifiers.splice(identIndex, 1);
}, {
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];
if ( ! inOutputArray)
{
outputValues.push(value);
inOutputArray = true;
}
}
// Separate the clause into separate pieces
var parts = _this3.parseJoin(fullClause);
// Remove the value from the literals list
// so it is not added twice
if (litIndex !== -1)
{
parts.literals.splice(litIndex, 1);
// 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;
if ( ! inOutputArray)
{
outputValues.push(value);
inOutputArray = true;
}
}
// Remove the identifier in question,
// and add to the output values array
if (identIndex !== -1) {
parts.identifiers.splice(identIndex, 1);
// 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) {
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);
// Filter false positive identifiers
parts.identifiers = parts.identifiers || [];
parts.identifiers = parts.identifiers.filter(item => {
let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
if (!inOutputArray) {
outputValues.push(value);
inOutputArray = true;
}
return isInCombinedMatches && isNotInBlackList;
}, this);
// Quote identifiers
if (helpers.isArray(parts.identifiers))
{
parts.identifiers.forEach(ident => {
let index = parts.combined.indexOf(ident);
if (index !== -1)
{
parts.combined[index] = driver.quoteIdentifiers(ident);
}
});
}
// 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] = '?';
// 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 (helpers.isArray(parts.literals))
{
parts.literals.forEach(lit => {
let litIndex = parts.combined.indexOf(lit);
if (!inOutputArray) {
outputValues.push(value);
inOutputArray = true;
}
}
if (litIndex !== -1)
{
parts.combined[litIndex] = (helpers.isArray(parts.operators)) ? '?' : '= ?';
outputValues.push(lit);
}
}
});
}
// 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;
outputMap.push(parts.combined.join(' '));
});
return isInCombinedMatches && isNotInBlackList;
}, _this3);
state.rawWhereValues = [];
state.whereValues = state.whereValues.concat(outputValues);
state.whereMap = outputMap;
// 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
return state;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,34 +1,29 @@
'use strict'
'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 = [];
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// Partials
this.selectString = '';
this.fromString = '';
this.setString = '';
this.orderString = '';
this.groupString = '';
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
// Other various values
this.limit = null;
this.offset = null;
}
}
// End of module State

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,50 +1,19 @@
'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; }; })();
let Adapter = require('../Adapter'),
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.exports = (function (_Adapter) {
_inherits(dblite, _Adapter);
function dblite() {
_classCallCheck(this, dblite);
return _possibleConstructorReturn(this, Object.getPrototypeOf(dblite).apply(this, arguments));
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);
}
_createClass(dblite, [{
key: 'execute',
/**
* 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);
}
}]);
return dblite;
})(_Adapter3.default);
//# sourceMappingURL=dblite.js.map
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,45 +1,20 @@
'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; }; })();
let Adapter = require('../Adapter'),
getArgs = require('getargs');
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.exports = (function (_Adapter) {
_inherits(mysql, _Adapter);
function mysql() {
_classCallCheck(this, mysql);
return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql).apply(this, arguments));
module.exports = class mysql 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);
return this.instance.query(args.sql, args.params, args.callback);
//this.instance.query.apply(this.instance, Array(args));
}
_createClass(mysql, [{
key: 'execute',
/**
* 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
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,45 +1,20 @@
'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; }; })();
let Adapter = require('../Adapter'),
getArgs = require('getargs');
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.exports = (function (_Adapter) {
_inherits(mysql2, _Adapter);
function mysql2() {
_classCallCheck(this, mysql2);
return _possibleConstructorReturn(this, Object.getPrototypeOf(mysql2).apply(this, arguments));
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*/) {
let args = getArgs('sql:string, [params], callback:function', arguments);
return this.instance.execute(args.sql, args.params, args.callback);
//this.instance.execute.apply(this.instance, args);
}
_createClass(mysql2, [{
key: 'execute',
/**
* 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
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,50 +1,19 @@
'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; }; })();
let Adapter = require('../Adapter'),
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.exports = (function (_Adapter) {
_inherits(nodefirebird, _Adapter);
function nodefirebird() {
_classCallCheck(this, nodefirebird);
return _possibleConstructorReturn(this, Object.getPrototypeOf(nodefirebird).apply(this, arguments));
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);
return this.instance.execute(args.sql, args.params, args.callback);
}
_createClass(nodefirebird, [{
key: 'execute',
/**
* 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);
}
}]);
return nodefirebird;
})(_Adapter3.default);
//# sourceMappingURL=node-firebird.js.map
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,58 +1,27 @@
'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; }; })();
let Adapter = require('../Adapter'),
getArgs = require('getargs');
var _Adapter2 = require('../Adapter');
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);
var _Adapter3 = _interopRequireDefault(_Adapter2);
// Replace question marks with numbered placeholders, because this adapter is different...
let count = 0;
args.sql = args.sql.replace(/\?/g, () => {
count++;
return '$' + count;
});
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.exports = (function (_Adapter) {
_inherits(pg, _Adapter);
function pg() {
_classCallCheck(this, pg);
return _possibleConstructorReturn(this, Object.getPrototypeOf(pg).apply(this, arguments));
this.instance.query(args.sql, args.params, args.callback);
}
_createClass(pg, [{
key: 'execute',
/**
* 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);
// Replace question marks with numbered placeholders, because this adapter is different...
var count = 0;
args.sql = args.sql.replace(/\?/g, function () {
count++;
return '$' + count;
});
this.instance.query(args.sql, args.params, args.callback);
}
}]);
return pg;
})(_Adapter3.default);
//# sourceMappingURL=pg.js.map
}

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,78 +1,44 @@
"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; }; })();
let helpers = require('../helpers'),
Driver = require('../DriverClass');
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, {
class Firebird extends Driver {
constructor() {
super({
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}
*/
* Set the limit clause
*
* @param {String} origSql - SQL statement to modify
* @param {Number} limit - Maximum number of rows to fetch
* @param {Number|null} offset - Number of rows to skip
* @return {String} - Modified SQL statement
*/
limit(origSql, limit, offset) {
let sql = `FIRST ${limit}`;
_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);
if (helpers.isNumber(offset))
{
sql += ` SKIP ${offset}`;
}
/**
* 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}
*/
return origSql.replace(/SELECT/i, "SELECT " + sql);
}
}, {
key: 'insertBatch',
value: function insertBatch() {
throw new Error("Not Implemented");
}
}]);
/**
* 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} - Query and data to insert
*/
insertBatch() {
throw new Error("Not Implemented");
}
}
return Firebird;
})(_DriverClass2.default);
module.exports = new Firebird();
//# sourceMappingURL=Firebird.js.map
module.exports = new Firebird();

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,54 +1,32 @@
"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; }; })();
let helpers = require('../helpers'),
Driver = require('../DriverClass');
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, {
class Mysql extends Driver {
constructor() {
super({
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;
/**
* Set the limit clause
*
* @param {String} sql - SQL statement to modify
* @param {Number} limit - Maximum number of rows to fetch
* @param {Number|null} offset - Number of rows to skip
* @return {String} - Modified SQL statement
*/
limit(sql, limit, offset) {
if ( ! helpers.isNumber(offset))
{
return sql += ` LIMIT ${limit}`;
}
}]);
return Mysql;
})(_DriverClass2.default);
return sql += ` LIMIT ${offset}, ${limit}`;
}
}
module.exports = new Mysql();
//# sourceMappingURL=Mysql.js.map
module.exports = new Mysql();

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,15 +1,10 @@
"use strict";
var _DriverClass = require("../DriverClass");
var _DriverClass2 = _interopRequireDefault(_DriverClass);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let Driver = require('../DriverClass');
/**
* Driver for PostgreSQL databases
*
* @module drivers/pg
*/
module.exports = new _DriverClass2.default();
//# sourceMappingURL=Pg.js.map
module.exports = new Driver();

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,94 +1,66 @@
"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; }; })();
let helpers = require('../helpers'),
Driver = require('../DriverClass');
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;
class Sqlite extends Driver {
constructor() {
super({
hasTruncate: false
});
}
_createClass(Sqlite, [{
key: 'insertBatch',
value: function insertBatch(table, data) {
var _this2 = this;
/**
* 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} - Query and data to insert
*/
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 = [];
// 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);
data.forEach(obj => {
let row = [];
Object.keys(obj).forEach(key => {
row.push(obj[key]);
});
vals.push(row);
});
sql += "INSERT INTO " + this.quoteTable(table) + "\n";
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));
// 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";
});
sql += "SELECT " + cols.join(', ') + "\n";
return {
sql: sql,
values: null
};
}
}
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
module.exports = new Sqlite();

View File

@ -1 +0,0 @@
{"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/"}

View File

@ -1,66 +1,62 @@
"use strict"
"use strict";
//require('es6-shim');
;
var helpers = {
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: function stringTrim(str) {
return str.trim();
* 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 - Object to type check
* @return {String} - Type of the object
*/
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;
},
/**
* Get the type of the variable passed
*
* @see https://techblog.badoo.com/blog/2013/11/01/type-checking-in-javascript/
* @see http://toddmotto.com/understanding-javascript-types-and-reliable-type-checking/
* @param {mixed} o
* @return {String}
*/
type: function type(o) {
var type = Object.prototype.toString.call(o).slice(8, -1).toLowerCase();
// handle NaN and Infinity
if (type === 'number') {
if (isNaN(o)) {
return 'nan';
}
if (!isFinite(o)) {
return 'infinity';
}
}
return type;
},
/**
* Determine whether an object is scalar
*
* @param {mixed} obj
* @return {bool}
*/
isScalar: function isScalar(obj) {
var scalar = ['string', 'number', 'boolean'];
* Determine whether an object is scalar
*
* @param {mixed} obj - Object to test
* @return {bool} - Is object scalar
*/
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: function arrayPluck(arr, key) {
var output = [];
* 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} - The new array of plucked values
*/
arrayPluck: (arr, key) => {
let output = [];
// Empty case
if (arr.length === 0) return output;
arr.forEach(function (obj) {
if (!helpers.isUndefined(obj[key])) {
arr.forEach(obj => {
if ( ! helpers.isUndefined(obj[key]))
{
output.push(obj[key]);
}
});
@ -68,22 +64,22 @@ var helpers = {
return output;
},
/**
* Determine if a value matching the passed regular expression is
* in the passed array
*
* @param {Array} arr - The array to search
* @param {RegExp} pattern - The pattern to match
* @return {Boolean} - If an array item matches the pattern
*/
regexInArray: function regexInArray(arr, pattern) {
* Determine if a value matching the passed regular expression is
* in the passed array
*
* @param {Array} arr - The array to search
* @param {RegExp} pattern - The pattern to match
* @return {Boolean} - If an array item matches the pattern
*/
regexInArray: (arr, pattern) => {
// Empty case(s)
if (!helpers.isArray(arr)) return false;
if ( ! helpers.isArray(arr)) return false;
if (arr.length === 0) return false;
var i = undefined,
l = arr.length;
let i, l = arr.length;
for (i = 0; i < l; i++) {
for(i=0; i< l; i++)
{
// Short circuit if any items match
if (pattern.test(arr[i])) return true;
}
@ -91,39 +87,39 @@ var helpers = {
return false;
},
/**
* Make the first letter of the string uppercase
*
* @param {String} str
* @return {String}
*/
upperCaseFirst: function upperCaseFirst(str) {
* Make the first letter of the string uppercase
*
* @param {String} str - The string to modify
* @return {String} - The modified string
*/
upperCaseFirst: str => {
str += '';
var first = str.charAt(0).toUpperCase();
let first = str.charAt(0).toUpperCase();
return first + str.substr(1);
}
};
// Define an 'is' method for each type
var types = ['Null', 'Undefined', 'Object', 'Array', 'String', 'Number', 'Boolean', 'Function', 'RegExp', 'NaN', 'Infinite'];
types.forEach(function (t) {
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';
}
* 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();
};
return helpers.type(o) === t.toLowerCase();
};
});
module.exports = helpers;
//# sourceMappingURL=helpers.js.map
module.exports = helpers;

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
"description": "A query builder for node based on the one in CodeIgniter",
"author": "Timothy J Warren <tim@timshomepage.net>",
"engines": {
"node": ">=0.10.0"
"node": ">=4.0.0"
},
"contributors": [
{
@ -38,10 +38,7 @@
"mysql2": "^0.15.8",
"node-firebird": "^0.7.0",
"pg": "^4.4.3",
"es6-shim": "",
"babel": "",
"babel-preset-es2015": "",
"babel-plugin-transform-es2015-modules-commonjs": ""
"require-reload": "*"
},
"optionalDependencies": {
"dblite": "*",
@ -49,22 +46,21 @@
"pg": "*"
},
"devDependencies": {
"chai": "",
"documentation": "",
"nodeunit": "",
"gulp": "",
"gulp-babel": "",
"gulp-babel-istanbul": "",
"gulp-sourcemaps": "",
"gulp-concat": "",
"gulp-documentation": "",
"gulp-nodeunit-runner": "",
"gulp-sloc": "",
"gulp-eslint": "",
"eslint": "",
"istanbul": ""
"gulp": "",
"gulp-documentation": "^2.1.0",
"gulp-eslint": "",
"gulp-istanbul": "^0.10.3",
"gulp-mocha": "^2.2.0",
"gulp-pipe": "^1.0.4",
"gulp-sloc": "",
"istanbul": "",
"mocha": ""
},
"license": "MIT",
"scripts": {
"test": "gulp nodeunit"
"test": "gulp test"
}
}

View File

@ -1,5 +1,5 @@
sonar.projectKey=node-query
sonar.projectName=NodeJS Query Builder
sonar.projectVersion=2.2.1
sonar.projectVersion=3.0.0
sonar.sources=lib
sonar.javascript.lcov.reportPath=coverage/lcov.info

View File

@ -1,26 +0,0 @@
'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");
}
}

View File

@ -1,164 +0,0 @@
'use strict';
import helpers from './helpers'
/**
* 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(str) {
return (helpers.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(sql, limit, offset) {
sql += " LIMIT " + limit;
if (helpers.isNumber(offset))
{
sql += " OFFSET " + offset;
}
return sql;
},
/**
* Quote database table name, and set prefix
*
* @param {String} table
* @return {String}
*/
quoteTable: function(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(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(helpers.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(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(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;

View File

@ -1,13 +0,0 @@
'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];
});
}
}

View File

@ -1,74 +0,0 @@
"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();

View File

@ -1,924 +0,0 @@
'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);
}
}

View File

@ -1,274 +0,0 @@
'use strict';
import helpers from './helpers';
// --------------------------------------------------------------------------
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @module query-parser
*/
module.exports = class QueryParser {
/**
* @constructor
* @param {Driver} - The driver object for the database in use
* @return {void}
*/
constructor(driver) {
this.driver = driver;
let matchPatterns = {
'function': /([a-z0-9_]+\((.*)\))/i,
operator: /\!=?|\=|\+|&&?|~|\|\|?|\^|\/|<>|>=?|<=?|\-|%|OR|AND|NOT|XOR/ig,
literal: /([0-9]+)|'(.*?)'|true|false/ig
};
// Full pattern for identifiers
// Making sure that literals and functions aren't matched
matchPatterns.identifier = new RegExp(
'('
+ '(?!'
+ matchPatterns['function'].source + '|'
+ matchPatterns.literal.source
+ ')'
+ '([a-z_\-]+[0-9]*\\.?)'
+ ')+'
, 'ig');
// Full pattern for determining ordering of the pieces
matchPatterns.joinCombined = new RegExp(
matchPatterns['function'].source + "+|"
+ matchPatterns.literal.source + '+|'
+ matchPatterns.identifier.source
+ '|(' + matchPatterns.operator.source + ')+'
, 'ig');
this.matchPatterns = matchPatterns;
this.identifierBlacklist = ['true','false','null'];
}
/**
* Filter matched patterns
*
* @param {Array} array
* @return {Array|null}
*/
filterMatches(array) {
let output = [];
// Return non-array matches
if (helpers.isNull(array)) return null;
if (helpers.isScalar(array) || helpers.isUndefined(array)) return output;
array.forEach((item) => {
output.push(item);
});
return output;
}
/**
* Check if the string contains an operator, and if so, return the operator(s).
* If there are no matches, return null
*
* @param {String} string - the string to check
* @return {Array|null}
*/
hasOperator(string) {
return this.filterMatches(string.match(this.matchPatterns.operator));
}
/**
* Tokenize the sql into parts for additional processing
*
* @param {String} sql
* @return {Object}
*/
parseJoin(sql) {
let matches = {};
let 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((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
*/
compileJoin(condition) {
let parts = this.parseJoin(condition);
let count = parts.identifiers.length;
let i;
// Quote the identifiers
parts.combined.forEach((part, i) => {
if (parts.identifiers.indexOf(part) !== -1 && ! helpers.isNumber(part))
{
parts.combined[i] = this.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
*/
parseWhere(driver, state) {
let whereMap = state.whereMap;
let whereValues = state.rawWhereValues;
let outputMap = [];
let outputValues = [];
Object.keys(whereMap).forEach((key) => {
// Combine fields, operators, functions and values into a full clause
// to have a common starting flow
let fullClause = '';
// Add an explicit = sign where one is inferred
if ( ! this.hasOperator(key))
{
fullClause = key + ' = ' + whereMap[key];
}
else if (whereMap[key] === key)
{
fullClause = key;
}
else
{
fullClause = key + ' ' + whereMap[key];
}
// Separate the clause into separate pieces
let parts = this.parseJoin(fullClause);
// Filter explicit literals from lists of matches
if (whereValues.indexOf(whereMap[key]) !== -1)
{
let value = whereMap[key];
let identIndex = (helpers.isArray(parts.identifiers)) ? parts.identifiers.indexOf(value) : -1;
let litIndex = (helpers.isArray(parts.literals)) ? parts.literals.indexOf(value) : -1;
let combIndex = (helpers.isArray(parts.combined)) ? parts.combined.indexOf(value) : -1;
let funcIndex = (helpers.isArray(parts.functions)) ? parts.functions.indexOf(value) : -1;
let inOutputArray = outputValues.indexOf(value) !== -1;
// Remove the identifier in question,
// and add to the output values array
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((item) => {
let isInCombinedMatches = parts.combined.indexOf(item) !== -1;
let isNotInBlackList = this.identifierBlacklist.indexOf(item.toLowerCase()) === -1;
return isInCombinedMatches && isNotInBlackList;
}, this);
// Quote identifiers
if (helpers.isArray(parts.identifiers))
{
parts.identifiers.forEach((ident) => {
let 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 (helpers.isArray(parts.literals))
{
parts.literals.forEach((lit) => {
let litIndex = parts.combined.indexOf(lit);
if (litIndex !== -1)
{
parts.combined[litIndex] = (helpers.isArray(parts.operators)) ? '?' : '= ?';
outputValues.push(lit);
}
});
}
outputMap.push(parts.combined.join(' '));
});
state.rawWhereValues = [];
state.whereValues = state.whereValues.concat(outputValues);
state.whereMap = outputMap;
return state;
}
}

View File

@ -1,29 +0,0 @@
'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

View File

@ -1,20 +0,0 @@
'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);
};
}

View File

@ -1,18 +0,0 @@
'use strict';
import Adapter from '../Adapter';
/** @module adapters/mysql */
module.exports = class mysql 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.query.apply(instance, arguments);
}
}

View File

@ -1,18 +0,0 @@
'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);
};
}

View File

@ -1,20 +0,0 @@
'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);
}
}

View File

@ -1,28 +0,0 @@
'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);
}
}

View File

@ -1,49 +0,0 @@
"use strict";
import helpers from '../helpers';
import Driver from '../DriverClass';
/**
* Driver for Firebird databases
*
* @module drivers/firebird
*/
class Firebird extends Driver {
constructor() {
super({
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}
*/
limit(origSql, limit, offset) {
let sql = `FIRST ${limit}`;
if (helpers.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}
*/
insertBatch() {
throw new Error("Not Implemented");
}
}
module.exports = new Firebird();

View File

@ -1,29 +0,0 @@
"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();

View File

@ -1,10 +0,0 @@
"use strict";
import Driver from '../DriverClass';
/**
* Driver for PostgreSQL databases
*
* @module drivers/pg
*/
module.exports = new Driver();

View File

@ -1,64 +0,0 @@
"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();

View File

@ -1,127 +0,0 @@
"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;

39
test/base_test.js Normal file
View File

@ -0,0 +1,39 @@
'use strict';
let assert = require('chai').assert;
let nodeQuery = require('../lib/NodeQuery');
suite('Base tests', () => {
test('Sanity check', () => {
let modules = {
helpers: require('../lib/helpers'),
driver: require('../lib/DriverBase'),
qb: require('../lib/QueryBuilder'),
'node-query': require('../lib/NodeQuery'),
'state': require('../lib/State'),
'drivers/pg': require('../lib/drivers/Pg'),
'drivers/mysql': require('../lib/drivers/Mysql'),
'drivers/sqlite': require('../lib/drivers/Sqlite'),
'adapters/mysql': require('../lib/adapters/mysql'),
'adapters/mysql2': require('../lib/adapters/mysql2'),
'adapters/pg': require('../lib/adapters/pg'),
'adapters/dblite': require('../lib/adapters/dblite')
};
Object.keys(modules).forEach(mod => {
assert.ok(modules[mod], mod + " module is sane");
});
});
test('NodeQuery.getQuery with no instance', () => {
assert.throws(() => {
nodeQuery.getQuery();
}, Error, "No Query Builder instance to return");
});
test('Invalid driver type', () => {
assert.throws(() => {
nodeQuery.init('foo', {}, 'bar');
}, Error, "Selected driver (Foo) does not exist!");
});
});

136
test/helpers_test.js Normal file
View File

@ -0,0 +1,136 @@
'use strict';
let chai = require('chai'),
assert = chai.assert,
expect = chai.expect,
should = chai.should();
let helpers = require('../lib/helpers');
suite('Helper Module Tests', () => {
suite('Type-checking methods', () => {
suite('Object wrappers are listed as their native type', () => {
test("Boolean Wrapper returns 'boolean' not 'object'", () => {
let item = Boolean(true);
expect(helpers.type(item)).to.deep.equal('boolean');
});
test("Number Wrapper returns 'number' not 'object", () => {
let item = Number(4867);
expect(helpers.type(item)).to.deep.equal('number');
});
test("String Wrapper returns 'string' not 'object'", () => {
let item = String("Foo");
expect(helpers.type(item)).to.deep.equal('string');
});
});
suite('is..Method methods exist', () => {
let types = ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp','NaN','Infinite'];
types.forEach(type => {
test(`is${type} method exists`, () => {
assert.ok(helpers[`is${type}`]);
});
});
});
suite('isScalar', () => {
let trueCases = {
'Strings are scalar': 'foo',
'Booleans are scalar': true,
'Numbers are scalar': 545
};
Object.keys(trueCases).forEach(desc => {
test(desc, () => {
expect(helpers.isScalar(trueCases[desc])).to.be.true;
});
});
let falseCases = {
'Arrays are not scalar': [],
'Objects are not scalar': [],
};
Object.keys(falseCases).forEach(desc => {
test(desc, () => {
expect(helpers.isScalar(falseCases[desc])).to.be.false;
});
});
});
suite('isInfinity', () => {
test('The type of 1/0 is infinity', () => {
expect(helpers.type(1/0)).to.equal('infinity');
});
test('isInfinity is the same as isInfinite', () => {
expect(helpers.isInfinite(1/0)).to.be.true;
});
});
suite('isNaN', () => {
test('The type of 0 / 0 is NaN', () => {
expect(helpers.type(0 / 0)).to.equal('nan');
});
test('isNaN method agrees with type', () => {
expect(helpers.isNaN(0 / 0)).to.be.true;
});
});
});
suite('Other helper methods', () => {
suite('stringTrim', () => {
test('stringTrim method works as expected', () => {
let orig = [' x y ', 'z ', ' q'];
let ret = ['x y', 'z', 'q'];
expect(orig.map(helpers.stringTrim)).to.be.deep.equal(ret);
});
});
suite('arrayPluck', () => {
let orig = [{
foo: 1
},{
foo: 2,
bar: 10
},{
foo: 3,
bar: 15
}];
test('Finding members in all objects', () => {
expect(helpers.arrayPluck(orig, 'foo')).to.be.deep.equal([1,2,3]);
});
test('Some members are missing in some objects', () => {
expect(helpers.arrayPluck(orig, 'bar')).to.be.deep.equal([10, 15]);
});
test('Empty case', () => {
expect(helpers.arrayPluck([], 'apple')).to.be.deep.equal([]);
});
});
suite('regexInArray', () => {
let orig = ['apple', ' string ', 6, 4, 7];
let cases = [{
'Dollar sign is not in any of the array items': /\$/,
'None of the numbers in the array match /5/': /5/
},{
"' string ' matches /^ ?string/": /^ ?string/,
"'apple' matches /APPLE/i": /APPLE/i
}];
[0, 1].forEach(i => {
let boolCase = cases[i];
Object.keys(boolCase).forEach(desc => {
test(desc, () => {
if (i) {
expect(helpers.regexInArray(orig, boolCase[desc])).to.be.true;
} else {
expect(helpers.regexInArray(orig, boolCase[desc])).to.be.false;
}
});
});
});
test('First argument is not an array', () => {
expect(helpers.regexInArray(5, /5/)).to.be.false;
});
test('Array is empty', () => {
expect(helpers.regexInArray([], /.*/)).to.be.false;
});
});
});
});

178
test/query-parser_test.js Normal file
View File

@ -0,0 +1,178 @@
"use strict";
let expect = require('chai').expect;
// Use the base driver as a mock for testing
let getArgs = require('getargs');
let helpers = require('../lib/helpers');
let driver = require('../lib/DriverBase');
let p = require('../lib/QueryParser');
let parser = new p(driver);
let State = require('../lib/State');
// Simulate query builder state
let state = new State();
let mixedSet = function 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];
state[args.$letName].push(pushVal);
}
else
{
state[args.$letName][k] = obj[k];
}
});
return state[args.$letName];
}
let whereMock = function() {
let args = getArgs('key:string|object, [val]', arguments);
state.whereMap = [];
state.whereValues = [];
mixedSet('rawWhereValues', 'value', args.key, args.val);
mixedSet('whereMap', 'both', args.key, args.val);
}
// -----------------------------------------------------------------------------
// ! Start Tests
// -----------------------------------------------------------------------------
suite('Query Parser Tests', () => {
suite('Has operator tests', () => {
test('Has operator', () => {
let matches = parser.hasOperator('foo <> 2');
expect(matches).to.be.deep.equal(['<>']);
});
test('Has no operator', () => {
let matches = parser.hasOperator('foo');
expect(matches).to.be.null;
})
});
suite('Where parser tests', () => {
setup(() => {
state = new State();
});
test('Has function full string', () => {
whereMock('time < SUM(FOO(BAR()))');
parser.parseWhere(driver, state);
expect(state.whereMap)
.to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
});
test('Has function key/val', () => {
whereMock('time <', 'SUM(FOO(BAR()))');
parser.parseWhere(driver, state);
expect(state.whereMap)
.to.be.deep.equal(['"time" < SUM(FOO(BAR()))']);
});
test('Has function key/val object', () => {
whereMock({
'time <': "SUM(FOO(BAR('x')))"
});
parser.parseWhere(driver, state);
expect(state.whereMap)
.to.be.deep.equal(['"time" < SUM(FOO(BAR(\'x\')))']);
});
test('Has literal value', () => {
whereMock({
'foo': 3
});
parser.parseWhere(driver, state);
expect(state.whereMap)
.to.be.deep.equal(['"foo" = ?']);
expect(state.whereValues)
.to.be.deep.equal(['3']);
});
test('Has multiple literal values', () => {
whereMock({
foo: 3,
bar: 5
});
parser.parseWhere(driver, state);
expect(state.whereMap)
.to.be.deep.equal(['"foo" = ?', '"bar" = ?']);
expect(state.whereValues)
.to.be.deep.equal(['3','5']);
});
});
suite('Parse join tests', () => {
let data = [{
desc: 'Simple equals condition',
join: 'table1.field1=table2.field2',
expected: ['table1.field1','=','table2.field2']
},{
desc: 'Db.table.field condition',
join: 'db1.table1.field1!=db2.table2.field2',
expected: ['db1.table1.field1','!=', 'db2.table2.field2']
},{
desc: 'Underscore in identifier',
join: 'table_1.field1 = tab_le2.field_2',
expected: ['table_1.field1', '=', 'tab_le2.field_2']
},{
desc: 'Function in condition',
join: 'table1.field1 > SUM(3+6)',
expected: ['table1.field1', '>', 'SUM(3+6)']
}];
data.forEach(datum => {
test(datum.desc, () => {
let matches = parser.parseJoin(datum.join);
expect(matches.combined).to.be.deep.equal(datum.expected);
})
});
});
suite('Compile join tests', () => {
let data = [{
desc: 'Simple equals condition',
clause: 'table1.field1=table2.field2',
expected: '"table1"."field1" = "table2"."field2"'
},{
desc: 'Db.table.field condition',
clause: 'db1.table1.field1!=db2.table2.field2',
expected: '"db1"."table1"."field1" != "db2"."table2"."field2"'
},{
desc: 'Underscore in identifier',
clause: 'table_1.field1 = tab_le2.field_2',
expected: '"table_1"."field1" = "tab_le2"."field_2"'
},{
desc: 'Function in condition',
clause: 'table1.field1 > SUM(3+6)',
expected: '"table1"."field1" > SUM(3+6)'
}];
data.forEach(datum => {
test(datum.desc, () => {
let join = parser.compileJoin(datum.clause);
expect(join).to.be.deep.equal(datum.expected);
});
});
});
});

View File

@ -1,91 +0,0 @@
'use strict';
// Load the test base
delete require.cache[require.resolve('../query-builder-base')];
var testBase = require('../query-builder-base');
var tests = testBase.tests;
// Load the test config file
var adapterName = 'dblite';
var sqlite = null;
var connection = null;
// Set up the connection
try {
sqlite = require(adapterName).withSQLite('3.7.11');
connection = sqlite(':memory:');
} catch (e) {
// Export an empty testsuite if module not loaded
console.log(e);
console.log("Database adapter dblite not found");
//return {};
}
if (connection)
{
// Set up the query builder object
var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('sqlite', connection, adapterName);
// Set up the sqlite database
var sql = 'CREATE TABLE IF NOT EXISTS "create_test" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);' +
'CREATE TABLE IF NOT EXISTS "create_join" ("id" INTEGER PRIMARY KEY, "key" TEXT, "val" TEXT);';
connection.query(sql);
// Set up the test base
testBase._setUp(qb, function(test, err, rows) {
if (err != null) {
test.done();
throw new Error(err);
}
// Insert/Update/Delete queries return undefined
if (rows === undefined) {
rows = {};
}
test.ok(rows, 'dblite: Invalid result for generated query');
test.done();
});
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests['Select tests']['Select with function and argument in WHERE clause'] = function(test) {
test.expect(1);
qb.select('id')
.from('create_test')
.where('id', 'ABS(-88)')
.get(function(err, rows) {
if (err != null) {
test.done();
throw new Error(err);
}
test.ok(rows, 'dblite: Valid result for generated query');
test.done();
});
};
tests["dblite adapter with query builder"] = function(test) {
test.expect(1);
test.ok(testBase.qb);
// Close the db connection
connection.close();
test.done();
};
// Export the final test object
module.exports = tests;
}
else
{
module.exports = {};
}

View File

@ -1,51 +0,0 @@
'use strict';
var configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load a fresh version of the test base
delete require.cache[require.resolve('../query-builder-base')];
var testBase = require('../query-builder-base');
var tests = testBase.tests;
// Load the test config file
var adapterName = 'mysql2';
var config = require(configFile)[adapterName];
// Set up the connection
var mysql2 = require(adapterName);
var connection = mysql2.createConnection(config.conn);
// Set up the query builder object
var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('mysql', connection, adapterName);
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
// Export the final test object
tests["mysql2 adapter with query builder"] = function(test) {
test.expect(1);
test.ok(testBase.qb);
// Close the db connection
connection.end();
test.done();
};
// Set up the test base
testBase._setUp(qb, function(test, err, rows) {
if (err != null) {
test.done();
throw new Error(err);
}
test.ok(rows, 'mysql2: Invalid result for generated query');
test.done();
});
module.exports = tests;

View File

@ -1,51 +0,0 @@
'use strict';
var configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load the test base
delete require.cache[require.resolve('../query-builder-base')];
var testBase = require('../query-builder-base');
var tests = testBase.tests;
// Load the test config file
var adapterName = 'mysql';
var config = require(configFile)[adapterName];
// Set up the connection
var mysql = require(adapterName);
var connection = mysql.createConnection(config.conn);
// Set up the query builder object
var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('mysql', connection);
// Set up the test base
testBase._setUp(qb, function(test, err, rows) {
if (err != null) {
test.done();
throw new Error(err);
}
test.ok(rows, 'mysql: Valid result for generated query');
test.done();
});
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["mysql adapter with query builder"] = function(test) {
test.expect(1);
test.ok(testBase.qb);
// Close the db connection
qb = null;
connection.destroy();
test.done();
};
// Export the final test object
module.exports = tests;

View File

@ -1,96 +0,0 @@
'use strict';
// Load the test base
var testBase = require('../query-builder-base');
// Load the test config file
var adapterName = 'node-firebird';
var config = require('../config.json')[adapterName];
config.conn.database = __dirname + config.conn.database;
var nodeQuery = require('../../lib/NodeQuery');
// Skip on TravisCi
if (process.env.CI || process.env.JENKINS_HOME)
{
module.exports = {};
return;
}
// Set up the connection
try {
var Firebird = require(adapterName);
var conn = null;
var qb = null;
// Setup testbase from the inside out
// Because the connection is async, utilize
// the setUp function from nodeunit to get the connection
testBase.tests.setUp = function(cb) {
if ( ! conn)
{
// Connect to the database
Firebird.attach(config.conn, function(err, db) {
if (err) {
console.error(err);
}
conn = db;
// Set up the query builder object
qb = nodeQuery.init('firebird', db, adapterName);
testBase._setUp(qb, function(test, err, result) {
if (err) {
test.done();
throw new Error(err);
}
result = result || [];
test.ok(result, 'firebird: Valid result for generated query');
test.done();
});
cb();
});
}
else
{
cb();
}
};
//delete testBase.tests['DB update tests'];
testBase.tests['DB update tests']['Test Insert Batch'] = function(test) {
test.expect(1);
test.throws(function() {
qb.insertBatch({}, (function() {}));
}, Error, "Insert Batch not implemented for firebird");
test.done();
};
testBase.tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
testBase.tests["firebird adapter with query builder"] = function(test) {
test.expect(1);
test.ok(testBase.qb);
// Disconnect from the db
conn.detach();
test.done();
};
module.exports = testBase.tests;
} catch (e) {
// Export an empty testBase.testsuite if module not loaded
console.log(e);
console.log("Database adapter firebird not found");
module.exports = {};
}

View File

@ -1,54 +0,0 @@
'use strict';
var configFile = (process.env.CI) ? '../config-travis.json' : '../config.json';
// Load the test base
delete require.cache[require.resolve('../query-builder-base')];
var testBase = require('../query-builder-base');
var tests = testBase.tests;
// Load the test config file
var adapterName = 'pg';
var config = require(configFile)[adapterName];
// Set up the connection
var pg = require(adapterName);
var connection = new pg.Client(config.conn);
connection.connect(function(err) {
if (err) {
throw new Error(err);
}
});
// Set up the query builder object
var nodeQuery = require('../../lib/NodeQuery');
var qb = nodeQuery.init('pg', connection);
// Set up the test base
testBase._setUp(qb, function(test, err, result) {
if (err) {
console.error('SQL syntax error', err);
}
test.ok(result, 'pg: Valid result for generated query');
test.done();
});
tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) {
test.expect(1);
test.deepEqual(qb, nodeQuery.getQuery(), "getQuery returns same object");
test.done();
};
tests["pg adapter with query builder"] = function(test) {
test.expect(1);
test.ok(testBase.qb);
// Close the db connection
connection.end();
test.done();
};
module.exports = tests;

View File

@ -1,42 +0,0 @@
"use strict";
var modules = {
helpers: require('../lib/helpers'),
driver: require('../lib/DriverBase'),
qb: require('../lib/QueryBuilder'),
'node-query': require('../lib/NodeQuery'),
'state': require('../lib/State'),
'drivers/pg': require('../lib/drivers/Pg'),
'drivers/mysql': require('../lib/drivers/Mysql'),
'drivers/sqlite': require('../lib/drivers/Sqlite'),
'adapters/mysql': require('../lib/adapters/mysql'),
'adapters/mysql2': require('../lib/adapters/mysql2'),
'adapters/pg': require('../lib/adapters/pg'),
'adapters/dblite': require('../lib/adapters/dblite')
};
module.exports = {
'Sanity check': function (test) {
test.expect(modules.length);
Object.keys(modules).forEach(function(mod) {
test.ok(modules[mod], mod + " module is sane");
});
test.done();
},
'NodeQuery.getQuery with no instance': function(test) {
test.expect(1);
test.throws(function() {
nodeQuery.getQuery();
}, Error, "No query builder instance if none created");
test.done();
},
'Invalid driver type': function(test) {
test.expect(1);
test.throws(function() {
nodeQuery.init('foo', {}, 'bar');
}, Error, "Bad driver throws exception");
test.done();
}
};

View File

@ -1,87 +0,0 @@
'use strict';
var helpers = require('../lib/helpers');
var helperTests = {
'Type checking method tests' : {
"Object wrappers are listed as their native type": function(test) {
test.deepEqual('boolean', helpers.type(new Boolean(true)), "Boolean Wrapper returns 'boolean' not 'object'");
test.deepEqual('number', helpers.type(new Number(4867)), "Number Wrapper returns 'number' not 'object");
test.deepEqual('string', helpers.type(new String("Foo")), "String Wrapper returns 'string' not 'object'");
test.done();
}
},
'is..Method tests exist' : function(test) {
test.expect(11);
var types = ['Null','Undefined','Object','Array','String','Number','Boolean','Function','RegExp','NaN','Infinite'];
types.forEach(function(type) {
test.ok(helpers['is' + type], 'is' + type + ' method exists');
});
test.done();
},
'isNaN': function(test) {
test.expect(2);
test.equal(helpers.type(0 / 0), 'nan');
test.deepEqual(helpers.isNaN(0 / 0), true);
test.done();
},
'isInfinity': function(test) {
test.expect(2);
test.equal(helpers.type(1/0), 'infinity');
test.deepEqual(helpers.isInfinite(1/0), true);
test.done();
},
'stringTrim': function(test) {
test.expect(1);
var orig = [' x y ', 'z ', ' q'];
var ret = ['x y', 'z', 'q'];
test.deepEqual(ret, orig.map(helpers.stringTrim));
test.done();
},
'arrayPluck': function(test) {
test.expect(3);
var orig = [{
foo: 1
},{
foo: 2,
bar: 10
},{
foo: 3,
bar: 15
}];
test.deepEqual([1,2,3], helpers.arrayPluck(orig, 'foo'), 'Finding members in all objects');
test.deepEqual([10,15], helpers.arrayPluck(orig, 'bar'), 'Some members are missing in some objects');
// Empty case
test.deepEqual([], helpers.arrayPluck([], 'apple'));
test.done();
},
'regexInArray': function(test) {
var orig = ['apple', ' string ', 6, 4, 7];
test.expect(6);
test.equal(false, helpers.regexInArray(orig, /\$/), 'Dollar sign is not in any of the array items');
test.equal(true, helpers.regexInArray(orig, /^ ?string/), "' string ' matches /^ ?string/");
test.equal(true, helpers.regexInArray(orig, /APPLE/i), "'apple' matches /APPLE/i");
test.equal(false, helpers.regexInArray(orig, /5/), 'None of the numbers in the array match /5/');
test.equal(false, helpers.regexInArray(5, /5/), 'First argument is not an array');
test.equal(false, helpers.regexInArray([], /.*/), 'Array is empty');
test.done();
}
};
module.exports = helperTests;

View File

@ -1,526 +0,0 @@
'use strict';
var helpers = require('../lib/helpers');
var State = require('../lib/State');
module.exports = (function QueryBuilderTestBase() {
// That 'new' keyword is annoying
if ( ! (this instanceof QueryBuilderTestBase)) return new QueryBuilderTestBase();
var base = {};
/**
* Inject the appropriate driver and adapter for the test suite
*
* @param {Object} qb - The adapter-specific query builder object
* @param {Function} callback - The test callback
* @return void
*/
this._setUp = function(qb, callback) {
base.qb = qb;
base.testCallback = callback;
this.qb = base.qb;
};
/**
* Generic query builder tests
*/
this.tests = {
// ! Get tests
'Get tests' : {
'Get with function': function(test) {
test.expect(1);
base.qb.select('id, COUNT(id) as count')
.from('create_test')
.groupBy('id')
.get(base.testCallback.bind(this, test));
},
'Basic select all get': function(test) {
test.expect(1);
base.qb.get('create_test', base.testCallback.bind(this, test));
},
'Basic select all with from': function(test) {
test.expect(1);
base.qb.from('create_test')
.get(base.testCallback.bind(this, test));
},
'Get with limit': function(test) {
test.expect(1);
base.qb.get('create_test', 2, base.testCallback.bind(this, test));
},
'Get with limit and offset': function(test) {
test.expect(1);
base.qb.get('create_test', 2, 1, base.testCallback.bind(this, test));
},
'Test get with having': function(test) {
test.expect(1);
base.qb.select('id')
.from('create_test')
.groupBy('id')
.having({'id >':1})
.having('id !=', 3)
.having('id', 900)
.get(base.testCallback.bind(this, test));
},
"Test get with 'orHaving'": function(test) {
test.expect(1);
base.qb.select('id')
.from('create_test')
.groupBy('id')
.having({'id >':1})
.orHaving('id !=', 3)
.get(base.testCallback.bind(this, test));
}
},
// ! Select tests
'Select tests' : {
'Select where get': function(test) {
test.expect(1);
base.qb.select(['id', 'key as k', 'val'])
.where('id >', 1)
.where('id <', 900)
.get('create_test', 2, 1, base.testCallback.bind(this, test));
},
'Select where get 2': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.where('id !=', 1)
.get('create_test', 2, 1, base.testCallback.bind(this, test));
},
'Multi Order By': function(test) {
test.expect(1);
base.qb.from('create_test')
.orderBy('id, key')
.get(base.testCallback.bind(this, test));
},
'Select get': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.get('create_test', 2, 1, base.testCallback.bind(this, test));
},
'Select from get': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test ct')
.where('id >', 1)
.get(base.testCallback.bind(this, test));
},
'Select from limit get': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test ct')
.where('id >', 1)
.limit(3)
.get(base.testCallback.bind(this, test));
},
'Select where IS NOT NULL': function(test) {
test.expect(1);
base.qb.select('id', 'key as k', 'val')
.from('create_test ct')
.whereIsNotNull('id')
.get(base.testCallback.bind(this, test));
},
'Select where IS NULL': function(test) {
test.expect(1);
base.qb.select('id', 'key as k', 'val')
.from('create_test ct')
.whereIsNull('id')
.get(base.testCallback.bind(this, test));
},
'Select where OR IS NOT NULL': function(test) {
test.expect(1);
base.qb.select('id', 'key as k', 'val')
.from('create_test ct')
.whereIsNull('id')
.orWhereIsNotNull('id')
.get(base.testCallback.bind(this, test));
},
'Select where OR IS NULL': function(test) {
test.expect(1);
base.qb.select('id', 'key as k', 'val')
.from('create_test ct')
.where('id', 3)
.orWhereIsNull('id')
.get(base.testCallback.bind(this, test));
},
'Select with string where value': function(test) {
test.expect(1);
base.qb.select('id','key as k', 'val')
.from('create_test ct')
.where('id > 3')
.get(base.testCallback.bind(this, test));
},
'Select with function and argument in WHERE clause': function(test) {
test.expect(1);
base.qb.select('id')
.from('create_test')
.where('id', 'CEILING(SQRT(88))')
.get(base.testCallback.bind(this, test));
}
},
// ! Grouping tests
'Grouping tests' : {
'Using grouping method': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.groupStart()
.where('id >', 1)
.where('id <', 900)
.groupEnd()
.limit(2, 1)
.get(base.testCallback.bind(this, test));
},
'Using where first grouping': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.where('id !=', 5)
.groupStart()
.where('id >', 1)
.where('id <', 900)
.groupEnd()
.limit(2, 1)
.get(base.testCallback.bind(this, test));
},
'Using or grouping method': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.groupStart()
.where('id >', 1)
.where('id <', 900)
.groupEnd()
.orGroupStart()
.where('id', 0)
.groupEnd()
.limit(2, 1)
.get(base.testCallback.bind(this, test));
},
'Using or not grouping method': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.groupStart()
.where('id >', 1)
.where('id <', 900)
.groupEnd()
.orNotGroupStart()
.where('id', 0)
.groupEnd()
.limit(2, 1)
.get(base.testCallback.bind(this, test));
}
},
// ! Where in tests
'Where in tests' : {
'Where in': function(test) {
test.expect(1);
base.qb.from('create_test')
.whereIn('id', [0, 6, 56, 563, 341])
.get(base.testCallback.bind(this, test));
},
'Or Where in': function(test) {
test.expect(1);
base.qb.from('create_test')
.where('key', 'false')
.orWhereIn('id', [0, 6, 56, 563, 341])
.get(base.testCallback.bind(this, test));
},
'Where Not in': function(test) {
test.expect(1);
base.qb.from('create_test')
.where('key', 'false')
.whereNotIn('id', [0, 6, 56, 563, 341])
.get(base.testCallback.bind(this, test));
},
'Or Where Not in': function(test) {
test.expect(1);
base.qb.from('create_test')
.where('key', 'false')
.orWhereNotIn('id', [0, 6, 56, 563, 341])
.get(base.testCallback.bind(this, test));
}
},
// ! Query modifier tests
'Query modifier tests': {
'Order By': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.where('id >', 0)
.where('id <', 9000)
.orderBy('id', 'DESC')
.orderBy('k', "ASC")
.limit(5, 2)
.get(base.testCallback.bind(this, test));
},
'Group by': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.where('id >', 0)
.where('id <', 9000)
.groupBy('k')
.groupBy(['id', 'val'])
.orderBy('id', 'DESC')
.orderBy('k', "ASC")
.limit(5, 2)
.get(base.testCallback.bind(this, test));
},
'Or Where': function(test) {
test.expect(1);
base.qb.select('id, key as k, val')
.from('create_test')
.where(' id ', 1)
.orWhere('key >', 0)
.limit(2, 1)
.get(base.testCallback.bind(this, test));
},
'Like' : function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og')
.get(base.testCallback.bind(this, test));
},
'Or Like': function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og')
.orLike('key', 'val')
.get(base.testCallback.bind(this, test));
},
'Not Like': function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og', 'before')
.notLike('key', 'val')
.get(base.testCallback.bind(this, test));
},
'Or Not Like': function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og', 'before')
.orNotLike('key', 'val')
.get(base.testCallback.bind(this, test));
},
'Like Before': function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og', 'before')
.get(base.testCallback.bind(this, test));
},
'Like After': function(test) {
test.expect(1);
base.qb.from('create_test')
.like('key', 'og', 'after')
.get(base.testCallback.bind(this, test));
},
'Basic Join': function(test) {
test.expect(1);
base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id')
.get(base.testCallback.bind(this, test));
},
'Left Join': function(test) {
test.expect(1);
base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id', 'left')
.get(base.testCallback.bind(this, test));
},
'InnerJoin': function(test) {
test.expect(1);
base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id', 'inner')
.get(base.testCallback.bind(this, test));
},
'Join with multiple where values': function(test) {
test.expect(1);
base.qb.from('create_test ct')
.join('create_join cj', 'cj.id=ct.id', 'inner')
.where({
'ct.id <': 3,
'ct.key': 'foo'
})
.get(base.testCallback.bind(this, test));
}
},
// ! DB Update test
'DB update tests' : {
setUp: function(callback) {
var sql = base.qb.driver.truncate('create_test');
base.qb.adapter.execute(sql, function(err, result) {
callback();
});
},
tearDown: function(callback) {
callback();
},
'Test Insert': function(test) {
test.expect(1);
base.qb.set('id', 98)
.set('key', "84")
.set('val', new Buffer("120"))
.insert('create_test', base.testCallback.bind(this, test));
},
'Test Insert Object': function(test) {
test.expect(1);
base.qb.insert('create_test', {
id: 587,
key: 1,
val: new Buffer('2')
}, base.testCallback.bind(this, test));
},
'Test Insert Batch': function(test) {
test.expect(1);
var data = [{
id: 544,
key: 3,
val: new Buffer('7')
}, {
id: 89,
key: 34,
val: new Buffer("10 o'clock")
}, {
id: 48,
key: 403,
val: new Buffer('97')
}];
base.qb.insertBatch('create_test', data, base.testCallback.bind(this, test));
},
'Test Update': function(test) {
test.expect(1);
base.qb.where('id', 7)
.update('create_test', {
id: 7,
key: 'gogle',
val: new Buffer('non-word')
}, base.testCallback.bind(this, test));
},
'Test set Array Update': function(test) {
test.expect(1);
var object = {
id: 22,
key: 'gogle',
val: new Buffer('non-word')
};
base.qb.set(object)
.where('id', 22)
.update('create_test', base.testCallback.bind(this, test));
},
'Test where set update': function(test) {
test.expect(1);
base.qb.where('id', 36)
.set('id', 36)
.set('key', 'gogle')
.set('val', new Buffer('non-word'))
.update('create_test', base.testCallback.bind(this, test));
},
'Test delete': function(test) {
test.expect(1);
base.qb.delete('create_test', {id: 5}, base.testCallback.bind(this, test));
},
'delete with where': function(test) {
test.expect(1);
base.qb.where('id', 5)
.delete('create_test', base.testCallback.bind(this, test));
},
'Delete multiple where values': function(test) {
test.expect(1);
base.qb.delete('create_test', {
id: 5,
key: 'gogle'
}, base.testCallback.bind(this, test));
}
},
// ! Get compiled tests
'Get compiled tests' : {
'select': function(test) {
test.expect(1);
var string = base.qb.select('id')
.from('create_test')
.getCompiledSelect(true);
test.equal(true, helpers.isString(string));
test.done();
},
'select from': function(test) {
test.expect(1);
var string = base.qb.select('id')
.getCompiledSelect('create_test', true);
test.equal(true, helpers.isString(string));
test.done();
},
'insert': function(test) {
test.expect(1);
var string = base.qb.set('id', 3)
.getCompiledInsert('create_test');
test.equal(true, helpers.isString(string));
test.done();
},
'update': function(test) {
test.expect(1);
var string = base.qb.set('id', 3)
.where('id', 5)
.getCompiledUpdate('create_test');
test.equal(true, helpers.isString(string));
test.done();
},
'delete': function(test) {
test.expect(1);
var string = base.qb.where('id', 5)
.getCompiledDelete('create_test');
test.equal(true, helpers.isString(string));
test.done();
}
},
// ! Misc tests
'Misc tests' : {
'Get State': function(test) {
test.expect(1);
base.qb.select('foo')
.from('bar')
.where('baz', 'foobar');
var state = new State();
test.notDeepEqual(JSON.stringify(state), JSON.stringify(base.qb.getState()));
test.done();
},
'Reset State': function(test) {
test.expect(1);
base.qb.select('foo')
.from('bar')
.where('baz', 'foobar');
base.qb.resetQuery();
var state = new State();
test.deepEqual(state, base.qb.getState());
test.done();
}
}
};
return this;
}());

View File

@ -1,178 +0,0 @@
'use strict';
// Use the base driver as a mock for testing
var getArgs = require('getargs');
var helpers = require('../lib/helpers');
var driver = require('../lib/DriverBase');
var p = require('../lib/QueryParser');
var parser = new p(driver);
var State = require('../lib/State');
// Simulate query builder state
var state = new State();
var 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];
}
var whereMock = function() {
var args = getArgs('key:string|object, [val]', arguments);
state.whereMap = [];
state.whereValues = [];
mixedSet('rawWhereValues', 'value', args.key, args.val);
mixedSet('whereMap', 'both', args.key, args.val);
}
// -----------------------------------------------------------------------------
// ! Start Tests
// -----------------------------------------------------------------------------
var tests = {
'Has operator tests': {
'Has operator': function(test) {
var matches = parser.hasOperator('foo <> 2');
test.deepEqual(['<>'], matches);
test.done();
},
'Has no operator': function(test) {
var matches = parser.hasOperator('foo');
test.equal(null, matches);
test.done();
}
},
'Where parser tests': {
'Has function full string': function(test) {
test.expect(1);
whereMock('time < SUM(FOO(BAR()))');
var result = parser.parseWhere(driver, state);
test.deepEqual(['"time" < SUM(FOO(BAR()))'], state.whereMap);
test.done();
},
'Has function key/val': function(test) {
test.expect(1);
var map = whereMock('time <', 'SUM(FOO(BAR()))');
state = parser.parseWhere(driver, state);
test.deepEqual(['"time" < SUM(FOO(BAR()))'], state.whereMap);
test.done();
},
'Has function key/val object': function(test) {
test.expect(1);
var map = whereMock({
'time <': "SUM(FOO(BAR('x')))"
});
state = parser.parseWhere(driver, state);
test.deepEqual(['"time" < SUM(FOO(BAR(\'x\')))'], state.whereMap);
test.done();
},
'Has literal value': function(test) {
test.expect(2);
var map = whereMock({
'foo': 3
});
state = parser.parseWhere(driver, state);
test.deepEqual(['"foo" = ?'], state.whereMap);
test.deepEqual(['3'], state.whereValues);
test.done();
},
'Has multiple literal values': function(test) {
test.expect(2);
var map = whereMock({
foo: 3,
bar: 5
});
state = parser.parseWhere(driver, state);
test.deepEqual(['"foo" = ?', '"bar" = ?'], state.whereMap);
test.deepEqual(['3','5'], state.whereValues);
test.done();
}
},
'Parse join tests' : {
'Simple equals condition': function(test) {
var matches = parser.parseJoin('table1.field1=table2.field2');
test.deepEqual(['table1.field1','=','table2.field2'], matches.combined);
test.done();
},
'Db.table.field condition': function(test) {
var matches = parser.parseJoin('db1.table1.field1!=db2.table2.field2');
test.deepEqual(['db1.table1.field1','!=', 'db2.table2.field2'], matches.combined);
test.done();
},
'Underscore in identifier': function(test) {
var matches = parser.parseJoin('table_1.field1 = tab_le2.field_2');
test.deepEqual(['table_1.field1', '=', 'tab_le2.field_2'], matches.combined);
test.done();
},
'Function in condition': function(test) {
var matches = parser.parseJoin('table1.field1 > SUM(3+6)');
test.deepEqual(['table1.field1', '>', 'SUM(3+6)'], matches.combined);
test.done();
}
},
'Compile join tests': {
'Simple equals condition': function(test) {
var join = parser.compileJoin('table1.field1=table2.field2');
test.deepEqual('"table1"."field1" = "table2"."field2"', join);
test.done();
},
'Db.table.field condition': function(test) {
var join = parser.compileJoin('db1.table1.field1!=db2.table2.field2');
test.deepEqual('"db1"."table1"."field1" != "db2"."table2"."field2"', join);
test.done();
},
'Underscore in identifier': function(test) {
var join = parser.compileJoin('table_1.field1 = tab_le2.field_2');
test.deepEqual('"table_1"."field1" = "tab_le2"."field_2"', join);
test.done();
},
'Function in condition': function(test) {
var join = parser.compileJoin('table1.field1 > SUM(3+6)');
test.deepEqual('"table1"."field1" > SUM(3+6)', join);
test.done();
}
}
};
module.exports = tests;