Object Manager
SQL Triggers
Overview of this chapter topics:
Trace Modification Trigger
Ask SQL Trigger
Block Database Conversion Trigger
Object View
Trace Modification Trigger
ALTER TRIGGER [dbo].[Object_TraceModifications_1200]
ON [dbo].[Object]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @SetupSQLCheckObjectLockType INTEGER = 0;
DECLARE @SkipSQLTrigger INTEGER = 0;
DECLARE @CheckObjectValid INTEGER = 0;
DECLARE @DatabaseLocked INTEGER = 0;
DECLARE @TraceModifications INTEGER = 0;
DECLARE @LockedBy NVARCHAR(100);
DECLARE @IsLocked INTEGER;
DECLARE @IsModification INTEGER;
DECLARE @CheckIsLocked INTEGER;
DECLARE @CalledFromRepository INTEGER;
DECLARE @ObjectType INTEGER = 0;
DECLARE @ObjectId INTEGER = 0;
DECLARE @ObjectName NVARCHAR(100);
DECLARE @ObjectDate DATETIME
DECLARE @ObjectTime DATETIME
DECLARE @ObjectTypeText NVARCHAR(100);
DECLARE @ObjectIdText NVARCHAR(100);
DECLARE @ObjectVersionList NVARCHAR(100);
DECLARE @Message NVARCHAR(100);
DECLARE @NoOfInserts INTEGER;
DECLARE @NoOfDeletes INTEGER;
DECLARE @NoOfModifies INTEGER;
DECLARE @Action INTEGER;
DECLARE @TokenNo INTEGER;
DECLARE @LockObjectAtSaving INTEGER;
DECLARE @Username NVARCHAR(100);
DECLARE @ShortUsername NVARCHAR(100);
DECLARE @LockedAdded INTEGER = 0;
DECLARE @ComputerName NVARCHAR(100);
DECLARE @IgnoreDatabaseLocked INTEGER = 0;
SET @Username = SYSTEM_USER;
SET @ShortUsername = UPPER(SYSTEM_USER);
SET @ComputerName = HOST_NAME();
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'OM - Expected Modification')
RETURN;
SELECT @Username = em.[User Id], @ShortUsername = UPPER(em.[User Id]), @ComputerName = em.[Computer Name]
FROM
[OM - Expected Modification] em,
(
SELECT [Type], [ID]
FROM inserted
UNION
SELECT [Type], [ID]
FROM deleted
) s
WHERE (em.[Object Type] = s.[Type] OR em.[Object Type] = 0)
AND (em.[Object No_] = s.[ID] OR em.[Object No_] = 0)
AND em.[Date Added] = CAST(CONVERT(VARCHAR(20), GETDATE(), 112) + ' 00:00:00' AS DATETIME)
AND em.[Time Added] > CAST('17540101 ' + CONVERT(VARCHAR(20), DATEADD(SECOND, -5, GETDATE()), 108) AS DATETIME);
IF (CHARINDEX('\', @ShortUsername) > 0)
SET @ShortUsername = SUBSTRING(@ShortUsername, CHARINDEX('\', @ShortUsername) + 1, 100);
SELECT TOP 1 @TraceModifications = [Boolean Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 3
AND [Setting] = 1
ORDER BY [Priority];
SELECT TOP 1 @SetupSQLCheckObjectLockType = [Integer Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 5
AND [Setting] = 3
ORDER BY [Priority];
SELECT TOP 1 @SkipSQLTrigger = [Boolean Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 9
AND [Setting] = 3
ORDER BY [Priority];
SELECT TOP 1 @IgnoreDatabaseLocked = [Boolean Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 9
AND [Setting] = 5
ORDER BY [Priority];
SELECT TOP 1 @LockObjectAtSaving = [Boolean Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 5
AND [Setting] = 4
ORDER BY [Priority];
SELECT TOP 1 @DatabaseLocked = [Integer Value]
FROM [OM - Setup Value]
WHERE [User Id] IN ('', @ShortUsername)
AND [Computer Name] IN ('', @ComputerName)
AND [Department] = 5
AND [Setting] = 6
ORDER BY [Priority];
IF @SkipSQLTrigger = 0
BEGIN
IF @DatabaseLocked = 1 OR (@DatabaseLocked = 2 AND @IgnoreDatabaseLocked = 0)
BEGIN
RAISERROR('Database is locked.', 16, 1);
ROLLBACK TRANSACTION;
END;
SELECT
@ObjectType = d.[Type],
@ObjectId = d.[ID],
@ObjectName = d.[Name],
@ObjectDate = d.[Date],
@ObjectTime = d.[Time],
@ObjectVersionList = d.[Version List]
FROM Deleted d
WHERE d.[Type] > 0;
IF @ObjectVersionList = '! CHECK OBJECT VALID !'
SET @CheckObjectValid = 1;
SELECT
@ObjectType = i.[Type],
@ObjectId = i.[ID],
@ObjectName = i.[Name],
@ObjectDate = i.[Date],
@ObjectTime = i.[Time],
@ObjectVersionList = i.[Version List]
FROM Inserted i
WHERE i.[Type] > 0;
IF @ObjectVersionList = '! CHECK OBJECT VALID !'
SET @CheckObjectValid = 1;
SET @CalledFromRepository = 0;
SELECT @CalledFromRepository = 1
FROM [OM - Repository Log] rl
WHERE rl.[Object Type] = @ObjectType
AND rl.[Object No_] = @ObjectId
AND rl.Status = 1;
IF @ObjectType > 0 AND (@ObjectId < 1000000000 OR @ObjectId >= 2000000000) AND @CalledFromRepository = 0 AND @CheckObjectValid = 0
BEGIN
SET @LockedBy = '';
SET @TokenNo = 0;
SET @IsLocked = 0;
SELECT
@LockedBy = ol.[Locked By],
@TokenNo = ol.[Token No_],
@IsLocked = 1
FROM [OM - Object Lock] ol
WHERE ol.[Object Type] = @ObjectType
AND ol.[Object No_] = @ObjectId;
SELECT @NoOfInserts = COUNT([Type]) FROM Inserted;
SELECT @NoOfDeletes = COUNT([Type]) FROM Deleted;
SELECT @NoOfModifies = COUNT(i.[Type])
FROM Inserted i
INNER JOIN Deleted d
ON i.[Type] = d.[Type] AND i.[ID] = d.[ID];
SET @IsModification = 0;
SET @CheckIsLocked = 0;
-- INSERT
IF @NoOfModifies = 0 AND @NoOfInserts > 0
BEGIN
SET @Action = 1;
SET @IsModification = 1;
END;
-- MODIFY
IF @NoOfModifies > 0
SET @Action = 2;
-- DELETE
IF @NoOfDeletes > 0 AND @NoOfInserts = 0
BEGIN
SET @Action = 3;
SET @IsModification = 1;
SET @CheckIsLocked = 1;
END;
-- RENAME
IF @NoOfModifies = 0 AND @NoOfDeletes > 0 AND @NoOfInserts > 0
BEGIN
SET @Action = 4
SET @IsModification = 1;
END;
-- MODIFY
IF @Action = 2
SELECT
@IsModification = 1,
@CheckIsLocked = 1
FROM Inserted i
INNER JOIN Deleted d
ON i.[Type] = d.[Type]
AND i.[ID] = d.[ID]
WHERE
(
i.[Date] <> d.[Date]
OR CONVERT(VARCHAR(20), i.[Time], 108) <> CONVERT(VARCHAR(20), d.[Time], 108)
OR i.[Name] <> d.[Name]
OR REPLACE(REPLACE(i.[Version List], ',', ''), '#', '') <>
REPLACE(REPLACE(d.[Version List], ',', ''), '#', '')
);
IF @SetupSQLCheckObjectLockType <> 0 AND @CheckIsLocked = 1 AND
UPPER(@LockedBy) <> UPPER(@Username) AND @LockedBy <> ''
BEGIN
SELECT
@ObjectTypeText =
CASE @ObjectType
WHEN 1 THEN 'Table'
WHEN 2 THEN 'Form'
WHEN 3 THEN 'Report'
WHEN 4 THEN 'Dataport'
WHEN 5 THEN 'Codeunit'
WHEN 6 THEN 'XMLport'
WHEN 7 THEN 'MenuSuite'
WHEN 8 THEN 'Page'
WHEN 9 THEN 'Query'
ELSE ''
END,
@ObjectIdText = @ObjectId;
SET @Message =
CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) +
'OBJECT MANAGER ERROR:' + CHAR(13) + CHAR(10) +
'Object %s %s - %s is locked by %s' + CHAR(13) + CHAR(10);
RAISERROR(@Message, 16, 1, @ObjectTypeText, @ObjectIdText, @ObjectName, @LockedBy);
ROLLBACK TRANSACTION;
END;
IF @LockObjectAtSaving = 1 AND @IsModification = 1 AND @LockedBy = '' AND @Action <> 4
BEGIN
IF EXISTS(
SELECT 1
FROM [OM - Repository Setup]
WHERE [Use Repository] = 1)
BEGIN
SET @Message =
CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) +
'OBJECT MANAGER ERROR:' + CHAR(13) + CHAR(10) +
'The option ''Lock Object at Saving'' cannot be ' +
'used in combination with repository' + CHAR(13) + CHAR(10);
RAISERROR(@Message, 16, 1);
ROLLBACK TRANSACTION;
END;
DELETE FROM [OM - Object Lock]
WHERE [Object Type] = @ObjectType
AND [Object No_] = @ObjectId;
INSERT INTO [OM - Object Lock]
(
[Object Type], [Object No_], [Locked By],
[Lock Date],
[Lock Time],
[Deleted], [Token No_], [Branch No_]
)
SELECT
@ObjectType, @ObjectId, @Username,
CAST(CONVERT(VARCHAR(20), GETDATE(), 112) + ' 00:00:00' AS DATETIME),
CAST('17540101 ' + CONVERT(VARCHAR(20), GETDATE(), 108) AS DATETIME),
0, 0, '';
UPDATE [Object]
SET [Locked] = 1,
[Locked By] = @Username
WHERE [Type] = @ObjectType
AND [ID] = @ObjectId
AND [Locked] = 0;
SET @IsLocked = 1;
SET @LockedAdded = 1;
SET @LockedBy = @Username;
END;
IF @SetupSQLCheckObjectLockType = 2 AND @CheckIsLocked = 1 AND @IsLocked = 0
BEGIN
SELECT
@ObjectTypeText =
CASE @ObjectType
WHEN 1 THEN 'Table'
WHEN 2 THEN 'Form'
WHEN 3 THEN 'Report'
WHEN 4 THEN 'Dataport'
WHEN 5 THEN 'Codeunit'
WHEN 6 THEN 'XMLport'
WHEN 7 THEN 'MenuSuite'
WHEN 8 THEN 'Page'
WHEN 9 THEN 'Query'
ELSE ''
END,
@ObjectIdText = @ObjectId;
SET @Message =
CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) +
'OBJECT MANAGER ERROR:' + CHAR(13) + CHAR(10) +
'Object %s %s - %s is not locked' + CHAR(13) + CHAR(10);
RAISERROR(@Message, 16, 1, @ObjectTypeText, @ObjectIdText, @ObjectName);
ROLLBACK TRANSACTION;
END;
IF @IsModification = 1 AND @TraceModifications = 1
INSERT INTO [OM - Modification]
(
[Object Type], [Object No_], [Object Name],
[Object Date], [Object Time],
[Status], [Inserted By],
[Insert Date],
[Insert Time],
[Assigned to Project No_], [Assigned By],
[Assign Date], [Assign Time], [Auto Assigned],
[Transport No_], [Object Date Time],
[Locked By], [Token No_], [Traced By SQL], [SQL Trigger], [SQL Status],
[System User], [Host Name]
)
SELECT
@ObjectType, @ObjectId, @ObjectName,
@ObjectDate, CAST('17540101 ' + CONVERT(VARCHAR(20), @ObjectTime, 108) AS DATETIME),
0, @ShortUsername,
CAST(CONVERT(VARCHAR(20), GETDATE(), 112) + ' 00:00:00' AS DATETIME),
CAST('17540101 ' + CONVERT(VARCHAR(20), GETDATE(), 108) AS DATETIME),
'', '',
CAST('17530101 00:00:00' AS DATETIME), CAST('17530101 00:00:00' AS DATETIME), 0,
'', CAST(CONVERT(VARCHAR(20), @ObjectDate, 112) + ' ' +
CONVERT(VARCHAR(20), @ObjectTime, 108) AS DATETIME),
@LockedBy, @TokenNo, 1, @Action, 1,
SUBSTRING(@ShortUsername, 1, 50), SUBSTRING(HOST_NAME(), 1, 50);
IF @Action = 1 OR @Action = 2
BEGIN
INSERT INTO [OM - Object Lock]
(
[Object Type], [Object No_], [Locked By],
[Lock Date],
[Lock Time],
[Deleted], [Token No_], [Branch No_]
)
SELECT
ob.[Type], ob.ID, ob.[Locked By],
CAST(CONVERT(VARCHAR(20), GETDATE(), 112) + ' 00:00:00' AS DATETIME),
CAST('17540101 ' + CONVERT(VARCHAR(20), GETDATE(), 108) AS DATETIME),
0, 0, ''
FROM Inserted ob
LEFT OUTER JOIN [OM - Object Lock] ol
ON ob.[Type] = ol.[Object Type]
AND ob.ID = ol.[Object No_]
WHERE (ob.Locked = 1 OR @LockedAdded = 1)
AND ol.[Object Type] IS NULL
AND ob.[Locked By] <> 'CheckSettings'
AND ob.[Type] > 0
GROUP BY ob.[Type], ob.ID, ob.[Locked By];
DELETE ol
FROM [OM - Object Lock] ol
INNER JOIN Inserted ob
ON ol.[Object Type] = ob.[Type]
AND ol.[Object No_] = ob.ID
WHERE (ob.Locked = 0 AND NOT @LockedAdded = 1)
AND ol.Deleted = 0;
END;
IF @Action = 3
DELETE ol
FROM [OM - Object Lock] ol
INNER JOIN Deleted ob
ON ol.[Object Type] = ob.[Type]
AND ol.[Object No_] = ob.ID
AND ol.Deleted = 0;
END;
END;
END;
Â
Ask SQL Trigger
ALTER TRIGGER [dbo].[OM_Ask_SQL_1301]
ON [dbo].[OM - Ask SQL]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE @Question INTEGER;
DECLARE @Answer NVARCHAR(100);
SELECT @Question = Question
FROM inserted;
SET @Answer = '';
IF @Question = 1
BEGIN
SET @Answer = '1301';
END;
IF @Question = 2
BEGIN
SET @Answer = '1';
DELETE FROM [OM - Where Used Status]
WHERE Question = 2;
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT ob.[Type], ob.ID, 2, 0
FROM [Object] ob
LEFT OUTER JOIN [OM - Known Object Export Error] ee
ON ob.[Type] = ee.[Object Type]
AND ob.ID = ee.[Object No_]
LEFT OUTER JOIN [OM - Where Used Object] wu
ON ob.[Type] = wu.[Object Type]
AND ob.ID = wu.[Object No_]
LEFT OUTER JOIN
(
SELECT ho2.[Object Type], ho2.[Object No_], MAX(ho2.[Entry No_]) [Entry No_]
FROM [OM - C_AL History Object] ho2
GROUP BY ho2.[Object Type], ho2.[Object No_]
) sho
ON ob.[Type] = sho.[Object Type]
AND ob.ID = sho.[Object No_]
LEFT OUTER JOIN [OM - C_AL History Object] ho
ON sho.[Entry No_] = ho.[Entry No_]
AND ob.[Type] = ho.[Object Type]
AND ob.ID = ho.[Object No_]
WHERE ob.[Type] <> 0
AND ee.[Object Type] IS NULL
AND
(
wu.[Object Type] IS NULL OR
ho.[Entry No_] IS NULL OR
REPLACE(REPLACE(REPLACE(ho.[Version List], ',', ''), '#', ''), 'LOCKED', '') <>
REPLACE(REPLACE(REPLACE(ob.[Version List], ',', ''), '#', ''), 'LOCKED', '') OR
ho.Modified <> ob.Modified OR
ho.[Object Name] <> ob.Name OR
ho.[Object Date] <> ob.Date OR
ABS(CAST(ho.[Object Time] AS FLOAT) - CAST(ob.[Time] AS FLOAT)) * 60 * 60 * 24 > 1 OR
wu.[Object Date] <> ob.Date OR
wu.[Object Time] <> ob.Time OR
wu.[Object Modified] <> ob.Modified
);
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT wu.[Object Type], wu.[Object No_], 2, 0
FROM [OM - Where Used Object] wu
LEFT OUTER JOIN [Object] ob
ON wu.[Object Type] = ob.[Type]
AND wu.[Object No_] = ob.ID
LEFT OUTER JOIN [OM - Extension Object] eo
ON wu.[Object Type] = eo.[Object Type]
AND wu.[Object No_] = eo.[Object No_]
WHERE wu.[Object No_] < 2000000000
AND ob.[Type] IS NULL
AND eo.[Object Type] IS NULL;
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT wu.[Object Type], wu.[Object No_], 2, 0
FROM [OM - Where Used Object] wu
LEFT OUTER JOIN [OM - Where Used Status] ws
ON wu.[Object Type] = ws.[Object Type]
AND wu.[Object No_] = ws.[Object No_]
AND ws.Question = 2
WHERE wu.[Object No_] < 2000000000
AND
(
wu.[C_AL Changed] = 1
OR wu.[Status] < 2
OR wu.[Version No_] < 701
)
AND ws.[Object Type] IS NULL;
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT eo.[Object Type], eo.[Object No_], 2, 0
FROM [OM - Extension Object] eo
LEFT OUTER JOIN [OM - Known Object Export Error] ee
ON eo.[Object Type] = ee.[Object Type]
AND eo.[Object No_] = ee.[Object No_]
LEFT OUTER JOIN [OM - Where Used Status] ws
ON eo.[Object Type] = ws.[Object Type]
AND eo.[Object No_] = ws.[Object No_]
AND ws.Question = 2
WHERE ee.[Object Type] IS NULL
AND eo.[Status] IN (1, 2)
AND ws.[Object Type] IS NULL;
SELECT TOP 1 @Answer = '0'
FROM [OM - Where Used Status]
WHERE Question = 2;
END;
IF @Question = 3
BEGIN
DECLARE @String NVARCHAR(250);
DECLARE @CaseSensitive INTEGER;
DELETE FROM [OM - Where Used Status]
WHERE Question = 3;
SELECT
@String = [Parameter 1],
@CaseSensitive = CONVERT(INTEGER, [Parameter 2])
FROM inserted;
IF @CaseSensitive = 1
BEGIN
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT 0, ho.[Entry No_], 3, CHARINDEX(@String COLLATE SQL_Latin1_General_CP1_CS_AS, CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), ho.[Source Code])))
FROM [OM - C_AL History Object] ho
INNER JOIN [OM - Where Used Status] wus
ON ho.[Entry No_] = wus.[Object No_]
AND wus.Question = 4;
END ELSE BEGIN
INSERT INTO [OM - Where Used Status] ([Object Type], [Object No_], Question, Answer)
SELECT 0, ho.[Entry No_], 3, CHARINDEX(@String COLLATE SQL_Latin1_General_CP1_CI_AS, CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), ho.[Source Code])))
FROM [OM - C_AL History Object] ho
INNER JOIN [OM - Where Used Status] wus
ON ho.[Entry No_] = wus.[Object No_]
AND wus.Question = 4;
END;
SET @Answer = '1';
END;
UPDATE [OM - Ask SQL] SET Answer = @Answer
FROM inserted i, [OM - Ask SQL] ASql
WHERE i.Question = ASql.Question;
END
Block Database Conversion Trigger
ALTER TRIGGER [dbo].[OM_Block_DB_Conversion_900]
ON [dbo].[$ndo$dbproperty]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @OtherDatabaseVersionNo INTEGER = 0;
DECLARE @Message NVARCHAR(100);
SELECT @OtherDatabaseVersionNo = 1
FROM Inserted i
INNER JOIN Deleted d
ON i.programid = d.programid
WHERE i.databaseversionno <> d.databaseversionno;
IF @OtherDatabaseVersionNo = 1
BEGIN
SET @Message =
CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) +
'OBJECT MANAGER ERROR:' + CHAR(13) + CHAR(10) +
'Database cannot be converted.' + CHAR(13) + CHAR(10) +
'Please first remove the Block Database Conversion trigger.' + CHAR(13) + CHAR(10);
RAISERROR(@Message, 16, 1);
ROLLBACK TRANSACTION;
END;
END
Block Database Conversion Trigger
Â
IDYN 2024