Files
SQLLint/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs

88 lines
3.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.SqlServer.TransactSql.ScriptDom;
using SQLLinter.Common;
using SQLLinter.Common.Helpers;
namespace SQLLinter.Infrastructure.Rules;
public class ProcedureLoggingRule : BaseRuleVisitor
{
public override string Text => "В процедурах обязательно логирование (@DebugLog, LABEL_FINISH): {0}";
public override void Visit(CreateProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
public override void Visit(CreateOrAlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
public override void Visit(AlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
private void check(TSqlStatement node, string name)
{
var tokens = node.ScriptTokenStream;
bool hasDebugLog = false;
bool hasLabelFinish = false;
foreach (var token in tokens)
{
if (token.Text is null) continue;
if (token.Text.Equals("@DebugLog", StringComparison.OrdinalIgnoreCase))
{
hasDebugLog = true;
}
else if (token.Text.Equals("LABEL_FINISH:", StringComparison.OrdinalIgnoreCase))
{
hasLabelFinish = true;
}
}
if (!hasDebugLog || !hasLabelFinish)
{
AddViolation(node, name);
}
}
}
public class ProcedureLoggingReturnRule : BaseRuleVisitor
{
public override string Text => "В процедурах с логированием RETURN запрещён: {0}";
public override void Visit(CreateProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
public override void Visit(CreateOrAlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
public override void Visit(AlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name));
private void check(TSqlStatement node, string name)
{
var tokens = node.ScriptTokenStream;
bool hasDebugLog = false;
bool hasLabelFinish = false;
bool hasReturn = false;
List<ReturnPosition> returnPositions = new();
foreach (var token in tokens)
{
if (token.Text is null) continue;
if (token.Text.Equals("@DebugLog", StringComparison.OrdinalIgnoreCase))
{
hasDebugLog = true;
}
else if (token.Text.Equals("LABEL_FINISH:", StringComparison.OrdinalIgnoreCase))
{
hasLabelFinish = true;
}
else if (token.Text.Equals("RETURN", StringComparison.OrdinalIgnoreCase))
{
hasReturn = true;
returnPositions.Add(new(Line: token.Line, Column: token.Column));
}
}
if ((hasDebugLog || hasLabelFinish) || hasReturn)
{
returnPositions.ForEach(t => AddViolation(Name, GetText(name), t.Line, t.Column));
}
}
private record ReturnPosition(int Line, int Column);
}