Skip to content

Commit eb7f29d

Browse files
author
Cyril CHAPON
committed
Support passing parent transaction leading to sub-transaction
1 parent a9331a3 commit eb7f29d

File tree

2 files changed

+85
-18
lines changed

2 files changed

+85
-18
lines changed

src/index.js

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,48 +20,62 @@ export default (args) => {
2020
defaultValue,
2121
newValues,
2222
queryInterface,
23+
sequelizeOptions = {},
2324
enumName = `enum_${tableName}_${columnName}`
2425
} = args;
2526

2627
const newEnumName = `${enumName}_new`;
2728

28-
return queryInterface.sequelize.transaction((t) => {
29-
const sequelizeOptions = { transaction: t };
29+
return queryInterface.sequelize.transaction(sequelizeOptions, (t) => {
30+
const newSequelizeOptions = {
31+
...(sequelizeOptions || {}),
32+
transaction: t
33+
};
3034

3135
// Create a copy of the type
32-
return createEnum(
33-
{ queryInterface, name: newEnumName, values: newValues, sequelizeOptions }
34-
)
36+
return createEnum({
37+
queryInterface,
38+
name: newEnumName,
39+
values: newValues,
40+
sequelizeOptions: newSequelizeOptions
41+
})
3542
// Drop default value (ALTER COLUMN cannot cast default values)
36-
.then(() => defaultValue && unsetDefaultValueFromEnum(
37-
{ queryInterface, tableName, columnName, sequelizeOptions }
38-
))
43+
.then(() => defaultValue && unsetDefaultValueFromEnum({
44+
queryInterface,
45+
tableName,
46+
columnName,
47+
sequelizeOptions: newSequelizeOptions
48+
}))
3949
// Change column type to the new ENUM TYPE
4050
.then(() => setColumnTypeToEnum({
4151
tableName,
4252
columnName,
4353
enumName: newEnumName,
4454
queryInterface,
45-
sequelizeOptions
55+
sequelizeOptions: newSequelizeOptions
4656
}))
4757
// Drop old ENUM
4858
.then(() => dropEnum(
49-
{ name: enumName, sequelizeOptions, queryInterface }
59+
{
60+
name: enumName,
61+
sequelizeOptions: newSequelizeOptions,
62+
queryInterface
63+
}
5064
))
5165
// Rename new ENUM name
5266
.then(() => renameEnum({
5367
oldEnumName: newEnumName,
5468
newEnumName: enumName,
5569
queryInterface,
56-
sequelizeOptions
70+
sequelizeOptions: newSequelizeOptions
5771
}))
5872
.then(() => defaultValue && setColumnDefault({
5973
tableName,
6074
columnName,
6175
defaultValue,
6276
defaultValueType: enumName,
6377
queryInterface,
64-
sequelizeOptions
78+
sequelizeOptions: newSequelizeOptions
6579
}));
6680
});
6781
};

test/index.js

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,27 @@ describe('replaceEnum() - enum replacement:', () => {
2222
expect(transactionSpy.calledOnce).to.be.true;
2323
});
2424

25+
it('should run all queries within a sub-transaction', async () => {
26+
const queryInterface = queryInterfaceMock();
27+
28+
const transactionSpy = sinon.spy(queryInterface.sequelize, 'transaction');
29+
30+
await replaceEnum({
31+
queryInterface,
32+
tableName: 'table1',
33+
columnName: 'column1',
34+
defaultValue: 'A',
35+
newValues: ['A', 'B', 'C'],
36+
enumName: 'enum1',
37+
sequelizeOptions: { transaction: { mockParentTransaction: true } }
38+
});
39+
40+
expect(transactionSpy.calledOnceWith(
41+
sinon.match({ transaction: { mockParentTransaction: true } }),
42+
sinon.match.func
43+
)).to.be.true;
44+
});
45+
2546
it('should pass correct queries to queryInterface', async () => {
2647
const queryInterface = queryInterfaceMock();
2748

@@ -84,11 +105,40 @@ describe('replaceEnum() - enum replacement:', () => {
84105

85106
expect(queries).to.have.length(6, 'should create 6 queries');
86107

87-
queries.forEach((query) =>
108+
queries.forEach((query) => {
88109
expect(query.options).to.deep.equal({
89-
transaction: { mockTransaction: true }
90-
})
91-
);
110+
transaction: {
111+
mockTransaction: true,
112+
sequelizeOptions: {}
113+
}
114+
});
115+
});
116+
});
117+
118+
it('should pass correct options - transaction and subtransaction', async () => {
119+
const queryInterface = queryInterfaceMock();
120+
await replaceEnum({
121+
queryInterface,
122+
tableName: 'table1',
123+
columnName: 'column1',
124+
defaultValue: 'A',
125+
newValues: ['A', 'B', 'C'],
126+
enumName: 'enum1',
127+
sequelizeOptions: { transaction: { mockParentTransaction: true } }
128+
});
129+
130+
const queries = queryInterface.getQueries();
131+
132+
expect(queries).to.have.length(6, 'should create 6 queries');
133+
134+
queries.forEach((query) => {
135+
expect(query.options).to.deep.equal({
136+
transaction: {
137+
mockTransaction: true,
138+
sequelizeOptions: { transaction: { mockParentTransaction: true } }
139+
}
140+
});
141+
});
92142
});
93143
});
94144

@@ -101,8 +151,11 @@ function queryInterfaceMock() {
101151
queries.push({ sql, options });
102152
return Promise.resolve();
103153
},
104-
async transaction(callback) {
105-
await callback({ mockTransaction: true });
154+
async transaction(...args) {
155+
const sequelizeOptions = (args.length > 1) ? args[0] : null;
156+
const callback = args.length ? args[args.length - 1] : null;
157+
158+
await callback({ mockTransaction: true, sequelizeOptions });
106159
return Promise.resolve();
107160
}
108161
},

0 commit comments

Comments
 (0)