dorisoy_OpenDBDiff/OpenDBDiff.SqlServer.Schema/Generates/GenerateTextObjects.cs
using OpenDBDiff.Abstractions.Schema.Events;
using OpenDBDiff.SqlServer.Schema.Generates.Util;
using OpenDBDiff.SqlServer.Schema.Model;
using OpenDBDiff.SqlServer.Schema.Options;
using System;
using System.Data.SqlClient;
using System.Text.RegularExpressions;

namespace OpenDBDiff.SqlServer.Schema.Generates
{
    public class GenerateTextObjects
    {
        private Generate root;

        public GenerateTextObjects(Generate root)
        {
            this.root = root;
        }

        private static string GetSQL(SqlOption options)
        {
            var filterQuery =  SQLQueries.SQLQueryFactory.Get("GetTextObjectsQuery");
            string filter = "";
            if (options.Ignore.FilterStoredProcedure)
                filter += "O.type = 'P' OR ";
            if (options.Ignore.FilterView)
                filter += "O.type = 'V' OR ";
            if (options.Ignore.FilterTrigger)
                filter += "O.type = 'TR' OR ";
            if (options.Ignore.FilterFunction)
                filter += "O.type IN ('IF','FN','TF') OR ";
            filter = filter.Substring(0, filter.Length - 4);
            return filterQuery.Replace("{FILTER}", filter);
        }

        public void Fill(Database database, string connectionString)
        {
            ICode code = null;
            try
            {
                if ((database.Options.Ignore.FilterStoredProcedure) || (database.Options.Ignore.FilterView) || (database.Options.Ignore.FilterFunction) || (database.Options.Ignore.FilterTrigger))
                {
                    root.RaiseOnReading(new ProgressEventArgs("Reading Text Objects...", Constants.READING_TEXTOBJECTS));
                    using (SqlConnection conn = new SqlConnection(connectionString))
                    {
                        using (SqlCommand command = new SqlCommand(GetSQL(database.Options), conn))
                        {
                            conn.Open();
                            command.CommandTimeout = 0;
                            using (SqlDataReader reader = command.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    code = null;
                                    root.RaiseOnReadingOne(reader["name"]);
                                    string type = reader["Type"].ToString().Trim();
                                    string name = reader["name"].ToString();
                                    string definition = reader["Text"].ToString();
                                    int id = (int)reader["object_id"];
                                    if (type.Equals("V"))
                                        code = (ICode)database.Views.Find(id);

                                    if (type.Equals("TR"))
                                        code = (ICode)database.Find(id);

                                    if (type.Equals("P"))
                                    {
                                        var procedure = database.Procedures.Find(id);
                                        if (procedure != null)
                                            ((ICode)procedure).Text = GetObjectDefinition(type, name, definition);
                                    }

                                    if (type.Equals("IF") || type.Equals("FN") || type.Equals("TF"))
                                        code = (ICode)database.Functions.Find(id);

                                    if (code != null)
                                        code.Text = reader["Text"].ToString();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private string GetObjectDefinition(string type, string name, string definition)
        {
            string rv = definition;

            string sqlDelimiters = @"(\r|\n|\s)+?";
            RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Multiline;
            Regex re = new Regex(@"CREATE" + sqlDelimiters + @"PROC(EDURE)?" + sqlDelimiters + @"(\w+\.|\[\w+\]\.)?\[?(?<spname>\w+)\]?" + sqlDelimiters, options);
            switch (type)
            {
                case "P":
                    Match match = re.Match(definition);
                    if (match != null && match.Success)
                    {
                        // Try to replace the name saved in the definition when the object was created by the one used for the object in sys.object
                        string oldName = match.Groups["spname"].Value;
                        //if (String.IsNullOrEmpty(oldName)) System.Diagnostics.Debugger.Break();
                        if (String.Compare(oldName, name) != 0)
                        {
                            rv = rv.Replace(oldName, name);
                        }
                    }
                    break;
                default:
                    //TODO : Add the logic used for other objects than procedures
                    break;
            }

            return rv;
        }
    }
}
