예제 #1
0
        /// <summary>
        /// Enumerate the nodes to be added to the upgrade path graph which create a new version of the database without a
        /// pre-existing version being present.
        /// </summary>
        /// <param name="databaseName">Name of the database to be upgraded.</param>
        /// <param name="paths">Paths of the directories containing the upgrade scripts.</param>
        /// <param name="insertTestData">True if test data is to be inserted along with running the upgrade scripts.</param>
        /// <returns>List of the nodes which create a new version of the database.</returns>
        private static IEnumerable <UpgradePathNode> GetCreateNodes(
            string databaseName,
            IEnumerable <string> paths,
            bool insertTestData)
        {
            var pattern = String.Format("{0}_*.sql", databaseName);

            var scriptPaths = paths.SelectMany(p => Directory.GetFiles(p, pattern));

            foreach (var scriptPath in scriptPaths)
            {
                var scriptName = Path.GetFileName(scriptPath);

                // ReSharper disable once PossibleNullReferenceException
                var scriptTargetVersionString = scriptName.Substring(
                    databaseName.Length + 1,
                    scriptName.Length - databaseName.Length - 5);

                if (scriptTargetVersionString.IndexOfAny(new[] { '-', '_' }) >= 0)
                {
                    continue;
                }

                var testDataScriptPath = scriptPath.Substring(0, scriptPath.Length - 4) + "_testdata.sql";

                if (insertTestData && !File.Exists(testDataScriptPath))
                {
                    throw new ApplicationException(String.Format(
                                                       "Missing test data insert script {0}.", Path.GetFileName(testDataScriptPath)));
                }

                DatabaseVersion scriptTargetVersion;
                if (!DatabaseVersion.TryParse(scriptTargetVersionString, out scriptTargetVersion))
                {
                    throw new ApplicationException(String.Format(
                                                       "Database script {0} has invalid target version.", scriptPath));
                }

                var stepGroup = new StepGroup(databaseName, scriptTargetVersion);
                // ReSharper disable once ObjectCreationAsStatement
                new RunScriptStep(
                    stepGroup,
                    null,
                    scriptPath,
                    insertTestData ? testDataScriptPath : null);

                var createdSchemas = new HashSet <string>(
                    stepGroup.SchemaNames,
                    StringComparer.InvariantCultureIgnoreCase);

                if (createdSchemas.Count > 0)
                {
                    // ReSharper disable once ObjectCreationAsStatement
                    new CreateSchemasStep(stepGroup, createdSchemas);
                }

                yield return(new UpgradePathNode(stepGroup));
            }
        }
