add an informative `__repr__` to all `SchemaItem` classes

Issue #2223 resolved
Former user created an issue

Trying to use sqlautocode, which essentially simply passes the class generation to sqlalchemy's reflection code.

I have a table with boolean fields in postgres.

When I try to reflect the table, it shows up with the proper columns, but also with an empty CheckConstraint() clause.

I believe CheckConstraint does not implement a repr, and it should.

I will see if I can figure out how to implement it, I have the basics done, but the values show up as bind params instead of values.

Comments (9)

  1. Former user Account Deleted

    This is different from #1443, since I believe it's not important which dialect you're using. Also, this is not a constraint explicitly defined in the table or in the column definition, but one added by types.Boolean.

  2. Former user Account Deleted

    The attached file attempts to give a representation of the CheckConstraint object, but it produces something like:

    CheckConstraint('platforms.configurable IN (:configurable_1, :configurable_2)', deferrable=None, initially=None, name=None),

    :configurable_1 etc should be values, not bind params.

  3. Mike Bayer repo owner

    First issue: "reflection on boolean fields does not work". I created a test case, cannot reproduce:

    from sqlalchemy import *
    from sqlalchemy.schema import CreateTable
    
    m = MetaData()
    t = Table('t', m, Column('x', Boolean))
    
    e = create_engine('postgresql://scott:tiger@localhost/test', echo='debug')
    m.drop_all(e)
    m.create_all(e)
    
    m2 = MetaData(e)
    t = Table('t', m2, autoload=True)
    assert isinstance(t.c.x.type, Boolean)
    

    passes. Boolean is reflected correctly.

    Next issue. "A check constraint is present". This is the behavior of the Boolean type such that a special constraint is added to the Table metadata, with a special conditional creation rule that only fires off if the Table DDL is generated on a platform where the constraint is required for the boolean. This is not a bug. It might be undesirable, would need to know what your use case is that this matters at all.

    Next issue. Constraint has no repr(). That's true, a large set of schema items don't have very good repr()s at the moment. A patch is added, needs tests for all SchemaItem classes with a variety of arguments. Can you confirm this is the only issue ? In the meantime I've renamed this ticket.

  4. Mike Bayer repo owner

    Also I'm -1 on making ClauseElement (the sqltext element here) do a compile. It's inconsistent to only do it within a constraint, especially only in CheckConstraint and nothing else - a ClauseElement should have the same repr() everywhere. Which then is not feasible for expressions to produce their "generic" compiled form - str() is used for that, and str() can also fail if the expression uses constructs that are only supported on certain dialects. To have SQL expressions fully produce their "constructor" form is not really feasible either, it produces enormous parenthesized expressions.

    If I'm debugging and I really need to poke around the sub-components of an expression I use pdb for that. repr() only goes so far.

  5. Former user Account Deleted

    I am sorry, this bug is not really a sqlalchemy bug at this point. As I was implying, I am trying to use sqlautocode, and I simply tested in the sqlautocode framework. I missed the part where they do:

    def monkey_patch_sa():
        sqlalchemy.sql.expression._TextClause.__repr__ = textclause_repr
        sqlalchemy.schema.Table.__repr__ = table_repr
        sqlalchemy.schema.Column.__repr__ = column_repr
        sqlalchemy.schema.ForeignKeyConstraint.__repr__ = foreignkeyconstraint_repr
        sqlalchemy.schema.Index.__repr__ = index_repr
    

    No wonder their representation was different than what I was used to.

    I silently assumed it was sqlalchemy's goal to have __repr___ methods that can be replayed as python models - that would indeed be nice and would eliminate the need for sqlautocode and possible drifts.

    Apologies for the confusion.

  6. Mike Bayer repo owner

    Replying to guest:

    I silently assumed it was sqlalchemy's goal to have __repr___ methods that can be replayed as python models - that would indeed be nice and would eliminate the need for sqlautocode and possible drifts.

    yes we'd have liked to do it that way, but when you consider the verbosity of representing a statement all the way down to every Table represented containing Column and TypeEngine objects, not to mention it's common that a particular SQL construct may be repeated, identity-wise, in many places throughout a statement, the __repr__() round trip scheme isn't really workable.

  7. Log in to comment