From f85358aff0b2325d212d6a13a7b5b0c84cea5db2 Mon Sep 17 00:00:00 2001 From: Timothy J Warren Date: Fri, 20 Nov 2015 09:14:09 -0500 Subject: [PATCH] Move from grunt to gulp --- .istanbul.yml | 5 +-- .travis.yml | 5 ++- Gruntfile.js | 30 ----------------- gulpfile.js | 30 +++++++++++++++++ lib/adapter.js | 2 +- lib/adapters/pg.js | 2 +- lib/driver.js | 25 ++++++++------ lib/drivers/mysql.js | 3 +- lib/drivers/sqlite.js | 63 ++++++++++++++++++++++++++++++++--- lib/helpers.js | 1 - package.json | 18 +++++----- sonar-project.properties | 4 +-- tests/adapters/dblite_test.js | 4 +-- tests/adapters/mysql2_test.js | 19 ++++++----- tests/query-builder-base.js | 4 --- 15 files changed, 135 insertions(+), 80 deletions(-) delete mode 100644 Gruntfile.js create mode 100644 gulpfile.js diff --git a/.istanbul.yml b/.istanbul.yml index 20395ce..1a66a95 100644 --- a/.istanbul.yml +++ b/.istanbul.yml @@ -1,9 +1,6 @@ reporting: reports: - lcov - - clover - - text-summary - lcovonly report-config: - clover: {file: ../build/clover.xml} - lcovonly: {file: ../build/lcov.info} \ No newline at end of file + lcovonly: {file: ../coverage/lcov.info} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 6c5f95b..b22fa3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,11 @@ node_js: - "0.10" before_script: + - npm install -g gulp - psql -c 'DROP DATABASE IF EXISTS test;' -U postgres - psql -c 'create database test;' -U postgres - mysql -e 'create database IF NOT EXISTS test;' - mysql -v -uroot test < ./tests/sql/mysql.sql - - psql test postgres -f ./tests/sql/pgsql.sql \ No newline at end of file + - psql test postgres -f ./tests/sql/pgsql.sql + +script: gulp \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index d3c5cf1..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = function(grunt) { - 'use strict'; - - // Project configuration - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - jsdoc: { - dist: { - src: ['lib/*.js', 'README.md'], - options: { - destination: 'docs' - } - } - }, - nodeunit: { - all: ['tests/**/*_test.js'], - options: { - reporter: 'verbose' - } - } - }); - - grunt.loadNpmTasks('grunt-jsdoc'); - grunt.loadNpmTasks('grunt-contrib-nodeunit'); - - - grunt.registerTask('default', ['nodeunit','jsdoc']); - grunt.registerTask('tests', 'nodeunit'); - grunt.registerTask('docs', 'jsdoc'); -}; \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..6e118ce --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,30 @@ +var gulp = require('gulp'), + documentation = require('gulp-documentation'), + nodeunit_runner = require('gulp-nodeunit-runner'), + istanbul = require('gulp-istanbul'); + +gulp.task('default', ['docs', 'test']); + +gulp.task('docs', function() { + gulp.src('./lib/node-query.js') + .pipe(documentation({format: 'html'})) + .pipe(gulp.dest('docs')); + gulp.src('./lib/node-query.js') + .pipe(documentation({format: 'md'})) + .pipe(gulp.dest('api-docs')); +}); + +gulp.task('pre-test', function() { + return gulp.src(['lib/**/*.js']) + .pipe(istanbul()) + .pipe(istanbul.hookRequire()); +}); + +gulp.task('test', ['pre-test'], function() { + return gulp.src(['tests/**/*_test.js']) + .pipe(nodeunit_runner()) + .pipe(istanbul.writeReports({ + dir: './coverage', + reporters: ['lcov', 'lcovonly', 'html', 'text'] + })); +}); \ No newline at end of file diff --git a/lib/adapter.js b/lib/adapter.js index d0e0a0a..2784ad1 100755 --- a/lib/adapter.js +++ b/lib/adapter.js @@ -11,7 +11,7 @@ module.exports = { * @param {Function} callback - Callback to run when a response is recieved * @return void */ - execute: function(sql, params, callback) { + execute: function(/*sql, params, callback*/) { throw new Error("Correct adapter not defined for query execution"); } }; \ No newline at end of file diff --git a/lib/adapters/pg.js b/lib/adapters/pg.js index e3caf75..0d4d164 100644 --- a/lib/adapters/pg.js +++ b/lib/adapters/pg.js @@ -22,7 +22,7 @@ var Pg = function(instance) { // Replace question marks with numbered placeholders, because this adapter is different... var count = 0; - args.sql = args.sql.replace(/\?/g, function(match, offset, string) { + args.sql = args.sql.replace(/\?/g, function() { count++; return '$' + count; }); diff --git a/lib/driver.js b/lib/driver.js index 0cad5a5..4c7a3ee 100755 --- a/lib/driver.js +++ b/lib/driver.js @@ -8,7 +8,8 @@ var helpers = require('./helpers'); * @module driver */ var d = { - identifierChar: '"', + identifierStartChar: '"', + identifierEndChar: '"', tablePrefix: null, hasTruncate: true, @@ -20,8 +21,8 @@ var d = { * @private */ _quote: function(str) { - return (helpers.isString(str) && ! (str.startsWith(d.identifierChar) || str.endsWith(d.identifierChar))) - ? d.identifierChar + str + d.identifierChar + return (helpers.isString(str) && ! (str.startsWith(d.identifierStartChar) || str.endsWith(d.identifierEndChar))) + ? d.identifierStartChar + str + d.identifierEndChar : str; }, @@ -63,7 +64,7 @@ var d = { */ quoteIdentifiers: function(str) { var hiers, raw; - var pattern = new RegExp(d.identifierChar + '(' + '([a-zA-Z0-9_]+)' + '(\((.*?)\))' + ')' + d.identifierChar, 'ig'); + var pattern = new RegExp(d.identifierStartChar + '(' + '([a-zA-Z0-9_]+)' + '(\((.*?)\))' + ')' + d.identifierEndChar, 'ig'); // Recurse for arrays of identifiiers if (Array.isArray(str)) @@ -122,10 +123,15 @@ var d = { * @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 - var vals = []; data.forEach(function(obj) { Object.keys(obj).forEach(function(key) { vals.push(obj[key]); @@ -134,17 +140,16 @@ var d = { // Get the field names from the keys of the first // object inserted - var fields = Object.keys(data[0]); table = d.quoteTable(table); - var sql = "INSERT INTO " + table + " (" + sql += "INSERT INTO " + table + " (" + d.quoteIdentifiers(fields).join(",") + ") VALUES "; // Create placeholder groups - var params = new Array(fields.length).fill('?'); - var paramString = "(" + params.join(',') + ")"; - var paramList = new Array(data.length).fill(paramString); + params = Array(fields.length).fill('?'); + paramString = "(" + params.join(',') + ")"; + paramList = Array(data.length).fill(paramString); sql += paramList.join(','); diff --git a/lib/drivers/mysql.js b/lib/drivers/mysql.js index c7c25bc..66663c5 100755 --- a/lib/drivers/mysql.js +++ b/lib/drivers/mysql.js @@ -11,7 +11,8 @@ module.exports = (function() { var driver = require('../driver'), helpers = require('../helpers'); - driver.identifierChar = '`'; + driver.identifierStartChar = '`'; + driver.identifierEndChar = '`'; /** * Override default limit method because mysql likes to be different diff --git a/lib/drivers/sqlite.js b/lib/drivers/sqlite.js index ffda240..1725df9 100644 --- a/lib/drivers/sqlite.js +++ b/lib/drivers/sqlite.js @@ -1,16 +1,71 @@ "use strict"; /** - * Driver for PostgreSQL databases + * Driver for Sqlite databases * - * @module drivers/pg + * @module drivers/sqlite */ module.exports = (function() { delete require.cache[require.resolve('../driver')]; - var driver = require('../driver'); + var driver = require('../driver'), + helpers = require('../helpers'); // Sqlite doesn't have a truncate command driver.hasTruncate = false; + /** + * SQL to insert a group of rows + * Override default to have better compatibility + * + * @param {String} table - The table to insert to + * @param {Array} [data] - The array of object containing data to insert + * @return {String} + */ + driver.insertBatch = function(table, data) { + + // Get the data values to insert, so they can + // be parameterized + var sql = "", + vals = [], + cols = [], + fields = [], + first = data.shift(), + params = [], + paramString = "", + paramList = []; + + + data.forEach(function(obj) { + var row = []; + Object.keys(obj).forEach(function(key) { + row.push(obj[key]); + }); + vals.push(row); + }); + + sql += "INSERT INTO " + driver.quoteTable(table) + "\n"; + + // Get the field names from the keys of the first + // object to be inserted + fields = Object.keys(first); + Object.keys(first).forEach(function(key) { + cols.push("'" + driver._quote(first[key]) + "' AS " + driver.quoteIdentifiers(key)); + }); + + sql += "SELECT " + cols.join(', ') + "\n"; + + vals.forEach(function(row_values) { + var quoted = row_values.map(function(value) { + return String(value).replace("'", "'\'"); + }); + sql += "UNION ALL SELECT '" + quoted.join("', '") + "'\n"; + }); + + return { + sql: sql, + values: null + }; + } + return driver; -}()); +}()); \ No newline at end of file diff --git a/lib/helpers.js b/lib/helpers.js index 57e7372..e90d346 100755 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -1,7 +1,6 @@ "use strict"; /** @module helpers */ -require('es6-shim'); /** @alias module:helpers */ var h = { diff --git a/package.json b/package.json index dc3bd26..a4d3024 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ci-node-query", - "version": "2.2.0", + "version": "2.2.1", "description": "A query builder for node based on the one in CodeIgniter", "author": "Timothy J Warren ", "engines": { @@ -33,9 +33,7 @@ }, "main": "lib/node-query.js", "dependencies": { - "es6-shim": "*", "getargs": "", - "grunt-istanbul": "*", "mysql": "^2.9.0", "mysql2": "^0.15.8", "node-firebird": "^0.7.0", @@ -47,14 +45,14 @@ "pg": "*" }, "devDependencies": { + "documentation": "", "nodeunit": "", - "grunt": "", - "grunt-cli": "", - "grunt-contrib-clean": "^0.6.0", - "grunt-contrib-nodeunit": "^0.4.1", - "grunt-istanbul": "", - "grunt-jsdoc": ">=0.6.1", - "jsdoc": "" + "gulp": "", + "gulp-documentation": "", + "gulp-istanbul": "", + "gulp-nodeunit-runner": "", + "jsdoc": "", + "istanbul": "" }, "license": "MIT", "scripts": { diff --git a/sonar-project.properties b/sonar-project.properties index 85bb4bd..6c7cb44 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,5 +1,5 @@ sonar.projectKey=node-query sonar.projectName=NodeJS Query Builder -sonar.projectVersion=1.0 +sonar.projectVersion=2.2.1 sonar.sources=lib -sonar.javascript.lcov.reportPath=build/lcov.info \ No newline at end of file +sonar.javascript.lcov.reportPath=coverage/lcov.info \ No newline at end of file diff --git a/tests/adapters/dblite_test.js b/tests/adapters/dblite_test.js index d2d7ddc..8bf0415 100644 --- a/tests/adapters/dblite_test.js +++ b/tests/adapters/dblite_test.js @@ -12,7 +12,7 @@ var connection = null; // Set up the connection try { - sqlite = require(adapterName).withSQLite('3.8.6+'); + sqlite = require(adapterName).withSQLite('3.7.11'); connection = sqlite(':memory:'); } catch (e) { // Export an empty testsuite if module not loaded @@ -44,7 +44,7 @@ if (connection) rows = {}; } - test.ok(rows, 'dblite: Valid result for generated query'); + test.ok(rows, 'dblite: Invalid result for generated query'); test.done(); }); diff --git a/tests/adapters/mysql2_test.js b/tests/adapters/mysql2_test.js index 60043c3..5db53e1 100644 --- a/tests/adapters/mysql2_test.js +++ b/tests/adapters/mysql2_test.js @@ -19,16 +19,7 @@ var connection = mysql2.createConnection(config.conn); var nodeQuery = require('../../lib/node-query'); var qb = nodeQuery.init('mysql', connection, adapterName); -// 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: Valid result for generated query'); - test.done(); -}); tests['nodeQuery.getQuery = nodeQuery.init'] = function(test) { test.expect(1); @@ -46,5 +37,15 @@ tests["mysql2 adapter with query builder"] = function(test) { 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; \ No newline at end of file diff --git a/tests/query-builder-base.js b/tests/query-builder-base.js index 56b9c15..88f1ee3 100644 --- a/tests/query-builder-base.js +++ b/tests/query-builder-base.js @@ -352,10 +352,6 @@ module.exports = (function QueryBuilderTestBase() { setUp: function(callback) { var sql = base.qb.driver.truncate('create_test'); base.qb.adapter.execute(sql, function(err, result) { - if (err) { - throw new Error(err); - } - callback(); }); },