不要怂,就是干,撸起袖子干!

Commit 99abdc3f by Matt Broadstone

switch from mssql to plain tedious

There is no need to use the mssql wrapped around tedious, and
switching to the lower level module allows better integration
as well as bypassing the mssql forced connection pooling
1 parent 31c484c4
"use strict"; "use strict";
var AbstractConnectionManager = require('../abstract/connection-manager') var AbstractConnectionManager = require('../abstract/connection-manager')
, Pooling = require('generic-pool')
, ConnectionManager , ConnectionManager
, Utils = require('../../utils') , Utils = require('../../utils')
, Promise = require('../../promise'); , Promise = require('../../promise');
...@@ -10,12 +10,10 @@ ConnectionManager = function(dialect, sequelize) { ...@@ -10,12 +10,10 @@ ConnectionManager = function(dialect, sequelize) {
this.sequelize = sequelize; this.sequelize = sequelize;
this.sequelize.config.port = this.sequelize.config.port || 1433; this.sequelize.config.port = this.sequelize.config.port || 1433;
this.connection = null;
try { try {
this.lib = require(sequelize.config.dialectModulePath || 'mssql'); this.lib = require(sequelize.config.dialectModulePath || 'tedious');
} catch (err) { } catch (err) {
throw new Error('Please install mssql package'); throw new Error('Please install tedious package manually');
} }
}; };
...@@ -25,12 +23,14 @@ ConnectionManager.prototype.connect = function(config) { ...@@ -25,12 +23,14 @@ ConnectionManager.prototype.connect = function(config) {
var self = this; var self = this;
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var connectionConfig = { var connectionConfig = {
host: config.host, userName: config.username,
port: config.port,
user: config.username,
password: config.password, password: config.password,
server: config.host,
/* domain: 'DOMAIN' */
options: {
port: config.port,
database: config.database, database: config.database,
timezone: self.sequelize.options.timezone }
}; };
if (config.dialectOptions) { if (config.dialectOptions) {
...@@ -39,63 +39,62 @@ ConnectionManager.prototype.connect = function(config) { ...@@ -39,63 +39,62 @@ ConnectionManager.prototype.connect = function(config) {
}); });
} }
if(!self.connection){ var connection = new self.lib.Connection(connectionConfig);
config = { connection.lib = self.lib;
user: connectionConfig.user,
password: connectionConfig.password,
server: connectionConfig.host,
port: connectionConfig.port,
database: connectionConfig.database,
pool: {
max: config.max,
min: config.min,
idleTimeoutMillis: config.idle
}
};
self.connection = {
config: config,
lib: self.lib
};
self.lib._transaction = null; connection.on('connect', function(err) {
var conn = new self.lib.Connection(config, function(err) {
if (err) { if (err) {
switch (err.code) {
case 'ELOGIN':
reject('Login failed.');
break;
case 'ETIMEOUT':
reject('Connection timeout.');
break;
case 'EALREADYCONNECTED':
reject('Database is already connected!');
break;
case 'EALREADYCONNECTING':
reject('Already connecting to database!');
break;
case 'EINSTLOOKUP':
reject('Instance lookup failed.');
break;
case 'ESOCKET':
reject('Socket error.');
break;
default:
reject(err); reject(err);
return; break;
} }
self.connection.context = conn; return;
resolve(self.connection);
});
}else{
resolve(self.connection);
} }
resolve(connection);
}); });
};
ConnectionManager.prototype.getConnection = function(options) {
var self = this;
options = options || {};
//TODO: dialect check
return new Promise(function (resolve, reject) {
resolve(self.$connect(self.config));
}); });
}; };
ConnectionManager.prototype.releaseConnection = function(connection) {
var self = this;
return new Promise(function (resolve, reject) {
//self.pool.release(connection);
resolve();
});
};
ConnectionManager.prototype.disconnect = function(connection) { ConnectionManager.prototype.disconnect = function(connection) {
// Dont disconnect a connection that is already disconnected
if (!connection.connected) {
return Promise.resolve();
}
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
resolve(); connection.on('error', function(err) {
// TODO: error checking
reject();
});
connection.on('end', resolve);
connection.close();
}); });
}; };
ConnectionManager.prototype.validate = function(connection) { ConnectionManager.prototype.validate = function(connection) {
// console.log('add code for validations here', connection); return connection && connection.loggedIn;
return true;
}; };
module.exports = ConnectionManager; module.exports = ConnectionManager;
...@@ -5,10 +5,10 @@ var _ = require('lodash') ...@@ -5,10 +5,10 @@ var _ = require('lodash')
, ConnectionManager = require('./connection-manager') , ConnectionManager = require('./connection-manager')
, Query = require('./query'); , Query = require('./query');
//MSSQL uses a single connection that pools on its own
var MssqlDialect = function(sequelize) { var MssqlDialect = function(sequelize) {
this.sequelize = sequelize; this.sequelize = sequelize;
this.connectionManager = new ConnectionManager(this, sequelize); this.connectionManager = new ConnectionManager(this, sequelize);
this.connectionManager.initPools();
}; };
MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), { MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), {
......
...@@ -236,7 +236,7 @@ module.exports = (function() { ...@@ -236,7 +236,7 @@ module.exports = (function() {
showIndexQuery: function(tableName, options) { showIndexQuery: function(tableName, options) {
// FIXME: temporary until I implement proper schema support // FIXME: temporary until I implement proper schema support
var dequotedTableName = tableName.toString().replace(/['"]+/g, ''); var dequotedTableName = tableName.toString().replace(/['"]+/g, '');
var sql = "EXEC sys.sp_helpindex @objname = N'[<%= tableName %>]'"; var sql = "EXEC sys.sp_helpindex @objname = N'[<%= tableName %>]';";
return Utils._.template(sql)({ return Utils._.template(sql)({
tableName: dequotedTableName tableName: dequotedTableName
}); });
...@@ -368,7 +368,8 @@ module.exports = (function() { ...@@ -368,7 +368,8 @@ module.exports = (function() {
}, },
setAutocommitQuery: function(value) { setAutocommitQuery: function(value) {
return 'SET IMPLICIT_TRANSACTIONS ' + (!!value ? 'OFF' : 'ON') + ';'; return '';
// return 'SET IMPLICIT_TRANSACTIONS ' + (!!value ? 'OFF' : 'ON') + ';';
}, },
setIsolationLevelQuery: function(value, options) { setIsolationLevelQuery: function(value, options) {
...@@ -381,11 +382,10 @@ module.exports = (function() { ...@@ -381,11 +382,10 @@ module.exports = (function() {
startTransactionQuery: function(transaction, options) { startTransactionQuery: function(transaction, options) {
if (options.parent) { if (options.parent) {
return ''; return 'SAVE TRANSACTION ' + SqlGenerator.quoteIdentifier(transaction.name) + ';';
//return 'SAVE TRANSACTION ' + SqlGenerator.quoteIdentifier(transaction.name) + ';';
} }
return 'BEGIN TRANSACTION'; return 'BEGIN TRANSACTION;';
}, },
commitTransactionQuery: function(options) { commitTransactionQuery: function(options) {
......
...@@ -34,61 +34,74 @@ module.exports = (function() { ...@@ -34,61 +34,74 @@ module.exports = (function() {
} }
var promise = new Utils.Promise(function(resolve, reject) { var promise = new Utils.Promise(function(resolve, reject) {
if (!sql) { // TRANSACTION SUPPORT
if (Utils._.contains(self.sql, 'BEGIN TRANSACTION')) {
self.connection.beginTransaction(function(err) {
if (!!err) {
console.log(err);
reject(self.formatError(err));
} else {
resolve(self.formatResults()); resolve(self.formatResults());
return promise;
} }
} /* name, isolation_level */);
if (self.sql === 'BEGIN TRANSACTION') { } else if (Utils._.contains(self.sql, 'COMMIT TRANSACTION')) {
var trans = new self.connection.lib.Transaction(self.connection.context); self.connection.commitTransaction(function(err) {
trans.begin(function(err){ if (!!err) {
if (err) { console.log(err);
this.sequelize.log(err.message);
reject(self.formatError(err)); reject(self.formatError(err));
} else { } else {
self.connection.lib._transaction = trans; resolve(self.formatResults());
resolve();
} }
}); });
} else if (Utils._.contains(self.sql, 'ROLLBACK TRANSACTION')) {
self.connection.rollbackTransaction(function(err) {
if (!!err) {
console.log(err);
reject(self.formatError(err));
} else { } else {
var request, transCommand; resolve(self.formatResults());
if (self.connection.lib._transaction && self.connection.uuid) {
request = new self.connection.lib.Request(self.connection.lib._transaction);
if (self.sql === 'COMMIT TRANSACTION;') {
transCommand = 'commit';
} else if (self.sql === 'ROLLBACK TRANSACTION;') {
transCommand = 'rollback';
} }
});
} else {
// QUERY SUPPORT
var results = []
, columns = {};
var request = new self.connection.lib.Request(self.sql, function(err, rowCount) {
promise.emit('sql', self.sql, self.connection.uuid);
if (self.sql === 'COMMIT TRANSACTION;' || self.sql === 'ROLLBACK TRANSACTION;') {
self.connection.lib._transaction[transCommand](function (err, result) {
if (err) { if (err) {
self.sequelize.log(err.message); err.sql = sql;
reject(self.formatError(err)); reject(self.formatError(err));
} else { } else {
resolve(self.formatResults(result)); resolve(self.formatResults(results));
} }
}); });
return promise; request.on('row', function(columns) {
var col, exi, row, _i, _len;
row = {};
for (_i = 0, _len = columns.length; _i < _len; _i++) {
col = columns[_i];
/* col.value = valueCorrection(col.value, col.metadata); */
// exi = row[col.metadata.colName];
exi = null;
if (exi !== null) {
if (exi instanceof Array) {
exi.push(col.value);
} else {
row[col.metadata.colName] = [exi, col.value];
} }
} else { } else {
request = new self.connection.lib.Request(self.connection.context); row[col.metadata.colName] = col.value;
} }
request.query(self.sql, function(err, recordset) {
if (promise) {
promise.emit('sql', self.sql, self.connection.uuid);
} }
if (err) { results.push(row);
self.sequelize.log(err.message);
reject(self.formatError(err));
} else {
resolve(self.formatResults(recordset));
}
}); });
self.connection.execSql(request);
} }
}); });
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
"sqlite3": "~3.0.0", "sqlite3": "~3.0.0",
"mysql": "~2.5.0", "mysql": "~2.5.0",
"pg": "~3.6.0", "pg": "~3.6.0",
"mssql": "^1.2.0", "tedious": "^1.7.0",
"watchr": "~2.4.11", "watchr": "~2.4.11",
"chai": "~1.9.2", "chai": "~1.9.2",
"mocha": "~2.0.0", "mocha": "~2.0.0",
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
"sqlite", "sqlite",
"postgresql", "postgresql",
"postgres", "postgres",
"mssql",
"orm", "orm",
"nodejs", "nodejs",
"object relational mapper" "object relational mapper"
......
...@@ -56,6 +56,13 @@ describe(Support.getTestDialectTeaser("Transaction"), function () { ...@@ -56,6 +56,13 @@ describe(Support.getTestDialectTeaser("Transaction"), function () {
})).to.eventually.be.rejected; })).to.eventually.be.rejected;
}); });
it('supports automatically rolling back with a rejection', function () {
return this.sequelize.transaction(function (t) {
return Promise.reject('Swag');
}).catch(function (err) {
expect(err).to.be.ok;
});
});
}); });
it('does not allow queries after commit', function () { it('does not allow queries after commit', function () {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!