- changed title to aliased column overrides don't override
- changed component to sql
aliased column overrides don't override
When using MySQL 4 table reflection with assign_mapper and a table column override, updating an object causes the following error:
sqlalchemy.exceptions.ConcurrentModificationError: Updated rowcount 0 does not match number of objects updated 1
The table setup looks like:
user_table = Table('ur', sac.get_metadata('default'),
Column('cs_rid', Integer, primary_key=True, key='id'),
autoload=True)
class User(object):
pass
assign_mapper(sac.session_context, User, user_table)
Upon removing the primary_key statement from the Column, the exception disappears.
Comments (7)
-
-
- changed milestone to 0.3.9
A fix for the case above is straightforward, but more thought needs to go into what the expected behavior is with regard to existing autoloaded keys and constraints, especially if the override specifies different pk/fk keying than the original.
-
- changed milestone to 0.4.0
-
repo owner im happy with just the "key" part of this for now; committed in changeset:2909.
oh i guess we'll leave the rest to 0.4 then....
-
repo owner - changed milestone to 0.5.0
here's a patch, make _link_to_name public too:
Index: lib/sqlalchemy/schema.py =================================================================== --- lib/sqlalchemy/schema.py (revision 5527) +++ lib/sqlalchemy/schema.py (working copy) @@ -769,7 +769,7 @@ __visit_name__ = 'foreign_key' - def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None): + def __init__(self, column, constraint=None, use_alter=False, name=None, onupdate=None, ondelete=None, deferrable=None, initially=None, _link_to_name=False): """ Construct a column-level FOREIGN KEY. @@ -812,6 +812,7 @@ self.ondelete = ondelete self.deferrable = deferrable self.initially = initially + self._link_to_name = _link_to_name def __repr__(self): return "ForeignKey(%r)" % self._get_colspec() @@ -888,10 +889,16 @@ else: _column = table.c[colname](colname) except KeyError, e: - raise exc.NoReferencedColumnError( - "Could not create ForeignKey '%s' on table '%s': " - "table '%s' has no column named '%s'" % ( - self._colspec, parenttable.name, table.name, str(e))) + _column = None + if self._link_to_name: + for c in table.c: + if c.name == colname: + _column = c + if not _column: + raise exc.NoReferencedColumnError( + "Could not create ForeignKey '%s' on table '%s': " + "table '%s' has no column named '%s'" % ( + self._colspec, parenttable.name, table.name, e)) elif hasattr(self._colspec, '__clause_element__'): _column = self._colspec.__clause_element__() @@ -1191,7 +1198,7 @@ """ __visit_name__ = 'foreign_key_constraint' - def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None): + def __init__(self, columns, refcolumns, name=None, onupdate=None, ondelete=None, use_alter=False, deferrable=None, initially=None, _link_to_name=False): """Construct a composite-capable FOREIGN KEY. columns @@ -1235,6 +1242,7 @@ self.elements = util.OrderedSet() self.onupdate = onupdate self.ondelete = ondelete + self._link_to_name = _link_to_name if self.name is None and use_alter: raise exc.ArgumentError("Alterable ForeignKey/ForeignKeyConstraint requires a name") self.use_alter = use_alter @@ -1247,7 +1255,7 @@ self.append_element(c, r) def append_element(self, col, refcol): - fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter) + fk = ForeignKey(refcol, constraint=self, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete, use_alter=self.use_alter, _link_to_name=self._link_to_name) fk._set_parent(self.table.c[col](col)) self._append_fk(fk) Index: lib/sqlalchemy/databases/sqlite.py =================================================================== --- lib/sqlalchemy/databases/sqlite.py (revision 5527) +++ lib/sqlalchemy/databases/sqlite.py (working copy) @@ -522,7 +522,7 @@ if refspec not in fk[1](1): fk[1](1).append(refspec) for name, value in fks.iteritems(): - table.append_constraint(schema.ForeignKeyConstraint(value[0](0), value[1](1))) + table.append_constraint(schema.ForeignKeyConstraint(value[0](0), value[1](1), _link_to_name=True)) # check for UNIQUE indexes c = connection.execute("%sindex_list(%s)" % (pragma, qtable)) unique_indexes = []
-
repo owner - changed status to resolved
reflected foreign keys target by column name only in 83a756c5415fad752933ed7f1aff69d2a184d618.
-
repo owner - removed milestone
Removing milestone: 0.5.0 (automated comment)
- Log in to comment
When aliased user columns (key=) are processed after autoload, ColumnCollection.add includes them via column.key, alongside the originals which had column.key == collumn.name.
This affects all autoloads, not related to mysql reflection in particular.