Beispiel #1
0
        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(ProgrammingAndViewSchemaTypes);

            var whereClauseVisitor = new WhereClauseVisitor();

            fragment.Accept(whereClauseVisitor);

            foreach (var whereClause in whereClauseVisitor.Statements)
            {
                var booleanComparisonVisitor = new BooleanComparisonVisitor();
                whereClause.Accept(booleanComparisonVisitor);

                var offenders = booleanComparisonVisitor.NotIgnoredStatements(RuleId)
                                .Where(c =>
                                       c.ComparisonType == BooleanComparisonType.NotEqualToBrackets ||
                                       c.ComparisonType == BooleanComparisonType.NotEqualToExclamation);

                var sqlObjName = ruleExecutionContext.GetObjectName(sqlObj);
                problems.AddRange(offenders.Select(t => new SqlRuleProblem(Message, sqlObj, t)));
            }

            return(problems);
        }
    public override IList <SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext)
    {
        var problems = new List <SqlRuleProblem>();
        var sqlObj   = ruleExecutionContext.ModelElement;   //proc / view / function

        try
        {
            if (sqlObj != null)
            {
                var fragment = ruleExecutionContext.ScriptFragment;
                //get the combined parameters and declare variables into one searchable list
                var variablesVisitor = new VariablesVisitor();
                fragment.AcceptChildren(variablesVisitor);
                var variables = variablesVisitor.GetVariables();
                var selectStatementVisitor = new SelectStatementVisitor();
                fragment.Accept(selectStatementVisitor);
                foreach (var select in selectStatementVisitor.Statements)
                {
                    var query = select.QueryExpression as QuerySpecification;
                    if (query != null && query.WhereClause != null)
                    {
                        var booleanComparisonVisitor = new BooleanComparisonVisitor();
                        query.WhereClause.Accept(booleanComparisonVisitor);
                        foreach (var comparison in booleanComparisonVisitor.Statements)
                        {
                            var datatype1 = GetDataType(sqlObj, query, comparison.FirstExpression, variables);
                            if (string.IsNullOrEmpty(datatype1))
                            {
                                continue;
                            }
                            var datatype2 = GetDataType(sqlObj, query, comparison.SecondExpression, variables);
                            if (string.IsNullOrEmpty(datatype2))
                            {
                                continue;
                            }
                            //when checking the numeric literal I am not sure if it is a bit or tinyint.
                            if ((_comparer.Equals(datatype1, "bit") && _comparer.Equals(datatype2, "tinyint")) || (_comparer.Equals(datatype1, "tinyint") && _comparer.Equals(datatype2, "bit")))
                            {
                                continue;
                            }
                            if (!_comparer.Equals(datatype1, datatype2))
                            {
                                string msg = string.Format(Message, sqlObj.ObjectType.Name, RuleUtils.GetElementName(ruleExecutionContext, sqlObj));
                                problems.Add(new SqlRuleProblem(msg, sqlObj, comparison));
                            }
                        }
                    }
                }
            }
        }
        catch (System.Exception ex)
        {
            //TODO: PROPERLY LOG THIS ERROR
            Debug.WriteLine(ex.ToString());
            //throw;
        }
        return(problems);
    }
        /// <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; //proc / view / function

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

            try
            {
                var fragment = ruleExecutionContext.ScriptFragment.GetFragment(ProgrammingAndViewSchemaTypes);

                //get the combined parameters and declare variables into one search-able list
                var variablesVisitor = new VariablesVisitor();
                fragment.AcceptChildren(variablesVisitor);
                var variables = variablesVisitor.GetVariables();

                var selectStatementVisitor = new SelectStatementVisitor();
                fragment.Accept(selectStatementVisitor);
                foreach (var select in selectStatementVisitor.Statements)
                {
                    if (select.QueryExpression is QuerySpecification query && query.WhereClause != null)
                    {
                        var booleanComparisonVisitor = new BooleanComparisonVisitor();
                        query.WhereClause.Accept(booleanComparisonVisitor);

                        foreach (var comparison in booleanComparisonVisitor.Statements)
                        {
                            if ((comparison.FirstExpression is NullLiteral || comparison.SecondExpression is NullLiteral) &&
                                (comparison.ComparisonType == BooleanComparisonType.Equals ||
                                 comparison.ComparisonType == BooleanComparisonType.NotEqualToBrackets ||
                                 comparison.ComparisonType == BooleanComparisonType.NotEqualToExclamation)   //probably can remove the ComparisonTypeCheck
                                )
                            {
                                problems.Add(new SqlRuleProblem(Message, sqlObj, comparison));
                            }
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                //TODO: PROPERLY LOG THIS ERROR
                Debug.WriteLine(ex.ToString());
                //throw;
            }

            return(problems);
        }
        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(ProgrammingAndViewSchemaTypes);

            var selectStatementVisitor = new SelectStatementVisitor();

            fragment.Accept(selectStatementVisitor);

            foreach (var select in selectStatementVisitor.Statements)
            {
                var booleanCompareVisitor = new BooleanComparisonVisitor();
                select.Accept(booleanCompareVisitor);

                var offenders =
                    from cmp in booleanCompareVisitor.NotIgnoredStatements(RuleId)
                    where TestCompare(cmp)
                    select cmp;

                problems.AddRange(offenders.Select(t => new SqlRuleProblem(Message, sqlObj, t)));
            }

            var actionStatementVisitor = new ActionStatementVisitor();

            fragment.Accept(actionStatementVisitor);

            foreach (var action in actionStatementVisitor.Statements)
            {
                var booleanCompareVisitor = new BooleanComparisonVisitor();
                action.Accept(booleanCompareVisitor);

                var offenders =
                    from cmp in booleanCompareVisitor.NotIgnoredStatements(RuleId)
                    where TestCompare(cmp)
                    select cmp;

                problems.AddRange(offenders.Select(t => new SqlRuleProblem(Message, sqlObj, t)));
            }

            return(problems);
        }
Beispiel #5
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(ProgrammingAndViewSchemaTypes);

            var scalarSubqueryVisitor = new ScalarSubqueryVisitor();

            fragment.Accept(scalarSubqueryVisitor);

            var offenders = scalarSubqueryVisitor.NotIgnoredStatements(RuleId).Where(s =>
            {
                var whereClause = (s.QueryExpression as QuerySpecification)?.WhereClause;
                if (whereClause == null)
                {
                    return(false);
                }

                var booleanCompares = new BooleanComparisonVisitor();
                whereClause.Accept(booleanCompares);

                foreach (var booleanCompare in booleanCompares.Statements)
                {
                    var colVisitor = new ColumnReferenceExpressionVisitor();
                    booleanCompare.AcceptChildren(colVisitor);
                    if (colVisitor.Count > 1)
                    {
                        return(true);
                    }
                }

                return(false);
            }).ToList();

            problems.AddRange(offenders.Select(o => new SqlRuleProblem(Message, sqlObj, o)));

            return(problems);
        }
