2014-09-01 17:18:45 +02:00
/*global describe, expect, it, testPromise*/
'use strict' ;
2014-06-06 17:27:59 -04:00
var Promise = testPromise ;
2016-02-01 20:40:06 +01:00
var Knex = require ( '../../../knex' ) ;
var _ = require ( 'lodash' ) ;
2013-09-11 23:36:55 -04:00
module . exports = function ( knex ) {
2013-09-12 13:30:47 -04:00
describe ( 'Transactions' , function ( ) {
2013-09-11 23:36:55 -04:00
2015-04-22 10:34:14 -04:00
it ( 'can run with asCallback' , function ( ok ) {
2014-03-19 11:54:18 -04:00
knex . transaction ( function ( t ) {
t . commit ( ) ;
2015-04-22 10:34:14 -04:00
} )
. asCallback ( ok )
2014-03-19 11:54:18 -04:00
} ) ;
2014-04-16 01:23:50 -04:00
it ( 'should be able to commit transactions' , function ( ) {
2013-09-11 23:36:55 -04:00
var id = null ;
return knex . transaction ( function ( t ) {
knex ( 'accounts' )
. transacting ( t )
. returning ( 'id' )
. insert ( {
first _name : 'Transacting' ,
last _name : 'User' ,
2014-05-08 18:04:55 -04:00
email : 'transaction-test1@example.com' ,
2013-09-11 23:36:55 -04:00
logins : 1 ,
about : 'Lorem ipsum Dolore labore incididunt enim.' ,
created _at : new Date ( ) ,
updated _at : new Date ( )
} ) . then ( function ( resp ) {
return knex ( 'test_table_two' ) . transacting ( t ) . insert ( {
account _id : ( id = resp [ 0 ] ) ,
details : '' ,
status : 1
} ) ;
} ) . then ( function ( ) {
t . commit ( 'Hello world' ) ;
} ) ;
} ) . then ( function ( commitMessage ) {
expect ( commitMessage ) . to . equal ( 'Hello world' ) ;
return knex ( 'accounts' ) . where ( 'id' , id ) . select ( 'first_name' ) ;
} ) . then ( function ( resp ) {
expect ( resp ) . to . have . length ( 1 ) ;
} ) ;
} ) ;
2014-04-16 01:23:50 -04:00
it ( 'should be able to rollback transactions' , function ( ) {
2013-09-11 23:36:55 -04:00
var id = null ;
var err = new Error ( 'error message' ) ;
return knex . transaction ( function ( t ) {
knex ( 'accounts' )
. transacting ( t )
. returning ( 'id' )
. insert ( {
first _name : 'Transacting' ,
last _name : 'User2' ,
email : 'transaction-test2@example.com' ,
logins : 1 ,
about : 'Lorem ipsum Dolore labore incididunt enim.' ,
created _at : new Date ( ) ,
updated _at : new Date ( )
} ) . then ( function ( resp ) {
return knex ( 'test_table_two' ) . transacting ( t ) . insert ( {
account _id : ( id = resp [ 0 ] ) ,
details : '' ,
status : 1
} ) ;
} ) . then ( function ( ) {
t . rollback ( err ) ;
} ) ;
2014-05-08 18:04:55 -04:00
} ) . catch ( function ( msg ) {
2013-09-11 23:36:55 -04:00
expect ( msg ) . to . equal ( err ) ;
return knex ( 'accounts' ) . where ( 'id' , id ) . select ( 'first_name' ) ;
} ) . then ( function ( resp ) {
2014-09-02 22:03:14 +02:00
expect ( resp . length ) . to . equal ( 0 ) ;
2014-05-08 18:04:55 -04:00
} ) ;
} ) ;
it ( 'should be able to commit transactions with a resolved trx query' , function ( ) {
2013-09-11 23:36:55 -04:00
2014-05-08 18:04:55 -04:00
var id = null ;
return knex . transaction ( function ( trx ) {
return trx ( 'accounts' )
. returning ( 'id' )
. insert ( {
first _name : 'Transacting' ,
last _name : 'User' ,
email : 'transaction-test3@example.com' ,
logins : 1 ,
about : 'Lorem ipsum Dolore labore incididunt enim.' ,
created _at : new Date ( ) ,
updated _at : new Date ( )
} ) . then ( function ( resp ) {
return trx ( 'test_table_two' ) . insert ( {
account _id : ( id = resp [ 0 ] ) ,
details : '' ,
status : 1
} ) ;
} ) . then ( function ( ) {
return 'Hello World' ;
} ) ;
} ) . then ( function ( commitMessage ) {
expect ( commitMessage ) . to . equal ( 'Hello World' ) ;
return knex ( 'accounts' ) . where ( 'id' , id ) . select ( 'first_name' ) ;
} ) . then ( function ( resp ) {
expect ( resp ) . to . have . length ( 1 ) ;
2013-09-11 23:36:55 -04:00
} ) ;
2014-05-08 18:04:55 -04:00
} ) ;
2013-09-11 23:36:55 -04:00
2014-05-08 18:04:55 -04:00
it ( 'should be able to rollback transactions with rejected trx query' , function ( ) {
var id = null ;
var err = new Error ( 'error message' ) ;
2015-04-17 15:00:08 -04:00
var _ _knexUid , count = 0 ;
2014-05-08 18:04:55 -04:00
return knex . transaction ( function ( trx ) {
return trx ( 'accounts' )
. returning ( 'id' )
. insert ( {
first _name : 'Transacting' ,
last _name : 'User2' ,
email : 'transaction-test4@example.com' ,
logins : 1 ,
about : 'Lorem ipsum Dolore labore incididunt enim.' ,
created _at : new Date ( ) ,
updated _at : new Date ( )
2014-06-06 17:27:59 -04:00
} )
. then ( function ( resp ) {
2014-05-08 18:04:55 -04:00
return trx . insert ( {
account _id : ( id = resp [ 0 ] ) ,
details : '' ,
status : 1
} ) . into ( 'test_table_two' ) ;
2014-06-06 17:27:59 -04:00
} )
. then ( function ( ) {
2014-05-08 18:04:55 -04:00
throw err ;
} ) ;
2014-05-08 18:31:25 -04:00
} )
. on ( 'query' , function ( obj ) {
count ++ ;
2015-04-17 15:00:08 -04:00
if ( ! _ _knexUid ) _ _knexUid = obj . _ _knexUid ;
expect ( _ _knexUid ) . to . equal ( obj . _ _knexUid ) ;
2014-05-08 18:31:25 -04:00
} )
. catch ( function ( msg ) {
2016-03-08 07:44:57 +01:00
// oracle & mssql: BEGIN & ROLLBACK not reported as queries
var expectedCount =
knex . client . dialect === 'oracle' ||
knex . client . dialect === 'mssql' ? 2 : 4 ;
expect ( count ) . to . equal ( expectedCount ) ;
2014-05-08 18:04:55 -04:00
expect ( msg ) . to . equal ( err ) ;
return knex ( 'accounts' ) . where ( 'id' , id ) . select ( 'first_name' ) ;
2014-06-06 17:27:59 -04:00
} )
. then ( function ( resp ) {
expect ( resp ) . to . eql ( [ ] ) ;
2014-05-08 18:04:55 -04:00
} ) ;
2013-09-11 23:36:55 -04:00
} ) ;
2014-06-06 17:27:59 -04:00
it ( 'should be able to run schema methods' , function ( ) {
2015-04-17 15:00:08 -04:00
var _ _knexUid , count = 0 ;
2014-06-06 17:27:59 -04:00
var err = new Error ( 'error message' ) ;
if ( knex . client . dialect === 'postgresql' ) {
2014-06-05 17:01:02 -07:00
return knex . transaction ( function ( trx ) {
2014-06-06 17:27:59 -04:00
return trx . schema . createTable ( 'test_schema_transactions' , function ( table ) {
2014-06-05 17:01:02 -07:00
table . increments ( ) ;
table . string ( 'name' ) ;
table . timestamps ( ) ;
} ) . then ( function ( ) {
2014-06-06 17:27:59 -04:00
return trx ( 'test_schema_transactions' ) . insert ( { name : 'bob' } ) ;
2014-06-05 17:01:02 -07:00
} ) . then ( function ( ) {
2014-06-06 17:27:59 -04:00
return trx ( 'test_schema_transactions' ) . count ( '*' ) ;
2014-06-05 17:01:02 -07:00
} ) . then ( function ( resp ) {
2014-06-06 17:27:59 -04:00
var _count = parseInt ( resp [ 0 ] . count , 10 ) ;
2014-06-05 17:01:02 -07:00
expect ( _count ) . to . equal ( 1 ) ;
throw err ;
} ) ;
} )
. on ( 'query' , function ( obj ) {
count ++ ;
2015-04-17 15:00:08 -04:00
if ( ! _ _knexUid ) _ _knexUid = obj . _ _knexUid ;
expect ( _ _knexUid ) . to . equal ( obj . _ _knexUid ) ;
2014-06-05 17:01:02 -07:00
} )
. catch ( function ( msg ) {
expect ( msg ) . to . equal ( err ) ;
expect ( count ) . to . equal ( 5 ) ;
2014-06-06 17:27:59 -04:00
return knex ( 'test_schema_migrations' ) . count ( '*' ) ;
2014-06-05 17:01:02 -07:00
} )
. catch ( function ( e ) {
2015-04-24 10:10:34 -04:00
expect ( e . message ) . to . equal ( 'select count(*) from \"test_schema_migrations\" - relation "test_schema_migrations" does not exist' ) ;
2014-06-05 17:01:02 -07:00
} ) ;
2014-06-06 17:27:59 -04:00
} else {
2014-06-05 17:01:02 -07:00
var id = null ;
return knex . transaction ( function ( trx ) {
return trx ( 'accounts' )
. returning ( 'id' )
. insert ( {
first _name : 'Transacting' ,
last _name : 'User3' ,
email : 'transaction-test5@example.com' ,
logins : 1 ,
about : 'Lorem ipsum Dolore labore incididunt enim.' ,
created _at : new Date ( ) ,
updated _at : new Date ( )
} ) . then ( function ( resp ) {
return trx ( 'test_table_two' ) . insert ( {
account _id : ( id = resp [ 0 ] ) ,
details : '' ,
status : 1
} ) ;
} ) . then ( function ( ) {
2014-06-06 17:27:59 -04:00
return trx . schema . createTable ( 'test_schema_transactions' , function ( table ) {
2014-06-05 17:01:02 -07:00
table . increments ( ) ;
table . string ( 'name' ) ;
table . timestamps ( ) ;
} ) ;
} ) ;
} )
. on ( 'query' , function ( obj ) {
count ++ ;
2015-04-17 15:00:08 -04:00
if ( ! _ _knexUid ) _ _knexUid = obj . _ _knexUid ;
expect ( _ _knexUid ) . to . equal ( obj . _ _knexUid ) ;
2014-06-05 17:01:02 -07:00
} ) . then ( function ( ) {
2015-12-09 17:53:53 -06:00
if ( knex . client . dialect === 'mssql' ) {
expect ( count ) . to . equal ( 3 ) ;
} else {
expect ( count ) . to . equal ( 5 ) ;
}
2014-06-05 17:01:02 -07:00
return knex ( 'accounts' ) . where ( 'id' , id ) . select ( 'first_name' ) ;
} ) . then ( function ( resp ) {
expect ( resp ) . to . have . length ( 1 ) ;
} ) . finally ( function ( ) {
return knex . schema . dropTableIfExists ( 'test_schema_transactions' ) ;
} ) ;
2014-06-06 17:27:59 -04:00
}
} ) ;
it ( 'should resolve with the correct value, #298' , function ( ) {
return knex . transaction ( function ( trx ) {
trx . debugging = true ;
2015-04-22 10:34:14 -04:00
return Promise . resolve ( null )
2014-06-06 17:27:59 -04:00
} ) . then ( function ( result ) {
2015-04-22 10:34:14 -04:00
expect ( result ) . to . equal ( null )
2014-06-05 17:01:02 -07:00
} ) ;
2014-06-06 17:27:59 -04:00
} ) ;
2014-06-05 17:01:02 -07:00
2015-04-23 16:04:48 -04:00
it ( 'should allow for nested transactions' , function ( ) {
return knex . transaction ( function ( trx ) {
return trx . select ( '*' ) . from ( 'accounts' ) . then ( function ( ) {
return trx . transaction ( function ( ) {
return trx . select ( '*' ) . from ( 'accounts' )
} )
} )
} )
} )
2015-09-20 15:29:07 +02:00
it ( '#855 - Query Event should trigger on Transaction Client AND main Client' , function ( done ) {
var queryEventTriggered = false ;
knex . once ( 'query' , function ( queryData ) {
queryEventTriggered = true ;
return queryData ;
} ) ;
function expectQueryEventToHaveBeenTriggered ( ) {
expect ( queryEventTriggered ) . to . equal ( true ) ;
done ( ) ;
}
knex . transaction ( function ( trx ) {
2015-09-23 19:32:27 +02:00
trx . select ( '*' ) . from ( 'accounts' ) . then ( trx . commit ) . catch ( trx . rollback ) ;
2015-09-20 15:29:07 +02:00
} )
. then ( expectQueryEventToHaveBeenTriggered )
. catch ( expectQueryEventToHaveBeenTriggered ) ;
} ) ;
2016-02-03 22:50:45 +01:00
it ( '#1040, #1171 - When pool is filled with transaction connections, Non-transaction queries should not hang the application, but instead throw a timeout error' , function ( ) {
2016-02-01 20:40:06 +01:00
//To make this test easier, I'm changing the pool settings to max 1.
var knexConfig = _ . clone ( knex . client . config ) ;
knexConfig . pool . min = 0 ;
knexConfig . pool . max = 1 ;
2016-02-03 22:50:45 +01:00
knexConfig . acquireConnectionTimeout = 1000 ;
2016-02-01 20:40:06 +01:00
var knexDb = new Knex ( knexConfig ) ;
//Create a transaction that will occupy the only available connection, and avoid trx.commit.
2016-10-09 14:00:55 -04:00
return knexDb . transaction ( function ( trx ) {
trx . raw ( 'SELECT 1 = 1' ) . then ( function ( ) {
//No connection is available, so try issuing a query without transaction.
//Since there is no available connection, it should throw a timeout error based on `aquireConnectionTimeout` from the knex config.
return knexDb . raw ( 'select * FROM accounts WHERE username = ?' , [ 'Test' ] )
} )
. then ( function ( ) {
//Should never reach this point
expect ( false ) . to . be . ok ( ) ;
} )
. catch ( function ( error ) {
expect ( error . bindings ) . to . be . an ( 'array' ) ;
expect ( error . bindings [ 0 ] ) . to . equal ( 'Test' ) ;
expect ( error . sql ) . to . equal ( 'select * FROM accounts WHERE username = ?' ) ;
expect ( error . message ) . to . equal ( 'Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?' ) ;
trx . commit ( ) ; //Test done
} ) ;
2016-02-03 22:50:45 +01:00
} ) ;
2016-02-01 20:40:06 +01:00
} ) ;
2016-10-09 14:00:55 -04:00
it ( '#1694, #1703 it should return connections to pool if acquireConnectionTimeout is triggered' , ( ) => {
const db = Knex ( {
client : knex . client . driverName ,
pool : {
min : 0 ,
max : 1
} ,
connection : knex . client . connectionSettings ,
acquireConnectionTimeout : 300
} )
return db . transaction ( function ( ) {
return db . transaction ( function ( ) { } )
} ) . then ( function ( ) {
throw new Error ( 'should not get here' )
} ) . catch ( ( error ) => {
// Should get here after 300 ms.
} )
} )
2013-09-11 23:36:55 -04:00
2016-10-09 14:00:55 -04:00
} ) ;
2014-08-21 23:39:12 +02:00
} ;