Beispiel #1
0
        private void createTempTables(SchemaChanges changes, IOutput output)
        {
            // For any tables with order-sensitivity and fields in different order between current and desired (ignoring fields that only exist in current),
            // Create a new table  "_nrdo_reorder" using "select (columns in correct order followed by columns to be dropped) from original table into newname"
            // Put the table, the fields (with nullability, datatype and identityness as current but in new order) and a PendingReorderTable into current
            // For any tables that need their fields reordered, create a copy of the table with the fields in the right order.
            foreach (var origTable in TableType.AllFrom(changes.Current))
            {
                // Tables that don't exist in desired state are to be dropped, they certainly don't need to be reordered!
                if (!changes.Desired.Contains(origTable))
                {
                    continue;
                }

                // Figure out whether a reorder is needed
                if (!FieldType.IsFieldReorderNeeded(changes, origTable.Identifier))
                {
                    continue;
                }

                // Put the fields in order.
                // At this point there may be extra fields that are to be dropped but haven't been yet. They need to stick around until
                // it's time to drop them, because before statements may rely on them. But we put those ones last (in the order they're currently in).
                var fieldsInOrder = from field in FieldType.ChildrenFrom(changes.Current, origTable.Identifier)
                                    let desired = changes.Desired.Get(field)
                                                  orderby
                                                  desired != null ? desired.State.OrdinalPosition : int.MaxValue,
                    field.State.OrdinalPosition
                select field;

                // Construct the state representation that will be used for the new table.
                // It inherits all before statements from the original table so that when it's renamed they'll still be there.
                // FIXME: This hardcodes the assumption that CreateTableAsSelect preserves field type, nullability and identity-ness, which may or may not be true on other DBs
                // FIXME: any other aspects of field state that we add support for (Default values, check constraints...) need to get dropped here.
                var tempTable       = TableType.Create(origTable.Name + "_nrdo_reorder");
                var pendingReorder  = PendingReorderTableType.Create(tempTable.Identifier, origTable.Name);
                var tempTableFields = from fi in fieldsInOrder.Select((field, index) => new { field, index })
                                      select fi.field
                                      .WithParent(tempTable.Identifier)
                                      .With(s => s.WithOrdinalPosition(fi.index));

                var tempTableBefores = from before in BeforeStatementType.ChildrenFrom(changes.Current, origTable.Identifier)
                                       select before.WithParent(tempTable.Identifier);

                // Gather all temporary objects into one list to put them into the database together
                var tempTableObjects =
                    new ObjectState[]
                {
                    tempTable,
                    pendingReorder
                }
                .Concat(tempTableFields)
                .Concat(tempTableBefores);

                var sql = changes.SchemaDriver.GetCreateTableAsSelectSql(tempTable.Name,
                                                                         string.Join(", ", from field in fieldsInOrder select changes.DbDriver.QuoteIdentifier(field.Name)),
                                                                         changes.DbDriver.QuoteSchemaIdentifier(origTable.Name));

                changes.Put(sql, tempTableObjects);
            }
        }