On Apr 8, 2011, at 7:57 AM, Szumo wrote:

> Hello all,
> 
> I've a following piece of code that used to work fine with SA 0.6.6,
> but no longer
> works with 0.7 due to table.columns becoming an immutable collection.
> 
> def alterTableDropColumns(connection, table, *columns):
>    """
>    Drop some columns of a table.
>    Parameters are expected to be sqlalchemy objects.
>    """
>    statement = []
>    names = []
>    for column in columns:
>        if isinstance(column, sqlalchemy.Column):
>            name = column.name
>        else:
>            name = column
>            column = table.columns[name]
>        names.append(name)
>        statement.append("DROP COLUMN %s" % name)
>    connection.execute("ALTER TABLE %s %s" % (table.fullname,
> ",".join(statement)))
>    for name in names:
>        del table.columns[name]
> 
> Can anyone suggest a workaround that would let me do the same stuff in
> 0.7?

So that code above technically isn't bug-free in any version.  Suppose that 
column being dropped is also part of a Constraint, within that Table, or 
another Table.  Or its part of the primary key and is referred to by a 
ForeignKeyConstraint elsewhere.   Suppose a mapper has mapped to it, or a 
select() construct somewhere references it.    The Column object that you're 
discarding still references the parent Table, and may still be referenced in 
many other places.   The graph of schema objects is essentially in an invalid 
state, unless all of these linkages are also updated.   So that's why we made 
the collection publicly immutable - someone specifically had an expectation of 
correct behavior after modifying the collection directly (I think he was 
adding, not removing though, same idea since that's not the public channel for 
additions either).

Usually, a running program shouldn't be modifying the underlying schema of the 
database, then continuing to run - unless this is an application designed 
expressly as a schema modification tool, which I'm assuming is the case.    For 
that kind of tool there are two approaches you can take:

- For a tool like that I would be generating the Table object in an ad-hoc 
fashion - i.e. alter table drop columns, create a new Table object with the new 
structure, return it.   This probably assumes each Table has its own MetaData 
object since MetaData.tables has similar restrictions now.    I'm working on a 
schema migration tool that produces ALTER constructs in this way, by creating a 
Table as needed with just those constructs necessary for the alter.

- for a quick hit, the actual collection is available as table._columns.   All 
of the above cautions apply.




> 
> Maciej Szumocki
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to