Permalink
Browse files

Transaction and cancellation support

  • Loading branch information...
1 parent bd05d5d commit e78ff107a2522ced17ab3ac4e008a3f92c42d8ee @cretz committed Jan 3, 2012
View
@@ -36,5 +36,5 @@ task 'compile', 'compile JS', ->
task 'test', 'test node-tds', ->
invoke 'clean'
compile false, ->
- run 'node', ['node_modules/mocha/bin/_mocha', '-t', '100s', '-R', 'spec', '--ignore-leaks', 'test/node-tds.statement.test.coffee'],
+ run 'node', ['node_modules/mocha/bin/_mocha', '-t', '100s', '-R', 'spec', '--ignore-leaks'],
-> 'Tests complete'
@@ -0,0 +1,26 @@
+var Packet,
+ __hasProp = Object.prototype.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
+
+Packet = require('./packet').Packet;
+
+exports.AttentionPacket = (function(_super) {
+
+ __extends(AttentionPacket, _super);
+
+ AttentionPacket.type = 0x06;
+
+ AttentionPacket.name = 'ATTENTION';
+
+ function AttentionPacket() {
+ this.type = 0x06;
+ this.name = 'ATTENTION';
+ }
+
+ AttentionPacket.prototype.toBuffer = function(builder, context) {
+ return this.insertPacketHeader(builder, context);
+ };
+
+ return AttentionPacket;
+
+})(Packet);
View
@@ -19,26 +19,27 @@ exports.DoneToken = (function(_super) {
DoneToken.name = 'DONE';
function DoneToken() {
+ var _this = this;
this.type = 0xFD;
this.name = 'DONE';
this.handlerFunction = 'done';
this.__defineGetter__('hasMore', function() {
- return this.status & 0x0001;
+ return _this.status & 0x01 !== 0;
});
this.__defineGetter__('isError', function() {
- return this.status & 0x0002;
+ return _this.status & 0x02 !== 0;
});
this.__defineGetter__('hasRowCount', function() {
- return this.status & 0x0010;
+ return _this.status & 0x10 !== 0;
});
this.__defineGetter__('isCanceled', function() {
- return this.status & 0x0020;
+ return _this.status & 0x20 !== 0;
});
this.__defineGetter__('isCancelled', function() {
- return this.status & 0x0020;
+ return _this.status & 0x20 !== 0;
});
this.__defineGetter__('isFatal', function() {
- return this.status & 0x0100;
+ return _this.status & 0x100 !== 0;
});
}
View
@@ -1,4 +1,5 @@
var EventEmitter, Statement, TdsClient, TdsError, TdsUtils,
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = Object.prototype.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
@@ -16,12 +17,26 @@ exports.Connection = (function(_super) {
var _ref, _ref2,
_this = this;
this._options = _options;
+ this.end = __bind(this.end, this);
+ this.rollback = __bind(this.rollback, this);
+ this.commit = __bind(this.commit, this);
+ this.setAutoCommit = __bind(this.setAutoCommit, this);
+ this.prepareBulkLoad = __bind(this.prepareBulkLoad, this);
+ this.createCall = __bind(this.createCall, this);
+ this.createStatement = __bind(this.createStatement, this);
+ this.connect = __bind(this.connect, this);
+ this._autoCommit = true;
this._client = new TdsClient({
message: function(message) {
- var err, _base, _base2;
+ var cb, err, _base, _base2;
if (message.error) {
err = new TdsError(message.text, message);
- if (_this._currentStatement != null) {
+ if (_this._pendingCallback != null) {
+ _this._currentStatement = null;
+ cb = _this._pendingCallback;
+ _this._pendingCallback = null;
+ return cb(err);
+ } else if (_this._currentStatement != null) {
return _this._currentStatement._error(err);
} else if (_this.handler != null) {
return typeof (_base = _this.handler).error === "function" ? _base.error(err) : void 0;
@@ -46,21 +61,31 @@ exports.Connection = (function(_super) {
return typeof cb === "function" ? cb() : void 0;
},
row: function(row) {
- return _this._currentStatement._row(row);
+ var _ref;
+ return (_ref = _this._currentStatement) != null ? _ref._row(row) : void 0;
},
colmetadata: function(colmetadata) {
- return _this._currentStatement._colmetadata(colmetadata);
+ var _ref;
+ return (_ref = _this._currentStatement) != null ? _ref._colmetadata(colmetadata) : void 0;
},
done: function(done) {
- var _ref;
- return (_ref = _this._currentStatement) != null ? _ref._done(done) : void 0;
+ var cb;
+ if (done.hasMore) return;
+ if (_this._pendingCallback != null) {
+ if (_this._currentStatement === '#setAutoCommit') {
+ _this._autoCommit = !_this._autoCommit;
+ }
+ _this._currentStatement = null;
+ cb = _this._pendingCallback;
+ _this._pendingCallback = null;
+ return cb();
+ } else if (_this._currentStatement != null) {
+ return _this._currentStatement._done(done);
+ }
}
});
this._client.logError = (_ref = this._options) != null ? _ref.logError : void 0;
this._client.logDebug = (_ref2 = this._options) != null ? _ref2.logDebug : void 0;
- this.__defineGetter__('isExecutingStatement', function() {
- return this._currentStatement != null;
- });
}
Connection.prototype.connect = function(_pendingLoginCallback) {
@@ -69,7 +94,7 @@ exports.Connection = (function(_super) {
};
Connection.prototype.createStatement = function(sql, params, handler) {
- if (this.isExecutingStatement) throw new Error('Statement currently running');
+ if (this._currentStatement) throw new Error('Statement currently running');
if (this._options.logDebug) {
console.log('Creating statement: %s with params: ', sql, params);
}
@@ -84,20 +109,46 @@ exports.Connection = (function(_super) {
throw new Error('Not yet implemented');
};
- Connection.prototype.setAutoCommit = function(autoCommit, cb) {
- this.autoCommit = autoCommit;
- throw new Error('Not yet implemented');
+ Connection.prototype.setAutoCommit = function(autoCommit, autoCommitCallback) {
+ if (this._autoCommit === autoCommit) {
+ return cb();
+ } else {
+ if (this._currentStatement != null) {
+ throw new Error('Cannot change auto commit while statement is executing');
+ }
+ this._pendingCallback = autoCommitCallback;
+ this._currentStatement = '#setAutoCommit';
+ if (autoCommit) {
+ return this._client.sqlBatch('SET IMPLICIT_TRANSACTIONS OFF');
+ } else {
+ return this._client.sqlBatch('SET IMPLICIT_TRANSACTIONS ON');
+ }
+ }
};
- Connection.prototype.commit = function(cb) {
- throw new Error('Not yet implemented');
+ Connection.prototype.commit = function(commitCallback) {
+ if (this._autoCommit) throw new Error('Auto commit is on');
+ if (this._currentStatement != null) {
+ throw new Error('Cannot commit while statement is executing');
+ }
+ this._pendingCallback = commitCallback;
+ this._currentStatement = '#commit';
+ return this._client.sqlBatch('IF @@TRANCOUNT > 0 COMMIT TRANSACTION');
};
- Connection.prototype.rollback = function(cb) {
- throw new Error('Not yet implemented');
+ Connection.prototype.rollback = function(rollbackCallback) {
+ if (this._autoCommit) throw new Error('Auto commit is on');
+ if (this._currentStatement != null) {
+ throw new Error('Cannot rollback while statement is executing');
+ }
+ this._pendingCallback = rollbackCallback;
+ this._currentStatement = '#rollback';
+ return this._client.sqlBatch('IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION');
};
Connection.prototype.end = function() {
+ this._autoCommit = true;
+ this._pendingCallback = null;
this._currentStatement = null;
return this._client.end();
};
@@ -116,6 +167,13 @@ Statement = exports.Statement = (function(_super) {
this._sql = _sql;
this._params = _params;
this.handler = handler;
+ this._done = __bind(this._done, this);
+ this._row = __bind(this._row, this);
+ this._colmetadata = __bind(this._colmetadata, this);
+ this._message = __bind(this._message, this);
+ this._error = __bind(this._error, this);
+ this.cancel = __bind(this.cancel, this);
+ this.execute = __bind(this.execute, this);
if (this._params != null) {
parameterString = TdsUtils.buildParameterDefinition(this._params);
if (parameterString !== '') {
@@ -126,6 +184,9 @@ Statement = exports.Statement = (function(_super) {
Statement.prototype.execute = function(paramValues) {
var sql;
+ if (this._connection._currentStatement != null) {
+ throw new Error('Another statement already executing');
+ }
this._connection._currentStatement = this;
if (!(this._params != null)) {
return this._connection._client.sqlBatch(this._sql);
@@ -136,7 +197,8 @@ Statement = exports.Statement = (function(_super) {
};
Statement.prototype.cancel = function() {
- throw new Error('Not yet implemented');
+ this._cancelling = true;
+ return this._connection._client.cancel();
};
Statement.prototype._error = function(err) {
@@ -159,26 +221,35 @@ Statement = exports.Statement = (function(_super) {
Statement.prototype._colmetadata = function(colmetadata) {
var _base;
- this.metadata = colmetadata;
- if (this.handler != null) {
- return typeof (_base = this.handler).metadata === "function" ? _base.metadata(this.metadata) : void 0;
- } else {
- return this.emit('metadata', this.metadata);
+ if (!this._cancelling) {
+ this.metadata = colmetadata;
+ if (this.handler != null) {
+ return typeof (_base = this.handler).metadata === "function" ? _base.metadata(this.metadata) : void 0;
+ } else {
+ return this.emit('metadata', this.metadata);
+ }
}
};
Statement.prototype._row = function(row) {
var _base;
- if (this.handler != null) {
- return typeof (_base = this.handler).row === "function" ? _base.row(row) : void 0;
- } else {
- return this.emit('row', row);
+ if (!this._cancelling) {
+ if (this.handler != null) {
+ return typeof (_base = this.handler).row === "function" ? _base.row(row) : void 0;
+ } else {
+ return this.emit('row', row);
+ }
}
};
Statement.prototype._done = function(done) {
var _base;
- if (!done.hasMore) this._connection._currentStatement = null;
+ if (this._cancelling) {
+ this._cancelling = void 0;
+ this._connection._currentStatement = null;
+ } else if (!done.hasMore) {
+ this._connection._currentStatement = null;
+ }
if (this.handler != null) {
return typeof (_base = this.handler).done === "function" ? _base.done(done) : void 0;
} else {
View
@@ -21,14 +21,13 @@ exports.RowToken = (function(_super) {
}
RowToken.prototype.fromBuffer = function(stream, context) {
- var column, index, val, _i, _len, _ref, _results;
+ var column, index, val, _len, _ref, _results;
this.metadata = context.colmetadata;
this.values = new Array(this.metadata.columns.length);
- index = -1;
_ref = this.metadata.columns;
_results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- column = _ref[_i];
+ for (index = 0, _len = _ref.length; index < _len; index++) {
+ column = _ref[index];
val = {};
switch (column.lengthType) {
case 'int32LE':
@@ -49,7 +48,7 @@ exports.RowToken = (function(_super) {
} else if (val.length > 0) {
val.buffer = stream.readBuffer(val.length);
}
- _results.push(this.values[++index] = val);
+ _results.push(this.values[index] = val);
}
return _results;
};
@@ -81,28 +80,28 @@ exports.RowToken = (function(_super) {
if (val.length === 0) {
return null;
} else {
- return val.buffer.readUInt8(0);
+ return val.buffer.readInt8(0);
}
break;
case 'SmallInt':
if (val.length === 0) {
return null;
} else {
- return val.buffer.readUInt16LE(0);
+ return val.buffer.readInt16LE(0);
}
break;
case 'Int':
if (val.length === 0) {
return null;
} else {
- return val.buffer.readUInt32LE(0);
+ return val.buffer.readInt32LE(0);
}
break;
case 'BigInt':
if (val.length === 0) {
return null;
} else {
- return TdsUtils.bigIntBufferToString(val);
+ return TdsUtils.bigIntBufferToString(val.buffer);
}
break;
case 'Char':
Oops, something went wrong.

0 comments on commit e78ff10

Please sign in to comment.