bulk-delete-query.test.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { DataTypes, literal } from '@sequelize/core';
  2. import { createSequelizeInstance, expectsql, sequelize } from '../../support';
  3. const dialect = sequelize.dialect;
  4. const limitNotSupportedError = new Error(
  5. 'Using LIMIT in bulkDeleteQuery requires specifying a model or model definition.',
  6. );
  7. describe('QueryGenerator#bulkDeleteQuery', () => {
  8. const queryGenerator = sequelize.queryGenerator;
  9. it('produces a delete query', () => {
  10. expectsql(queryGenerator.bulkDeleteQuery('myTable', { where: { name: 'barry' } }), {
  11. default: `DELETE FROM [myTable] WHERE [name] = 'barry'`,
  12. mssql: `DELETE FROM [myTable] WHERE [name] = N'barry'; SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  13. });
  14. });
  15. it('produces a delete query with a limit', () => {
  16. expectsql(
  17. () => queryGenerator.bulkDeleteQuery('myTable', { where: { name: 'barry' }, limit: 10 }),
  18. {
  19. default: `DELETE FROM [myTable] WHERE [name] = 'barry' LIMIT 10`,
  20. sqlite3:
  21. "DELETE FROM `myTable` WHERE rowid IN (SELECT rowid FROM `myTable` WHERE `name` = 'barry' LIMIT 10)",
  22. 'db2 ibmi': `DELETE FROM "myTable" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`,
  23. 'mssql postgres snowflake': limitNotSupportedError,
  24. },
  25. );
  26. });
  27. it('produces a delete query with a limit using a model', () => {
  28. const MyModel = sequelize.define('MyModel', {});
  29. expectsql(queryGenerator.bulkDeleteQuery(MyModel, { where: { name: 'barry' }, limit: 10 }), {
  30. default: `DELETE FROM [MyModels] WHERE [name] = 'barry' LIMIT 10`,
  31. mssql: `DELETE FROM [MyModels] WHERE [id] IN (SELECT [id] FROM [MyModels] WHERE [name] = N'barry' ORDER BY [id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY); SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  32. sqlite3:
  33. "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)",
  34. 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`,
  35. 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`,
  36. });
  37. });
  38. it('produces a delete query with a limit using a model definition', () => {
  39. const MyModel = sequelize.define('MyModel', {});
  40. const myDefinition = MyModel.modelDefinition;
  41. expectsql(
  42. queryGenerator.bulkDeleteQuery(myDefinition, { where: { name: 'barry' }, limit: 10 }),
  43. {
  44. default: `DELETE FROM [MyModels] WHERE [name] = 'barry' LIMIT 10`,
  45. mssql: `DELETE FROM [MyModels] WHERE [id] IN (SELECT [id] FROM [MyModels] WHERE [name] = N'barry' ORDER BY [id] OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY); SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  46. sqlite3:
  47. "DELETE FROM `MyModels` WHERE rowid IN (SELECT rowid FROM `MyModels` WHERE `name` = 'barry' LIMIT 10)",
  48. 'db2 ibmi': `DELETE FROM "MyModels" WHERE "name" = 'barry' FETCH NEXT 10 ROWS ONLY`,
  49. 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE "name" = 'barry' ORDER BY "id" LIMIT 10)`,
  50. },
  51. );
  52. });
  53. // you'll find more replacement tests in query-generator tests
  54. it('produces a delete query with named replacements in literals', () => {
  55. const MyModel = sequelize.define('MyModel', {});
  56. const query = queryGenerator.bulkDeleteQuery(MyModel, {
  57. limit: literal(':limit'),
  58. where: literal('name = :name'),
  59. replacements: {
  60. limit: 1,
  61. name: 'Zoe',
  62. },
  63. });
  64. expectsql(query, {
  65. default: `DELETE FROM [MyModels] WHERE name = 'Zoe' LIMIT 1`,
  66. mssql: `DELETE FROM [MyModels] WHERE [id] IN (SELECT [id] FROM [MyModels] WHERE name = N'Zoe' ORDER BY [id] OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY); SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  67. sqlite3: `DELETE FROM \`MyModels\` WHERE rowid IN (SELECT rowid FROM \`MyModels\` WHERE name = 'Zoe' LIMIT 1)`,
  68. 'db2 ibmi': `DELETE FROM "MyModels" WHERE name = 'Zoe' FETCH NEXT 1 ROWS ONLY`,
  69. 'postgres snowflake': `DELETE FROM "MyModels" WHERE "id" IN (SELECT "id" FROM "MyModels" WHERE name = 'Zoe' ORDER BY "id" LIMIT 1)`,
  70. });
  71. });
  72. it('fails to produce a delete query with undefined parameter in where', () => {
  73. expectsql(() => queryGenerator.bulkDeleteQuery('myTable', { where: { name: undefined } }), {
  74. default:
  75. new Error(`Invalid value received for the "where" option. Refer to the sequelize documentation to learn which values the "where" option accepts.
  76. Value: { name: undefined }
  77. Caused by: "undefined" cannot be escaped`),
  78. });
  79. });
  80. it('produces a delete query with a model where primary key has a field name different from attribute name', () => {
  81. const MyModel = sequelize.define('MyModel', {
  82. id: {
  83. type: DataTypes.INTEGER,
  84. primaryKey: true,
  85. autoIncrement: true,
  86. field: 'my_model_id',
  87. },
  88. });
  89. expectsql(queryGenerator.bulkDeleteQuery(MyModel, { where: { id: 2 } }), {
  90. default: 'DELETE FROM [MyModels] WHERE [my_model_id] = 2',
  91. mssql: 'DELETE FROM [MyModels] WHERE [my_model_id] = 2; SELECT @@ROWCOUNT AS AFFECTEDROWS;',
  92. });
  93. });
  94. it('produces a delete query with a schema', () => {
  95. expectsql(
  96. queryGenerator.bulkDeleteQuery(
  97. { tableName: 'myTable', schema: 'mySchema' },
  98. { where: { name: 'barry' } },
  99. ),
  100. {
  101. default: `DELETE FROM [mySchema].[myTable] WHERE [name] = 'barry'`,
  102. mssql: `DELETE FROM [mySchema].[myTable] WHERE [name] = N'barry'; SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  103. sqlite3: "DELETE FROM `mySchema.myTable` WHERE `name` = 'barry'",
  104. },
  105. );
  106. });
  107. it('produces a delete query with a default schema', () => {
  108. expectsql(
  109. queryGenerator.bulkDeleteQuery(
  110. { tableName: 'myTable', schema: dialect.getDefaultSchema() },
  111. { where: { name: 'barry' } },
  112. ),
  113. {
  114. default: `DELETE FROM [myTable] WHERE [name] = 'barry'`,
  115. mssql: `DELETE FROM [myTable] WHERE [name] = N'barry'; SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  116. sqlite3: "DELETE FROM `myTable` WHERE `name` = 'barry'",
  117. },
  118. );
  119. });
  120. it('produces a delete query with a globally set schema', () => {
  121. const sequelizeSchema = createSequelizeInstance({ schema: 'mySchema' });
  122. const queryGeneratorSchema = sequelizeSchema.queryGenerator;
  123. expectsql(queryGeneratorSchema.bulkDeleteQuery('myTable', { where: { name: 'barry' } }), {
  124. default: `DELETE FROM [mySchema].[myTable] WHERE [name] = 'barry'`,
  125. mssql: `DELETE FROM [mySchema].[myTable] WHERE [name] = N'barry'; SELECT @@ROWCOUNT AS AFFECTEDROWS;`,
  126. sqlite3: "DELETE FROM `mySchema.myTable` WHERE `name` = 'barry'",
  127. });
  128. });
  129. it('produces a delete query with schema and custom delimiter argument', () => {
  130. // This test is only relevant for dialects that do not support schemas
  131. if (dialect.supports.schemas) {
  132. return;
  133. }
  134. expectsql(
  135. queryGenerator.bulkDeleteQuery(
  136. { tableName: 'myTable', schema: 'mySchema', delimiter: 'custom' },
  137. { where: { name: 'barry' } },
  138. ),
  139. {
  140. sqlite3: "DELETE FROM `mySchemacustommyTable` WHERE `name` = 'barry'",
  141. },
  142. );
  143. });
  144. });