Пример #1
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var pending in PendingReorderTableType.AllFrom(changes.Current))
            {
                var originalTable = TableType.Identifier(pending.Name);
                var tempTable     = pending.ParentIdentifier;

                if (object.Equals(originalTable, tempTable))
                {
                    // If the database fails at precisely the wrong time, the rename can be succeed without dropping the PendingReorder,
                    // so the table thinks it's to be renamed to itself. In that case we need to drop the PendingReorder, NOT drop the table!
                    output.Verbose("Cleaning up after completed reorder of columns in " + originalTable);
                    changes.Remove(null, pending);
                }
                else if (changes.Current.ContainsRoot(originalTable))
                {
                    // If the original table still exists, we drop the temp table so we can start over (in case the data in the table has changed since the temp table
                    // was created, or the reordering has somehow become unnecessary).
                    output.Verbose("Clearing pending reorder of columns in " + originalTable);
                    changes.Remove(changes.SchemaDriver.GetDropTableSql(pending.ParentName), changes.Current.GetRoot(pending.ParentIdentifier));
                }
                else
                {
                    // The original table has been dropped so we need to recreate it by renaming the temp table.
                    output.Verbose("Completing pending reordering of columns in " + originalTable);
                    changes.Rename(changes.SchemaDriver.GetRenameTableSql(tempTable.Name, originalTable.Name), tempTable, originalTable);

                    // And forget about the pending rename.
                    changes.Remove(null, pending.WithParent(originalTable));
                }
            }
        }
Пример #2
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            if (changes.Options.FieldDropBehavior == DropBehavior.SkipDrop)
            {
                return;
            }
            var errorResponse = changes.Options.FieldDropBehavior == DropBehavior.TryDrop ? ErrorResponse.Ignore : ErrorResponse.Fail;

            foreach (var current in FieldType.AllFrom(changes.Current))
            {
                if (changes.Desired.Contains(current))
                {
                    continue;
                }

                // If we're going to drop the whole table then don't bother dropping the field
                if (!changes.Desired.ContainsRoot(current.ParentIdentifier))
                {
                    continue;
                }

                if (!changes.AllowDropWithPossibleDataLoss(current, changes.Options.FieldDropBehavior))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropFieldSql(current.ParentName, current.Name), current);
            }
        }
Пример #3
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            // This isn't really anything to do with pre-upgrade-hooks but there's no other good place to give this warning!
            foreach (var query in QueryType.AllFrom(changes.Current))
            {
                if (query.State != null && query.State.Body.StartsWith("<FAIL>"))
                {
                    output.Warning(query.State.Body.Substring(6));
                }
            }

            foreach (var hook in PreUpgradeHookType.AllFrom(changes.Current))
            {
                var proc = QueryType.GetFrom(changes.Current, hook.ParentIdentifier);
                if (proc.State == null || proc.State is QueryType.FunctionState || proc.State.Parameters.Any())
                {
                    output.Warning("Cannot execute pre-upgrade hook " + proc.Name + ": stored procedure does not exist or has parameters.");
                }

                changes.Put(changes.SchemaDriver.GetExecuteProcSql(hook.ParentName));

                if (changes.Desired.Get(hook) == null)
                {
                    changes.Remove(null, hook);
                }
            }
        }
Пример #4
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var current in TriggerType.AllFrom(changes.Current))
            {
                if (!TriggerType.TriggerHasChanged(changes, current))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropTriggerSql(current.ParentName, current.Name), current);
            }
        }
Пример #5
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var current in SequenceType.AllFrom(changes.Current))
            {
                if (changes.Desired.Contains(current))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropSequenceSql(current.Name), current);
            }
        }
Пример #6
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var current in ViewType.AllFrom(changes.Current))
            {
                var desired = changes.Desired.Get(current);
                if (desired != null && ViewType.IsEqual(current.State, desired.State, changes.DbDriver))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropViewSql(current.Name), current);
            }
        }
Пример #7
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            // This step covers both unique keys (including primary keys) and non-unique indexes
            foreach (var current in UniqueIndexType.AllFrom(changes.Current))
            {
                if (!UniqueIndexType.IndexHasChanged(changes, current))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropUniqueConstraintSql(current.ParentName, current.Name), current);
            }
            foreach (var current in NonUniqueIndexType.AllFrom(changes.Current))
            {
                if (!NonUniqueIndexType.IndexHasChanged(changes, current))
                {
                    continue;
                }

                changes.Remove(changes.SchemaDriver.GetDropIndexSql(current.ParentName, current.Name), current);
            }
        }
