On 06/01/2016 02:40 PM, Chase wrote:
We have found it useful to be able to print out the schema in SQL to
look at it, and to diff versions of it alongside versions of the orm.
Printing it out is relatively straightforward, diffing slightly less;
currently we're using something very close to the following:

def dump_schema(TheModelBase):
    out = StringIO()

    def dump(sql, *multiparams, **params):
        out.write(('%s' % sql.compile(dialect=engine.dialect)).strip()+';\n\n')

    engine = create_engine('postgres://', strategy='mock', executor=dump)
    # patch tables with consistent collections so things get output in a
# consistent order
# Note: This doesn't fully work. The topo sort yields sets of nodes from the
# graph, these sets are not guaranteed to be consistent.
tables = TheModelBase.metadata.tables
    for table in tables.values():
        table.indexes = SortedSet(table.indexes)
    TheModelBase.metadata.tables = OrderedDict(
        (k, tables[k]) for k in sorted(tables.keys())
    )
    TheModelBase.metadata.create_all(engine)
    TheModelBase.metadata.tables = tables

    # tweak the spacing
text = out.getvalue().strip()
    text = text.replace('\t', ' ')
    text = re.sub(r' *$', '', text, flags=re.MULTILINE)
    # Make this and "PRIMARY KEY (" line up
text = text.replace('FOREIGN KEY(', 'FOREIGN KEY (')

    # alphabetically sort certain statements within their groupings
def sort_statement_groups(text, prefix):
        return '\n\n'.join(it.chain(*[
            sorted(statements) if prefixed else list(statements)
            for prefixed, statements in it.groupby(text.split('\n\n'), 
key=lambda x: x.startswith(prefix))
        ]))
    text = sort_statement_groups(text, 'CREATE TYPE')
    text = sort_statement_groups(text, 'CREATE INDEX')

    HEADER = '-- Autogenerated SQL, manual edits will be discarded\n\n\n'
return HEADER + text + '\n'


I think this has been pretty useful, I'm wondering if it would be worth
having upstream, or if the consensus is that just the first four lines
of this function are "good enough" (it wasn't good enough for me).

There's always been an interest in the part of this that adds newlines and whitespace in the form of "pretty printing", but for this feature to be part of SQLAlchemy it needs to be implemented as a SQLCompiler class that acts as a filter on top of an existing SQLCompiler. There have been some attempts by contributors to implement parts of this but nobody has seen this through to a real feature.

As far as the deterministic ordering, the mechanisms internally are there to do this but they are not called upon within the DDL emission scheme; that is, if you call upon metadata.sorted_tables, you get the tables sorted not just by constraint dependency but deterministically within those groups. But the DDL rendering scheme doesn't make use of the secondary sorting right now, it sends the list of tables into the constraint-dependency sort without first sorting them alphabetically. It would need to be made to do so, and similar logic applied to the rendering of indexes.

Until then, what you have here is a useful recipe for sure.



~Cheers

--
You received this message because you are subscribed to the Google
Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to sqlalchemy+unsubscr...@googlegroups.com
<mailto:sqlalchemy+unsubscr...@googlegroups.com>.
To post to this group, send email to sqlalchemy@googlegroups.com
<mailto:sqlalchemy@googlegroups.com>.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to