kreta/Kreta.DataAccess.Migrations/DBScripts/Database/auditlog/sp_Global_GenerateAsyncAuditTrigger.sql
2024-03-13 00:33:46 +01:00

230 lines
No EOL
8.7 KiB
Transact-SQL

DROP PROCEDURE IF EXISTS dev.sp_Global_GenerateAsyncAuditTrigger
GO
CREATE PROCEDURE dev.sp_Global_GenerateAsyncAuditTrigger
@tableName nvarchar(50)
,@disabled bit = 0
AS
DECLARE
@newColumnList nvarchar(max)
,@oldColumnList nvarchar(max)
,@SQL nvarchar(max)
,@ColumnIntezmenyId nvarchar(1000) = '0'
,@ColumnTanevId nvarchar(1000) = '0'
,@JoinKeys nvarchar(4000);
SELECT @newColumnList = ISNULL(@newColumnList + ', ', '') + 'i.' + COLUMN_NAME + N' AS ''new.' + COLUMN_NAME + '''',
@oldColumnList = ISNULL(@oldColumnList + ', ', '') + 'd.' + COLUMN_NAME + N' AS ''old.' + COLUMN_NAME + ''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @tableName
AND TABLE_SCHEMA = 'dbo'
AND DATA_TYPE NOT IN ('varbinary', 'binary')
AND COLUMN_NAME NOT IN ('SERIAL', 'LASTCHANGED', 'CREATED', 'ID', 'C_INTEZMENYID', 'C_ALINTEZMENYID', 'C_TANEVID', 'C_ALTANEVID');
SELECT @ColumnIntezmenyId = CASE WHEN TABLE_NAME = 'T_INTEZMENY' THEN 'i.ID' ELSE 'i.' + COLUMN_NAME END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo' AND COLUMN_NAME IN ('C_INTEZMENYID', 'C_ALINTEZMENYID');
SELECT @ColumnTanevId = CASE WHEN TABLE_NAME = 'T_TANEV' THEN 'i.ID' ELSE 'i.' + COLUMN_NAME END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @tableName AND TABLE_SCHEMA = 'dbo' AND COLUMN_NAME IN ('C_TANEVID', 'C_ALTANEVID');
SELECT @JoinKeys = COALESCE(@JoinKeys + ' AND ', '') + 'i.' + c.name + ' = d.' + c.name
FROM sys.key_constraints kc
INNER JOIN sys.index_columns ic ON ic.index_id = kc.unique_index_id AND ic.object_id = kc.parent_object_id
INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE kc.parent_object_id = object_id('dbo.' + @tableName)
and kc.type = 'PK'
ORDER BY ic.index_column_id ASC;
SET @SQL = '
CREATE OR ALTER TRIGGER [tr_AsyncAudit' + UPPER(SUBSTRING(@tableName, 3, 100)) + '] ON [' + @tableName + ']
WITH EXECUTE AS ''kreta_tech_user''
FOR INSERT, UPDATE, DELETE
AS
DECLARE @rowcount INT = @@ROWCOUNT;
DECLARE @json NVARCHAR(MAX);
DECLARE @key INT = 0;
DECLARE @limit INT = 1000;
DECLARE @action TINYINT = 0;
DECLARE @now NVARCHAR(20) = CONVERT(NVARCHAR(20), GETDATE(), 120);
DECLARE @handle UNIQUEIDENTIFIER;
DECLARE @userid INT;
SET NOCOUNT ON;
SET @action += CASE WHEN EXISTS(SELECT * FROM inserted) THEN 1 ELSE 0 END;
SET @action += CASE WHEN EXISTS(SELECT * FROM deleted) THEN 2 ELSE 0 END;
IF @rowcount = 0 SET @rowcount = (SELECT COUNT(*) FROM inserted);
IF @rowcount = 0 SET @rowcount = (SELECT COUNT(*) FROM deleted);
IF @rowcount = 0 RETURN;
SET @userid = TRY_CAST(SESSION_CONTEXT(N''USERID'') AS INT);
' + IIF(EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = 'MODIFIER'), 'IF ISNULL(@userid, 0) = 0 AND (UPDATE(MODIFIER) OR UPDATE(CREATOR)) SET @userid = (SELECT TOP 1 NULLIF(ISNULL(MODIFIER, CREATOR), 0) FROM inserted);', '') + '
IF @rowcount > @limit
BEGIN
SELECT TOP 0 * INTO #audit_trigger_inserted FROM inserted UNION ALL SELECT TOP 0 * FROM inserted;
SELECT TOP 0 * INTO #audit_trigger_deleted FROM deleted UNION ALL SELECT TOP 0 * FROM deleted;
ALTER TABLE #audit_trigger_inserted ADD TRIGGER_ADDED_KEY INT NOT NULL IDENTITY(1, 1);
ALTER TABLE #audit_trigger_deleted ADD TRIGGER_ADDED_KEY INT NOT NULL IDENTITY(1, 1);
INSERT INTO #audit_trigger_inserted SELECT * FROM inserted;
INSERT INTO #audit_trigger_deleted SELECT * FROM deleted;
ALTER TABLE #audit_trigger_inserted ADD PRIMARY KEY CLUSTERED(TRIGGER_ADDED_KEY);
ALTER TABLE #audit_trigger_deleted ADD PRIMARY KEY CLUSTERED(TRIGGER_ADDED_KEY);
-- ALTER TABLE #audit_trigger_inserted ADD UNIQUE NONCLUSTERED (TRIGGER_ADDED_KEY);
-- ALTER TABLE #audit_trigger_deleted ADD UNIQUE NONCLUSTERED (TRIGGER_ADDED_KEY);
END
BEGIN DIALOG CONVERSATION @handle
FROM SERVICE AuditService
TO SERVICE ''AuditService''
ON CONTRACT AuditContract
WITH ENCRYPTION = OFF, LIFETIME = 10000;
WHILE (1 = 1)
BEGIN
IF @action = 1 -- INSERT
IF @rowcount > @limit
BEGIN
SET @json = (
SELECT TOP (@limit)
i.ID AS ID,
' + @ColumnTanevId + ' AS TID,
' + @ColumnIntezmenyId + ' AS IID,
ISNULL(i.MODIFIER, i.CREATOR) AS [UID],
' + @newColumnList + '
FROM #audit_trigger_inserted i
WHERE i.TRIGGER_ADDED_KEY > @key
ORDER BY i.TRIGGER_ADDED_KEY ASC
FOR JSON PATH, INCLUDE_NULL_VALUES
)
SELECT TOP (@limit) @key = TRIGGER_ADDED_KEY FROM #audit_trigger_inserted WHERE TRIGGER_ADDED_KEY > @key ORDER BY TRIGGER_ADDED_KEY;
END
ELSE
SET @json = (
SELECT
i.ID AS ID,
' + @ColumnTanevId + ' AS TID,
' + @ColumnIntezmenyId + ' AS IID,
ISNULL(i.MODIFIER, i.CREATOR) AS [UID],
' + @newColumnList + '
FROM inserted i
FOR JSON PATH, INCLUDE_NULL_VALUES
)
IF @action = 2 -- DELETE
IF @rowcount > @limit
BEGIN
SET @json = (
SELECT TOP (@limit)
d.ID AS ID,
' + replace(@ColumnTanevId, 'i.', 'd.') + ' AS TID,
' + replace(@ColumnIntezmenyId, 'i.', 'd.') + ' AS IID,
ISNULL(d.MODIFIER, d.CREATOR) AS [UID],
' + @oldColumnList + '
FROM #audit_trigger_deleted d
WHERE d.TRIGGER_ADDED_KEY > @key
ORDER BY d.TRIGGER_ADDED_KEY ASC
FOR JSON PATH, INCLUDE_NULL_VALUES
)
SELECT TOP (@limit) @key = TRIGGER_ADDED_KEY FROM #audit_trigger_deleted WHERE TRIGGER_ADDED_KEY > @key ORDER BY TRIGGER_ADDED_KEY;
END
ELSE
SET @json = (
SELECT
d.ID AS ID,
' + replace(@ColumnTanevId, 'i.', 'd.') + ' AS TID,
' + replace(@ColumnIntezmenyId, 'i.', 'd.') + ' AS IID,
ISNULL(d.MODIFIER, d.CREATOR) AS [UID],
' + @oldColumnList + '
FROM deleted d
FOR JSON PATH, INCLUDE_NULL_VALUES
)
IF @action = 3 --UPDATE
IF @rowcount > @limit
BEGIN
SET @json = (
SELECT TOP (@limit)
i.ID AS ID,
' + @ColumnTanevId + ' AS TID,
' + @ColumnIntezmenyId + ' AS IID,
ISNULL(i.MODIFIER, i.CREATOR) AS [UID],
' + @oldColumnList + ',
' + @newColumnList + '
FROM #audit_trigger_inserted i
INNER JOIN #audit_trigger_deleted d ON i.TRIGGER_ADDED_KEY = d.TRIGGER_ADDED_KEY
WHERE i.TRIGGER_ADDED_KEY > @key
ORDER BY i.TRIGGER_ADDED_KEY ASC
FOR JSON PATH, INCLUDE_NULL_VALUES
)
SELECT TOP (@limit) @key = TRIGGER_ADDED_KEY FROM #audit_trigger_inserted WHERE TRIGGER_ADDED_KEY > @key ORDER BY TRIGGER_ADDED_KEY;
END
ELSE
SET @json = (
SELECT
i.ID AS ID,
' + @ColumnTanevId + ' AS TID,
' + @ColumnIntezmenyId + ' AS IID,
ISNULL(i.MODIFIER, i.CREATOR) AS [UID],
' + @oldColumnList + ',
' + @newColumnList + '
FROM inserted i
INNER JOIN deleted d ON ' + @JoinKeys + '
FOR JSON PATH, INCLUDE_NULL_VALUES
)
IF @json IS NULL BREAK;
SET @json = CONCAT(
''{'',
''"ENTITY":"' + @tableName + '",'',
''"REASON":"'', CHOOSE(@action, ''New'', ''Removed'', ''Modified''), ''",'',
''"DATETIME":"'', @now, ''",'',
''"ACTION":'', @action, '','',
''"HOST":"'', HOST_NAME(), ''",'',
''"LOGIN":"'', REPLACE(ORIGINAL_LOGIN(), ''\'', ''\\''), ''",'',
''"USERID":'', COALESCE(CAST(@userid AS VARCHAR(10)), ''null''), '','',
''"ROWCOUNT":'', @rowcount, '', '',
''"ROWS": '', @json,
''}'');
SEND ON CONVERSATION @handle MESSAGE TYPE AuditMessage (@json);
IF @rowcount <= @limit BREAK;
END
END CONVERSATION @handle;
'
-- SELECT @SQL
EXEC sys.sp_executesql @SQL;
IF @disabled = 1
BEGIN
SET @SQL = 'DISABLE TRIGGER [tr_AsyncAudit' + UPPER(SUBSTRING(@tableName, 3, 100)) + '] ON [' + @tableName + ']';
EXEC(@SQL);
END
GO