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

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";
var AbstractConnectionManager = require('../abstract/connection-manager')
, Pooling = require('generic-pool')
, ConnectionManager
, Utils = require('../../utils')
, Promise = require('../../promise');
......@@ -10,12 +10,10 @@ ConnectionManager = function(dialect, sequelize) {
this.sequelize = sequelize;
this.sequelize.config.port = this.sequelize.config.port || 1433;
this.connection = null;
try {
this.lib = require(sequelize.config.dialectModulePath || 'mssql');
this.lib = require(sequelize.config.dialectModulePath || 'tedious');
} 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) {
var self = this;
return new Promise(function (resolve, reject) {
var connectionConfig = {
host: config.host,
port: config.port,
user: config.username,
userName: config.username,
password: config.password,
database: config.database,
timezone: self.sequelize.options.timezone
server: config.host,
/* domain: 'DOMAIN' */
options: {
port: config.port,
database: config.database,
}
};
if (config.dialectOptions) {
......@@ -39,63 +39,62 @@ ConnectionManager.prototype.connect = function(config) {
});
}
if(!self.connection){
config = {
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
};
var connection = new self.lib.Connection(connectionConfig);
connection.lib = self.lib;
self.lib._transaction = null;
var conn = new self.lib.Connection(config, function(err) {
if (err) {
connection.on('connect', function(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);
return;
break;
}
self.connection.context = conn;
resolve(self.connection);
});
}else{
resolve(self.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;
}
return new Promise(function (resolve, reject) {
//self.pool.release(connection);
resolve();
resolve(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) {
resolve();
connection.on('error', function(err) {
// TODO: error checking
reject();
});
connection.on('end', resolve);
connection.close();
});
};
ConnectionManager.prototype.validate = function(connection) {
// console.log('add code for validations here', connection);
return true;
return connection && connection.loggedIn;
};
module.exports = ConnectionManager;
......@@ -5,10 +5,10 @@ var _ = require('lodash')
, ConnectionManager = require('./connection-manager')
, Query = require('./query');
//MSSQL uses a single connection that pools on its own
var MssqlDialect = function(sequelize) {
this.sequelize = sequelize;
this.connectionManager = new ConnectionManager(this, sequelize);
this.connectionManager.initPools();
};
MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), {
......
......@@ -236,7 +236,7 @@ module.exports = (function() {
showIndexQuery: function(tableName, options) {
// FIXME: temporary until I implement proper schema support
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)({
tableName: dequotedTableName
});
......@@ -368,7 +368,8 @@ module.exports = (function() {
},
setAutocommitQuery: function(value) {
return 'SET IMPLICIT_TRANSACTIONS ' + (!!value ? 'OFF' : 'ON') + ';';
return '';
// return 'SET IMPLICIT_TRANSACTIONS ' + (!!value ? 'OFF' : 'ON') + ';';
},
setIsolationLevelQuery: function(value, options) {
......@@ -381,11 +382,10 @@ module.exports = (function() {
startTransactionQuery: function(transaction, options) {
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) {
......
......@@ -34,62 +34,75 @@ module.exports = (function() {
}
var promise = new Utils.Promise(function(resolve, reject) {
if (!sql) {
resolve(self.formatResults());
return promise;
}
// 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());
}
} /* name, isolation_level */);
} else if (Utils._.contains(self.sql, 'COMMIT TRANSACTION')) {
self.connection.commitTransaction(function(err) {
if (!!err) {
console.log(err);
reject(self.formatError(err));
} else {
resolve(self.formatResults());
}
});
} else if (Utils._.contains(self.sql, 'ROLLBACK TRANSACTION')) {
self.connection.rollbackTransaction(function(err) {
if (!!err) {
console.log(err);
reject(self.formatError(err));
} else {
resolve(self.formatResults());
}
});
} else {
// QUERY SUPPORT
var results = []
, columns = {};
if (self.sql === 'BEGIN TRANSACTION') {
var trans = new self.connection.lib.Transaction(self.connection.context);
trans.begin(function(err){
if (err) {
this.sequelize.log(err.message);
reject(self.formatError(err));
} else {
self.connection.lib._transaction = trans;
resolve();
}
});
} else {
var request, transCommand;
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';
}
if (self.sql === 'COMMIT TRANSACTION;' || self.sql === 'ROLLBACK TRANSACTION;') {
self.connection.lib._transaction[transCommand](function (err, result) {
if (err) {
self.sequelize.log(err.message);
reject(self.formatError(err));
var request = new self.connection.lib.Request(self.sql, function(err, rowCount) {
promise.emit('sql', self.sql, self.connection.uuid);
if (err) {
err.sql = sql;
reject(self.formatError(err));
} else {
resolve(self.formatResults(results));
}
});
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 {
resolve(self.formatResults(result));
row[col.metadata.colName] = col.value;
}
});
}
return promise;
}
} else {
request = new self.connection.lib.Request(self.connection.context);
}
results.push(row);
});
request.query(self.sql, function(err, recordset) {
if (promise) {
promise.emit('sql', self.sql, self.connection.uuid);
}
if (err) {
self.sequelize.log(err.message);
reject(self.formatError(err));
} else {
resolve(self.formatResults(recordset));
}
});
}
self.connection.execSql(request);
}
});
return promise;
......
......@@ -48,7 +48,7 @@
"sqlite3": "~3.0.0",
"mysql": "~2.5.0",
"pg": "~3.6.0",
"mssql": "^1.2.0",
"tedious": "^1.7.0",
"watchr": "~2.4.11",
"chai": "~1.9.2",
"mocha": "~2.0.0",
......@@ -69,6 +69,7 @@
"sqlite",
"postgresql",
"postgres",
"mssql",
"orm",
"nodejs",
"object relational mapper"
......
......@@ -56,6 +56,13 @@ describe(Support.getTestDialectTeaser("Transaction"), function () {
})).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 () {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!