예제 #2
0
        /// <summary>
        /// Enumerate the nodes to be added to the upgrade path graph which upgrade a specific version of the database.
        /// </summary>
        /// <param name="databaseName">Name of the database to be upgraded.</param>
        /// <param name="sourceVersion">Installed version of the database or null if the database is not installed.
        /// </param>
        /// <param name="existingSchemaNames">The name of the schemas associated with the previous version of the logical
        /// database.</param>
        /// <param name="paths">Paths of the directories containing the upgrade scripts.</param>
        /// <param name="insertTestData">True if test data is to be inserted along with running the upgrade scripts.</param>
        /// <returns>List of the nodes which upgrade the specified version of the database to a new version.</returns>
        private static IEnumerable <UpgradePathNode> GetUpgradeNodes(
            string databaseName,
            DatabaseVersion sourceVersion,
            IEnumerable <string> existingSchemaNames,
            IEnumerable <string> paths,
            bool insertTestData)
        {
            var pattern = String.Format("{0}_*.sql", databaseName);

            var scriptPaths = paths.SelectMany(p => Directory.GetFiles(p, pattern));

            foreach (var scriptPath in scriptPaths)
            {
                var scriptName = Path.GetFileName(scriptPath);

                // ReSharper disable once PossibleNullReferenceException
                var versionsString = scriptName.Substring(
                    databaseName.Length + 1,
                    scriptName.Length - databaseName.Length - 5);

                if (versionsString.Contains("_"))
                {
                    continue;
                }

                var index = versionsString.IndexOf('-');
                if (index == -1)
                {
                    continue;
                }

                var scriptSourceVersionString = versionsString.Substring(0, index);
                var scriptTargetVersionString = versionsString.Substring(index + 1);

                if (scriptTargetVersionString.Contains("-"))
                {
                    continue;
                }

                if (scriptPath.ToLowerInvariant().EndsWith("_localization.sql"))
                {
                    continue;
                }

                DatabaseVersion scriptSourceVersion;
                if (!DatabaseVersion.TryParse(scriptSourceVersionString, out scriptSourceVersion))
                {
                    throw new ApplicationException(String.Format(
                                                       "Database script {0} has invalid source version.", scriptPath));
                }

                if (scriptSourceVersion != sourceVersion)
                {
                    continue;
                }

                var testDataScriptPath = scriptPath.Substring(0, scriptPath.Length - 4) + "_testdata.sql";

                if (insertTestData && !File.Exists(testDataScriptPath))
                {
                    throw new ApplicationException(String.Format(
                                                       "Missing test data insert script {0}.", Path.GetFileName(testDataScriptPath)));
                }

                DatabaseVersion scriptTargetVersion;
                if (!DatabaseVersion.TryParse(scriptTargetVersionString, out scriptTargetVersion))
                {
                    throw new ApplicationException(String.Format(
                                                       "Database script {0} has invalid target version.", scriptPath));
                }

                var stepGroup = new StepGroup(databaseName, scriptTargetVersion);
                // ReSharper disable once ObjectCreationAsStatement
                new RunScriptStep(
                    stepGroup,
                    sourceVersion,
                    scriptPath,
                    insertTestData ? testDataScriptPath : null);

                // ReSharper disable PossibleMultipleEnumeration
                var createdSchemas = new HashSet <string>(
                    stepGroup.SchemaNames.Except(existingSchemaNames),
                    StringComparer.InvariantCultureIgnoreCase);
                var deletedSchemas = new HashSet <string>(
                    existingSchemaNames
                    .Except(stepGroup.SchemaNames)
                    .Except(new[] { "dbo" }),
                    StringComparer.InvariantCultureIgnoreCase);
                // ReSharper restore PossibleMultipleEnumeration

                if (createdSchemas.Count > 0)
                {
                    // ReSharper disable once ObjectCreationAsStatement
                    new CreateSchemasStep(stepGroup, createdSchemas);
                }

                if (deletedSchemas.Count > 0)
                {
                    // ReSharper disable once ObjectCreationAsStatement
                    new DropSchemasStep(stepGroup, deletedSchemas);
                }

                yield return(new UpgradePathNode(stepGroup));
            }
        }
