knex/test/integration/query/trigger-deletes.js
2021-10-02 23:45:17 +03:00

301 lines
9.6 KiB
JavaScript

'use strict';
const { expect } = require('chai');
const { TEST_TIMESTAMP } = require('../../util/constants');
const { isMssql } = require('../../util/db-helpers');
const {
dropTables,
createAccounts,
createTestTableTwo,
} = require('../../util/tableCreatorHelper');
const {
insertAccounts,
insertTestTableTwoData,
} = require('../../util/dataInsertHelper');
module.exports = function (knex) {
describe('Deletes with Triggers', function () {
// Trigger options
const triggerOptions = { includeTriggerModifications: true };
before(function () {
if (!isMssql(knex)) {
this.skip('This test is MSSQL only');
}
});
before(async () => {
await dropTables(knex);
await createAccounts(knex);
await createTestTableTwo(knex);
await insertAccounts(knex);
await insertTestTableTwoData(knex);
});
describe('Trigger Specific Tests', function () {
// Reused variables
// Table Names
const primaryTable = 'test_return_with_trigger_primary';
const secondaryTable = 'test_return_with_trigger_secondary';
// Foreign Key Column Names
const primaryLink = 'foreign_id';
const secondaryLink = 'looping_id';
// Trigger Name
const triggerName = 'tr_test_delete_with_trigger';
// Create proper environment for tests
before(async function () {
if (!isMssql(knex)) {
this.skip('This test is MSSQL only');
}
await knex.schema.hasTable('users').then(async function (exists) {
if (exists) {
await knex.schema.dropTable(primaryTable);
await knex.schema.dropTable(secondaryTable);
}
// Create tables
await knex.schema.createTable(primaryTable, function (table) {
table.increments().primary();
table.string('data').defaultsTo('');
table.integer(primaryLink).nullable();
});
await knex.schema.createTable(secondaryTable, function (table) {
table.increments().primary();
table.string('data').defaultsTo('');
table.integer(secondaryLink).nullable();
});
await knex.raw(`
CREATE TRIGGER [dbo].[${triggerName}] ON [dbo].[${secondaryTable}]
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
BEGIN
delete ${primaryTable}
from ${primaryTable} as pt
inner join deleted as d
on pt.id = d.${secondaryLink}
END
END
`);
});
});
// Clean-up test specific tables
after(async function () {
if (!isMssql(knex)) {
return;
}
// Drop table (Trigger is removed with table)
await knex.schema.dropTable(primaryTable);
await knex.schema.dropTable(secondaryTable);
});
// Reset tables for each test
beforeEach(async function () {
// "Truncate" tables instead of recreate for each test for speed gains
await knex.raw(`
delete from ${primaryTable} dbcc checkident('${primaryTable}', reseed, 0);
delete from ${secondaryTable} dbcc checkident('${secondaryTable}', reseed, 0);
`);
});
it('#4152 Should allow returns with deletes on tables with triggers', async function () {
let reachedEnd = false;
await knex.transaction(async function () {
let insertedId;
let deletedId;
async function insertWithReturn() {
const insertPrimary = {
data: 'Testing Data',
};
const insertSecondary = {
data: 'Test Linking',
};
// Setup primary table for trigger use case
const primaryId = await knex(primaryTable).insert(
[insertPrimary],
['id'],
triggerOptions
);
insertSecondary[secondaryLink] = primaryId[0];
// Insert to table with trigger to test delete
insertedId = (
await knex(secondaryTable).insert(
[insertSecondary],
['id'],
triggerOptions
)
)[0];
}
async function deleteTriggerTable() {
// Test returning value from delete statement on a table with a trigger
deletedId = (
await knex(secondaryTable)
.whereRaw(`id = ${insertedId}`)
.delete(['id'], triggerOptions)
)[0];
}
await insertWithReturn();
await deleteTriggerTable();
expect(Number.parseInt(deletedId)).to.be.finite;
reachedEnd = true;
});
expect(reachedEnd).to.be.true;
});
it('#4152 Should allow returns with deletes on tables with triggers using returning function', async function () {
let reachedEnd = false;
await knex.transaction(async function () {
let insertedId;
let deletedId;
async function insertWithReturn() {
const insertPrimary = {
data: 'Testing Data',
};
const insertSecondary = {
data: 'Test Linking',
};
// Setup primary table for trigger use case
const primaryId = await knex(primaryTable).insert(
[insertPrimary],
['id'],
triggerOptions
);
insertSecondary[secondaryLink] = primaryId[0];
// Insert to table with trigger to test delete
insertedId = (
await knex(secondaryTable).insert(
[insertSecondary],
['id'],
triggerOptions
)
)[0];
}
async function deleteTriggerTable() {
// Test returning value from delete statement on a table with a trigger
deletedId = (
await knex(secondaryTable)
.whereRaw(`id = ${insertedId}`)
.returning(['id'], triggerOptions)
.delete()
)[0];
}
await insertWithReturn();
await deleteTriggerTable();
expect(Number.parseInt(deletedId)).to.be.finite;
reachedEnd = true;
});
expect(reachedEnd).to.be.true;
});
});
describe('Re-test all Delete Functions with trigger option and returns', function () {
before(async function () {
if (!isMssql(knex)) {
this.skip('This test is MSSQL only');
}
// Reset all table data to original stats of original tests
});
it('should allow returning for deletes in postgresql and mssql', function () {
return knex('accounts')
.where('id', 2)
.del('*', triggerOptions)
.testSql(function (tester) {
tester('mysql', 'delete from `accounts` where `id` = ?', [2], 1);
tester(
'pg',
'delete from "accounts" where "id" = ? returning *',
[2],
[
{
id: '2',
first_name: 'Test',
last_name: 'User',
email: 'test2@example.com',
logins: 1,
balance: 0,
about: 'Lorem ipsum Dolore labore incididunt enim.',
created_at: TEST_TIMESTAMP,
updated_at: TEST_TIMESTAMP,
phone: null,
},
]
);
tester(
'pg-redshift',
'delete from "accounts" where "id" = ?',
[2],
1
);
tester('sqlite3', 'delete from `accounts` where `id` = ?', [2], 1);
tester('oracledb', 'delete from "accounts" where "id" = ?', [2], 1);
tester(
'mssql',
'select top(0) [t].* into #out from [accounts] as t left join [accounts] on 0=1;delete from [accounts] output deleted.* into #out where [id] = ?; select * from #out; drop table #out;',
[2],
[
{
id: '2',
first_name: 'Test',
last_name: 'User',
email: 'test2@example.com',
logins: 1,
balance: 0,
about: 'Lorem ipsum Dolore labore incididunt enim.',
created_at: TEST_TIMESTAMP,
updated_at: TEST_TIMESTAMP,
phone: null,
},
]
);
});
});
});
it('should handle delete with join and trigger options', function () {
return knex('test_table_two')
.join('accounts', 'accounts.id', 'test_table_two.account_id')
.where({ 'accounts.email': 'test3@example.com' })
.del('*', triggerOptions)
.testSql(function (tester) {
tester(
'mssql',
'select top(0) [t].* into #out from [test_table_two] as t left join [test_table_two] on 0=1;delete [test_table_two] output deleted.* into #out from [test_table_two] inner join [accounts] on [accounts].[id] = [test_table_two].[account_id] where [accounts].[email] = ?; select * from #out; drop table #out;',
['test3@example.com'],
[{ id: 3, account_id: 3, details: '', status: 1 }]
);
});
});
});
};