This commit is contained in:
Tim Griesser 2014-06-09 16:27:03 -04:00
parent 531f824530
commit 6af64d32a1
9 changed files with 155 additions and 3 deletions

View File

@ -11,6 +11,7 @@ var excluded = {
mariasql: ['mariasql'],
sqlite3: ['sqlite3'],
mysql: ['mysql'],
mysql2: ['mysql2'],
pg: ['pg', 'pg.js', 'pg-query-stream'],
websql: ['sqlite3']
};
@ -18,12 +19,13 @@ var excluded = {
var bases = {
mariasql: './lib/dialects/maria',
mysql: './lib/dialects/mysql',
mysql2: './lib/dialects/mysql2',
pg: './lib/dialects/postgres',
sqlite3: './lib/dialects/sqlite3',
websql: './lib/dialects/websql'
};
var all = ['mysql', 'mariasql', 'pg', 'sqlite3', 'websql'];
var all = ['mysql', 'mysql2', 'mariasql', 'pg', 'sqlite3', 'websql'];
var externals = ['lodash', 'bluebird'];
var alwaysExcluded = ['generic-pool-redux', 'readable-stream', './lib/migrate/index.js'];

View File

@ -24,6 +24,7 @@ var Raw = require('./lib/raw');
// Doing it this way makes it easier to build for browserify.
var mysql = function() { return require('./lib/dialects/mysql'); };
var mysql2 = function() { return require('./lib/dialects/mysql2'); };
var maria = function() { return require('./lib/dialects/maria'); };
var pg = function() { return require('./lib/dialects/postgres'); };
var sqlite3 = function() { return require('./lib/dialects/sqlite3'); };
@ -32,6 +33,7 @@ var websql = function() { return require('./lib/dialects/websql'); };
// The client names we'll allow in the `{name: lib}` pairing.
var Clients = Knex.Clients = {
'mysql' : mysql,
'mysql2' : mysql2,
'maria' : maria,
'mariadb' : maria,
'mariasql' : maria,

View File

@ -0,0 +1,45 @@
// MySQL2 Client
// -------
var inherits = require('inherits');
var _ = require('lodash');
var Client_MySQL = require('../mysql');
var Promise = require('../../promise');
var mysql2;
// Always initialize with the "QueryBuilder" and "QueryCompiler"
// objects, which extend the base 'lib/query/builder' and
// 'lib/query/compiler', respectively.
function Client_MySQL2() {
Client_MySQL.apply(this, arguments);
}
inherits(Client_MySQL2, Client_MySQL);
// The "dialect", for reference elsewhere.
Client_MySQL2.prototype.dialect = 'mysql2';
// Lazy-load the mysql2 dependency, since we might just be
// using the client to generate SQL strings.
Client_MySQL2.prototype.initDriver = function() {
mysql2 = mysql2 || require('mysql2');
};
// Initialize the query "runner"
Client_MySQL2.prototype.initRunner = function() {
require('./runner')(this);
};
// Get a raw connection, called by the `pool` whenever a new
// connection needs to be added to the pool.
Client_MySQL2.prototype.acquireRawConnection = function() {
var connection = mysql2.createConnection(_.pick(this.connectionSettings, 'user', 'database', 'connection'));
return new Promise(function(resolver, rejecter) {
connection.connect(function(err) {
if (err) return rejecter(err);
resolver(connection);
});
});
};
module.exports = Client_MySQL2;

View File

@ -0,0 +1,81 @@
// MySQL Runner
// ------
module.exports = function(client) {
var _ = require('lodash');
var inherits = require('inherits');
var Promise = require('../../promise');
var Runner = require('../../runner');
var helpers = require('../../helpers');
// Inherit from the `Runner` constructor's prototype,
// so we can add the correct `then` method.
function Runner_MySQL2() {
this.client = client;
Runner.apply(this, arguments);
}
inherits(Runner_MySQL2, Runner);
// Grab a connection, run the query via the MySQL streaming interface,
// and pass that through to the stream we've sent back to the client.
Runner_MySQL2.prototype._stream = Promise.method(function(sql, stream, options) {
var runner = this;
return new Promise(function(resolver, rejecter) {
stream.on('error', rejecter);
stream.on('end', resolver);
return runner.query().map(function(row) {
stream.write(row);
}).catch(function() {
stream.emit('error');
}).then(function() {
stream.end();
});
});
});
// Runs the query on the specified connection, providing the bindings
// and any other necessary prep work.
Runner_MySQL2.prototype._query = Promise.method(function(obj) {
var sql = obj.sql;
if (this.isDebugging()) this.debug(obj);
if (obj.options) sql = _.extend({sql: sql}, obj.options);
var connection = this.connection;
if (!sql) throw new Error('The query is empty');
return new Promise(function(resolver, rejecter) {
connection.query(sql, obj.bindings, function(err, rows, fields) {
if (err) return rejecter(err);
obj.response = [rows, fields];
resolver(obj);
});
});
});
// Process the response as returned from the query.
Runner_MySQL2.prototype.processResponse = function(obj) {
var response = obj.response;
var method = obj.method;
var rows = response[0];
var fields = response[1];
if (obj.output) return obj.output.call(this, rows, fields);
switch (method) {
case 'select':
case 'pluck':
case 'first':
var resp = helpers.skim(rows);
if (method === 'pluck') return _.pluck(resp, obj.pluck);
return method === 'first' ? resp[0] : resp;
case 'insert':
return [rows.insertId];
case 'del':
case 'update':
return rows.affectedRows;
default:
return response;
}
};
// Assign the newly extended `Runner` constructor to the client object.
client.Runner = Runner_MySQL2;
};

View File

@ -5,7 +5,7 @@ var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
function Raw(sql, bindings) {
if (sql.toSQL) {
if (sql && sql.toSQL) {
var output = sql.toSQL();
sql = output.sql;
bindings = output.bindings;

View File

@ -26,7 +26,8 @@
"sinon": "^1.10.0",
"sinon-chai": "^2.5.0",
"sqlite3": "^2.2.3",
"mariasql": "~0.1.21"
"mariasql": "~0.1.21",
"mysql2": "~0.12.1"
},
"dependencies": {
"bluebird": "1.2.x",

View File

@ -28,6 +28,7 @@ module.exports = function(knex) {
it('should allow raw queries directly with `knex.raw`', function() {
var tables = {
mysql: 'SHOW TABLES',
mysql2: 'SHOW TABLES',
mariasql: 'SHOW TABLES',
postgresql: "SELECT table_name FROM information_schema.tables WHERE table_schema='public'",
sqlite3: "SELECT name FROM sqlite_master WHERE type='table';"

View File

@ -5,10 +5,12 @@ module.exports = function(testSuite) {
var fs = require('fs');
var mysql = logger.client(Knex(config.mysql));
var mysql2 = logger.client(Knex(config.mysql2));
var postgres = logger.client(Knex(config.postgres));
var sqlite3 = logger.client(Knex(config.sqlite3));
require('./suite')(mysql);
require('./suite')(mysql2);
require('./suite')(postgres);
require('./suite')(sqlite3);

View File

@ -45,6 +45,24 @@ module.exports = {
migrations: migrations
},
mysql2: {
client: 'mysql2',
connection: testConfig.mysql || {
database: "knex_test",
user: "root",
charset: 'utf8'
},
pool: _.extend({}, pool, {
afterCreate: function(connection, callback) {
Promise.promisify(connection.query, connection)("SET sql_mode='TRADITIONAL';", []).then(function() {
callback(null, connection);
});
}
}),
migrations: migrations
},
postgres: {
client: 'postgres',
connection: testConfig.postgres || {