diff --git a/mocha.start.js b/mocha.start.js index 35ad722..af0bffa 100644 --- a/mocha.start.js +++ b/mocha.start.js @@ -38,7 +38,8 @@ var globals = module.exports = { }], TYPES_EXCEPT_FUNCTION: ['string', 123, 123.123, null, undefined, {}, [], true, false], assert: assert, - adapter: undefined + adapter: undefined, + co: require('co') }; var test = new mocha(); diff --git a/package.json b/package.json index f1f8598..499f7f9 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "babel-loader": "5.3.2", "bluebird": "2.10.2", "chai": "3.3.0", + "co": "^4.6.0", "co-mocha": "1.1.2", "mocha": "2.3.3", "standard": "5.3.1", diff --git a/src/index.js b/src/index.js index 0f74d41..410d0aa 100644 --- a/src/index.js +++ b/src/index.js @@ -19,9 +19,10 @@ function getTable (resourceConfig) { return resourceConfig.table || underscore(resourceConfig.name) } -function filterQuery (resourceConfig, params) { +function filterQuery (resourceConfig, params, options) { let table = getTable(resourceConfig) - let query = this.query.select(`${table}.*`).from(table) + let query = options && options.transaction || this.query + query = query.select(`${table}.*`).from(table) params = params || {} params.where = params.where || {} params.orderBy = params.orderBy || params.sort @@ -301,7 +302,8 @@ class DSSqlAdapter { let instance options = options || {} options.with = options.with || [] - return this.query + let query = options && options.transaction || this.query + return query .select('*') .from(getTable(resourceConfig)) .where(resourceConfig.idAttribute, toString(id)) @@ -328,7 +330,8 @@ class DSSqlAdapter { create (resourceConfig, attrs, options) { attrs = DSUtils.removeCircular(DSUtils.omit(attrs, resourceConfig.relationFields || [])) - return this.query(getTable(resourceConfig)) + let query = options && options.transaction || this.query + return query(getTable(resourceConfig)) .insert(attrs, resourceConfig.idAttribute) .then(ids => { if (attrs[resourceConfig.idAttribute]) { @@ -343,7 +346,8 @@ class DSSqlAdapter { update (resourceConfig, id, attrs, options) { attrs = DSUtils.removeCircular(DSUtils.omit(attrs, resourceConfig.relationFields || [])) - return this.query(getTable(resourceConfig)) + let query = options && options.transaction || this.query + return query(getTable(resourceConfig)) .where(resourceConfig.idAttribute, toString(id)) .update(attrs) .then(() => this.find(resourceConfig, id, options)) @@ -364,8 +368,9 @@ class DSSqlAdapter { }) } - destroy (resourceConfig, id) { - return this.query(getTable(resourceConfig)) + destroy (resourceConfig, id, options) { + let query = options && options.transaction || this.query + return query(getTable(resourceConfig)) .where(resourceConfig.idAttribute, toString(id)) .del().then(() => undefined) } diff --git a/test/create_trx.spec.js b/test/create_trx.spec.js new file mode 100644 index 0000000..7808b79 --- /dev/null +++ b/test/create_trx.spec.js @@ -0,0 +1,42 @@ +describe('DSSqlAdapter#create + transaction', function () { + it('commit should persist created user in a sql db', function* () { + var id; + + yield adapter.query.transaction(co.wrap(function * (trx) { + var createUser = yield adapter.create(User, {name: 'Jane'}, {transaction: trx}); + id = createUser.id; + assert.equal(createUser.name, 'Jane'); + assert.isDefined(createUser.id); + })); + + var findUser = yield adapter.find(User, id); + assert.isObject(findUser, 'user committed to database'); + assert.equal(findUser.name, 'Jane'); + assert.isDefined(findUser.id); + assert.equalObjects(findUser, {id: id, name: 'Jane', age: null, profileId: null}); + }); + + it('rollback should not persist created user in a sql db', function* () { + var id; + + try { + yield adapter.query.transaction(co.wrap(function * (trx) { + var createUser = yield adapter.create(User, {name: 'John'}, {transaction: trx}); + id = createUser.id; + assert.equal(createUser.name, 'John'); + assert.isDefined(createUser.id); + + throw new Error('rollback'); + })); + } catch (err) { + assert.equal(err.message, 'rollback'); + } + + try { + var findUser = yield adapter.find(User, id); + throw new Error('user committed to database'); + } catch(err) { + assert.equal(err.message, 'Not Found!'); + } + }); +}); diff --git a/test/destroy_trx.spec.js b/test/destroy_trx.spec.js new file mode 100644 index 0000000..2d7b47c --- /dev/null +++ b/test/destroy_trx.spec.js @@ -0,0 +1,35 @@ +describe('DSSqlAdapter#destroy + transaction', function () { + it('commit should destroy a user from a Sql db', function* () { + var createUser = yield adapter.create(User, {name: 'John'}) + var id = createUser.id; + + yield adapter.query.transaction(co.wrap(function * (trx) { + return adapter.destroy(User, id, {transaction: trx}); + })); + + try { + var findUser = yield adapter.find(User, id); + throw new Error('Should not have reached here!'); + } catch (err) { + assert.equal(err.message, 'Not Found!'); + } + }); + + it('rollback should not destroy a user from a Sql db', function* () { + var createUser = yield adapter.create(User, {name: 'John'}) + var id = createUser.id; + + try { + yield adapter.query.transaction(co.wrap(function * (trx) { + yield adapter.destroy(User, createUser.id, {transaction: trx}); + + throw new Error('rollback'); + })); + } catch (err) { + assert.equal(err.message, 'rollback'); + } + + var findUser = yield adapter.find(User, id); + assert.isObject(findUser, 'user still exists'); + }); +}); diff --git a/test/update_trx.spec.js b/test/update_trx.spec.js new file mode 100644 index 0000000..fe16b0c --- /dev/null +++ b/test/update_trx.spec.js @@ -0,0 +1,45 @@ +describe('DSSqlAdapter#update + transaction', function () { + it('commit should update a user in a Sql db', function* () { + var user = yield adapter.create(User, {name: 'John'}) + var id = user.id; + assert.equal(user.name, 'John'); + assert.isDefined(user.id); + + yield adapter.query.transaction(co.wrap(function * (trx) { + var updatedUser = yield adapter.update(User, id, {name: 'Johnny'}, {transaction: trx}); + assert.equal(updatedUser.name, 'Johnny'); + assert.isDefined(updatedUser.id); + assert.equalObjects(updatedUser, {id: id, name: 'Johnny', age: null, profileId: null}); + })); + + var foundUser = yield adapter.find(User, id); + assert.equal(foundUser.name, 'Johnny'); + assert.isDefined(foundUser.id); + assert.equalObjects(foundUser, {id: id, name: 'Johnny', age: null, profileId: null}); + }); + + it('rollback should not update a user in a Sql db', function* () { + var user = yield adapter.create(User, {name: 'John'}) + var id = user.id; + assert.equal(user.name, 'John'); + assert.isDefined(user.id); + + try { + yield adapter.query.transaction(co.wrap(function * (trx) { + var updatedUser = yield adapter.update(User, id, {name: 'Johnny'}, {transaction: trx}); + assert.equal(updatedUser.name, 'Johnny'); + assert.isDefined(updatedUser.id); + assert.equalObjects(updatedUser, {id: id, name: 'Johnny', age: null, profileId: null}); + + throw new Error('rollback'); + })); + } catch (err) { + assert.equal(err.message, 'rollback'); + } + + var foundUser = yield adapter.find(User, id); + assert.equal(foundUser.name, 'John'); + assert.isDefined(foundUser.id); + assert.equalObjects(foundUser, {id: id, name: 'John', age: null, profileId: null}); + }); +});