Пример #8
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var current in QueryType.AllFrom(changes.Current))
            {
                // Queries that are neither stored proc or stored function in the current schema don't need to be dropped!
                if (current.State == null)
                {
                    continue;
                }

                var desired = changes.Desired.Get(current);
                if (desired != null)
                {
                    if (changes.SchemaDriver.IsCreateOrReplaceProcSupported)
                    {
                        // If CREATE OR REPLACE PROCEDURE is supported in the current database, there's no need to drop it unless
                        // it's changed from function to procedure or vice versa.
                        if (QueryType.IsTypeEqual(current.State, desired.State))
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // Even if CREATE OR REPLACE PROCEDURE is not supported, we don't need to drop it if it's
                        // not changed at all.
                        if (QueryType.IsEqual(current.State, desired.State, changes.DbDriver))
                        {
                            continue;
                        }
                    }
                }

                var dropSql = current.State is QueryType.FunctionState
                    ? changes.SchemaDriver.GetDropFunctionSql(current.Name)
                    : changes.SchemaDriver.GetDropProcSql(current.Name);

                if (desired != null)
                {
                    // The query isn't going away entirely so we don't want to lose its associated before statements
                    changes.Put(dropSql, QueryType.CreateUnstored(current.Name));
                }
                else
                {
                    changes.Remove(dropSql, current);
                }
            }
        }
Пример #9
0
        private void renameTempTables(SchemaChanges changes, IOutput output)
        {
            // For any PendingReorderTables where the original table doesn't exist, rename the table to the target name and remove the pending rename.
            foreach (var pending in PendingReorderTableType.AllFrom(changes.Current))
            {
                var originalTable = TableType.Identifier(pending.Name);
                var tempTable     = pending.ParentIdentifier;

                if (changes.Current.ContainsRoot(originalTable))
                {
                    continue;
                }

                changes.Rename(changes.SchemaDriver.GetRenameTableSql(tempTable.Name, originalTable.Name), tempTable, originalTable);
                changes.Remove(null, pending.WithParent(originalTable));
            }
        }
Пример #10
0
        private void dropOriginalTables(SchemaChanges changes, IOutput output)
        {
            // For any tables that are the target of existing PendingReorderTables, drop them (without prompting).
            foreach (var pending in PendingReorderTableType.AllFrom(changes.Current))
            {
                var originalTable = TableType.Identifier(pending.Name);
                var tempTable     = pending.ParentIdentifier;

                if (!changes.Current.ContainsRoot(originalTable))
                {
                    continue;
                }

                // FIXME: (Consider sanity checks before doing this - anything from "confirm all the right column names exist" to "confirm the right number of rows exist" to
                // "confirm all the data is identical in all the rows")
                changes.Remove(changes.SchemaDriver.GetDropTableSql(originalTable.Name), changes.Current.GetRoot(originalTable));
            }
        }
Пример #11
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            foreach (var current in FieldType.AllFrom(changes.Current))
            {
                var desired = FieldType.GetDesired(changes, current);

                // At this point we are only dropping changed fields, not fields that are being
                // removed entirely, which we keep around til later to allow them to be used by
                // before statements for migration. So we only want to drop fields that conflict
                // with fields in the eventual state of the table (including the conflict
                // that would occur if two identity fields existed in the same table).
                if (desired == null && !isSequencedPkeyToBeDropped(changes, current))
                {
                    continue;
                }

                // If the type and sequenced-ness are unchanged then we don't need to do anything here.
                if (desired != null && FieldType.IsTypeEqual(current.State, desired.State, changes.SchemaDriver.IsSequencedPartOfFieldDeclaration))
                {
                    continue;
                }

                // Fields being dropped here need to be replaced later, so failing to drop them has to be fatal regardless of FieldDropBehavior
                if (!changes.AllowDropWithPossibleDataLoss(current, DropBehavior.Drop))
                {
                    continue;
                }

                // If we are about to drop the last field from a table, add a temporary field so that the drop will be allowed
                if (FieldType.ChildrenFrom(changes.Current, current.ParentIdentifier).Count() == 1)
                {
                    var placeholder = FieldType.Create(current.ParentIdentifier, "nrdo_placeholder_field", 2, "int", true);
                    changes.Put(changes.SchemaDriver.GetAddFieldSql(placeholder.ParentName, placeholder.Name, placeholder.State.DataType, false, null), placeholder);
                    if (changes.HasFailed)
                    {
                        continue;
                    }
                }

                // Drop the field
                changes.Remove(changes.SchemaDriver.GetDropFieldSql(current.ParentName, current.Name), current);
            }
        }
Пример #12
0
        public override void Perform(SchemaChanges changes, IOutput output)
        {
            if (changes.Options.TableDropBehavior == DropBehavior.SkipDrop)
            {
                return;
            }
            var errorResponse = changes.Options.TableDropBehavior == DropBehavior.TryDrop ? ErrorResponse.Ignore : ErrorResponse.Fail;

            foreach (var current in TableType.AllFrom(changes.Current))
            {
                if (changes.Desired.Contains(current))
                {
                    continue;
                }

                if (!changes.AllowDropWithPossibleDataLoss(current, changes.Options.TableDropBehavior))
                {
                    continue;
                }

                // Drop the table
                changes.Remove(changes.SchemaDriver.GetDropTableSql(current.Name), errorResponse, current);
            }
        }