On Feb 22, 2013, at 12:04 AM, Rick Harris <[email protected]> wrote:

> Hi all,
> 
> I recently ran into an issue where one of our `sqlalchemy-migrate` downgrade 
> scripts was failing because it was trying to drop an index twice.
> 
> The root cause appears to be that SQLAlchemy's `idx.drop()` call does not 
> update the `indexes` set for  the associated table.
> 
> I've attached a test case which hopefully explains the situation a little 
> better.
> 
> My question is: is this expected behavior? Given that `index.create` mutates 
> `table.indexes`, should we expect `index.drop` to do the inverse and remove 
> it?
> 
> My naive assumption that it should, but if that wrong, I'd love to hear why.

index.create() doesn't mutate table.indexes, just the creation of the index 
does:

    assert len(users.indexes) == 0
    email_idx = sa.Index('idx_users_email', users.c.email)
    assert len(users.indexes) == 1

the structure of table metadata (by that term we mean, the whole structure of 
MetaData, Table, Column, Index, Constraint, etc.) is intended to be a fixed 
structure with only "additive" mutability - that is, you build one up to fully 
represent a particular schema.   It then offers create()/drop() hooks at 
various locations which provide the service of emitting DDL for a particular 
part of the metadata to a particular database connection.   However, the 
metadata structure is not by any definition be "tied" to one particular 
database.  You can emit create()/drop() for many engines/connections and this 
has no effect on the metadata structure itself - it only serves as a form that 
can be rendered into some particular DDL.

This is why you'll see that the concept of saying "metadata.bind = engine" or 
"MetaData(engine)" as it does in your test script is getting very hard to find 
in the documentation; this is a convenience feature that I identified some 
years ago as far more confusing to a lot of users than it is potentially useful 
as it creates the impression that the MetaData structure represents some kind 
of synchronized representation of a database; it doesn't.   So I never use this 
feature and I've been discouraging its use for years.  You'll see some 
exposition of this in the green note in this section: 
http://docs.sqlalchemy.org/en/rel_0_8/core/connections.html#connectionless-execution-implicit-execution

The sqlalchemy-migrate project tried to twist the MetaData structure into one 
that represents a "live" database structure, such that adding/removing items 
would emit ALTER statements and similar to a database; but this was never a 
great way to do things and it's a key reason I eventually found the resources 
to create the Alembic product which doesn't rely upon this pattern.     

In general, the metadata structure has only extremely limited support for 
non-additive mutability.






> 
> Thanks!
> 
> -- 
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>  
>  
> <test_drop_index.py>

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to