bulk-create.test.js 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. 'use strict';
  2. const { expect } = require('chai');
  3. const {
  4. beforeEach2,
  5. createMultiTransactionalTestSequelizeInstance,
  6. sequelize,
  7. } = require('../support');
  8. const { col, DataTypes, Op } = require('@sequelize/core');
  9. const dialect = sequelize.dialect;
  10. const dialectName = dialect.name;
  11. describe('Model', () => {
  12. beforeEach(async function () {
  13. this.customSequelize = await createMultiTransactionalTestSequelizeInstance(this.sequelize);
  14. this.User = this.customSequelize.define('User', {
  15. username: DataTypes.STRING,
  16. secretValue: {
  17. type: DataTypes.STRING,
  18. field: 'secret_value',
  19. },
  20. data: DataTypes.STRING,
  21. intVal: DataTypes.INTEGER,
  22. theDate: DataTypes.DATE,
  23. aBool: DataTypes.BOOLEAN,
  24. uniqueName: { type: DataTypes.STRING, unique: true },
  25. });
  26. this.Account = this.customSequelize.define('Account', {
  27. accountName: DataTypes.STRING,
  28. });
  29. this.Student = this.customSequelize.define('Student', {
  30. no: { type: DataTypes.INTEGER, primaryKey: true },
  31. name: { type: DataTypes.STRING, allowNull: false },
  32. });
  33. this.Car = this.customSequelize.define('Car', {
  34. plateNumber: {
  35. type: DataTypes.STRING,
  36. primaryKey: true,
  37. field: 'plate_number',
  38. },
  39. color: {
  40. type: DataTypes.TEXT,
  41. },
  42. });
  43. await this.customSequelize.sync({ force: true });
  44. });
  45. afterEach(function () {
  46. return this.customSequelize.close();
  47. });
  48. describe('bulkCreate', () => {
  49. if (dialect.supports.transactions) {
  50. it('supports transactions', async function () {
  51. const User = this.customSequelize.define('User', {
  52. username: DataTypes.STRING,
  53. });
  54. await User.sync({ force: true });
  55. const transaction = await this.customSequelize.startUnmanagedTransaction();
  56. await User.bulkCreate([{ username: 'foo' }, { username: 'bar' }], { transaction });
  57. const count1 = await User.count();
  58. const count2 = await User.count({ transaction });
  59. expect(count1).to.equal(0);
  60. expect(count2).to.equal(2);
  61. await transaction.rollback();
  62. });
  63. }
  64. it('should not alter options', async function () {
  65. const User = this.customSequelize.define('User');
  66. await User.sync({ force: true });
  67. const options = { anOption: 1 };
  68. await User.bulkCreate([{}], options);
  69. expect(options).to.eql({ anOption: 1 });
  70. });
  71. it('should be able to set createdAt and updatedAt if using silent: true', async function () {
  72. const User = this.customSequelize.define(
  73. 'user',
  74. {
  75. name: DataTypes.STRING,
  76. },
  77. {
  78. timestamps: true,
  79. },
  80. );
  81. const createdAt = new Date(2012, 10, 10, 10, 10, 10);
  82. const updatedAt = new Date(2011, 11, 11, 11, 11, 11);
  83. const values = Array.from({ length: 10 }).fill({
  84. createdAt,
  85. updatedAt,
  86. });
  87. await User.sync({ force: true });
  88. await User.bulkCreate(values, {
  89. silent: true,
  90. });
  91. const users = await User.findAll({
  92. where: {
  93. updatedAt: {
  94. [Op.ne]: null,
  95. },
  96. },
  97. });
  98. for (const user of users) {
  99. expect(createdAt.getTime()).to.equal(user.get('createdAt').getTime());
  100. expect(updatedAt.getTime()).to.equal(user.get('updatedAt').getTime());
  101. }
  102. });
  103. it('should not fail on validate: true and individualHooks: true', async function () {
  104. const User = this.customSequelize.define('user', {
  105. name: DataTypes.STRING,
  106. });
  107. await User.sync({ force: true });
  108. await User.bulkCreate([{ name: 'James' }], { validate: true, individualHooks: true });
  109. });
  110. it('should not map instance dataValues to fields with individualHooks: true', async function () {
  111. const User = this.customSequelize.define('user', {
  112. name: DataTypes.STRING,
  113. type: {
  114. type: DataTypes.STRING,
  115. allowNull: false,
  116. field: 'user_type',
  117. },
  118. createdAt: {
  119. field: 'created_at',
  120. },
  121. updatedAt: {
  122. field: 'modified_at',
  123. },
  124. });
  125. await User.sync({ force: true });
  126. await User.bulkCreate(
  127. [
  128. { name: 'James', type: 'A' },
  129. { name: 'Alan', type: 'Z' },
  130. ],
  131. { individualHooks: true },
  132. );
  133. });
  134. it('should not insert NULL for unused fields', async function () {
  135. const Beer = this.customSequelize.define('Beer', {
  136. style: DataTypes.STRING,
  137. size: DataTypes.INTEGER,
  138. });
  139. await Beer.sync({ force: true });
  140. await Beer.bulkCreate(
  141. [
  142. {
  143. style: 'ipa',
  144. },
  145. ],
  146. {
  147. logging(sql) {
  148. switch (dialectName) {
  149. case 'postgres':
  150. case 'ibmi': {
  151. expect(sql).to.include(
  152. 'INSERT INTO "Beers" ("id","style","createdAt","updatedAt") VALUES (DEFAULT',
  153. );
  154. break;
  155. }
  156. case 'db2': {
  157. expect(sql).to.include(
  158. 'INSERT INTO "Beers" ("style","createdAt","updatedAt") VALUES',
  159. );
  160. break;
  161. }
  162. case 'mssql': {
  163. expect(sql).to.include('INSERT INTO [Beers] ([style],[createdAt],[updatedAt]) ');
  164. break;
  165. }
  166. default: {
  167. // mysql, sqlite3
  168. expect(sql).to.include(
  169. 'INSERT INTO `Beers` (`id`,`style`,`createdAt`,`updatedAt`) VALUES (NULL',
  170. );
  171. }
  172. }
  173. },
  174. },
  175. );
  176. });
  177. it('properly handles disparate field lists', async function () {
  178. const data = [
  179. { username: 'Peter', secretValue: '42', uniqueName: '1' },
  180. { username: 'Paul', uniqueName: '2' },
  181. { username: 'Steve', uniqueName: '3' },
  182. ];
  183. await this.User.bulkCreate(data);
  184. const users = await this.User.findAll({ where: { username: 'Paul' } });
  185. expect(users.length).to.equal(1);
  186. expect(users[0].username).to.equal('Paul');
  187. expect(users[0].secretValue).to.be.null;
  188. });
  189. it('inserts multiple values respecting the white list', async function () {
  190. const data = [
  191. { username: 'Peter', secretValue: '42', uniqueName: '1' },
  192. { username: 'Paul', secretValue: '23', uniqueName: '2' },
  193. ];
  194. await this.User.bulkCreate(data, { fields: ['username', 'uniqueName'] });
  195. const users = await this.User.findAll({ order: ['id'] });
  196. expect(users.length).to.equal(2);
  197. expect(users[0].username).to.equal('Peter');
  198. expect(users[0].secretValue).to.be.null;
  199. expect(users[1].username).to.equal('Paul');
  200. expect(users[1].secretValue).to.be.null;
  201. });
  202. it('should store all values if no whitelist is specified', async function () {
  203. const data = [
  204. { username: 'Peter', secretValue: '42', uniqueName: '1' },
  205. { username: 'Paul', secretValue: '23', uniqueName: '2' },
  206. ];
  207. await this.User.bulkCreate(data);
  208. const users = await this.User.findAll({ order: ['id'] });
  209. expect(users.length).to.equal(2);
  210. expect(users[0].username).to.equal('Peter');
  211. expect(users[0].secretValue).to.equal('42');
  212. expect(users[1].username).to.equal('Paul');
  213. expect(users[1].secretValue).to.equal('23');
  214. });
  215. it('parses values that come from the database', async function () {
  216. // Because bulkCreate uses a different code path than create,
  217. // there was a bug where values coming back from the database
  218. // weren't being run through the parsers/validators.
  219. // This test ensures that the bug is fixed.
  220. // https://github.com/sequelize/sequelize/issues/15640
  221. const [user] = await this.User.bulkCreate([{ theDate: new Date(), uniqueName: '1' }]);
  222. expect(user.theDate).to.be.instanceOf(Date);
  223. });
  224. it('should set isNewRecord = false', async function () {
  225. const data = [
  226. { username: 'Peter', secretValue: '42', uniqueName: '1' },
  227. { username: 'Paul', secretValue: '23', uniqueName: '2' },
  228. ];
  229. await this.User.bulkCreate(data);
  230. const users = await this.User.findAll({ order: ['id'] });
  231. expect(users.length).to.equal(2);
  232. for (const user of users) {
  233. expect(user.isNewRecord).to.equal(false);
  234. }
  235. });
  236. it('saves data with single quote', async function () {
  237. const quote = "Single'Quote";
  238. const data = [
  239. { username: 'Peter', data: quote, uniqueName: '1' },
  240. { username: 'Paul', data: quote, uniqueName: '2' },
  241. ];
  242. await this.User.bulkCreate(data);
  243. const users = await this.User.findAll({ order: ['id'] });
  244. expect(users.length).to.equal(2);
  245. expect(users[0].username).to.equal('Peter');
  246. expect(users[0].data).to.equal(quote);
  247. expect(users[1].username).to.equal('Paul');
  248. expect(users[1].data).to.equal(quote);
  249. });
  250. it('saves data with double quote', async function () {
  251. const quote = 'Double"Quote';
  252. const data = [
  253. { username: 'Peter', data: quote, uniqueName: '1' },
  254. { username: 'Paul', data: quote, uniqueName: '2' },
  255. ];
  256. await this.User.bulkCreate(data);
  257. const users = await this.User.findAll({ order: ['id'] });
  258. expect(users.length).to.equal(2);
  259. expect(users[0].username).to.equal('Peter');
  260. expect(users[0].data).to.equal(quote);
  261. expect(users[1].username).to.equal('Paul');
  262. expect(users[1].data).to.equal(quote);
  263. });
  264. it('saves stringified JSON data', async function () {
  265. const json = JSON.stringify({ key: 'value' });
  266. const data = [
  267. { username: 'Peter', data: json, uniqueName: '1' },
  268. { username: 'Paul', data: json, uniqueName: '2' },
  269. ];
  270. await this.User.bulkCreate(data);
  271. const users = await this.User.findAll({ order: ['id'] });
  272. expect(users.length).to.equal(2);
  273. expect(users[0].username).to.equal('Peter');
  274. expect(users[0].data).to.equal(json);
  275. expect(users[1].username).to.equal('Paul');
  276. expect(users[1].data).to.equal(json);
  277. });
  278. it('properly handles a model with a length column', async function () {
  279. const UserWithLength = this.customSequelize.define('UserWithLength', {
  280. length: DataTypes.INTEGER,
  281. });
  282. await UserWithLength.sync({ force: true });
  283. await UserWithLength.bulkCreate([{ length: 42 }, { length: 11 }]);
  284. });
  285. it('stores the current date in createdAt', async function () {
  286. const data = [
  287. { username: 'Peter', uniqueName: '1' },
  288. { username: 'Paul', uniqueName: '2' },
  289. ];
  290. await this.User.bulkCreate(data);
  291. const users = await this.User.findAll({ order: ['id'] });
  292. expect(users.length).to.equal(2);
  293. expect(users[0].username).to.equal('Peter');
  294. expect(Number.parseInt(Number(users[0].createdAt) / 5000, 10)).to.be.closeTo(
  295. Number.parseInt(Date.now() / 5000, 10),
  296. 1.5,
  297. );
  298. expect(users[1].username).to.equal('Paul');
  299. expect(Number.parseInt(Number(users[1].createdAt) / 5000, 10)).to.be.closeTo(
  300. Number.parseInt(Date.now() / 5000, 10),
  301. 1.5,
  302. );
  303. });
  304. it('emits an error when validate is set to true', async function () {
  305. const Tasks = this.customSequelize.define('Task', {
  306. name: {
  307. type: DataTypes.STRING,
  308. allowNull: false,
  309. },
  310. code: {
  311. type: DataTypes.STRING,
  312. validate: {
  313. len: [3, 10],
  314. },
  315. },
  316. });
  317. await Tasks.sync({ force: true });
  318. try {
  319. await Tasks.bulkCreate(
  320. [{ name: 'foo', code: '123' }, { code: '1234' }, { name: 'bar', code: '1' }],
  321. { validate: true },
  322. );
  323. } catch (error) {
  324. const expectedValidationError = 'Validation len on code failed';
  325. const expectedNotNullError = 'notNull violation: Task.name cannot be null';
  326. expect(error.toString())
  327. .to.include(expectedValidationError)
  328. .and.to.include(expectedNotNullError);
  329. const { errors } = error;
  330. expect(errors).to.have.length(2);
  331. const e0name0 = errors[0].errors.get('name')[0];
  332. expect(errors[0].record.code).to.equal('1234');
  333. expect(e0name0.type || e0name0.origin).to.equal('notNull violation');
  334. expect(errors[1].record.name).to.equal('bar');
  335. expect(errors[1].record.code).to.equal('1');
  336. expect(errors[1].errors.get('code')[0].message).to.equal(expectedValidationError);
  337. }
  338. });
  339. it("doesn't emit an error when validate is set to true but our selectedValues are fine", async function () {
  340. const Tasks = this.customSequelize.define('Task', {
  341. name: {
  342. type: DataTypes.STRING,
  343. validate: {
  344. notEmpty: true,
  345. },
  346. },
  347. code: {
  348. type: DataTypes.STRING,
  349. validate: {
  350. len: [3, 10],
  351. },
  352. },
  353. });
  354. await Tasks.sync({ force: true });
  355. await Tasks.bulkCreate([{ name: 'foo', code: '123' }, { code: '1234' }], {
  356. fields: ['code'],
  357. validate: true,
  358. });
  359. });
  360. it('should allow blank arrays (return immediately)', async function () {
  361. const Worker = this.customSequelize.define('Worker', {});
  362. await Worker.sync();
  363. const workers = await Worker.bulkCreate([]);
  364. expect(workers).to.be.ok;
  365. expect(workers.length).to.equal(0);
  366. });
  367. it('should allow blank creates (with timestamps: false)', async function () {
  368. const Worker = this.customSequelize.define('Worker', {}, { timestamps: false });
  369. await Worker.sync();
  370. const workers = await Worker.bulkCreate([{}, {}]);
  371. expect(workers).to.be.ok;
  372. });
  373. it('should allow autoincremented attributes to be set', async function () {
  374. const Worker = this.customSequelize.define('Worker', {}, { timestamps: false });
  375. await Worker.sync();
  376. await Worker.bulkCreate([{ id: 5 }, { id: 10 }]);
  377. const workers = await Worker.findAll({ order: [['id', 'ASC']] });
  378. expect(workers[0].id).to.equal(5);
  379. expect(workers[1].id).to.equal(10);
  380. });
  381. if (dialect.supports.schemas) {
  382. it('should support schemas', async function () {
  383. const Dummy = this.customSequelize.define(
  384. 'Dummy',
  385. {
  386. foo: DataTypes.STRING,
  387. bar: DataTypes.STRING,
  388. },
  389. {
  390. schema: 'space1',
  391. tableName: 'Dummy',
  392. },
  393. );
  394. await this.customSequelize.createSchema('space1');
  395. await Dummy.sync({ force: true });
  396. await Dummy.bulkCreate([
  397. { foo: 'a', bar: 'b' },
  398. { foo: 'c', bar: 'd' },
  399. ]);
  400. });
  401. }
  402. if (dialect.supports.inserts.ignoreDuplicates || dialect.supports.inserts.onConflictDoNothing) {
  403. it('should support the ignoreDuplicates option', async function () {
  404. const data = [
  405. { uniqueName: 'Peter', secretValue: '42' },
  406. { uniqueName: 'Paul', secretValue: '23' },
  407. ];
  408. await this.User.bulkCreate(data, { fields: ['uniqueName', 'secretValue'] });
  409. data.push({ uniqueName: 'Michael', secretValue: '26' });
  410. await this.User.bulkCreate(data, {
  411. fields: ['uniqueName', 'secretValue'],
  412. ignoreDuplicates: true,
  413. });
  414. const users = await this.User.findAll({ order: ['id'] });
  415. expect(users.length).to.equal(3);
  416. expect(users[0].uniqueName).to.equal('Peter');
  417. expect(users[0].secretValue).to.equal('42');
  418. expect(users[1].uniqueName).to.equal('Paul');
  419. expect(users[1].secretValue).to.equal('23');
  420. expect(users[2].uniqueName).to.equal('Michael');
  421. expect(users[2].secretValue).to.equal('26');
  422. });
  423. } else {
  424. it('should throw an error when the ignoreDuplicates option is passed', async function () {
  425. const data = [
  426. { uniqueName: 'Peter', secretValue: '42' },
  427. { uniqueName: 'Paul', secretValue: '23' },
  428. ];
  429. await this.User.bulkCreate(data, { fields: ['uniqueName', 'secretValue'] });
  430. data.push({ uniqueName: 'Michael', secretValue: '26' });
  431. try {
  432. await this.User.bulkCreate(data, {
  433. fields: ['uniqueName', 'secretValue'],
  434. ignoreDuplicates: true,
  435. });
  436. } catch (error) {
  437. expect(error.message).to.equal(
  438. `${dialectName} does not support the ignoreDuplicates option.`,
  439. );
  440. }
  441. });
  442. }
  443. if (dialect.supports.inserts.updateOnDuplicate) {
  444. describe('updateOnDuplicate', () => {
  445. it('should support the updateOnDuplicate option', async function () {
  446. const data = [
  447. { uniqueName: 'Peter', secretValue: '42' },
  448. { uniqueName: 'Paul', secretValue: '23' },
  449. ];
  450. await this.User.bulkCreate(data, {
  451. fields: ['uniqueName', 'secretValue'],
  452. updateOnDuplicate: ['secretValue'],
  453. });
  454. const new_data = [
  455. { uniqueName: 'Peter', secretValue: '43' },
  456. { uniqueName: 'Paul', secretValue: '24' },
  457. { uniqueName: 'Michael', secretValue: '26' },
  458. ];
  459. await this.User.bulkCreate(new_data, {
  460. fields: ['uniqueName', 'secretValue'],
  461. updateOnDuplicate: ['secretValue'],
  462. });
  463. const users = await this.User.findAll({ order: ['id'] });
  464. expect(users.length).to.equal(3);
  465. expect(users[0].uniqueName).to.equal('Peter');
  466. expect(users[0].secretValue).to.equal('43');
  467. expect(users[1].uniqueName).to.equal('Paul');
  468. expect(users[1].secretValue).to.equal('24');
  469. expect(users[2].uniqueName).to.equal('Michael');
  470. expect(users[2].secretValue).to.equal('26');
  471. });
  472. describe('should support the updateOnDuplicate option with primary keys', () => {
  473. it('when the primary key column names and model field names are the same', async function () {
  474. const data = [
  475. { no: 1, name: 'Peter' },
  476. { no: 2, name: 'Paul' },
  477. ];
  478. await this.Student.bulkCreate(data, {
  479. fields: ['no', 'name'],
  480. updateOnDuplicate: ['name'],
  481. });
  482. const new_data = [
  483. { no: 1, name: 'Peterson' },
  484. { no: 2, name: 'Paulson' },
  485. { no: 3, name: 'Michael' },
  486. ];
  487. await this.Student.bulkCreate(new_data, {
  488. fields: ['no', 'name'],
  489. updateOnDuplicate: ['name'],
  490. });
  491. const students = await this.Student.findAll({ order: ['no'] });
  492. expect(students.length).to.equal(3);
  493. expect(students[0].name).to.equal('Peterson');
  494. expect(students[0].no).to.equal(1);
  495. expect(students[1].name).to.equal('Paulson');
  496. expect(students[1].no).to.equal(2);
  497. expect(students[2].name).to.equal('Michael');
  498. expect(students[2].no).to.equal(3);
  499. });
  500. it('when the primary key column names and model field names are different', async function () {
  501. const data = [
  502. { plateNumber: 'abc', color: 'Grey' },
  503. { plateNumber: 'def', color: 'White' },
  504. ];
  505. await this.Car.bulkCreate(data, {
  506. fields: ['plateNumber', 'color'],
  507. updateOnDuplicate: ['color'],
  508. });
  509. const new_data = [
  510. { plateNumber: 'abc', color: 'Red' },
  511. { plateNumber: 'def', color: 'Green' },
  512. { plateNumber: 'ghi', color: 'Blue' },
  513. ];
  514. await this.Car.bulkCreate(new_data, {
  515. fields: ['plateNumber', 'color'],
  516. updateOnDuplicate: ['color'],
  517. });
  518. const cars = await this.Car.findAll({ order: ['plateNumber'] });
  519. expect(cars.length).to.equal(3);
  520. expect(cars[0].plateNumber).to.equal('abc');
  521. expect(cars[0].color).to.equal('Red');
  522. expect(cars[1].plateNumber).to.equal('def');
  523. expect(cars[1].color).to.equal('Green');
  524. expect(cars[2].plateNumber).to.equal('ghi');
  525. expect(cars[2].color).to.equal('Blue');
  526. });
  527. it('when the primary key column names and model field names are different and have unique constraints', async function () {
  528. const Person = this.customSequelize.define(
  529. 'Person',
  530. {
  531. emailAddress: {
  532. type: DataTypes.STRING,
  533. allowNull: false,
  534. primaryKey: true,
  535. unique: true,
  536. field: 'email_address',
  537. },
  538. name: {
  539. type: DataTypes.STRING,
  540. allowNull: false,
  541. field: 'name',
  542. },
  543. },
  544. {},
  545. );
  546. await Person.sync({ force: true });
  547. const inserts = [{ emailAddress: 'a@example.com', name: 'Alice' }];
  548. const people0 = await Person.bulkCreate(inserts);
  549. expect(people0.length).to.equal(1);
  550. expect(people0[0].emailAddress).to.equal('a@example.com');
  551. expect(people0[0].name).to.equal('Alice');
  552. const updates = [
  553. { emailAddress: 'a@example.com', name: 'CHANGED NAME' },
  554. { emailAddress: 'b@example.com', name: 'Bob' },
  555. ];
  556. const people = await Person.bulkCreate(updates, {
  557. updateOnDuplicate: ['emailAddress', 'name'],
  558. });
  559. expect(people.length).to.equal(2);
  560. expect(people[0].emailAddress).to.equal('a@example.com');
  561. expect(people[0].name).to.equal('CHANGED NAME');
  562. expect(people[1].emailAddress).to.equal('b@example.com');
  563. expect(people[1].name).to.equal('Bob');
  564. });
  565. it('when the composite primary key column names and model field names are different', async function () {
  566. const Person = this.customSequelize.define(
  567. 'Person',
  568. {
  569. systemId: {
  570. type: DataTypes.INTEGER,
  571. allowNull: false,
  572. primaryKey: true,
  573. field: 'system_id',
  574. },
  575. system: {
  576. type: DataTypes.STRING,
  577. allowNull: false,
  578. primaryKey: true,
  579. field: 'system',
  580. },
  581. name: {
  582. type: DataTypes.STRING,
  583. allowNull: false,
  584. field: 'name',
  585. },
  586. },
  587. {},
  588. );
  589. await Person.sync({ force: true });
  590. const inserts = [{ systemId: 1, system: 'system1', name: 'Alice' }];
  591. const people0 = await Person.bulkCreate(inserts);
  592. expect(people0.length).to.equal(1);
  593. expect(people0[0].systemId).to.equal(1);
  594. expect(people0[0].system).to.equal('system1');
  595. expect(people0[0].name).to.equal('Alice');
  596. const updates = [
  597. { systemId: 1, system: 'system1', name: 'CHANGED NAME' },
  598. { systemId: 1, system: 'system2', name: 'Bob' },
  599. ];
  600. const people = await Person.bulkCreate(updates, {
  601. updateOnDuplicate: ['systemId', 'system', 'name'],
  602. });
  603. expect(people.length).to.equal(2);
  604. expect(people[0].systemId).to.equal(1);
  605. expect(people[0].system).to.equal('system1');
  606. expect(people[0].name).to.equal('CHANGED NAME');
  607. expect(people[1].systemId).to.equal(1);
  608. expect(people[1].system).to.equal('system2');
  609. expect(people[1].name).to.equal('Bob');
  610. });
  611. it('when the primary key column names and model field names are different and have composite unique constraints', async function () {
  612. const Person = this.customSequelize.define(
  613. 'Person',
  614. {
  615. id: {
  616. type: DataTypes.INTEGER,
  617. allowNull: false,
  618. primaryKey: true,
  619. field: 'id',
  620. },
  621. systemId: {
  622. type: DataTypes.INTEGER,
  623. allowNull: false,
  624. unique: 'system_id_system_unique',
  625. field: 'system_id',
  626. },
  627. system: {
  628. type: DataTypes.STRING,
  629. allowNull: false,
  630. unique: 'system_id_system_unique',
  631. field: 'system',
  632. },
  633. name: {
  634. type: DataTypes.STRING,
  635. allowNull: false,
  636. field: 'name',
  637. },
  638. },
  639. {},
  640. );
  641. await Person.sync({ force: true });
  642. const inserts = [{ id: 1, systemId: 1, system: 'system1', name: 'Alice' }];
  643. const people0 = await Person.bulkCreate(inserts);
  644. expect(people0.length).to.equal(1);
  645. expect(people0[0].systemId).to.equal(1);
  646. expect(people0[0].system).to.equal('system1');
  647. expect(people0[0].name).to.equal('Alice');
  648. const updates = [
  649. { id: 1, systemId: 1, system: 'system1', name: 'CHANGED NAME' },
  650. { id: 2, systemId: 1, system: 'system2', name: 'Bob' },
  651. ];
  652. const people = await Person.bulkCreate(updates, {
  653. updateOnDuplicate: ['systemId', 'system', 'name'],
  654. });
  655. expect(people.length).to.equal(2);
  656. expect(people[0].systemId).to.equal(1);
  657. expect(people[0].system).to.equal('system1');
  658. expect(people[0].name).to.equal('CHANGED NAME');
  659. expect(people[1].systemId).to.equal(1);
  660. expect(people[1].system).to.equal('system2');
  661. expect(people[1].name).to.equal('Bob');
  662. });
  663. it('[#12516] when the primary key column names and model field names are different and have composite unique index constraints', async function () {
  664. const Person = this.customSequelize.define(
  665. 'Person',
  666. {
  667. id: {
  668. type: DataTypes.INTEGER,
  669. allowNull: false,
  670. autoIncrement: true,
  671. primaryKey: true,
  672. field: 'id',
  673. },
  674. systemId: {
  675. type: DataTypes.INTEGER,
  676. allowNull: false,
  677. field: 'system_id',
  678. },
  679. system: {
  680. type: DataTypes.STRING,
  681. allowNull: false,
  682. field: 'system',
  683. },
  684. name: {
  685. type: DataTypes.STRING,
  686. allowNull: false,
  687. field: 'name',
  688. },
  689. },
  690. {
  691. indexes: [
  692. {
  693. unique: true,
  694. fields: ['system_id', 'system'],
  695. },
  696. ],
  697. },
  698. );
  699. await Person.sync({ force: true });
  700. const inserts = [{ systemId: 1, system: 'system1', name: 'Alice' }];
  701. const people0 = await Person.bulkCreate(inserts);
  702. expect(people0.length).to.equal(1);
  703. expect(people0[0].systemId).to.equal(1);
  704. expect(people0[0].system).to.equal('system1');
  705. expect(people0[0].name).to.equal('Alice');
  706. const updates = [
  707. { systemId: 1, system: 'system1', name: 'CHANGED NAME' },
  708. { systemId: 1, system: 'system2', name: 'Bob' },
  709. ];
  710. const people = await Person.bulkCreate(updates, {
  711. updateOnDuplicate: ['systemId', 'system', 'name'],
  712. });
  713. expect(people.length).to.equal(2);
  714. expect(people[0].systemId).to.equal(1);
  715. expect(people[0].system).to.equal('system1');
  716. expect(people[0].name).to.equal('CHANGED NAME');
  717. expect(people[1].systemId).to.equal(1);
  718. expect(people[1].system).to.equal('system2');
  719. expect(people[1].name).to.equal('Bob');
  720. });
  721. });
  722. it('should reject for non array updateOnDuplicate option', async function () {
  723. const data = [
  724. { uniqueName: 'Peter', secretValue: '42' },
  725. { uniqueName: 'Paul', secretValue: '23' },
  726. ];
  727. await expect(this.User.bulkCreate(data, { updateOnDuplicate: true })).to.be.rejectedWith(
  728. 'updateOnDuplicate option only supports non-empty array.',
  729. );
  730. });
  731. it('should reject for empty array updateOnDuplicate option', async function () {
  732. const data = [
  733. { uniqueName: 'Peter', secretValue: '42' },
  734. { uniqueName: 'Paul', secretValue: '23' },
  735. ];
  736. await expect(this.User.bulkCreate(data, { updateOnDuplicate: [] })).to.be.rejectedWith(
  737. 'updateOnDuplicate option only supports non-empty array.',
  738. );
  739. });
  740. if (dialect.supports.inserts.conflictFields) {
  741. it('should respect the conflictAttributes option', async function () {
  742. const Permissions = this.customSequelize.define(
  743. 'permissions',
  744. {
  745. userId: {
  746. type: DataTypes.INTEGER,
  747. allowNull: false,
  748. field: 'user_id',
  749. },
  750. permissions: {
  751. type: new DataTypes.ENUM('owner', 'admin', 'member'),
  752. allowNull: false,
  753. default: 'member',
  754. },
  755. },
  756. {
  757. timestamps: false,
  758. },
  759. );
  760. await Permissions.sync({ force: true });
  761. // We don't want to create this index with the table, since we don't want our sequelize instance
  762. // to know it exists. This prevents it from being inferred.
  763. await this.customSequelize.queryInterface.addIndex('permissions', ['user_id'], {
  764. unique: true,
  765. });
  766. const initialPermissions = [
  767. {
  768. userId: 1,
  769. permissions: 'member',
  770. },
  771. {
  772. userId: 2,
  773. permissions: 'admin',
  774. },
  775. {
  776. userId: 3,
  777. permissions: 'owner',
  778. },
  779. ];
  780. const initialResults = await Permissions.bulkCreate(initialPermissions, {
  781. conflictAttributes: ['userId'],
  782. updateOnDuplicate: ['permissions'],
  783. });
  784. expect(initialResults.length).to.eql(3);
  785. for (let i = 0; i < 3; i++) {
  786. const result = initialResults[i];
  787. const exp = initialPermissions[i];
  788. expect(result).to.not.eql(null);
  789. expect(result.userId).to.eql(exp.userId);
  790. expect(result.permissions).to.eql(exp.permissions);
  791. }
  792. const newPermissions = [
  793. {
  794. userId: 1,
  795. permissions: 'owner',
  796. },
  797. {
  798. userId: 2,
  799. permissions: 'member',
  800. },
  801. {
  802. userId: 3,
  803. permissions: 'admin',
  804. },
  805. ];
  806. const newResults = await Permissions.bulkCreate(newPermissions, {
  807. conflictAttributes: ['userId'],
  808. updateOnDuplicate: ['permissions'],
  809. });
  810. expect(newResults.length).to.eql(3);
  811. for (let i = 0; i < 3; i++) {
  812. const result = newResults[i];
  813. const exp = newPermissions[i];
  814. expect(result).to.not.eql(null);
  815. expect(result.id).to.eql(initialResults[i].id);
  816. expect(result.userId).to.eql(exp.userId);
  817. expect(result.permissions).to.eql(exp.permissions);
  818. }
  819. });
  820. describe('conflictWhere', () => {
  821. const options = {
  822. conflictWhere: { time_deleted: null },
  823. conflictAttributes: ['user_id', 'foreign_id'],
  824. updateOnDuplicate: ['user_id', 'foreign_id', 'time_deleted'],
  825. };
  826. const vars = beforeEach2(async () => {
  827. const Memberships = sequelize.define(
  828. 'memberships',
  829. {
  830. // ID of the member (no foreign key constraint for testing purposes)
  831. user_id: DataTypes.INTEGER,
  832. // ID of what the member is a member of
  833. foreign_id: DataTypes.INTEGER,
  834. time_deleted: DataTypes.DATE,
  835. },
  836. {
  837. createdAt: false,
  838. updatedAt: false,
  839. deletedAt: 'time_deleted',
  840. indexes: [
  841. {
  842. fields: ['user_id', 'foreign_id'],
  843. unique: true,
  844. where: { time_deleted: null },
  845. },
  846. ],
  847. },
  848. );
  849. await Memberships.sync({ force: true });
  850. return { Memberships };
  851. });
  852. it('should insert items with conflictWhere', async () => {
  853. const { Memberships } = vars;
  854. const memberships = Array.from({ length: 10 })
  855. .fill()
  856. .map((_, i) => ({
  857. user_id: i + 1,
  858. foreign_id: i + 20,
  859. time_deleted: null,
  860. }));
  861. const results = await Memberships.bulkCreate(memberships, options);
  862. for (let i = 0; i < 10; i++) {
  863. expect(results[i].user_id).to.eq(memberships[i].user_id);
  864. expect(results[i].team_id).to.eq(memberships[i].team_id);
  865. expect(results[i].time_deleted).to.eq(null);
  866. }
  867. });
  868. it('should not conflict with soft deleted memberships', async () => {
  869. const { Memberships } = vars;
  870. const memberships = Array.from({ length: 10 })
  871. .fill()
  872. .map((_, i) => ({
  873. user_id: i + 1,
  874. foreign_id: i + 20,
  875. time_deleted: new Date(),
  876. }));
  877. let results = await Memberships.bulkCreate(memberships, options);
  878. for (let i = 0; i < 10; i++) {
  879. expect(results[i].user_id).to.eq(memberships[i].user_id);
  880. expect(results[i].team_id).to.eq(memberships[i].team_id);
  881. expect(results[i].time_deleted).to.not.eq(null);
  882. }
  883. results = await Memberships.bulkCreate(
  884. memberships.map(membership => ({
  885. ...membership,
  886. time_deleted: null,
  887. })),
  888. options,
  889. );
  890. for (let i = 0; i < 10; i++) {
  891. expect(results[i].user_id).to.eq(memberships[i].user_id);
  892. expect(results[i].team_id).to.eq(memberships[i].team_id);
  893. expect(results[i].time_deleted).to.eq(null);
  894. }
  895. const count = await Memberships.count();
  896. expect(count).to.eq(20);
  897. });
  898. it('should upsert existing memberships', async () => {
  899. const { Memberships } = vars;
  900. const memberships = Array.from({ length: 10 })
  901. .fill()
  902. .map((_, i) => ({
  903. user_id: i + 1,
  904. foreign_id: i + 20,
  905. time_deleted: i % 2 ? new Date() : null,
  906. }));
  907. let results = await Memberships.bulkCreate(memberships, options);
  908. for (let i = 0; i < 10; i++) {
  909. expect(results[i].user_id).to.eq(memberships[i].user_id);
  910. expect(results[i].team_id).to.eq(memberships[i].team_id);
  911. if (i % 2) {
  912. expect(results[i].time_deleted).to.not.eq(null);
  913. } else {
  914. expect(results[i].time_deleted).to.eq(null);
  915. }
  916. }
  917. for (const membership of memberships) {
  918. membership.time_deleted;
  919. }
  920. results = await Memberships.bulkCreate(
  921. memberships.map(membership => ({
  922. ...membership,
  923. time_deleted: null,
  924. })),
  925. options,
  926. );
  927. for (let i = 0; i < 10; i++) {
  928. expect(results[i].user_id).to.eq(memberships[i].user_id);
  929. expect(results[i].team_id).to.eq(memberships[i].team_id);
  930. expect(results[i].time_deleted).to.eq(null);
  931. }
  932. const count = await Memberships.count({ paranoid: false });
  933. expect(count).to.eq(15);
  934. });
  935. });
  936. if (dialect.supports.inserts.onConflictWhere) {
  937. describe('conflictWhere', () => {
  938. const options = {
  939. conflictWhere: { time_deleted: null },
  940. conflictAttributes: ['user_id', 'foreign_id'],
  941. updateOnDuplicate: ['user_id', 'foreign_id', 'time_deleted'],
  942. };
  943. const vars = beforeEach2(async () => {
  944. const Memberships = sequelize.define(
  945. 'memberships',
  946. {
  947. // ID of the member (no foreign key constraint for testing purposes)
  948. user_id: DataTypes.INTEGER,
  949. // ID of what the member is a member of
  950. foreign_id: DataTypes.INTEGER,
  951. time_deleted: DataTypes.DATE,
  952. },
  953. {
  954. createdAt: false,
  955. updatedAt: false,
  956. deletedAt: 'time_deleted',
  957. indexes: [
  958. {
  959. fields: ['user_id', 'foreign_id'],
  960. unique: true,
  961. where: { time_deleted: null },
  962. },
  963. ],
  964. },
  965. );
  966. await Memberships.sync({ force: true });
  967. return { Memberships };
  968. });
  969. it('should insert items with conflictWhere', async () => {
  970. const { Memberships } = vars;
  971. const memberships = Array.from({ length: 10 })
  972. .fill()
  973. .map((_, i) => ({
  974. user_id: i + 1,
  975. foreign_id: i + 20,
  976. time_deleted: null,
  977. }));
  978. const results = await Memberships.bulkCreate(memberships, options);
  979. for (let i = 0; i < 10; i++) {
  980. expect(results[i].user_id).to.eq(memberships[i].user_id);
  981. expect(results[i].team_id).to.eq(memberships[i].team_id);
  982. expect(results[i].time_deleted).to.eq(null);
  983. }
  984. });
  985. it('should not conflict with soft deleted memberships', async () => {
  986. const { Memberships } = vars;
  987. const memberships = Array.from({ length: 10 })
  988. .fill()
  989. .map((_, i) => ({
  990. user_id: i + 1,
  991. foreign_id: i + 20,
  992. time_deleted: new Date(),
  993. }));
  994. let results = await Memberships.bulkCreate(memberships, options);
  995. for (let i = 0; i < 10; i++) {
  996. expect(results[i].user_id).to.eq(memberships[i].user_id);
  997. expect(results[i].team_id).to.eq(memberships[i].team_id);
  998. expect(results[i].time_deleted).to.not.eq(null);
  999. }
  1000. results = await Memberships.bulkCreate(
  1001. memberships.map(membership => ({
  1002. ...membership,
  1003. time_deleted: null,
  1004. })),
  1005. options,
  1006. );
  1007. for (let i = 0; i < 10; i++) {
  1008. expect(results[i].user_id).to.eq(memberships[i].user_id);
  1009. expect(results[i].team_id).to.eq(memberships[i].team_id);
  1010. expect(results[i].time_deleted).to.eq(null);
  1011. }
  1012. const count = await Memberships.count();
  1013. expect(count).to.eq(20);
  1014. });
  1015. it('should upsert existing memberships', async () => {
  1016. const { Memberships } = vars;
  1017. const memberships = Array.from({ length: 10 })
  1018. .fill()
  1019. .map((_, i) => ({
  1020. user_id: i + 1,
  1021. foreign_id: i + 20,
  1022. time_deleted: i % 2 ? new Date() : null,
  1023. }));
  1024. let results = await Memberships.bulkCreate(memberships, options);
  1025. for (let i = 0; i < 10; i++) {
  1026. expect(results[i].user_id).to.eq(memberships[i].user_id);
  1027. expect(results[i].team_id).to.eq(memberships[i].team_id);
  1028. if (i % 2) {
  1029. expect(results[i].time_deleted).to.not.eq(null);
  1030. } else {
  1031. expect(results[i].time_deleted).to.eq(null);
  1032. }
  1033. }
  1034. for (const membership of memberships) {
  1035. membership.time_deleted;
  1036. }
  1037. results = await Memberships.bulkCreate(
  1038. memberships.map(membership => ({
  1039. ...membership,
  1040. time_deleted: null,
  1041. })),
  1042. options,
  1043. );
  1044. for (let i = 0; i < 10; i++) {
  1045. expect(results[i].user_id).to.eq(memberships[i].user_id);
  1046. expect(results[i].team_id).to.eq(memberships[i].team_id);
  1047. expect(results[i].time_deleted).to.eq(null);
  1048. }
  1049. const count = await Memberships.count({ paranoid: false });
  1050. expect(count).to.eq(15);
  1051. });
  1052. });
  1053. }
  1054. }
  1055. });
  1056. }
  1057. if (dialect.supports.returnValues) {
  1058. describe('return values', () => {
  1059. it('should make the auto incremented values available on the returned instances', async function () {
  1060. const User = this.customSequelize.define('user', {});
  1061. await User.sync({ force: true });
  1062. const users0 = await User.bulkCreate([{}, {}, {}], {
  1063. returning: true,
  1064. });
  1065. const actualUsers0 = await User.findAll({ order: ['id'] });
  1066. const [users, actualUsers] = [users0, actualUsers0];
  1067. expect(users.length).to.eql(actualUsers.length);
  1068. for (const [i, user] of users.entries()) {
  1069. expect(user.get('id')).to.be.ok;
  1070. expect(user.get('id'))
  1071. .to.equal(actualUsers[i].get('id'))
  1072. .and.to.equal(i + 1);
  1073. }
  1074. });
  1075. it('should make the auto incremented values available on the returned instances with custom fields', async function () {
  1076. const User = this.customSequelize.define('user', {
  1077. maId: {
  1078. type: DataTypes.INTEGER,
  1079. primaryKey: true,
  1080. autoIncrement: true,
  1081. field: 'yo_id',
  1082. },
  1083. });
  1084. await User.sync({ force: true });
  1085. const users0 = await User.bulkCreate([{}, {}, {}], {
  1086. returning: true,
  1087. });
  1088. const actualUsers0 = await User.findAll({ order: ['maId'] });
  1089. const [users, actualUsers] = [users0, actualUsers0];
  1090. expect(users.length).to.eql(actualUsers.length);
  1091. for (const [i, user] of users.entries()) {
  1092. expect(user.get('maId')).to.be.ok;
  1093. expect(user.get('maId'))
  1094. .to.equal(actualUsers[i].get('maId'))
  1095. .and.to.equal(i + 1);
  1096. }
  1097. });
  1098. it('should only return fields that are not defined in the model (with returning: true)', async function () {
  1099. const User = this.customSequelize.define('user');
  1100. await User.sync({ force: true });
  1101. await this.customSequelize.queryInterface.addColumn(
  1102. 'users',
  1103. 'not_on_model',
  1104. DataTypes.STRING,
  1105. );
  1106. const users0 = await User.bulkCreate([{}, {}, {}], {
  1107. returning: true,
  1108. });
  1109. const actualUsers0 = await User.findAll();
  1110. const [users, actualUsers] = [users0, actualUsers0];
  1111. expect(users.length).to.eql(actualUsers.length);
  1112. for (const user of users) {
  1113. expect(user.get()).not.to.have.property('not_on_model');
  1114. }
  1115. });
  1116. it('should return fields that are not defined in the model (with returning: ["*"])', async function () {
  1117. const User = this.customSequelize.define('user');
  1118. await User.sync({ force: true });
  1119. await this.customSequelize.queryInterface.addColumn(
  1120. 'users',
  1121. 'not_on_model',
  1122. DataTypes.STRING,
  1123. );
  1124. const users0 = await User.bulkCreate([{}, {}, {}], {
  1125. returning: [col('*')],
  1126. });
  1127. const actualUsers0 = await User.findAll();
  1128. const [users, actualUsers] = [users0, actualUsers0];
  1129. expect(users.length).to.eql(actualUsers.length);
  1130. for (const user of users) {
  1131. expect(user.get()).to.have.property('not_on_model');
  1132. }
  1133. });
  1134. });
  1135. }
  1136. describe('enums', () => {
  1137. it('correctly restores enum values', async function () {
  1138. const Item = this.customSequelize.define('Item', {
  1139. state: { type: DataTypes.ENUM(['available', 'in_cart', 'shipped']) },
  1140. name: DataTypes.STRING,
  1141. });
  1142. await Item.sync({ force: true });
  1143. await Item.bulkCreate([
  1144. { state: 'in_cart', name: 'A' },
  1145. { state: 'available', name: 'B' },
  1146. ]);
  1147. const item = await Item.findOne({ where: { state: 'available' } });
  1148. expect(item.name).to.equal('B');
  1149. });
  1150. });
  1151. it('should properly map field names to attribute names', async function () {
  1152. const Maya = this.customSequelize.define('Maya', {
  1153. name: DataTypes.STRING,
  1154. secret: {
  1155. field: 'secret_given',
  1156. type: DataTypes.STRING,
  1157. },
  1158. createdAt: {
  1159. field: 'created_at',
  1160. },
  1161. updatedAt: {
  1162. field: 'updated_at',
  1163. },
  1164. });
  1165. const M1 = { id: 1, name: 'Prathma Maya', secret: 'You are on list #1' };
  1166. const M2 = { id: 2, name: 'Dwitiya Maya', secret: 'You are on list #2' };
  1167. await Maya.sync({ force: true });
  1168. const m0 = await Maya.create(M1);
  1169. expect(m0.createdAt).to.be.ok;
  1170. expect(m0.id).to.be.eql(M1.id);
  1171. expect(m0.name).to.be.eql(M1.name);
  1172. expect(m0.secret).to.be.eql(M1.secret);
  1173. const [m] = await Maya.bulkCreate([M2]);
  1174. // only attributes are returned, no fields are mixed
  1175. expect(m.createdAt).to.be.ok;
  1176. expect(m.created_at).to.not.exist;
  1177. expect(m.secret_given).to.not.exist;
  1178. expect(m.get('secret_given')).to.be.undefined;
  1179. expect(m.get('created_at')).to.be.undefined;
  1180. // values look fine
  1181. expect(m.id).to.be.eql(M2.id);
  1182. expect(m.name).to.be.eql(M2.name);
  1183. expect(m.secret).to.be.eql(M2.secret);
  1184. });
  1185. describe('handles auto increment values', () => {
  1186. it('should return auto increment primary key values', async function () {
  1187. const Maya = this.customSequelize.define('Maya', {});
  1188. const M1 = {};
  1189. const M2 = {};
  1190. await Maya.sync({ force: true });
  1191. const ms = await Maya.bulkCreate([M1, M2], { returning: true });
  1192. expect(ms[0].id).to.be.eql(1);
  1193. expect(ms[1].id).to.be.eql(2);
  1194. });
  1195. it('should return supplied values on primary keys', async function () {
  1196. const User = this.customSequelize.define('user', {});
  1197. await User.sync({ force: true });
  1198. const users0 = await User.bulkCreate([{ id: 1 }, { id: 2 }, { id: 3 }], {
  1199. returning: true,
  1200. });
  1201. const actualUsers0 = await User.findAll({ order: [['id', 'ASC']] });
  1202. const [users, actualUsers] = [users0, actualUsers0];
  1203. expect(users.length).to.eql(actualUsers.length);
  1204. expect(users[0].get('id')).to.equal(1).and.to.equal(actualUsers[0].get('id'));
  1205. expect(users[1].get('id')).to.equal(2).and.to.equal(actualUsers[1].get('id'));
  1206. expect(users[2].get('id')).to.equal(3).and.to.equal(actualUsers[2].get('id'));
  1207. });
  1208. it('should return supplied values on primary keys when some instances already exists', async function () {
  1209. const User = this.customSequelize.define('user', {});
  1210. await User.sync({ force: true });
  1211. await User.bulkCreate([{ id: 1 }, { id: 3 }]);
  1212. const users = await User.bulkCreate([{ id: 2 }, { id: 4 }, { id: 5 }], { returning: true });
  1213. expect(users.length).to.eql(3);
  1214. expect(users[0].get('id')).to.equal(2);
  1215. expect(users[1].get('id')).to.equal(4);
  1216. expect(users[2].get('id')).to.equal(5);
  1217. });
  1218. });
  1219. describe('virtual attribute', () => {
  1220. beforeEach(function () {
  1221. this.User = this.customSequelize.define('user', {
  1222. password: {
  1223. type: DataTypes.VIRTUAL,
  1224. validate: {
  1225. customValidator: () => {
  1226. throw new Error('always invalid');
  1227. },
  1228. },
  1229. },
  1230. });
  1231. });
  1232. it('should validate', async function () {
  1233. try {
  1234. await this.User.sync({ force: true });
  1235. await this.User.bulkCreate([{ password: 'password' }], { validate: true });
  1236. expect.fail();
  1237. } catch (error) {
  1238. expect(error.errors.length).to.equal(1);
  1239. expect(error.errors[0].message).to.match(/.*always invalid.*/);
  1240. }
  1241. });
  1242. it('should not validate', async function () {
  1243. await this.User.sync({ force: true });
  1244. const users0 = await this.User.bulkCreate([{ password: 'password' }], { validate: false });
  1245. expect(users0.length).to.equal(1);
  1246. const users = await this.User.bulkCreate([{ password: 'password' }]);
  1247. expect(users.length).to.equal(1);
  1248. });
  1249. });
  1250. });
  1251. });