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.