예제 #1
0
        /// <summary>
        /// Performs analysis and returns a list of problems detected
        /// </summary>
        /// <param name="ruleExecutionContext">Contains the schema model and model element to analyze</param>
        /// <returns>
        /// The problems detected by the rule in the given element
        /// </returns>
        public override IList <SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext)
        {
            var problems = new List <SqlRuleProblem>();
            var sqlObj   = ruleExecutionContext.ModelElement;

            if (sqlObj == null || sqlObj.IsWhiteListed())
            {
                return(problems);
            }

            var fragment = ruleExecutionContext.ScriptFragment.GetFragment(ProgrammingSchemaTypes);
            var visitor  = new UpdateVisitor();

            fragment.Accept(visitor);

            foreach (var stmt in visitor.NotIgnoredStatements(RuleId))
            {
                if (stmt.UpdateSpecification.WhereClause != null ||
                    !(stmt.UpdateSpecification.Target is NamedTableReference))
                {
                    continue;
                }

                var tableName = ((NamedTableReference)stmt.UpdateSpecification.Target).SchemaObject.Identifiers.Last().Value;

                if (stmt.UpdateSpecification.FromClause != null)
                {
                    var tableVisitor = new TableReferenceVisitor();
                    stmt.UpdateSpecification.FromClause.Accept(tableVisitor);

                    var table = tableVisitor.Statements.OfType <NamedTableReference>()
                                .FirstOrDefault(t => _comparer.Equals(t.Alias?.Value, tableName));
                    if (table != null)
                    {
                        tableName = table.SchemaObject.Identifiers.Last().Value;
                    }
                }
                if (!(tableName.StartsWith("#") || tableName.StartsWith("@")))
                {
                    problems.Add(new SqlRuleProblem(Message, sqlObj, stmt));
                }
            }

            return(problems);
        }
예제 #2
0
        /// <summary>
        /// Performs analysis and returns a list of problems detected
        /// </summary>
        /// <param name="ruleExecutionContext">Contains the schema model and model element to analyze</param>
        /// <returns>
        /// The problems detected by the rule in the given element
        /// </returns>
        public override IList <SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext)
        {
            var problems = new List <SqlRuleProblem>();
            var sqlObj   = ruleExecutionContext.ModelElement;
            var model    = ruleExecutionContext.SchemaModel;

            if (sqlObj == null || sqlObj.IsWhiteListed())
            {
                return(problems);
            }

            var fragment = ruleExecutionContext.ScriptFragment.GetFragment(ProgrammingSchemaTypes);

            var updateVisitor = new UpdateVisitor();

            fragment.Accept(updateVisitor);
            foreach (var update in updateVisitor.NotIgnoredStatements(RuleId))
            {
                if (!(update.UpdateSpecification.Target is NamedTableReference target) || target.GetName().Contains("#"))
                {
                    continue;
                }

                //we have an aliased table we need to find out what the real table is so we can look up its columns
                if (update.UpdateSpecification.FromClause != null)
                {
                    var namedTableVisitor = new NamedTableReferenceVisitor()
                    {
                        TypeFilter = ObjectTypeFilter.PermanentOnly
                    };
                    update.UpdateSpecification.FromClause.Accept(namedTableVisitor);

                    target = namedTableVisitor.Statements
                             .FirstOrDefault(t => _comparer.Equals(t.Alias?.Value, target.SchemaObject.Identifiers.LastOrDefault()?.Value));
                    if (target == null)
                    {
                        continue;
                    }
                }

                var targetSqlObj = model.GetObject(Table.TypeClass, target.GetObjectIdentifier(), DacQueryScopes.All);
                if (targetSqlObj == null)
                {
                    continue;
                }

                var pk = targetSqlObj.GetReferencing(PrimaryKeyConstraint.Host, DacQueryScopes.UserDefined).FirstOrDefault();
                if (pk == null)
                {
                    continue;
                }
                var primaryKeyColumns = pk.GetReferenced(PrimaryKeyConstraint.Columns, DacQueryScopes.All);

                var hasOffense = update.UpdateSpecification.SetClauses.OfType <AssignmentSetClause>().Any(setClause =>
                {
                    if (setClause.Column?.MultiPartIdentifier == null)
                    {
                        return(false);
                    }
                    return(primaryKeyColumns.Any(pkc => pkc.Name.CompareTo(setClause.Column?.MultiPartIdentifier) >= 5));
                });

                if (hasOffense)
                {
                    problems.Add(new SqlRuleProblem(Message, sqlObj, update));
                }
            }
            return(problems);
        }