private void UpdateSchemas(Database database, StreamWriter writer, PgDatabase oldDatabase, PgDatabase newDatabase)
        {
            var newAndOldSchemas = new Dictionary <PgSchema, PgSchema>();

            foreach (var newSchema in newDatabase.Schemas)
            {
                // ignore the ignored schemas
                if (database.IgnoredSchemas.Contains(newSchema.Name))
                {
                    continue;
                }

                var searchPathHelper = new SearchPathHelper(newSchema);
                var oldSchema        = oldDatabase.GetSchema(newSchema.Name);
                if (oldSchema != null)
                {
                    if ((oldSchema.Comment == null && newSchema.Comment != null) ||
                        (oldSchema.Comment != null && newSchema.Comment != null && !oldSchema.Comment.Equals(newSchema.Comment)))
                    {
                        writer.WriteLine();
                        writer.Write("COMMENT ON SCHEMA ");
                        writer.Write(newSchema.Name.QuoteName());
                        writer.Write(" IS ");
                        writer.Write(newSchema.Comment);
                        writer.WriteLine(';');
                    }
                    else if (oldSchema.Comment != null && newSchema.Comment == null)
                    {
                        writer.WriteLine();
                        writer.Write("COMMENT ON SCHEMA ");
                        writer.Write(newSchema.Name.QuoteName());
                        writer.WriteLine(" IS NULL;");
                    }
                }

                newAndOldSchemas.Add(newSchema, oldSchema);
            }

            var schemaActions = new List <Action <StreamWriter, PgSchema, PgSchema> >()
            {
                (w, newSchema, oldSchema) => { PgDiffTriggers.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffAggregate.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffFunctions.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffViews.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffRules.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.Drop(w, oldSchema, newSchema, true, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.Drop(w, oldSchema, newSchema, false, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffIndexes.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTables.DropClusters(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTables.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTypes.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffSequences.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffSequences.Alter(w, oldSchema, newSchema, new SearchPathHelper(newSchema), false); },
                (w, newSchema, oldSchema) => { PgDiffTables.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTables.Alter(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffSequences.AlterCreatedSequences(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffFunctions.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema), false); },
                (w, newSchema, oldSchema) => { PgDiffAggregate.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.Create(w, oldSchema, newSchema, true, false, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.Create(w, oldSchema, newSchema, false, false, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.Create(w, oldSchema, newSchema, false, true, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffIndexes.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTables.CreateClusters(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTriggers.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffViews.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffViews.Alter(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffRules.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffSequences.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffPrivileges.Create(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },

                // drop type after table is altered
                (w, newSchema, oldSchema) => { PgDiffTypes.Drop(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },

                (w, newSchema, oldSchema) => { PgDiffFunctions.AlterComments(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffConstraints.AlterComments(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffIndexes.AlterComments(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
                (w, newSchema, oldSchema) => { PgDiffTriggers.AlterComments(w, oldSchema, newSchema, new SearchPathHelper(newSchema)); },
            };

            foreach (var action in schemaActions)
            {
                foreach (var newAndOldSchema in newAndOldSchemas)
                {
                    action(writer, newAndOldSchema.Key, newAndOldSchema.Value);
                }
            }
        }