Beispiel #6
0
        public override IList <SqlRuleProblem> Analyze(SqlRuleExecutionContext ruleExecutionContext)
        {
            var problems = new List <SqlRuleProblem>();
            var sqlObj   = ruleExecutionContext.ModelElement; //proc / view / function

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

            try
            {
                var fragment = ruleExecutionContext.ScriptFragment.GetFragment(ProgrammingAndViewSchemaTypes);
                //get the combined parameters and declare variables into one searchable list
                var variablesVisitor = new VariablesVisitor();
                fragment.AcceptChildren(variablesVisitor);
                var variables = variablesVisitor.GetVariables();

                var selectStatementVisitor = new SelectStatementVisitor();
                fragment.Accept(selectStatementVisitor);
                foreach (var select in selectStatementVisitor.Statements)
                {
                    if (select.QueryExpression is QuerySpecification query && query.WhereClause != null && query.FromClause != null)
                    {
                        var booleanComparisonVisitor = new BooleanComparisonVisitor();
                        query.WhereClause.Accept(booleanComparisonVisitor);
                        var comparisons = booleanComparisonVisitor.Statements
                                          .Where(x =>
                                                 (x.FirstExpression is ColumnReferenceExpression ||
                                                  x.SecondExpression is ColumnReferenceExpression));

                        if (!comparisons.Any())
                        {
                            continue;
                        }
                        var dataTypesList = new Dictionary <NamedTableView, IDictionary <string, DataTypeView> >();
                        select.GetTableColumnDataTypes(dataTypesList, ruleExecutionContext.SchemaModel);

                        foreach (var comparison in comparisons)
                        {
                            var col1      = comparison.FirstExpression as ColumnReferenceExpression;
                            var col2      = comparison.SecondExpression as ColumnReferenceExpression;
                            var datatype1 = string.Empty;
                            var datatype2 = string.Empty;

                            if (col1 != null)
                            {
                                var dtView = dataTypesList.GetDataTypeView(col1);
                                if (dtView != null)
                                {
                                    datatype1 = dtView.DataType;
                                }
                            }
                            else
                            {
                                datatype1 = GetDataType(sqlObj,
                                                        query,
                                                        comparison.FirstExpression,
                                                        variables,
                                                        ruleExecutionContext.SchemaModel);
                            }

                            if (col2 != null)
                            {
                                var dtView = dataTypesList.GetDataTypeView(col2);
                                if (dtView != null)
                                {
                                    datatype2 = dtView.DataType;
                                }
                            }
                            else
                            {
                                datatype2 = GetDataType(sqlObj,
                                                        query,
                                                        comparison.SecondExpression,
                                                        variables,
                                                        ruleExecutionContext.SchemaModel);
                            }

                            if (string.IsNullOrWhiteSpace(datatype1) || string.IsNullOrWhiteSpace(datatype2))
                            {
                                continue;
                            }

                            //when checking the numeric literal I am not sure if it is a bit or tinyint.
                            if ((_comparer.Equals(datatype1, "bit") && _comparer.Equals(datatype2, "tinyint")) ||
                                (_comparer.Equals(datatype1, "tinyint") && _comparer.Equals(datatype2, "bit")))
                            {
                                continue;
                            }

                            if (!_comparer.Equals(datatype1, datatype2))
                            {
                                problems.Add(new SqlRuleProblem(Message, sqlObj, comparison));
                            }
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                //TODO: PROPERLY LOG THIS ERROR
                Debug.WriteLine(ex.ToString());
                //throw;
            }

            return(problems);
        }
Beispiel #7
0
        public static IList <JoinInfo> GetFromClauseJoinTables(this FromClause from)
        {
            if (from == null)
            {
                throw new ArgumentNullException(nameof(from));
            }
            var joins = new List <JoinInfo>();

            if (from.TableReferences.Count == 0 || from.TableReferences.First().GetType() != typeof(QualifiedJoin))
            {
                return(joins);
            }

            var joinVisitor = new JoinVisitor();

            from.Accept(joinVisitor);

            //build the list of pure tables along with the list of boolean comparisons
            foreach (var join in joinVisitor.QualifiedJoins)
            {
                var joinInfo = new JoinInfo {
                };

                var boolVisitor = new BooleanComparisonVisitor();
                join.SearchCondition.Accept(boolVisitor);
                joinInfo.Compares = new List <BooleanComparisonExpression>(boolVisitor.Statements);

                if (join.FirstTableReference.GetType() == typeof(NamedTableReference))
                {
                    joinInfo.Table1 = join.FirstTableReference as NamedTableReference;
                }
                if (join.SecondTableReference.GetType() == typeof(NamedTableReference))
                {
                    joinInfo.Table2 = join.SecondTableReference as NamedTableReference;
                }
                joins.Add(joinInfo);
            }

            //table2 should always have a table..... maybe. unless the table is actually a sub-select. Then we will ignore it
            foreach (var join in joins.Where(j => j.Table2 != null))
            {
                var table1      = join.Table1;
                var table2      = join.Table2;
                var table2Alias = table2.Alias?.Value;
                var table2Name  = new ObjectIdentifier(table2.SchemaObject.Identifiers.Select(x => x.Value));

                //we need to figure out which side of the comparison goes to which table..... PITA. yes.....
                foreach (var compare in join.Compares
                         .Where(x => x.FirstExpression is ColumnReferenceExpression && x.SecondExpression is ColumnReferenceExpression))
                {
                    //we use a loop as we need to check both the first expression and the second expression to see which table the columns belong to
                    for (int i = 0; i < 2; i++)
                    {
                        var col        = (i == 0 ? compare.FirstExpression : compare.SecondExpression) as ColumnReferenceExpression;
                        var colTblName = GetTableOrAliasName(col.MultiPartIdentifier.Identifiers);
                        if (table2Alias.StringEquals(colTblName.First()) || table2Name.CompareTo(colTblName) >= 5)
                        {
                            join.Table2JoinColumns.Add(col);
                            continue;
                        }

                        //use table1 if it was supplied in the compare. else scan the joins to find the matching table to the column
                        var tbl = table1 ?? joins.Select(x =>
                        {
                            if (CheckName(x.Table2, col))
                            {
                                return(x.Table2);
                            }
                            if (CheckName(x.Table1, col))
                            {
                                return(x.Table1);
                            }
                            return(null);
                        }).FirstOrDefault(x => x != null);

                        if (tbl != null)
                        {
                            var tblAlias = tbl.Alias?.Value;
                            var tblName  = new ObjectIdentifier(tbl.SchemaObject.Identifiers.Select(x => x.Value));

                            if (join.Table1 == null)
                            {
                                join.Table1 = tbl;
                            }
                            if (tblAlias.StringEquals(colTblName.First()) || tblName.CompareTo(colTblName) >= 5)
                            {
                                join.Table1JoinColumns.Add(col);
                            }
                        }
                    }
                }
            }

            return(joins);
        }