Skip to content

Commit

Permalink
Merge pull request sequelize#2697 from mbroadst/feature/mssql-dialect
Browse files Browse the repository at this point in the history
Feature/mssql dialect
  • Loading branch information
mickhansen committed Dec 10, 2014
2 parents 3a8ef3b + adfeea8 commit 78ba32c
Show file tree
Hide file tree
Showing 32 changed files with 1,453 additions and 191 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ env:
- DB=mysql DIALECT=postgres-native
- DB=mysql DIALECT=sqlite
- DB=mysql DIALECT=mariadb
- DB=mysql DIALECT=mssql

addons:
postgresql: "9.3"

before_script:
- "mysql -e 'create database sequelize_test;'"
- "psql -c 'create database sequelize_test;' -U postgres"
Expand All @@ -39,6 +40,8 @@ matrix:
allow_failures:
- node_js: "0.10"
env: COVERAGE=true
- node_js: "0.10"
env: DB=mysql DIALECT=mssql

notifications:
hipchat:
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ sqlite:
@DIALECT=sqlite make test
mysql:
@DIALECT=mysql make test
mssql:
@DIALECT=mssql make test
postgres:
@DIALECT=postgres make test
postgres-native:
Expand Down
105 changes: 105 additions & 0 deletions lib/dialects/mssql/connection-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"use strict";
var AbstractConnectionManager = require('../abstract/connection-manager')
, ConnectionManager
, Utils = require('../../utils')
, Promise = require('../../promise')
, sequelizeErrors = require('../../errors');

ConnectionManager = function(dialect, sequelize) {
AbstractConnectionManager.call(this, dialect, sequelize);

this.sequelize = sequelize;
this.sequelize.config.port = this.sequelize.config.port || 1433;
try {
this.lib = require(sequelize.config.dialectModulePath || 'tedious');
} catch (err) {
throw new Error('Please install tedious package manually');
}
};

Utils._.extend(ConnectionManager.prototype, AbstractConnectionManager.prototype);

ConnectionManager.prototype.connect = function(config) {
var self = this;
return new Promise(function (resolve, reject) {
var connectionConfig = {
userName: config.username,
password: config.password,
server: config.host,
/* domain: 'DOMAIN' */
options: {
port: config.port,
database: config.database,
}
};

if (config.dialectOptions) {
Object.keys(config.dialectOptions).forEach(function(key) {
connectionConfig[key] = config.dialectOptions[key];
});
}

var connection = new self.lib.Connection(connectionConfig);
connection.lib = self.lib;

connection.on('connect', function(err) {
if (!err) {
resolve(connection);
return;
}

if (!err.code) {
reject(new sequelizeErrors.ConnectionError(err));
return;
}

switch (err.code) {
case 'ESOCKET':
if (Utils._.contains(err.message, 'connect EHOSTUNREACH')) {
reject(new sequelizeErrors.HostNotReachableError(err));
} else if (Utils._.contains(err.message, 'connect ECONNREFUSED')) {
reject(new sequelizeErrors.ConnectionRefusedError(err));
} else {
reject(new sequelizeErrors.ConnectionError(err));
}
break;
case 'ECONNREFUSED':
reject(new sequelizeErrors.ConnectionRefusedError(err));
break;
case 'ER_ACCESS_DENIED_ERROR':
reject(new sequelizeErrors.AccessDeniedError(err));
break;
case 'ENOTFOUND':
reject(new sequelizeErrors.HostNotFoundError(err));
break;
case 'EHOSTUNREACH':
reject(new sequelizeErrors.HostNotReachableError(err));
break;
case 'EINVAL':
reject(new sequelizeErrors.InvalidConnectionError(err));
break;
default:
reject(new sequelizeErrors.ConnectionError(err));
break;
}
});
});
};

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) {
connection.on('end', resolve);
connection.close();
});
};

ConnectionManager.prototype.validate = function(connection) {
return connection && connection.loggedIn;
};

module.exports = ConnectionManager;
29 changes: 29 additions & 0 deletions lib/dialects/mssql/data-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

var DataTypes = require('../../data-types');

//drop table Group
DataTypes.BOOLEAN = 'BIT';
DataTypes.NOW = 'GETDATE()';
DataTypes.UUID = 'UNIQUEIDENTIFIER';
DataTypes.BLOB = 'VARBINARY(MAX)';
DataTypes.STRING._typeName = 'NVARCHAR';

DataTypes.STRING.prototype = {
get BINARY() {
this._binary = true;
return this;
},
get type() {
return this.toString();
},
toString: function() {
if(!this._binary){
return 'NVARCHAR(' + this._length + ')';
}else{
return 'BINARY(' + this._length + ')';
}
}
};

module.exports = DataTypes;
43 changes: 43 additions & 0 deletions lib/dialects/mssql/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

var _ = require('lodash')
, Abstract = require('../abstract')
, ConnectionManager = require('./connection-manager')
, Query = require('./query');

var MssqlDialect = function(sequelize) {
this.sequelize = sequelize;
this.connectionManager = new ConnectionManager(this, sequelize);
this.connectionManager.initPools();
};

MssqlDialect.prototype.supports = _.merge(_.cloneDeep(Abstract.prototype.supports), {
'RETURNING': false,
'OUTPUT': true,
'DEFAULT': true,
'DEFAULT VALUES': true,
'LIMIT ON UPDATE': true,
lock: false,
transactions: false,
migrations: false,
upserts: false,
autoIncrement: {
identityInsert: true,
defaultValue: false,
update: false
},
constraints: {
restrict: false
},
index: {
collate: false,
length: false,
parser: false,
type: true,
using: false,
}
});

MssqlDialect.prototype.Query = Query;

module.exports = MssqlDialect;
Loading

0 comments on commit 78ba32c

Please sign in to comment.