Exemplo n.º 1
0
        /// <summary>
        /// Compares <paramref name="sourceSchema"/> and <paramref name="targetSchema"/>.
        /// </summary>
        /// <param name="sourceSchema">The source schema.</param>
        /// <param name="targetSchema">The target schema.</param>
        /// <param name="schemaHints">The upgrade hints.</param>
        /// <param name="upgradeHints"><see cref="UpgradeHint"/>s to be applied.</param>
        /// <param name="schemaUpgradeMode">A <see cref="SchemaUpgradeMode"/> being used.</param>
        /// <param name="model">A <see cref="DomainModel"/> of a storage.</param>
        /// <param name="briefExceptionFormat">Indicates whether brief or full exception format should be used.</param>
        /// <param name="upgradeStage">A current <see cref="UpgradeStage"/>.</param>
        /// <returns>Comparison result.</returns>
        public static SchemaComparisonResult Compare(
            StorageModel sourceSchema, StorageModel targetSchema,
            HintSet schemaHints, SetSlim <UpgradeHint> upgradeHints,
            SchemaUpgradeMode schemaUpgradeMode, DomainModel model,
            bool briefExceptionFormat, UpgradeStage upgradeStage)
        {
            if (schemaHints == null)
            {
                schemaHints = new HintSet(sourceSchema, targetSchema);
            }

            var comparer                = new Comparer();
            var difference              = comparer.Compare(sourceSchema, targetSchema, schemaHints);
            var actions                 = GetUpgradeActions(comparer, difference, schemaHints);
            var actionList              = actions.Flatten().ToList();
            var comparisonStatus        = GetComparisonStatus(actionList, schemaUpgradeMode);
            var unsafeActions           = GetUnsafeActions(actionList, upgradeHints);
            var columnTypeChangeActions = actionList.OfType <PropertyChangeAction>().Where(IsTypeChangeAction).ToList();

            if (schemaUpgradeMode != SchemaUpgradeMode.ValidateLegacy)
            {
                return(new SchemaComparisonResult(
                           comparisonStatus, columnTypeChangeActions.Count > 0, null,
                           schemaHints, difference, actions, unsafeActions));
            }

            // Legacy comparison

            var systemTablesSequence = model.Types.Where(type => type.IsSystem).Select(type => type.MappingName);
            var systemTables         = new HashSet <string>(systemTablesSequence, Comparer);

            var createTableActions = actionList
                                     .OfType <CreateNodeAction>()
                                     .Where(
                action => {
                var table = action.Difference.Target as TableInfo;
                return(table != null && !systemTables.Contains(table.Name));
            })
                                     .ToList();

            var createColumnActions = actionList
                                      .OfType <CreateNodeAction>()
                                      .Where(
                action => {
                var column = action.Difference.Target as StorageColumnInfo;
                return(column != null && !systemTables.Contains(column.Parent.Name));
            })
                                      .ToList();

            columnTypeChangeActions = columnTypeChangeActions
                                      .Where(
                action => {
                var sourceType = action.Difference.Source as StorageTypeInfo;
                var targetType = action.Difference.Target as StorageTypeInfo;
                return(sourceType == null || targetType == null || sourceType.IsTypeUndefined ||
                       sourceType.Type.ToNullable() != targetType.Type.ToNullable());
            })
                                      .ToList();


            var isCompatibleInLegacyMode =
                createTableActions.Count == 0 &&
                createColumnActions.Count == 0 &&
                columnTypeChangeActions.Count == 0;

            if (briefExceptionFormat)
            {
                unsafeActions =
                    createTableActions.Cast <NodeAction>()
                    .Concat(createColumnActions.Cast <NodeAction>())
                    .Concat(columnTypeChangeActions.Cast <NodeAction>())
                    .ToList();
            }

            return(new SchemaComparisonResult(
                       comparisonStatus, columnTypeChangeActions.Count > 0, isCompatibleInLegacyMode,
                       schemaHints, difference, actions, unsafeActions));
        }
