diff --git a/test/JDBC/expected/fk_trigger_temp-vu-cleanup.out b/test/JDBC/expected/fk_trigger_temp-vu-cleanup.out new file mode 100644 index 0000000000..6448d39bfa --- /dev/null +++ b/test/JDBC/expected/fk_trigger_temp-vu-cleanup.out @@ -0,0 +1,50 @@ +-- triggers +DROP TRIGGER IF EXISTS tr_SpecialChar_Insert +DROP TRIGGER IF EXISTS tr_Child_CaseInsensitive +DROP TRIGGER IF EXISTS tr_Level3_Insert +DROP TRIGGER IF EXISTS tr_Child_NullHandling +DROP TRIGGER IF EXISTS tr_Parent_Insert +DROP TRIGGER IF EXISTS tr_Child_Update +DROP TRIGGER IF EXISTS tr_Child_Insert +DROP TRIGGER IF EXISTS [trg_i_COD] +DROP TRIGGER IF EXISTS tr_UniqueChild_Insert; +DROP TRIGGER IF EXISTS tr_UniqueChild_Update; +DROP TRIGGER IF EXISTS tr_UniqueChild_ComplexInsert; +GO + +-- constraints +ALTER TABLE UniqueChild DROP CONSTRAINT IF EXISTS FK_UniqueChild_UniqueParent; +ALTER TABLE ChildNoAction DROP CONSTRAINT IF EXISTS FK_ChildNoAction_Parent; +ALTER TABLE ChildCascade DROP CONSTRAINT IF EXISTS FK_ChildCascade_Parent; +ALTER TABLE ChildSetNull DROP CONSTRAINT IF EXISTS FK_ChildSetNull_Parent; +ALTER TABLE ChildSetDefault DROP CONSTRAINT IF EXISTS FK_ChildSetDefault_Parent; +ALTER TABLE [dbo].[OrderItem] DROP CONSTRAINT IF EXISTS [FK_OrderItem_Order]; +ALTER TABLE [dbo].[Parent] DROP CONSTRAINT IF EXISTS [FK_Parent_GrandParent]; +ALTER TABLE [dbo].[Child] DROP CONSTRAINT IF EXISTS [FK_Child_Parent]; +ALTER TABLE [dbo].[Child#Table] DROP CONSTRAINT IF EXISTS [FK_ChildTable_ParentTable]; +ALTER TABLE [dbo].[Level2] DROP CONSTRAINT IF EXISTS [FK_Level2_Level1]; +ALTER TABLE [dbo].[Level3] DROP CONSTRAINT IF EXISTS [FK_Level3_Level2]; +GO + +-- tables +DROP TABLE IF EXISTS ChildNoAction +DROP TABLE IF EXISTS ChildCascade +DROP TABLE IF EXISTS ChildSetNull +DROP TABLE IF EXISTS ChildSetDefault +DROP TABLE IF EXISTS ParentNoAction +DROP TABLE IF EXISTS ParentCascade +DROP TABLE IF EXISTS ParentSetNull +DROP TABLE IF EXISTS ParentSetDefault +DROP TABLE IF EXISTS Level3 +DROP TABLE IF EXISTS Level2 +DROP TABLE IF EXISTS Level1 +DROP TABLE IF EXISTS [Child#Table] +DROP TABLE IF EXISTS [Parent@Table] +DROP TABLE IF EXISTS Child +DROP TABLE IF EXISTS Parent +DROP TABLE IF EXISTS GrandParent +DROP TABLE IF EXISTS [dbo].[OrderItem] +DROP TABLE IF EXISTS [order] +DROP TABLE IF EXISTS UniqueChild; +DROP TABLE IF EXISTS UniqueParent; +GO diff --git a/test/JDBC/expected/fk_trigger_temp-vu-prepare.out b/test/JDBC/expected/fk_trigger_temp-vu-prepare.out new file mode 100644 index 0000000000..2731be8b03 --- /dev/null +++ b/test/JDBC/expected/fk_trigger_temp-vu-prepare.out @@ -0,0 +1,248 @@ +USE MASTER; +GO + +CREATE TABLE [order] ( + pkorder INT IDENTITY(25001000,1) PRIMARY KEY, + screatedby sys.varchar(255) +); +GO + +CREATE TABLE orderitem ( + pkorderitem INT IDENTITY(1,1) PRIMARY KEY, + fkorder integer, + screatedby sys.varchar(255) +); +GO + +ALTER TABLE [dbo].[OrderItem] ADD CONSTRAINT [FK_OrderItem_Order] FOREIGN KEY([fkOrder])REFERENCES [dbo].[Order] ([pkOrder]); +GO + + + + + + + +CREATE TRIGGER [trg_i_COD] ON [dbo].[OrderItem] + AFTER INSERT +AS +BEGIN +SET NOCOUNT ON ; + DECLARE @HasMoreRow BIT , + @pkOrderItem INT , + @IsExpedit BIT , + @IsShippingItem BIT , + @IsPackage BIT , + @IsAddOn BIT , + @IsCrossSell BIT , + @ExpeditePackageBitValue INT , + @PackageRelationshipType INT, + @ShippingRelationshipType INT , + @AddOnRelationshipType INT , + @CrossSellRelationshipType INT +DECLARE @OrderItemList TABLE + ( + pkOrderItem INT NOT NULL , + IsUsed BIT DEFAULT ( 0 )/*REWRITTEN*/ , /**/ PRIMARY KEY ( pkOrderItem ) + ) + INSERT INTO @OrderItemList + ( pkOrderItem ) + SELECT pkOrderItem + FROM inserted + SELECT TOP 1 + @pkOrderItem = pkOrderItem , + @hasMoreRow = 1 + FROM @OrderItemList + WHERE IsUsed = 0 + END +GO + +INSERT INTO [dbo].[order] (sCreatedBy) VALUES('test'); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO [dbo].[orderItem] (fkOrder, sCreatedBy) VALUES(25001000, 'test'); +GO +~~ROW COUNT: 1~~ + + +-- Create base tables +CREATE TABLE GrandParent (ID INT PRIMARY KEY); +GO + +CREATE TABLE Parent ( + ID INT PRIMARY KEY, + GrandParentID INT +); +GO + +ALTER TABLE [dbo].[Parent] ADD CONSTRAINT [FK_Parent_GrandParent] FOREIGN KEY ([GrandParentID]) REFERENCES [dbo].[GrandParent] ([ID]); +GO + +CREATE TABLE Child ( + ID INT PRIMARY KEY, + ParentID INT +); +GO + +ALTER TABLE [dbo].[Child] ADD CONSTRAINT [FK_Child_Parent] FOREIGN KEY ([ParentID]) REFERENCES [dbo].[Parent] ([ID]); +GO + +-- Create special character tables +CREATE TABLE [Parent@Table] (ID INT PRIMARY KEY); +GO + +CREATE TABLE [Child#Table] ( + ID INT PRIMARY KEY, + ParentID INT +); +GO + +ALTER TABLE [dbo].[Child#Table] ADD CONSTRAINT [FK_ChildTable_ParentTable] FOREIGN KEY ([ParentID]) REFERENCES [dbo].[Parent@Table] ([ID]); +GO + +-- Insert some initial data +INSERT INTO GrandParent VALUES (1), (2); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO Parent VALUES (1, 1), (2, 2); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO [Parent@Table] VALUES (1), (2); +GO +~~ROW COUNT: 2~~ + + +-- Create multi-level tables for nesting tests +CREATE TABLE Level1 (ID INT PRIMARY KEY); +GO + +CREATE TABLE Level2 ( + ID INT PRIMARY KEY, + Level1ID INT +); +GO + +ALTER TABLE [dbo].[Level2] ADD CONSTRAINT [FK_Level2_Level1] FOREIGN KEY ([Level1ID]) REFERENCES [dbo].[Level1] ([ID]); +GO + +CREATE TABLE Level3 ( + ID INT PRIMARY KEY, + Level2ID INT +); +GO + +ALTER TABLE [dbo].[Level3] ADD CONSTRAINT [FK_Level3_Level2] FOREIGN KEY ([Level2ID]) REFERENCES [dbo].[Level2] ([ID]); +GO + +INSERT INTO Level1 VALUES (1), (2); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO Level2 VALUES (1, 1), (2, 2); +GO +~~ROW COUNT: 2~~ + + +CREATE TABLE UniqueParent ( + ID INT PRIMARY KEY, + UniqueValue VARCHAR(50) UNIQUE +); +GO + +CREATE TABLE UniqueChild ( + ID INT PRIMARY KEY, + ParentID INT, + UniqueChildValue VARCHAR(50) UNIQUE +); +GO + +ALTER TABLE UniqueChild ADD CONSTRAINT FK_UniqueChild_UniqueParent FOREIGN KEY (ParentID) REFERENCES UniqueParent(ID); +GO + +INSERT INTO UniqueParent (ID, UniqueValue) VALUES (1, 'Parent1'), (2, 'Parent2'); +GO +~~ROW COUNT: 2~~ + + +CREATE TABLE ParentNoAction (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentCascade (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentSetNull (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentSetDefault (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ChildNoAction (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildCascade (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildSetNull (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildSetDefault (ChildID INT PRIMARY KEY, ParentID INT DEFAULT 0, ChildName NVARCHAR(50)); +GO + +ALTER TABLE ChildNoAction ADD CONSTRAINT FK_ChildNoAction_Parent FOREIGN KEY (ParentID) REFERENCES ParentNoAction(ParentID); +GO + +ALTER TABLE ChildCascade ADD CONSTRAINT FK_ChildCascade_Parent FOREIGN KEY (ParentID) REFERENCES ParentCascade(ParentID) ON DELETE CASCADE ON UPDATE CASCADE; +GO + +ALTER TABLE ChildSetNull ADD CONSTRAINT FK_ChildSetNull_Parent FOREIGN KEY (ParentID) REFERENCES ParentSetNull(ParentID) ON DELETE SET NULL ON UPDATE SET NULL; +GO + +ALTER TABLE ChildSetDefault ADD CONSTRAINT FK_ChildSetDefault_Parent FOREIGN KEY (ParentID) REFERENCES ParentSetDefault(ParentID) ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; +GO + +INSERT INTO ParentNoAction (ParentID, ParentName) VALUES (1, 'ParentNoAction1'), (2, 'ParentNoAction2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ParentCascade (ParentID, ParentName) VALUES (1, 'ParentCascade1'), (2, 'ParentCascade2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ParentSetNull (ParentID, ParentName) VALUES (1, 'ParentSetNull1'), (2, 'ParentSetNull2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ParentSetDefault (ParentID, ParentName) VALUES (1, 'ParentSetDefault1'), (2, 'ParentSetDefault2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ChildNoAction (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildNoAction1'), (2, 2, 'ChildNoAction2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ChildCascade (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildCascade1'), (2, 2, 'ChildCascade2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ChildSetNull (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildSetNull1'), (2, 2, 'ChildSetNull2'); +GO +~~ROW COUNT: 2~~ + + +INSERT INTO ChildSetDefault (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildSetDefault1'), (2, 2, 'ChildSetDefault2'); +GO +~~ROW COUNT: 2~~ + diff --git a/test/JDBC/expected/fk_trigger_temp-vu-verify.out b/test/JDBC/expected/fk_trigger_temp-vu-verify.out new file mode 100644 index 0000000000..3dccc8a80e --- /dev/null +++ b/test/JDBC/expected/fk_trigger_temp-vu-verify.out @@ -0,0 +1,461 @@ +-- tsql user=jdbc_user password=12345678 +-- Case 1: Original repro issue +INSERT INTO [dbo].[orderitem] (fkorder, screatedby) VALUES(25001000, 'test'); +GO +~~ROW COUNT: 1~~ + + +INSERT INTO [dbo].[orderitem] (fkorder, screatedby) VALUES(25001000, 'test'); +GO +~~ROW COUNT: 1~~ + + +-- tsql user=jdbc_user password=12345678 + +-- Case 2: Trigger Functionality with Table Variables +CREATE TRIGGER tr_Child_Insert ON Child AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempParents TABLE (ID INT); + INSERT INTO @TempParents (ID) + SELECT DISTINCT ParentID FROM inserted; + IF EXISTS ( + SELECT 1 FROM @TempParents t + LEFT JOIN Parent p ON t.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('One or more parents do not exist', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Child VALUES (1, 1); -- Should succeed +GO +~~ROW COUNT: 1~~ + + +INSERT INTO Child VALUES (2, 999); -- Should fail +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "child" violates foreign key constraint "fk_child_parent")~~ + + +-- tsql user=jdbc_user password=12345678 + + +-- Case 3: Trigger Functionality with Temporary Tables +CREATE TRIGGER tr_Child_Update ON Child AFTER UPDATE AS +BEGIN + SET NOCOUNT ON; + IF UPDATE(ParentID) + BEGIN + CREATE TABLE #UpdatedParents (ID INT); + INSERT INTO #UpdatedParents (ID) + SELECT DISTINCT ParentID FROM inserted; + IF EXISTS ( + SELECT 1 FROM #UpdatedParents u + LEFT JOIN Parent p ON u.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid ParentID', 16, 1); + ROLLBACK TRANSACTION; + END + DROP TABLE #UpdatedParents; + END +END; +GO + +UPDATE Child SET ParentID = 2 WHERE ID = 1; -- Should succeed +GO +~~ROW COUNT: 1~~ + + +UPDATE Child SET ParentID = 999 WHERE ID = 1; -- Should fail +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "child" violates foreign key constraint "fk_child_parent")~~ + + +-- tsql user=jdbc_user password=12345678 + +-- Case 4: Complex Trigger Scenarios +CREATE TRIGGER tr_Parent_Insert ON Parent AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempGrandParents TABLE (ID INT); + INSERT INTO @TempGrandParents (ID) + SELECT DISTINCT GrandParentID FROM inserted; + IF EXISTS ( + SELECT 1 FROM @TempGrandParents t + LEFT JOIN GrandParent gp ON t.ID = gp.ID + WHERE gp.ID IS NULL + ) + BEGIN + RAISERROR ('GrandParent does not exist', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Parent VALUES (3, 1); -- Should succeed +GO +~~ROW COUNT: 1~~ + + +INSERT INTO Parent VALUES (4, 999); -- Should fail +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "parent" violates foreign key constraint "fk_parent_grandparent")~~ + + +-- tsql user=jdbc_user password=12345678 + +-- Case 5: NULL test +CREATE TRIGGER tr_Child_NullHandling ON Child AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @NullTemp TABLE (ID INT); + INSERT INTO @NullTemp (ID) + SELECT ParentID FROM inserted WHERE ParentID IS NOT NULL + UNION ALL + SELECT NULL; + IF EXISTS ( + SELECT 1 FROM @NullTemp t + LEFT JOIN Parent p ON t.ID = p.ID + WHERE (p.ID IS NULL AND t.ID IS NOT NULL) OR t.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid or NULL ParentID', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Child VALUES (1000, NULL); -- Should fail +GO +~~ERROR (Code: 50000)~~ + +~~ERROR (Message: One or more parents do not exist)~~ + + +-- tsql user=jdbc_user password=12345678 + +-- Case 6: Nesting test +CREATE TRIGGER tr_Level3_Insert ON Level3 AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @Temp3 TABLE (ID INT); + INSERT INTO @Temp3 (ID) + SELECT DISTINCT Level2ID FROM inserted; + IF EXISTS ( + SELECT 1 FROM @Temp3 t + LEFT JOIN Level2 l2 ON t.ID = l2.ID + WHERE l2.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid Level2ID', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Level3 VALUES (1, 1); -- Should succeed +GO +~~ROW COUNT: 1~~ + + +INSERT INTO Level3 VALUES (2, 999); -- Should fail +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "level3" violates foreign key constraint "fk_level3_level2")~~ + + +-- tsql user=jdbc_user password=12345678 + +-- Case 7: Special Characters support test +CREATE TRIGGER tr_SpecialChar_Insert ON [Child#Table] AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @SpecialTemp TABLE (ID INT); + INSERT INTO @SpecialTemp (ID) + SELECT DISTINCT ParentID FROM inserted; + IF EXISTS ( + SELECT 1 FROM @SpecialTemp t + LEFT JOIN [Parent@Table] p ON t.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid ParentID in special character tables', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO [Child#Table] VALUES (1, 1); -- Should succeed +GO +~~ROW COUNT: 1~~ + + +INSERT INTO [Child#Table] VALUES (2, 999); -- Should fail +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "child#table" violates foreign key constraint "fk_childtable_parenttable")~~ + + +-- tsql user=jdbc_user password=12345678 +-- Case 8: Unique constraints +-- Trigger with unique constraint check +CREATE TRIGGER tr_UniqueChild_Insert ON UniqueChild AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempUnique TABLE ( + ParentID INT, + UniqueValue VARCHAR(50) + ); + + INSERT INTO @TempUnique (ParentID, UniqueValue) + SELECT i.ParentID, p.UniqueValue + FROM inserted i + JOIN UniqueParent p ON i.ParentID = p.ID; + + IF EXISTS ( + SELECT 1 FROM @TempUnique t + JOIN UniqueChild c ON t.UniqueValue = c.UniqueChildValue + WHERE c.ID NOT IN (SELECT ID FROM inserted) + ) + BEGIN + RAISERROR ('Unique constraint violation', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (1, 1, 'Child1'); +GO +~~ROW COUNT: 1~~ + + +-- Should fail (unique constraint violation) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (2, 2, 'Child1'); +GO +~~ERROR (Code: 2627)~~ + +~~ERROR (Message: duplicate key value violates unique constraint "uniquechild_uniquechildvalue_key")~~ + + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (2, 2, 'Child2'); +GO +~~ROW COUNT: 1~~ + + +-- tsql user=jdbc_user password=12345678 +-- Trigger with temporary table and unique constraint +CREATE TRIGGER tr_UniqueChild_Update ON UniqueChild AFTER UPDATE AS +BEGIN + SET NOCOUNT ON; + IF UPDATE(UniqueChildValue) + BEGIN + CREATE TABLE #UpdatedUnique ( + ID INT, + NewValue VARCHAR(50) + ); + + INSERT INTO #UpdatedUnique (ID, NewValue) + SELECT i.ID, i.UniqueChildValue + FROM inserted i; + + IF EXISTS ( + SELECT 1 FROM #UpdatedUnique u + JOIN UniqueChild c ON u.NewValue = c.UniqueChildValue + WHERE c.ID <> u.ID + ) + BEGIN + RAISERROR ('Update violates unique constraint', 16, 1); + ROLLBACK TRANSACTION; + END + + DROP TABLE #UpdatedUnique; + END +END; +GO + +-- Should succeed +UPDATE UniqueChild SET UniqueChildValue = 'UpdatedChild1' WHERE ID = 1; +GO +~~ROW COUNT: 1~~ + + +-- Should fail (unique constraint violation) +UPDATE UniqueChild SET UniqueChildValue = 'UpdatedChild1' WHERE ID = 2; +GO +~~ERROR (Code: 2627)~~ + +~~ERROR (Message: duplicate key value violates unique constraint "uniquechild_uniquechildvalue_key")~~ + + +-- tsql user=jdbc_user password=12345678 +-- Complex trigger with multiple unique constraints +CREATE TRIGGER tr_UniqueChild_ComplexInsert ON UniqueChild AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempComplex TABLE ( + ID INT, + ParentID INT, + ParentUniqueValue VARCHAR(50), + ChildUniqueValue VARCHAR(50) + ); + + INSERT INTO @TempComplex (ID, ParentID, ParentUniqueValue, ChildUniqueValue) + SELECT i.ID, i.ParentID, p.UniqueValue, i.UniqueChildValue + FROM inserted i + JOIN UniqueParent p ON i.ParentID = p.ID; + + IF EXISTS ( + SELECT 1 FROM @TempComplex t + WHERE t.ParentUniqueValue = t.ChildUniqueValue + ) + BEGIN + RAISERROR ('Child value cannot be the same as parent unique value', 16, 1); + ROLLBACK TRANSACTION; + END + + IF EXISTS ( + SELECT 1 FROM @TempComplex t + GROUP BY t.ChildUniqueValue + HAVING COUNT(*) > 1 + ) + BEGIN + RAISERROR ('Duplicate child unique values in batch insert', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (3, 2, 'Child3'); +GO +~~ROW COUNT: 1~~ + + +-- Should fail (child value same as parent unique value) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (4, 1, 'Parent1'); +GO +~~ERROR (Code: 50000)~~ + +~~ERROR (Message: Child value cannot be the same as parent unique value)~~ + + +-- Should fail (duplicate child unique values in batch insert) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) +VALUES (5, 1, 'Child5'), (6, 2, 'Child5'); +GO +~~ERROR (Code: 2627)~~ + +~~ERROR (Message: duplicate key value violates unique constraint "uniquechild_uniquechildvalue_key")~~ + + +-- tsql user=jdbc_user password=12345678 +-- Case 9: DELETE/UPDATE NO ACTION +-- should fail (operation conflicts with the REFERENCE constraint) +DELETE FROM ParentNoAction WHERE ParentID = 1; +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: update or delete on table "parentnoaction" violates foreign key constraint "fk_childnoaction_parent" on table "childnoaction")~~ + + +-- should fail (operation conflicts with the REFERENCE constraint) +UPDATE ParentNoAction SET ParentID = 3 WHERE ParentID = 1; +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: update or delete on table "parentnoaction" violates foreign key constraint "fk_childnoaction_parent" on table "childnoaction")~~ + + +-- tsql user=jdbc_user password=12345678 +-- Case 10: DELETE/UPDATE CASCADE +DELETE FROM ParentCascade WHERE ParentID = 1; +GO +~~ROW COUNT: 1~~ + + +-- (All child rows with ParentID = 1 should be deleted) +SELECT COUNT(*) FROM ChildCascade WHERE ParentID = 1; +GO +~~START~~ +int +0 +~~END~~ + + +UPDATE ParentCascade SET ParentID = 3 WHERE ParentID = 2; +GO +~~ROW COUNT: 1~~ + + +-- (The child row should have its ParentID updated from 2 to 3, matching the update in the parent table.) +SELECT COUNT(*) FROM ChildCascade WHERE ParentID = 3 +GO +~~START~~ +int +1 +~~END~~ + + +-- tsql user=jdbc_user password=12345678 +-- Case 11: DELETE/UPDATE SET NULL +DELETE FROM ParentSetNull WHERE ParentID = 1; +GO +~~ROW COUNT: 1~~ + + +-- (One child row should have its ParentID set to NULL after the corresponding parent row is deleted.) +SELECT COUNT(*) FROM ChildSetNull WHERE ParentID IS NULL +GO +~~START~~ +int +1 +~~END~~ + + +UPDATE ParentSetNull SET ParentID = 3 WHERE ParentID = 2; +GO +~~ROW COUNT: 1~~ + + +-- (Both child rows should now have NULL ParentIDs. One from the previous DELETE test, and one from this UPDATE test.) +SELECT COUNT(*) FROM ChildSetNull WHERE ParentID IS NULL; +GO +~~START~~ +int +2 +~~END~~ + + +-- tsql user=jdbc_user password=12345678 +-- Case 12: DELETE/UPDATE SET DEFAULT +-- should fail (operation conflicts with the REFERENCE constraint) +DELETE FROM ParentSetDefault WHERE ParentID = 1; +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "childsetdefault" violates foreign key constraint "fk_childsetdefault_parent")~~ + + +-- should fail (operation conflicts with the REFERENCE constraint) +UPDATE ParentSetDefault SET ParentID = 3 WHERE ParentID = 2; +GO +~~ERROR (Code: 547)~~ + +~~ERROR (Message: insert or update on table "childsetdefault" violates foreign key constraint "fk_childsetdefault_parent")~~ + diff --git a/test/JDBC/input/fk_trigger_temp-vu-cleanup.mix b/test/JDBC/input/fk_trigger_temp-vu-cleanup.mix new file mode 100644 index 0000000000..80f02923fd --- /dev/null +++ b/test/JDBC/input/fk_trigger_temp-vu-cleanup.mix @@ -0,0 +1,50 @@ +-- triggers +DROP TRIGGER IF EXISTS tr_SpecialChar_Insert +DROP TRIGGER IF EXISTS tr_Child_CaseInsensitive +DROP TRIGGER IF EXISTS tr_Level3_Insert +DROP TRIGGER IF EXISTS tr_Child_NullHandling +DROP TRIGGER IF EXISTS tr_Parent_Insert +DROP TRIGGER IF EXISTS tr_Child_Update +DROP TRIGGER IF EXISTS tr_Child_Insert +DROP TRIGGER IF EXISTS [trg_i_COD] +DROP TRIGGER IF EXISTS tr_UniqueChild_Insert; +DROP TRIGGER IF EXISTS tr_UniqueChild_Update; +DROP TRIGGER IF EXISTS tr_UniqueChild_ComplexInsert; +GO + +-- constraints +ALTER TABLE UniqueChild DROP CONSTRAINT IF EXISTS FK_UniqueChild_UniqueParent; +ALTER TABLE ChildNoAction DROP CONSTRAINT IF EXISTS FK_ChildNoAction_Parent; +ALTER TABLE ChildCascade DROP CONSTRAINT IF EXISTS FK_ChildCascade_Parent; +ALTER TABLE ChildSetNull DROP CONSTRAINT IF EXISTS FK_ChildSetNull_Parent; +ALTER TABLE ChildSetDefault DROP CONSTRAINT IF EXISTS FK_ChildSetDefault_Parent; +ALTER TABLE [dbo].[OrderItem] DROP CONSTRAINT IF EXISTS [FK_OrderItem_Order]; +ALTER TABLE [dbo].[Parent] DROP CONSTRAINT IF EXISTS [FK_Parent_GrandParent]; +ALTER TABLE [dbo].[Child] DROP CONSTRAINT IF EXISTS [FK_Child_Parent]; +ALTER TABLE [dbo].[Child#Table] DROP CONSTRAINT IF EXISTS [FK_ChildTable_ParentTable]; +ALTER TABLE [dbo].[Level2] DROP CONSTRAINT IF EXISTS [FK_Level2_Level1]; +ALTER TABLE [dbo].[Level3] DROP CONSTRAINT IF EXISTS [FK_Level3_Level2]; +GO + +-- tables +DROP TABLE IF EXISTS ChildNoAction +DROP TABLE IF EXISTS ChildCascade +DROP TABLE IF EXISTS ChildSetNull +DROP TABLE IF EXISTS ChildSetDefault +DROP TABLE IF EXISTS ParentNoAction +DROP TABLE IF EXISTS ParentCascade +DROP TABLE IF EXISTS ParentSetNull +DROP TABLE IF EXISTS ParentSetDefault +DROP TABLE IF EXISTS Level3 +DROP TABLE IF EXISTS Level2 +DROP TABLE IF EXISTS Level1 +DROP TABLE IF EXISTS [Child#Table] +DROP TABLE IF EXISTS [Parent@Table] +DROP TABLE IF EXISTS Child +DROP TABLE IF EXISTS Parent +DROP TABLE IF EXISTS GrandParent +DROP TABLE IF EXISTS [dbo].[OrderItem] +DROP TABLE IF EXISTS [order] +DROP TABLE IF EXISTS UniqueChild; +DROP TABLE IF EXISTS UniqueParent; +GO \ No newline at end of file diff --git a/test/JDBC/input/fk_trigger_temp-vu-prepare.mix b/test/JDBC/input/fk_trigger_temp-vu-prepare.mix new file mode 100644 index 0000000000..b961f44b36 --- /dev/null +++ b/test/JDBC/input/fk_trigger_temp-vu-prepare.mix @@ -0,0 +1,216 @@ +USE MASTER; +GO + +CREATE TABLE [order] ( + pkorder INT IDENTITY(25001000,1) PRIMARY KEY, + screatedby sys.varchar(255) +); +GO + +CREATE TABLE orderitem ( + pkorderitem INT IDENTITY(1,1) PRIMARY KEY, + fkorder integer, + screatedby sys.varchar(255) +); +GO + +ALTER TABLE [dbo].[OrderItem] ADD CONSTRAINT [FK_OrderItem_Order] FOREIGN KEY([fkOrder])REFERENCES [dbo].[Order] ([pkOrder]); +GO + +CREATE TRIGGER [trg_i_COD] ON [dbo].[OrderItem] + AFTER INSERT +AS +BEGIN +SET NOCOUNT ON ; + + DECLARE @HasMoreRow BIT , + @pkOrderItem INT , + @IsExpedit BIT , + @IsShippingItem BIT , + @IsPackage BIT , + @IsAddOn BIT , + @IsCrossSell BIT , + @ExpeditePackageBitValue INT , + @PackageRelationshipType INT, + @ShippingRelationshipType INT , + @AddOnRelationshipType INT , + @CrossSellRelationshipType INT +DECLARE @OrderItemList TABLE + ( + pkOrderItem INT NOT NULL , + IsUsed BIT DEFAULT ( 0 )/*REWRITTEN*/ , /**/ PRIMARY KEY ( pkOrderItem ) + ) + + + INSERT INTO @OrderItemList + ( pkOrderItem ) + SELECT pkOrderItem + FROM inserted + + + + SELECT TOP 1 + @pkOrderItem = pkOrderItem , + @hasMoreRow = 1 + FROM @OrderItemList + WHERE IsUsed = 0 + END +GO + +INSERT INTO [dbo].[order] (sCreatedBy) VALUES('test'); +GO + +INSERT INTO [dbo].[orderItem] (fkOrder, sCreatedBy) VALUES(25001000, 'test'); +GO + +-- Create base tables +CREATE TABLE GrandParent (ID INT PRIMARY KEY); +GO + +CREATE TABLE Parent ( + ID INT PRIMARY KEY, + GrandParentID INT +); +GO + +ALTER TABLE [dbo].[Parent] ADD CONSTRAINT [FK_Parent_GrandParent] FOREIGN KEY ([GrandParentID]) REFERENCES [dbo].[GrandParent] ([ID]); +GO + +CREATE TABLE Child ( + ID INT PRIMARY KEY, + ParentID INT +); +GO + +ALTER TABLE [dbo].[Child] ADD CONSTRAINT [FK_Child_Parent] FOREIGN KEY ([ParentID]) REFERENCES [dbo].[Parent] ([ID]); +GO + +-- Create special character tables +CREATE TABLE [Parent@Table] (ID INT PRIMARY KEY); +GO + +CREATE TABLE [Child#Table] ( + ID INT PRIMARY KEY, + ParentID INT +); +GO + +ALTER TABLE [dbo].[Child#Table] ADD CONSTRAINT [FK_ChildTable_ParentTable] FOREIGN KEY ([ParentID]) REFERENCES [dbo].[Parent@Table] ([ID]); +GO + +-- Insert some initial data +INSERT INTO GrandParent VALUES (1), (2); +GO + +INSERT INTO Parent VALUES (1, 1), (2, 2); +GO + +INSERT INTO [Parent@Table] VALUES (1), (2); +GO + +-- Create multi-level tables for nesting tests +CREATE TABLE Level1 (ID INT PRIMARY KEY); +GO + +CREATE TABLE Level2 ( + ID INT PRIMARY KEY, + Level1ID INT +); +GO + +ALTER TABLE [dbo].[Level2] ADD CONSTRAINT [FK_Level2_Level1] FOREIGN KEY ([Level1ID]) REFERENCES [dbo].[Level1] ([ID]); +GO + +CREATE TABLE Level3 ( + ID INT PRIMARY KEY, + Level2ID INT +); +GO + +ALTER TABLE [dbo].[Level3] ADD CONSTRAINT [FK_Level3_Level2] FOREIGN KEY ([Level2ID]) REFERENCES [dbo].[Level2] ([ID]); +GO + +INSERT INTO Level1 VALUES (1), (2); +GO + +INSERT INTO Level2 VALUES (1, 1), (2, 2); +GO + +CREATE TABLE UniqueParent ( + ID INT PRIMARY KEY, + UniqueValue VARCHAR(50) UNIQUE +); +GO + +CREATE TABLE UniqueChild ( + ID INT PRIMARY KEY, + ParentID INT, + UniqueChildValue VARCHAR(50) UNIQUE +); +GO + +ALTER TABLE UniqueChild ADD CONSTRAINT FK_UniqueChild_UniqueParent FOREIGN KEY (ParentID) REFERENCES UniqueParent(ID); +GO + +INSERT INTO UniqueParent (ID, UniqueValue) VALUES (1, 'Parent1'), (2, 'Parent2'); +GO + +CREATE TABLE ParentNoAction (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentCascade (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentSetNull (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ParentSetDefault (ParentID INT PRIMARY KEY, ParentName NVARCHAR(50)); +GO + +CREATE TABLE ChildNoAction (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildCascade (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildSetNull (ChildID INT PRIMARY KEY, ParentID INT, ChildName NVARCHAR(50)); +GO + +CREATE TABLE ChildSetDefault (ChildID INT PRIMARY KEY, ParentID INT DEFAULT 0, ChildName NVARCHAR(50)); +GO + +ALTER TABLE ChildNoAction ADD CONSTRAINT FK_ChildNoAction_Parent FOREIGN KEY (ParentID) REFERENCES ParentNoAction(ParentID); +GO + +ALTER TABLE ChildCascade ADD CONSTRAINT FK_ChildCascade_Parent FOREIGN KEY (ParentID) REFERENCES ParentCascade(ParentID) ON DELETE CASCADE ON UPDATE CASCADE; +GO + +ALTER TABLE ChildSetNull ADD CONSTRAINT FK_ChildSetNull_Parent FOREIGN KEY (ParentID) REFERENCES ParentSetNull(ParentID) ON DELETE SET NULL ON UPDATE SET NULL; +GO + +ALTER TABLE ChildSetDefault ADD CONSTRAINT FK_ChildSetDefault_Parent FOREIGN KEY (ParentID) REFERENCES ParentSetDefault(ParentID) ON DELETE SET DEFAULT ON UPDATE SET DEFAULT; +GO + +INSERT INTO ParentNoAction (ParentID, ParentName) VALUES (1, 'ParentNoAction1'), (2, 'ParentNoAction2'); +GO + +INSERT INTO ParentCascade (ParentID, ParentName) VALUES (1, 'ParentCascade1'), (2, 'ParentCascade2'); +GO + +INSERT INTO ParentSetNull (ParentID, ParentName) VALUES (1, 'ParentSetNull1'), (2, 'ParentSetNull2'); +GO + +INSERT INTO ParentSetDefault (ParentID, ParentName) VALUES (1, 'ParentSetDefault1'), (2, 'ParentSetDefault2'); +GO + +INSERT INTO ChildNoAction (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildNoAction1'), (2, 2, 'ChildNoAction2'); +GO + +INSERT INTO ChildCascade (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildCascade1'), (2, 2, 'ChildCascade2'); +GO + +INSERT INTO ChildSetNull (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildSetNull1'), (2, 2, 'ChildSetNull2'); +GO + +INSERT INTO ChildSetDefault (ChildID, ParentID, ChildName) VALUES (1, 1, 'ChildSetDefault1'), (2, 2, 'ChildSetDefault2'); +GO \ No newline at end of file diff --git a/test/JDBC/input/fk_trigger_temp-vu-verify.mix b/test/JDBC/input/fk_trigger_temp-vu-verify.mix new file mode 100644 index 0000000000..2795c428e5 --- /dev/null +++ b/test/JDBC/input/fk_trigger_temp-vu-verify.mix @@ -0,0 +1,355 @@ +-- tsql user=jdbc_user password=12345678 +-- Case 1: Original repro issue +INSERT INTO [dbo].[orderitem] (fkorder, screatedby) VALUES(25001000, 'test'); +GO + +INSERT INTO [dbo].[orderitem] (fkorder, screatedby) VALUES(25001000, 'test'); +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 2: Trigger Functionality with Table Variables +CREATE TRIGGER tr_Child_Insert ON Child AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempParents TABLE (ID INT); + INSERT INTO @TempParents (ID) + SELECT DISTINCT ParentID FROM inserted; + + IF EXISTS ( + SELECT 1 FROM @TempParents t + LEFT JOIN Parent p ON t.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('One or more parents do not exist', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Child VALUES (1, 1); -- Should succeed +GO + +INSERT INTO Child VALUES (2, 999); -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 3: Trigger Functionality with Temporary Tables +CREATE TRIGGER tr_Child_Update ON Child AFTER UPDATE AS +BEGIN + SET NOCOUNT ON; + IF UPDATE(ParentID) + BEGIN + CREATE TABLE #UpdatedParents (ID INT); + INSERT INTO #UpdatedParents (ID) + SELECT DISTINCT ParentID FROM inserted; + + IF EXISTS ( + SELECT 1 FROM #UpdatedParents u + LEFT JOIN Parent p ON u.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid ParentID', 16, 1); + ROLLBACK TRANSACTION; + END + + DROP TABLE #UpdatedParents; + END +END; +GO + +UPDATE Child SET ParentID = 2 WHERE ID = 1; -- Should succeed +GO + +UPDATE Child SET ParentID = 999 WHERE ID = 1; -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 4: Complex Trigger Scenarios +CREATE TRIGGER tr_Parent_Insert ON Parent AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempGrandParents TABLE (ID INT); + INSERT INTO @TempGrandParents (ID) + SELECT DISTINCT GrandParentID FROM inserted; + + IF EXISTS ( + SELECT 1 FROM @TempGrandParents t + LEFT JOIN GrandParent gp ON t.ID = gp.ID + WHERE gp.ID IS NULL + ) + BEGIN + RAISERROR ('GrandParent does not exist', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Parent VALUES (3, 1); -- Should succeed +GO + +INSERT INTO Parent VALUES (4, 999); -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 5: NULL test +CREATE TRIGGER tr_Child_NullHandling ON Child AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @NullTemp TABLE (ID INT); + INSERT INTO @NullTemp (ID) + SELECT ParentID FROM inserted WHERE ParentID IS NOT NULL + UNION ALL + SELECT NULL; + + IF EXISTS ( + SELECT 1 FROM @NullTemp t + LEFT JOIN Parent p ON t.ID = p.ID + WHERE (p.ID IS NULL AND t.ID IS NOT NULL) OR t.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid or NULL ParentID', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Child VALUES (1000, NULL); -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 6: Nesting test +CREATE TRIGGER tr_Level3_Insert ON Level3 AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @Temp3 TABLE (ID INT); + INSERT INTO @Temp3 (ID) + SELECT DISTINCT Level2ID FROM inserted; + + IF EXISTS ( + SELECT 1 FROM @Temp3 t + LEFT JOIN Level2 l2 ON t.ID = l2.ID + WHERE l2.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid Level2ID', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO Level3 VALUES (1, 1); -- Should succeed +GO + +INSERT INTO Level3 VALUES (2, 999); -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 7: Special Characters support test +CREATE TRIGGER tr_SpecialChar_Insert ON [Child#Table] AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @SpecialTemp TABLE (ID INT); + INSERT INTO @SpecialTemp (ID) + SELECT DISTINCT ParentID FROM inserted; + + IF EXISTS ( + SELECT 1 FROM @SpecialTemp t + LEFT JOIN [Parent@Table] p ON t.ID = p.ID + WHERE p.ID IS NULL + ) + BEGIN + RAISERROR ('Invalid ParentID in special character tables', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +INSERT INTO [Child#Table] VALUES (1, 1); -- Should succeed +GO + +INSERT INTO [Child#Table] VALUES (2, 999); -- Should fail +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 8: Unique constraints +-- Trigger with unique constraint check +CREATE TRIGGER tr_UniqueChild_Insert ON UniqueChild AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempUnique TABLE ( + ParentID INT, + UniqueValue VARCHAR(50) + ); + + INSERT INTO @TempUnique (ParentID, UniqueValue) + SELECT i.ParentID, p.UniqueValue + FROM inserted i + JOIN UniqueParent p ON i.ParentID = p.ID; + + IF EXISTS ( + SELECT 1 FROM @TempUnique t + JOIN UniqueChild c ON t.UniqueValue = c.UniqueChildValue + WHERE c.ID NOT IN (SELECT ID FROM inserted) + ) + BEGIN + RAISERROR ('Unique constraint violation', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (1, 1, 'Child1'); +GO + +-- Should fail (unique constraint violation) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (2, 2, 'Child1'); +GO + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (2, 2, 'Child2'); +GO + +-- tsql user=jdbc_user password=12345678 +-- Trigger with temporary table and unique constraint +CREATE TRIGGER tr_UniqueChild_Update ON UniqueChild AFTER UPDATE AS +BEGIN + SET NOCOUNT ON; + IF UPDATE(UniqueChildValue) + BEGIN + CREATE TABLE #UpdatedUnique ( + ID INT, + NewValue VARCHAR(50) + ); + + INSERT INTO #UpdatedUnique (ID, NewValue) + SELECT i.ID, i.UniqueChildValue + FROM inserted i; + + IF EXISTS ( + SELECT 1 FROM #UpdatedUnique u + JOIN UniqueChild c ON u.NewValue = c.UniqueChildValue + WHERE c.ID <> u.ID + ) + BEGIN + RAISERROR ('Update violates unique constraint', 16, 1); + ROLLBACK TRANSACTION; + END + + DROP TABLE #UpdatedUnique; + END +END; +GO + +-- Should succeed +UPDATE UniqueChild SET UniqueChildValue = 'UpdatedChild1' WHERE ID = 1; +GO + +-- Should fail (unique constraint violation) +UPDATE UniqueChild SET UniqueChildValue = 'UpdatedChild1' WHERE ID = 2; +GO + +-- tsql user=jdbc_user password=12345678 +-- Complex trigger with multiple unique constraints +CREATE TRIGGER tr_UniqueChild_ComplexInsert ON UniqueChild AFTER INSERT AS +BEGIN + SET NOCOUNT ON; + DECLARE @TempComplex TABLE ( + ID INT, + ParentID INT, + ParentUniqueValue VARCHAR(50), + ChildUniqueValue VARCHAR(50) + ); + + INSERT INTO @TempComplex (ID, ParentID, ParentUniqueValue, ChildUniqueValue) + SELECT i.ID, i.ParentID, p.UniqueValue, i.UniqueChildValue + FROM inserted i + JOIN UniqueParent p ON i.ParentID = p.ID; + + IF EXISTS ( + SELECT 1 FROM @TempComplex t + WHERE t.ParentUniqueValue = t.ChildUniqueValue + ) + BEGIN + RAISERROR ('Child value cannot be the same as parent unique value', 16, 1); + ROLLBACK TRANSACTION; + END + + IF EXISTS ( + SELECT 1 FROM @TempComplex t + GROUP BY t.ChildUniqueValue + HAVING COUNT(*) > 1 + ) + BEGIN + RAISERROR ('Duplicate child unique values in batch insert', 16, 1); + ROLLBACK TRANSACTION; + END +END; +GO + +-- Should succeed +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (3, 2, 'Child3'); +GO + +-- Should fail (child value same as parent unique value) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) VALUES (4, 1, 'Parent1'); +GO + +-- Should fail (duplicate child unique values in batch insert) +INSERT INTO UniqueChild (ID, ParentID, UniqueChildValue) +VALUES (5, 1, 'Child5'), (6, 2, 'Child5'); +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 9: DELETE/UPDATE NO ACTION +-- should fail (operation conflicts with the REFERENCE constraint) +DELETE FROM ParentNoAction WHERE ParentID = 1; +GO + +-- should fail (operation conflicts with the REFERENCE constraint) +UPDATE ParentNoAction SET ParentID = 3 WHERE ParentID = 1; +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 10: DELETE/UPDATE CASCADE +DELETE FROM ParentCascade WHERE ParentID = 1; +GO + +-- (All child rows with ParentID = 1 should be deleted) +SELECT COUNT(*) FROM ChildCascade WHERE ParentID = 1; +GO + +UPDATE ParentCascade SET ParentID = 3 WHERE ParentID = 2; +GO + +-- (The child row should have its ParentID updated from 2 to 3, matching the update in the parent table.) +SELECT COUNT(*) FROM ChildCascade WHERE ParentID = 3 +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 11: DELETE/UPDATE SET NULL +DELETE FROM ParentSetNull WHERE ParentID = 1; +GO + +-- (One child row should have its ParentID set to NULL after the corresponding parent row is deleted.) +SELECT COUNT(*) FROM ChildSetNull WHERE ParentID IS NULL +GO + +UPDATE ParentSetNull SET ParentID = 3 WHERE ParentID = 2; +GO + +-- (Both child rows should now have NULL ParentIDs. One from the previous DELETE test, and one from this UPDATE test.) +SELECT COUNT(*) FROM ChildSetNull WHERE ParentID IS NULL; +GO + +-- tsql user=jdbc_user password=12345678 +-- Case 12: DELETE/UPDATE SET DEFAULT +-- should fail (operation conflicts with the REFERENCE constraint) +DELETE FROM ParentSetDefault WHERE ParentID = 1; +GO + +-- should fail (operation conflicts with the REFERENCE constraint) +UPDATE ParentSetDefault SET ParentID = 3 WHERE ParentID = 2; +GO \ No newline at end of file diff --git a/test/JDBC/upgrade/latest/schedule b/test/JDBC/upgrade/latest/schedule index 12f59365e2..15165e591d 100644 --- a/test/JDBC/upgrade/latest/schedule +++ b/test/JDBC/upgrade/latest/schedule @@ -214,6 +214,7 @@ datediff dateadd datepart datetime2fromparts-after-15-2 +fk_trigger_temp forjson forjson-datatypes forjson-subquery