bulk-insert.test.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { DataTypes, Transaction } from '@sequelize/core';
  2. import { expect } from 'chai';
  3. import range from 'lodash/range';
  4. import sinon from 'sinon';
  5. import { beforeAll2, expectPerDialect, sequelize, toMatchRegex, toMatchSql } from '../../support';
  6. describe('QueryInterface#bulkInsert', () => {
  7. const vars = beforeAll2(() => {
  8. const User = sequelize.define(
  9. 'User',
  10. {
  11. firstName: DataTypes.STRING,
  12. },
  13. { timestamps: false },
  14. );
  15. return { User };
  16. });
  17. afterEach(() => {
  18. sinon.restore();
  19. });
  20. it('uses minimal insert queries when rows <=1000', async () => {
  21. const { User } = vars;
  22. const stub = sinon.stub(sequelize, 'queryRaw').resolves([[], 0]);
  23. const users = range(1000).map(i => ({ firstName: `user${i}` }));
  24. await sequelize.queryInterface.bulkInsert(User.table, users);
  25. expect(stub.callCount).to.eq(1);
  26. const firstCall = stub.getCall(0).args[0];
  27. expectPerDialect(() => firstCall, {
  28. default: toMatchRegex(
  29. /^INSERT INTO (?:`|")Users(?:`|") \((?:`|")firstName(?:`|")\) VALUES (?:\('\w+'\),){999}\('\w+'\);$/,
  30. ),
  31. ibmi: toMatchRegex(
  32. /^SELECT \* FROM FINAL TABLE \(INSERT INTO "Users" \("firstName"\) VALUES (?:\('\w+'\),){999}\('\w+'\)\)$/,
  33. ),
  34. mssql: toMatchRegex(
  35. /^INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);$/,
  36. ),
  37. });
  38. });
  39. it('uses minimal insert queries when rows >1000', async () => {
  40. const { User } = vars;
  41. const stub = sinon.stub(sequelize, 'queryRaw').resolves([[], 0]);
  42. const transaction = new Transaction(sequelize, {});
  43. const users = range(2000).map(i => ({ firstName: `user${i}` }));
  44. await sequelize.queryInterface.bulkInsert(User.table, users, { transaction });
  45. expect(stub.callCount).to.eq(1);
  46. const firstCall = stub.getCall(0).args[0];
  47. expectPerDialect(() => firstCall, {
  48. default: toMatchRegex(
  49. /^INSERT INTO (?:`|")Users(?:`|") \((?:`|")firstName(?:`|")\) VALUES (?:\('\w+'\),){1999}\('\w+'\);$/,
  50. ),
  51. ibmi: toMatchRegex(
  52. /^SELECT \* FROM FINAL TABLE \(INSERT INTO "Users" \("firstName"\) VALUES (?:\('\w+'\),){1999}\('\w+'\)\)$/,
  53. ),
  54. mssql: toMatchRegex(
  55. /^(?:INSERT INTO \[Users\] \(\[firstName\]\) VALUES (?:\(N'\w+'\),){999}\(N'\w+'\);){2}$/,
  56. ),
  57. });
  58. });
  59. // you'll find more replacement tests in query-generator tests
  60. it('does not parse replacements outside of raw sql', async () => {
  61. const { User } = vars;
  62. const stub = sinon.stub(sequelize, 'queryRaw').resolves([[], 0]);
  63. await sequelize.queryInterface.bulkInsert(
  64. User.table,
  65. [
  66. {
  67. firstName: ':injection',
  68. },
  69. ],
  70. {
  71. replacements: {
  72. injection: 'raw sql',
  73. },
  74. },
  75. );
  76. expect(stub.callCount).to.eq(1);
  77. const firstCall = stub.getCall(0).args[0];
  78. expectPerDialect(() => firstCall, {
  79. default: toMatchSql('INSERT INTO "Users" ("firstName") VALUES (\':injection\');'),
  80. 'mysql mariadb sqlite3': toMatchSql(
  81. "INSERT INTO `Users` (`firstName`) VALUES (':injection');",
  82. ),
  83. mssql: toMatchSql(`INSERT INTO [Users] ([firstName]) VALUES (N':injection');`),
  84. // TODO: db2 should use the same system as ibmi
  85. ibmi: toMatchSql(
  86. `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES (':injection'))`,
  87. ),
  88. });
  89. });
  90. });