Exemplo n.º 2
0
        private void SynchronizeSchema(
            Domain domain, SchemaUpgrader upgrader, SchemaExtractor extractor, SchemaUpgradeMode schemaUpgradeMode)
        {
            using (UpgradeLog.InfoRegion(Strings.LogSynchronizingSchemaInXMode, schemaUpgradeMode)) {
                StorageModel targetSchema = null;
                if (schemaUpgradeMode == SchemaUpgradeMode.Skip)
                {
                    if (context.ParentDomain == null)
                    {
                        //If we build main domain we should log target model.
                        //Log of Storage Node target model is not necessary
                        //because storage target model exactly the same.
                        targetSchema = GetTargetModel(domain);
                        context.TargetStorageModel = targetSchema;
                        if (UpgradeLog.IsLogged(LogLevel.Info))
                        {
                            UpgradeLog.Info(Strings.LogTargetSchema);
                            targetSchema.Dump();
                        }
                    }
                    var builder = ExtractedModelBuilderFactory.GetBuilder(context);
                    context.ExtractedSqlModelCache = builder.Run();
                    OnSchemaReady();
                    return; // Skipping comparison completely
                }

                var extractedSchema = extractor.GetSchema();

                // Hints
                var triplet = BuildTargetModelAndHints(extractedSchema);
                var hintProcessingResult = triplet.Third;
                targetSchema = triplet.First;
                context.TargetStorageModel = targetSchema;
                var hints = triplet.Second;
                if (UpgradeLog.IsLogged(LogLevel.Info))
                {
                    UpgradeLog.Info(Strings.LogExtractedSchema);
                    extractedSchema.Dump();
                    UpgradeLog.Info(Strings.LogTargetSchema);
                    targetSchema.Dump();
                }
                OnSchemaReady();

                var breifExceptionFormat = domain.Configuration.SchemaSyncExceptionFormat == SchemaSyncExceptionFormat.Brief;
                var result = SchemaComparer.Compare(extractedSchema, targetSchema,
                                                    hints, context.Hints, schemaUpgradeMode, domain.Model, breifExceptionFormat, context.Stage);
                var shouldDumpSchema = !schemaUpgradeMode.In(
                    SchemaUpgradeMode.Skip, SchemaUpgradeMode.ValidateCompatible, SchemaUpgradeMode.Recreate);
                if (shouldDumpSchema && UpgradeLog.IsLogged(LogLevel.Info))
                {
                    UpgradeLog.Info(result.ToString());
                }

                if (UpgradeLog.IsLogged(LogLevel.Info))
                {
                    UpgradeLog.Info(Strings.LogComparisonResultX, result);
                }

                context.SchemaDifference     = (NodeDifference)result.Difference;
                context.SchemaUpgradeActions = result.UpgradeActions;

                switch (schemaUpgradeMode)
                {
                case SchemaUpgradeMode.ValidateExact:
                    if (result.SchemaComparisonStatus != SchemaComparisonStatus.Equal || result.HasColumnTypeChanges)
                    {
                        throw new SchemaSynchronizationException(result);
                    }
                    if (!hintProcessingResult.AreAllTypesMapped() && hintProcessingResult.SuspiciousTypes.Any())
                    {
                        throw new SchemaSynchronizationException(Strings.ExExtractedAndTargetSchemasAreEqualButThereAreChangesInTypeIdentifiersSet);
                    }
                    break;

                case SchemaUpgradeMode.ValidateCompatible:
                    if (result.SchemaComparisonStatus != SchemaComparisonStatus.Equal &&
                        result.SchemaComparisonStatus != SchemaComparisonStatus.TargetIsSubset)
                    {
                        throw new SchemaSynchronizationException(result);
                    }
                    break;

                case SchemaUpgradeMode.PerformSafely:
                    if (result.HasUnsafeActions)
                    {
                        throw new SchemaSynchronizationException(result);
                    }
                    goto case SchemaUpgradeMode.Perform;

                case SchemaUpgradeMode.Recreate:
                case SchemaUpgradeMode.Perform:
                    upgrader.UpgradeSchema(extractor.GetSqlSchema(), extractedSchema, targetSchema, result.UpgradeActions);
                    if (result.UpgradeActions.Any())
                    {
                        extractor.ClearCache();
                    }
                    break;

                case SchemaUpgradeMode.ValidateLegacy:
                    if (result.IsCompatibleInLegacyMode != true)
                    {
                        throw new SchemaSynchronizationException(result);
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException("schemaUpgradeMode");
                }
            }
        }
Exemplo n.º 3
0
        private static SchemaComparisonStatus GetComparisonStatus(ICollection <NodeAction> actions, SchemaUpgradeMode schemaUpgradeMode)
        {
            var filter = schemaUpgradeMode != SchemaUpgradeMode.ValidateCompatible
        ? (Func <Type, bool>)(targetType => true)
        : targetType => targetType.In(WellKnownUpgradeTypes.TableInfo, WellKnownUpgradeTypes.StorageColumnInfo);
            var hasCreateActions = actions
                                   .OfType <CreateNodeAction>()
                                   .Select(action => action.Difference.Target.GetType())
                                   .Any(filter);
            var hasRemoveActions = actions
                                   .OfType <RemoveNodeAction>()
                                   .Select(action => action.Difference.Source.GetType())
                                   .Any(sourceType => sourceType.In(WellKnownUpgradeTypes.TableInfo, WellKnownUpgradeTypes.StorageColumnInfo));

            if (hasCreateActions && hasRemoveActions)
            {
                return(SchemaComparisonStatus.NotEqual);
            }
            if (hasCreateActions)
            {
                return(SchemaComparisonStatus.TargetIsSuperset);
            }
            if (hasRemoveActions)
            {
                return(SchemaComparisonStatus.TargetIsSubset);
            }
            return(SchemaComparisonStatus.Equal);
        }