diff --git a/src/60createtable.js b/src/60createtable.js index 35811f916d..a91229388e 100755 --- a/src/60createtable.js +++ b/src/60createtable.js @@ -332,10 +332,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { for (var tr in table.beforeinsert) { var trigger = table.beforeinsert[tr]; if (trigger) { - if (trigger.funcid) { - if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true; - } else if (trigger.statement) { - if (trigger.statement.execute(databaseid) === false) prevent = prevent || true; + if (alasql.executeTrigger(trigger, databaseid, r) === false) { + prevent = prevent || true; } } } @@ -347,11 +345,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { escape = true; trigger = table.insteadofinsert[tr]; if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](r); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); - } + alasql.executeTrigger(trigger, databaseid, r); } } if (escape) return; @@ -488,11 +482,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { for (var tr in table.afterinsert) { var trigger = table.afterinsert[tr]; if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](r); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); - } + alasql.executeTrigger(trigger, databaseid, r); } } alasql.inserted = oldinserted; @@ -507,10 +497,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { for (var tr in table.beforedelete) { var trigger = table.beforedelete[tr]; if (trigger) { - if (trigger.funcid) { - if (alasql.fn[trigger.funcid](r) === false) prevent = prevent || true; - } else if (trigger.statement) { - if (trigger.statement.execute(databaseid) === false) prevent = prevent || true; + if (alasql.executeTrigger(trigger, databaseid, r) === false) { + prevent = prevent || true; } } } @@ -522,11 +510,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { escape = true; var trigger = table.insteadofdelete[tr]; if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](r); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); - } + alasql.executeTrigger(trigger, databaseid, r); } } if (escape) return; @@ -613,10 +597,8 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { for (var tr in table.beforeupdate) { var trigger = table.beforeupdate[tr]; if (trigger) { - if (trigger.funcid) { - if (alasql.fn[trigger.funcid](this.data[i], r) === false) prevent = prevent || true; - } else if (trigger.statement) { - if (trigger.statement.execute(databaseid) === false) prevent = prevent || true; + if (alasql.executeTrigger(trigger, databaseid, this.data[i], r) === false) { + prevent = prevent || true; } } } @@ -628,11 +610,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { escape = true; var trigger = table.insteadofupdate[tr]; if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](this.data[i], r); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); - } + alasql.executeTrigger(trigger, databaseid, this.data[i], r); } } if (escape) return; @@ -685,11 +663,7 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) { for (var tr in table.afterupdate) { var trigger = table.afterupdate[tr]; if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](this.data[i], r); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); - } + alasql.executeTrigger(trigger, databaseid, this.data[i], r); } } }; diff --git a/src/71trigger.js b/src/71trigger.js index 10a705e9cb..a31bab454a 100755 --- a/src/71trigger.js +++ b/src/71trigger.js @@ -108,3 +108,27 @@ yy.DropTrigger.prototype.execute = function (databaseid, params, cb) { if (cb) res = cb(res); return res; }; + +/** + * Helper function to execute a trigger with proper parameter passing + * @param {object} trigger - The trigger object + * @param {string} databaseid - Database ID for statement execution + * @param {...any} args - Arguments to pass to the trigger function + * @return {*} Result from trigger execution (typically boolean or undefined) + */ +alasql.executeTrigger = function (trigger, databaseid, ...args) { + if (!trigger) return; + + if (trigger.funcid) { + // Direct function ID (older syntax: CREATE TRIGGER ... tablename funcname) + return alasql.fn[trigger.funcid](...args); + } else if (trigger.statement) { + // CALL syntax: CREATE TRIGGER ... CALL funcname() + if (trigger.statement.expression && trigger.statement.expression.funcid) { + return alasql.fn[trigger.statement.expression.funcid](...args); + } else { + // Fallback: execute statement without parameters (for non-CALL statements) + return trigger.statement.execute(databaseid); + } + } +}; diff --git a/src/72delete.js b/src/72delete.js index 277a8052c3..03a6f33ed7 100755 --- a/src/72delete.js +++ b/src/72delete.js @@ -88,8 +88,8 @@ yy.Delete.prototype.compile = function (databaseid) { var deletedRows = []; for (var i = 0, ilen = table.data.length; i < ilen; i++) { if (wherefn(table.data[i], params, alasql)) { - // Track deleted row for OUTPUT clause - if (self.output) { + // Track deleted row for OUTPUT clause and AFTER DELETE trigger + if (self.output || table.afterdelete) { deletedRows.push(cloneDeep(table.data[i])); } // Check for transaction - if it is not possible then return all back @@ -104,14 +104,16 @@ yy.Delete.prototype.compile = function (databaseid) { } table.data = newtable; - // Trigger prevent functionality - for (var tr in table.afterdelete) { - var trigger = table.afterdelete[tr]; - if (trigger) { - if (trigger.funcid) { - alasql.fn[trigger.funcid](); - } else if (trigger.statement) { - trigger.statement.execute(databaseid); + // AFTER DELETE triggers - call for each deleted row + // Note: Triggers are called once per row per trigger (row-level triggers) + // For N deleted rows and M triggers, this results in N×M trigger calls + if (table.afterdelete) { + for (var i = 0; i < deletedRows.length; i++) { + for (var tr in table.afterdelete) { + var trigger = table.afterdelete[tr]; + if (trigger) { + alasql.executeTrigger(trigger, databaseid, deletedRows[i]); + } } } } diff --git a/test/test1119.js b/test/test1119.js index 01ca1d96bf..6bfbc53417 100644 --- a/test/test1119.js +++ b/test/test1119.js @@ -3,7 +3,7 @@ if (typeof exports === 'object') { var alasql = require('..'); // You might need to adjust the path depending on where you save the test file } -describe.skip('Test 1119 - Trigger callback parameter', function () { +describe('Test 1119 - Trigger callback parameter', function () { const test = '1119'; // Test file number before(function () {