using Microsoft.SqlServer.TransactSql.ScriptDom; using SQLLinter.Common; using SQLLinter.Common.Helpers; namespace SQLLinter.Infrastructure.Rules; public class CountStarRule : BaseRuleVisitor, IRule { public override string Text => "COUNT(*) запрещен. Используйте COUNT(1) или COUNT()"; public override void Visit(FunctionCall node) { var functionName = node.FunctionName?.Value; if (functionName == null || !functionName.ToUpper().Equals("COUNT")) { return; } foreach (ScalarExpression param in node.Parameters) { var paramVisitor = new ParameterVisitor(); param.Accept(paramVisitor); if (paramVisitor.IsWildcard) { AddViolation(node); } } } public override void FixViolation(List fileLines, IRuleViolation ruleViolation, FileLineActions actions) { var node = FixHelpers.FindViolatingNode(fileLines, ruleViolation); foreach (ScalarExpression param in node.Parameters) { var paramVisitor = new ParameterVisitor(); param.Accept(paramVisitor); if (paramVisitor.IsWildcard) { var whileCard = paramVisitor.Expression; actions.RepaceInlineAt(whileCard.StartLine - 1, whileCard.StartColumn - 1, "1"); } } } private class ParameterVisitor : TSqlFragmentVisitor { public bool IsWildcard { get; private set; } public ColumnReferenceExpression Expression { get; private set; } public ParameterVisitor() { IsWildcard = false; } public override void Visit(ColumnReferenceExpression node) { IsWildcard = node.ColumnType.Equals(ColumnType.Wildcard); Expression = node; } } }