From b8c9917cddc8c7dadf2ce14fb627ffca4243bdc3 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Wed, 1 Nov 2023 14:53:34 +0000 Subject: [PATCH 1/9] Fix Crash when Instead of View Trigger calls itself This change will fix crashes when an Instead of Trigger on View calls itself directly and indirectly Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- contrib/babelfishpg_tsql/src/hooks.c | 22 +++++ test/JDBC/expected/BABEL-2170-vu-verify.out | 94 +++++++++++++++++++ .../input/triggers/BABEL-2170-vu-verify.sql | 72 ++++++++++++++ 3 files changed, 188 insertions(+) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 0a186dac9ea..6e4163a1058 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -736,6 +736,28 @@ static bool pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event) { TriggerDesc *trigDesc = view->trigdesc; + if (triggerOids) + { + int i; + for (i = 0; i < trigDesc->numtriggers; i++) + { + Trigger *trigger = &trigDesc->triggers[i]; + Oid current_tgoid = trigger->tgoid; + Oid prev_tgoid = InvalidOid; + prev_tgoid = lfirst_oid(list_tail(triggerOids)); + if (prev_tgoid == current_tgoid) + { + return false; /** Direct recursive trigger case*/ + } + else if (list_member_oid(triggerOids, current_tgoid)) + { + /** Indirect recursive trigger case*/ + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"))); + } + } + } switch (event) { diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 94e3ee9a167..3e1386e68a1 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -483,6 +483,100 @@ int#!#varchar#!#varchar#!#numeric DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO +-- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_insert; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_insert ON babel_2170_vu_employees_view +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); +END +GO + +INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees; +GO +~~START~~ +int +3 +~~END~~ + + +SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees_view; +GO +~~START~~ +int +3 +~~END~~ + + + +-- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 +CREATE TABLE babel_2170_vu_employees_rec +( + EmployeeID int NOT NULL, + EmployeeName VARCHAR(50), + EmployeeAddress VARCHAR(50), + MonthSalary NUMERIC(10, 2) +) +GO + +CREATE VIEW babel_2170_vu_employees_view_rec AS +SELECT EmployeeID, + EmployeeName, + EmployeeAddress, + MonthSalary +FROM babel_2170_vu_employees_rec +WHERE EmployeeName LIKE 'a%'; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view_rec VALUES(4, 'adam', '1st Street', '4000'); +END +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: cannot create trigger "babel_2170_vu_employees_view_iot_rec" for relation "babel_2170_vu_employees_view" because an INSTEAD OF INSERT trigger already exists on this object.)~~ + + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); +END +GO + +INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; +GO + +DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; +GO + +DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +GO + -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index c7802b6db5c..0b2253dea7d 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -253,6 +253,78 @@ GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO +-- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_insert; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_insert ON babel_2170_vu_employees_view +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); +END +GO + +INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); +GO + +SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees; +GO + +SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees_view; +GO + +-- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 + +CREATE TABLE babel_2170_vu_employees_rec +( + EmployeeID int NOT NULL, + EmployeeName VARCHAR(50), + EmployeeAddress VARCHAR(50), + MonthSalary NUMERIC(10, 2) +) +GO + +CREATE VIEW babel_2170_vu_employees_view_rec AS +SELECT EmployeeID, + EmployeeName, + EmployeeAddress, + MonthSalary +FROM babel_2170_vu_employees_rec +WHERE EmployeeName LIKE 'a%'; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view_rec VALUES(4, 'adam', '1st Street', '4000'); +END +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec +INSTEAD OF INSERT +AS +BEGIN + INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); +END +GO + +INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; +GO + +DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; +GO + +DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +GO + -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO From 7205c548f325295f582f2fa9a29b0a781eb57604 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Wed, 1 Nov 2023 15:14:00 +0000 Subject: [PATCH 2/9] Empty-Commit From e2007df8c0d194a2d9c1ed638bc0b0a4b5799fdf Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Thu, 2 Nov 2023 08:41:52 +0000 Subject: [PATCH 3/9] Fix for failing test case Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- contrib/babelfishpg_tsql/src/hooks.c | 7 -- test/JDBC/expected/BABEL-2170-vu-verify.out | 84 +++---------------- .../input/triggers/BABEL-2170-vu-verify.sql | 67 ++------------- 3 files changed, 18 insertions(+), 140 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 6e4163a1058..02eb0a6d879 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -749,13 +749,6 @@ pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event) { return false; /** Direct recursive trigger case*/ } - else if (list_member_oid(triggerOids, current_tgoid)) - { - /** Indirect recursive trigger case*/ - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"))); - } } } diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 3e1386e68a1..472cbad0c44 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -55,7 +55,7 @@ Trigger db1_BABEL2170.dbo.babel_2170_vu_employees_view_iot_update Invoked ~~ROW COUNT: 1~~ -SELECT EmployeeID,EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees WHERE EmployeeID = 2 ORDER BY EmployeeID; +SELECT EmployeeID,EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees WHERE EmployeeID = 2; GO ~~START~~ int#!#varchar#!#varchar#!#numeric @@ -484,97 +484,33 @@ DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO -- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_insert; +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO -CREATE TRIGGER babel_2170_vu_employees_view_iot_insert ON babel_2170_vu_employees_view -INSTEAD OF INSERT +CREATE TRIGGER babel_2170_vu_employees_view_iot_update ON babel_2170_vu_employees_view +INSTEAD OF UPDATE AS BEGIN - INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); + UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; END GO -INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); +UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; GO ~~ROW COUNT: 1~~ ~~ROW COUNT: 1~~ -SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees; -GO -~~START~~ -int -3 -~~END~~ - - -SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees_view; +SELECT EmployeeID, EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees_view WHERE EmployeeID = 2; GO ~~START~~ -int -3 +int#!#varchar#!#varchar#!#numeric +2#!#angel#!#1st Street#!#2100.00 ~~END~~ - --- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 -CREATE TABLE babel_2170_vu_employees_rec -( - EmployeeID int NOT NULL, - EmployeeName VARCHAR(50), - EmployeeAddress VARCHAR(50), - MonthSalary NUMERIC(10, 2) -) -GO - -CREATE VIEW babel_2170_vu_employees_view_rec AS -SELECT EmployeeID, - EmployeeName, - EmployeeAddress, - MonthSalary -FROM babel_2170_vu_employees_rec -WHERE EmployeeName LIKE 'a%'; -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view -INSTEAD OF INSERT -AS -BEGIN - INSERT INTO babel_2170_vu_employees_view_rec VALUES(4, 'adam', '1st Street', '4000'); -END -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: cannot create trigger "babel_2170_vu_employees_view_iot_rec" for relation "babel_2170_vu_employees_view" because an INSTEAD OF INSERT trigger already exists on this object.)~~ - - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec -INSTEAD OF INSERT -AS -BEGIN - INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); -END -GO - -INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); -GO -~~ROW COUNT: 1~~ - -~~ROW COUNT: 1~~ - - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; -GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; -GO - -DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; -GO - -DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO -- test multi-db mode diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index 0b2253dea7d..f5cfa356fee 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -31,7 +31,7 @@ GO UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; GO -SELECT EmployeeID,EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees WHERE EmployeeID = 2 ORDER BY EmployeeID; +SELECT EmployeeID,EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees WHERE EmployeeID = 2; GO BEGIN TRANSACTION @@ -254,75 +254,24 @@ DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO -- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_insert; -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_insert ON babel_2170_vu_employees_view -INSTEAD OF INSERT -AS -BEGIN - INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); -END -GO - -INSERT INTO babel_2170_vu_employees_view VALUES(3, 'adam', '1st Street', '3000'); -GO - -SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees; -GO - -SELECT COUNT(EmployeeID) FROM babel_2170_vu_employees_view; +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO --- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 - -CREATE TABLE babel_2170_vu_employees_rec -( - EmployeeID int NOT NULL, - EmployeeName VARCHAR(50), - EmployeeAddress VARCHAR(50), - MonthSalary NUMERIC(10, 2) -) -GO - -CREATE VIEW babel_2170_vu_employees_view_rec AS -SELECT EmployeeID, - EmployeeName, - EmployeeAddress, - MonthSalary -FROM babel_2170_vu_employees_rec -WHERE EmployeeName LIKE 'a%'; -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view -INSTEAD OF INSERT -AS -BEGIN - INSERT INTO babel_2170_vu_employees_view_rec VALUES(4, 'adam', '1st Street', '4000'); -END -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec -INSTEAD OF INSERT +CREATE TRIGGER babel_2170_vu_employees_view_iot_update ON babel_2170_vu_employees_view +INSTEAD OF UPDATE AS BEGIN - INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); + UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; END GO -INSERT INTO babel_2170_vu_employees_view VALUES(4, 'adam', '1st Street', '4000'); -GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; -GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; +UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; GO -DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; +SELECT EmployeeID, EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees_view WHERE EmployeeID = 2; GO -DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO -- test multi-db mode From dd08e2ea3bd06a45d1d17087915932fb42112bca Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Mon, 6 Nov 2023 09:51:30 +0000 Subject: [PATCH 4/9] Added case for indirect recusion Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- contrib/babelfishpg_tsql/src/hooks.c | 7 ++ test/JDBC/expected/BABEL-2170-vu-verify.out | 67 +++++++++++++++++++ .../input/triggers/BABEL-2170-vu-verify.sql | 59 ++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 02eb0a6d879..33cd89953f6 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -749,6 +749,13 @@ pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event) { return false; /** Direct recursive trigger case*/ } + else if (list_member_oid(triggerOids, current_tgoid)) + { + /** Indirect recursive trigger case*/ + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"))); + } } } diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 472cbad0c44..93dc02734a2 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -513,6 +513,73 @@ int#!#varchar#!#varchar#!#numeric DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO + + +-- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 +CREATE TABLE babel_2170_vu_employees_rec +( + EmployeeID int NOT NULL, + EmployeeName VARCHAR(50), + EmployeeAddress VARCHAR(50), + MonthSalary NUMERIC(10, 2) +) +GO + +INSERT INTO babel_2170_vu_employees_rec VALUES(1, 'amber', '1st Street', '1000'); +INSERT INTO babel_2170_vu_employees_rec VALUES(2, 'angel', '1st Street', '2000'); +GO +~~ROW COUNT: 1~~ + +~~ROW COUNT: 1~~ + + +CREATE VIEW babel_2170_vu_employees_view_rec AS +SELECT EmployeeID, + EmployeeName, + EmployeeAddress, + MonthSalary +FROM babel_2170_vu_employees_rec +WHERE EmployeeName LIKE 'a%'; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; +END +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; +END +GO + +UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ + + + +-- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +-- GO +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; +GO + +DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; +GO + +DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +GO + -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index f5cfa356fee..39ddcf85c6a 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -274,6 +274,65 @@ GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO + +-- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 + +CREATE TABLE babel_2170_vu_employees_rec +( + EmployeeID int NOT NULL, + EmployeeName VARCHAR(50), + EmployeeAddress VARCHAR(50), + MonthSalary NUMERIC(10, 2) +) +GO + +INSERT INTO babel_2170_vu_employees_rec VALUES(1, 'amber', '1st Street', '1000'); +INSERT INTO babel_2170_vu_employees_rec VALUES(2, 'angel', '1st Street', '2000'); +GO + +CREATE VIEW babel_2170_vu_employees_view_rec AS +SELECT EmployeeID, + EmployeeName, + EmployeeAddress, + MonthSalary +FROM babel_2170_vu_employees_rec +WHERE EmployeeName LIKE 'a%'; +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; +END +GO + +CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; +END +GO + +UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +GO + +-- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +-- GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; +GO + +DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; +GO + +DROP TABLE IF EXISTS babel_2170_vu_employees_rec; +GO + -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO From 6ab813bf8725a5476b4071279d3d12f419e03908 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Mon, 6 Nov 2023 10:41:22 +0000 Subject: [PATCH 5/9] Crash fix IO view trigger inserted is used with join This commit will solve crash script listed in BABEL-4514 When inserted table is used with join inside trigger body, Instead of Trigger on View was causing server crash Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- test/JDBC/expected/BABEL-2170-vu-verify.out | 32 +++++++++++++++++-- .../input/triggers/BABEL-2170-vu-verify.sql | 21 +++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 93dc02734a2..98b41239d90 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -483,10 +483,38 @@ int#!#varchar#!#varchar#!#numeric DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO --- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO +-- Transition table join test +CREATE TRIGGER babel_2170_vu_employees_view_transition ON babel_2170_vu_employees_view +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view set MonthSalary = i.MonthSalary + 15 FROM inserted as i + JOIN babel_2170_vu_employees_view AS v ON v.EmployeeID = i.EmployeeID +END +GO + +UPDATE babel_2170_vu_employees_view SET MonthSalary = 5 WHERE EmployeeID = 2; +GO +~~ROW COUNT: 2~~ + +~~ROW COUNT: 1~~ + + +SELECT EmployeeID, EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees_view WHERE EmployeeID = 2; +GO +~~START~~ +int#!#varchar#!#varchar#!#numeric +2#!#angel#!#1st Street#!#2015.00 +~~END~~ + + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_transition; +GO + +-- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 CREATE TRIGGER babel_2170_vu_employees_view_iot_update ON babel_2170_vu_employees_view INSTEAD OF UPDATE AS @@ -506,7 +534,7 @@ SELECT EmployeeID, EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu GO ~~START~~ int#!#varchar#!#varchar#!#numeric -2#!#angel#!#1st Street#!#2100.00 +2#!#angel#!#1st Street#!#2115.00 ~~END~~ diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index 39ddcf85c6a..de4fd6e234c 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -253,10 +253,29 @@ GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_txn_delete; GO --- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO +-- Transition table join test +CREATE TRIGGER babel_2170_vu_employees_view_transition ON babel_2170_vu_employees_view +INSTEAD OF UPDATE +AS +BEGIN + UPDATE babel_2170_vu_employees_view set MonthSalary = i.MonthSalary + 15 FROM inserted as i + JOIN babel_2170_vu_employees_view AS v ON v.EmployeeID = i.EmployeeID +END +GO + +UPDATE babel_2170_vu_employees_view SET MonthSalary = 5 WHERE EmployeeID = 2; +GO + +SELECT EmployeeID, EmployeeName, EmployeeAddress, MonthSalary FROM babel_2170_vu_employees_view WHERE EmployeeID = 2; +GO + +DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_transition; +GO + +-- Recursive Trigger test Direct Recursion Trigger calling itself trigger 1 -> trigger 1 CREATE TRIGGER babel_2170_vu_employees_view_iot_update ON babel_2170_vu_employees_view INSTEAD OF UPDATE AS From 25e2990432e7469fbd2378625b25d38bfb911d63 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Thu, 9 Nov 2023 15:53:19 +0000 Subject: [PATCH 6/9] Added function to fix crash with indirect recursion happening previously The query plan might be cached and cant rely on erroring out iin analyzer phase. Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- contrib/babelfishpg_tsql/src/hooks.c | 18 ++++-------------- test/JDBC/expected/BABEL-2170-vu-verify.out | 8 ++++++-- .../input/triggers/BABEL-2170-vu-verify.sql | 4 ++-- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 33cd89953f6..35ce9ca3bea 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -736,26 +736,16 @@ static bool pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event) { TriggerDesc *trigDesc = view->trigdesc; - if (triggerOids) + if (triggerOids && trigDesc) { int i; for (i = 0; i < trigDesc->numtriggers; i++) { Trigger *trigger = &trigDesc->triggers[i]; Oid current_tgoid = trigger->tgoid; - Oid prev_tgoid = InvalidOid; - prev_tgoid = lfirst_oid(list_tail(triggerOids)); - if (prev_tgoid == current_tgoid) - { - return false; /** Direct recursive trigger case*/ - } - else if (list_member_oid(triggerOids, current_tgoid)) - { - /** Indirect recursive trigger case*/ - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"))); - } + Oid prev_tgoid = lfirst_oid(list_tail(triggerOids)); + if(prev_tgoid == current_tgoid) + return false; // Trigger calls itself } } diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 98b41239d90..4c17a01a80e 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -593,9 +593,13 @@ GO ~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ +UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ + --- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; --- GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; GO diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index de4fd6e234c..18f42242938 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -337,8 +337,8 @@ GO UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; GO --- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; --- GO +UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; GO From 1645ee5bfe591b3416d9a446461601423ca47ee2 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Wed, 1 Nov 2023 15:14:00 +0000 Subject: [PATCH 7/9] Empty-Commit From d2e4b625fbe29452b44ba3f206ceaf90e83112f9 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Wed, 22 Nov 2023 19:45:34 +0000 Subject: [PATCH 8/9] Revert "Added function to fix crash with indirect recursion happening previously" This reverts commit ce1eff3f395c5abaa6725b227dc7baff98cf1497. --- contrib/babelfishpg_tsql/src/hooks.c | 18 ++++++++++++++---- test/JDBC/expected/BABEL-2170-vu-verify.out | 8 ++------ .../input/triggers/BABEL-2170-vu-verify.sql | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/contrib/babelfishpg_tsql/src/hooks.c b/contrib/babelfishpg_tsql/src/hooks.c index 35ce9ca3bea..33cd89953f6 100644 --- a/contrib/babelfishpg_tsql/src/hooks.c +++ b/contrib/babelfishpg_tsql/src/hooks.c @@ -736,16 +736,26 @@ static bool pltsql_bbfViewHasInsteadofTrigger(Relation view, CmdType event) { TriggerDesc *trigDesc = view->trigdesc; - if (triggerOids && trigDesc) + if (triggerOids) { int i; for (i = 0; i < trigDesc->numtriggers; i++) { Trigger *trigger = &trigDesc->triggers[i]; Oid current_tgoid = trigger->tgoid; - Oid prev_tgoid = lfirst_oid(list_tail(triggerOids)); - if(prev_tgoid == current_tgoid) - return false; // Trigger calls itself + Oid prev_tgoid = InvalidOid; + prev_tgoid = lfirst_oid(list_tail(triggerOids)); + if (prev_tgoid == current_tgoid) + { + return false; /** Direct recursive trigger case*/ + } + else if (list_member_oid(triggerOids, current_tgoid)) + { + /** Indirect recursive trigger case*/ + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"))); + } } } diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 4c17a01a80e..98b41239d90 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -593,13 +593,9 @@ GO ~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ -UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ - +-- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +-- GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; GO diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index 18f42242938..de4fd6e234c 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -337,8 +337,8 @@ GO UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; GO -UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; -GO +-- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; +-- GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; GO From e2d8cf1adc84d18d6164113d4951da81a6af41b2 Mon Sep 17 00:00:00 2001 From: Deepakshi Mittal Date: Wed, 22 Nov 2023 20:51:48 +0000 Subject: [PATCH 9/9] Removed indirect recuriosn test case, will fix it seperately Task: BABEL-2170 Signed-off-by: Deepakshi Mittal --- test/JDBC/expected/BABEL-2170-vu-verify.out | 67 ------------------- .../input/triggers/BABEL-2170-vu-verify.sql | 59 ---------------- 2 files changed, 126 deletions(-) diff --git a/test/JDBC/expected/BABEL-2170-vu-verify.out b/test/JDBC/expected/BABEL-2170-vu-verify.out index 98b41239d90..06f834bcb6a 100644 --- a/test/JDBC/expected/BABEL-2170-vu-verify.out +++ b/test/JDBC/expected/BABEL-2170-vu-verify.out @@ -541,73 +541,6 @@ int#!#varchar#!#varchar#!#numeric DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO - - --- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 -CREATE TABLE babel_2170_vu_employees_rec -( - EmployeeID int NOT NULL, - EmployeeName VARCHAR(50), - EmployeeAddress VARCHAR(50), - MonthSalary NUMERIC(10, 2) -) -GO - -INSERT INTO babel_2170_vu_employees_rec VALUES(1, 'amber', '1st Street', '1000'); -INSERT INTO babel_2170_vu_employees_rec VALUES(2, 'angel', '1st Street', '2000'); -GO -~~ROW COUNT: 1~~ - -~~ROW COUNT: 1~~ - - -CREATE VIEW babel_2170_vu_employees_view_rec AS -SELECT EmployeeID, - EmployeeName, - EmployeeAddress, - MonthSalary -FROM babel_2170_vu_employees_rec -WHERE EmployeeName LIKE 'a%'; -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view -INSTEAD OF UPDATE -AS -BEGIN - UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; -END -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec -INSTEAD OF UPDATE -AS -BEGIN - UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; -END -GO - -UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; -GO -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32))~~ - - - --- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; --- GO -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; -GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; -GO - -DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; -GO - -DROP TABLE IF EXISTS babel_2170_vu_employees_rec; -GO - -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO diff --git a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql index de4fd6e234c..18b63fa2364 100644 --- a/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql +++ b/test/JDBC/input/triggers/BABEL-2170-vu-verify.sql @@ -293,65 +293,6 @@ GO DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_update; GO - --- Recursive Trigger test Indirect Recursion trigger 1 -> trigger 2 -> trigger 1 - -CREATE TABLE babel_2170_vu_employees_rec -( - EmployeeID int NOT NULL, - EmployeeName VARCHAR(50), - EmployeeAddress VARCHAR(50), - MonthSalary NUMERIC(10, 2) -) -GO - -INSERT INTO babel_2170_vu_employees_rec VALUES(1, 'amber', '1st Street', '1000'); -INSERT INTO babel_2170_vu_employees_rec VALUES(2, 'angel', '1st Street', '2000'); -GO - -CREATE VIEW babel_2170_vu_employees_view_rec AS -SELECT EmployeeID, - EmployeeName, - EmployeeAddress, - MonthSalary -FROM babel_2170_vu_employees_rec -WHERE EmployeeName LIKE 'a%'; -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec ON babel_2170_vu_employees_view -INSTEAD OF UPDATE -AS -BEGIN - UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; -END -GO - -CREATE TRIGGER babel_2170_vu_employees_view_iot_rec2 ON babel_2170_vu_employees_view_rec -INSTEAD OF UPDATE -AS -BEGIN - UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +1 WHERE EmployeeID = 2; -END -GO - -UPDATE babel_2170_vu_employees_view SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; -GO - --- UPDATE babel_2170_vu_employees_view_rec SET MonthSalary = MonthSalary +100 WHERE EmployeeID = 2; --- GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec; -GO - -DROP TRIGGER IF EXISTS babel_2170_vu_employees_view_iot_rec2; -GO - -DROP VIEW IF EXISTS babel_2170_vu_employees_view_rec; -GO - -DROP TABLE IF EXISTS babel_2170_vu_employees_rec; -GO - -- test multi-db mode SELECT set_config('role', 'jdbc_user', false); GO