예제 #3
0
        /// <summary>
        /// Lekérdezi a metadatokat
        /// </summary>
        /// <param name="connection">Kapcsolati infó</param>
        /// <param name="transaction">Tranzakciópéldány</param>
        /// <param name="databaseName">Adatbázisnév</param>
        /// <param name="currentVersion">Adatbázis-változat</param>
        /// <param name="existingSchemaNames">A már létező sémák neve</param>
        private static void GetMetadata(
            SqlConnection connection,
            SqlTransaction transaction,
            string databaseName,
            out DatabaseVersion currentVersion,
            out HashSet <string> existingSchemaNames)
        {
            using (var command = new SqlCommand(GET_METADATA_QUERY, connection, transaction))
            {
                command.Parameters.Add(new SqlParameter("@name", SqlDbType.NVarChar)
                {
                    Value = databaseName
                });

                var dataSet = new DataSet();

                using (var adapter = new SqlDataAdapter(command))
                {
                    adapter.Fill(dataSet);
                }

                if (dataSet.Tables.Count != 2)
                {
                    throw new ApplicationException("Metadata retrieval query returned unexpected number of tables.");
                }

                var versionTable    = dataSet.Tables[0];
                var schemaNameTable = dataSet.Tables[1];

                switch (versionTable.Rows.Count)
                {
                case 0:
                    currentVersion = null;
                    break;

                case 1:
                    var version = versionTable.Rows[0][0];
                    if (version == null || version == DBNull.Value)
                    {
                        currentVersion = null;
                    }
                    else
                    {
                        if (!(version is string) ||
                            !DatabaseVersion.TryParse((string)version, out currentVersion))
                        {
                            throw new ApplicationException("The installed logical database version is invalid.");
                        }
                    }
                    break;

                default:
                    throw new ApplicationException("Metadata retrieval query returned multiple version numbers.");
                }

                existingSchemaNames = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
                foreach (var schemaName in from DataRow schemaNameRow in schemaNameTable.Rows select schemaNameRow[0])
                {
                    if (schemaName == null || schemaName == DBNull.Value || !(schemaName is string))
                    {
                        throw new ApplicationException("The installed logical database has an invalid schema name.");
                    }

                    existingSchemaNames.Add((string)schemaName);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Create a new instance of the <see cref="UnresolvedDependency"/> class from a descriptor in an upgrade script.
        /// </summary>
        /// <param name="type">Type of the dependency.</param>
        /// <param name="descriptor">Descriptor from which the <see cref="UnresolvedDependency"/> should be created.
        /// </param>
        /// <param name="sourceVersion">Source version of the upgrade script the descriptor is found in.</param>
        /// <param name="scriptName">Name of the upgrade script.</param>
        /// <returns></returns>
        public static UnresolvedDependency FromDescriptor(
            DependencyType type,
            string descriptor,
            DatabaseVersion sourceVersion,
            string scriptName)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException("descriptor");
            }

            if (scriptName == null)
            {
                throw new ArgumentNullException("scriptName");
            }

            string          name;
            DatabaseVersion minVersion;
            DatabaseVersion maxVersion;

            var index = descriptor.IndexOf('-');

            if (index == -1)
            {
                if (sourceVersion == null)
                {
                    throw new ApplicationException(String.Format(
                                                       "Invalid dependency descriptor in {0}: {1}.", scriptName, descriptor));
                }

                name       = descriptor;
                minVersion = sourceVersion;
                maxVersion = sourceVersion;
            }
            else
            {
                name = descriptor.Substring(0, index);
                var versions = descriptor.Substring(index + 1);

                index = versions.IndexOf('-');
                if (index == -1)
                {
                    if (versions == "*")
                    {
                        minVersion = DatabaseVersion.MinValue;
                        maxVersion = DatabaseVersion.MaxValue;
                    }
                    else
                    {
                        if (!DatabaseVersion.TryParse(versions, out minVersion))
                        {
                            throw new ApplicationException(String.Format(
                                                               "Invalid dependency descriptor in {0}: {1}.", scriptName, descriptor));
                        }

                        maxVersion = minVersion;
                    }
                }
                else
                {
                    var minVersionString = versions.Substring(0, index);
                    var maxVersionString = versions.Substring(index + 1);

                    if (minVersionString == "*")
                    {
                        minVersion = DatabaseVersion.MinValue;
                    }
                    else if (!DatabaseVersion.TryParse(minVersionString, out minVersion))
                    {
                        throw new ApplicationException(String.Format(
                                                           "Invalid dependency descriptor in {0}: {1}.", scriptName, descriptor));
                    }

                    if (maxVersionString == "*")
                    {
                        maxVersion = DatabaseVersion.MaxValue;
                    }
                    else if (!DatabaseVersion.TryParse(maxVersionString, out maxVersion))
                    {
                        throw new ApplicationException(String.Format(
                                                           "Invalid dependency descriptor in {0}: {1}.", scriptName, descriptor));
                    }
                }
            }

            return(new UnresolvedDependency(type, name, minVersion, maxVersion));
        }
예제 #5
0
        /// <summary>
        /// Értelmezi a parancs argumentumait
        /// </summary>
        /// <param name="option">Az opció neve</param>
        /// <param name="argument">Az argumentum értéke</param>
        /// <param name="original">A parancs szövege</param>
        /// <returns>Sikerült az értelmezés?</returns>
        protected override bool DoParseOption(string option, string argument, string original)
        {
            if (base.DoParseOption(option, argument, original))
            {
                return(true);
            }
            switch (option)
            {
            case "databases":
            case "database":
            case "d":
            case "db":
            case "ds":
            case "dbs":
            case "logicaldatabases":
            case "logicaldatabase":
            case "ld":
            case "ldb":
            case "lds":
            case "ldbs":
                argument = ParameterHelper.Mandatory(argument, original);

                var databases = argument.Split(',');
                _databases.Clear();

                foreach (var database in databases)
                {
                    string name;
                    string version;

                    var index = database.IndexOf('-');
                    if (index == -1)
                    {
                        name    = database.Trim();
                        version = "";
                    }
                    else
                    {
                        name    = database.Substring(0, index).Trim();
                        version = database.Substring(index + 1).Trim();
                    }

                    if (String.IsNullOrWhiteSpace(name))
                    {
                        throw new ParameterException("Logical database name cannot be empty.");
                    }

                    if (name.IndexOfAny(new[] { '?', '*' }) != -1)
                    {
                        throw new ArgumentException("Database name may not contain path wildcards.");
                    }

                    DatabaseVersion parsedVersion;
                    if (String.IsNullOrWhiteSpace(version))
                    {
                        parsedVersion = VersionHelper.DatabaseVersion;
                    }
                    else if (!DatabaseVersion.TryParse(version, out parsedVersion))
                    {
                        throw new ParameterException("Invalid version number specified for logical database");
                    }

                    _databases.Add(new DatabaseNameVersionPair(name, parsedVersion));
                }
                return(true);

            case "paths":
            case "path":
            case "p":
            case "ps":
            case "scriptpaths":
            case "sqlpaths":
            case "scriptpath":
            case "sqlpath":
            case "sp":
            case "sps":
            case "sqlp":
            case "sqlps":
                argument = ParameterHelper.Mandatory(argument, original);

                var paths = argument.Split(',');
                _paths.Clear();

                if (paths.Length == 1 && String.IsNullOrEmpty(paths[0]))
                {
                    return(true);
                }

                foreach (var path in paths)
                {
                    bool isAbsolute;

                    try
                    {
                        isAbsolute = Path.IsPathRooted(path);
                    }
                    catch (ArgumentException)
                    {
                        throw new ParameterException("Database script path must be a valid path.");
                    }

                    _paths.Add(isAbsolute
                            ? path
                            : Path.Combine(Environment.CurrentDirectory, path));
                }
                return(true);

            case "serviceuser":
            case "serviceusers":
            case "su":
            case "sus":
            case "user":
            case "users":
            case "u":
            case "us":
                argument = ParameterHelper.Mandatory(argument, original);

                var users = argument.Split(',');
                _serviceUsers.Clear();

                foreach (var user in users)
                {
                    if (String.IsNullOrWhiteSpace(user))
                    {
                        throw new ParameterException("Service user name cannot be empty.");
                    }
                    _serviceUsers.Add(user.Trim());
                }
                return(true);

            case "testdata":
            case "t":
            case "td":
            case "test":
            case "inserttestdata":
            case "it":
            case "itd":
                argument = ParameterHelper.Mandatory(argument, original).Trim();
                switch (argument.ToLower())
                {
                case "0":
                case "no":
                case "false":
                    _insertTestData = false;
                    break;

                case "1":
                case "yes":
                case "true":
                    _insertTestData = true;
                    break;

                default:
                    throw new ParameterException(String.Format(
                                                     "Option {0} requires a boolean argument.", original));
                }
                return(true);

            default:
                throw new ParameterException(String.Format(
                                                 "Unknown option {0} for command {1}.", original, Original));
            }
        }