the fix? was to add a check for self referential foreign keys in non-
self-referential relations, and do not add those as part of the
relation's foreign key collection,

is this anywhere near the correct thing to do?

                # ignore self referential keys
                if not (self.secondaryjoin or
self._is_self_referential() or binary.left.table !=
binary.right.table):
                    return


def _determine_fks(self):
        if len(self._legacy_foreignkey) and not
self._is_self_referential():
            self.foreign_keys = self._legacy_foreignkey

        def col_is_part_of_mappings(col):
            if self.secondary is None:
                return
self.parent.mapped_table.corresponding_column(col, raiseerr=False) is
not None or \
                    self.target.corresponding_column(col,
raiseerr=False) is not None
            else:
                return
self.parent.mapped_table.corresponding_column(col, raiseerr=False) is
not None or \
                    self.target.corresponding_column(col,
raiseerr=False) is not None or \
                    self.secondary.corresponding_column(col,
raiseerr=False) is not None

        if len(self.foreign_keys):
            self._opposite_side = util.Set()
            def visit_binary(binary):
                if binary.operator != '=' or not
isinstance(binary.left, schema.Column) or not isinstance(binary.right,
schema.Column):
                    return
                if binary.left in self.foreign_keys:
                    self._opposite_side.add(binary.right)
                if binary.right in self.foreign_keys:
                    self._opposite_side.add(binary.left)
 
mapperutil.BinaryVisitor(visit_binary).traverse(self.primaryjoin)
            if self.secondaryjoin is not None:
 
mapperutil.BinaryVisitor(visit_binary).traverse(self.secondaryjoin)
        else:
            self.foreign_keys = util.Set()
            self._opposite_side = util.Set()
            def visit_binary(binary):
                if binary.operator != '=' or not
isinstance(binary.left, schema.Column) or not isinstance(binary.right,
schema.Column):
                    return

                # this check is for when the user put the "view_only"
flag on and has tables that have nothing
                # to do with the relationship's parent/child mappings
in the join conditions.  we dont want cols
                # or clauses related to those external tables dealt
with.  see orm.relationships.ViewOnlyTest
                if not col_is_part_of_mappings(binary.left) or not
col_is_part_of_mappings(binary.right):
                    return

                # ignore self referential keys
                if not (self.secondaryjoin or
self._is_self_referential() or binary.left.table !=
binary.right.table):
                    return

                for f in binary.left.foreign_keys:
                    if f.references(binary.right.table):
                        self.foreign_keys.add(binary.left)
                        self._opposite_side.add(binary.right)
                for f in binary.right.foreign_keys:
                    if f.references(binary.left.table):
                        self.foreign_keys.add(binary.right)
                        self._opposite_side.add(binary.left)
 
mapperutil.BinaryVisitor(visit_binary).traverse(self.primaryjoin)

            if len(self.foreign_keys) == 0:
                raise exceptions.ArgumentError(
                    "Can't locate any foreign key columns in primary
join "
                    "condition '%s' for relationship '%s'.  Specify "
                    "'foreign_keys' argument to indicate which columns
in "
                    "the join condition are foreign." %
(str(self.primaryjoin), str(self)))
            if self.secondaryjoin is not None:
 
mapperutil.BinaryVisitor(visit_binary).traverse(self.secondaryjoin)

On Nov 6, 9:11 pm, Esceo <[EMAIL PROTECTED]> wrote:
> Just wondering if this is a bug in _determine_fks
>
> i.e. 'child.id'  probably should not be part of the foreign key
> pointing to parent
>
> On Nov 6, 7:42 pm, Esceo <[EMAIL PROTECTED]> wrote:
>
>
>
> > Hi, all
>
> > the followings are the code snippet
>
> > from sqlalchemy import *
> > meta = MetaData('sqlite://')
>
> > parent = Table('parent', meta,
> >         Column('id', Integer, primary_key=True),
> >         Column('name', Integer)
> > )
>
> > child = Table('child', meta,
> >         Column('id', Integer, primary_key=True),
> >         Column('current_id', Integer),
> >         Column('parent_id', Integer),
> >         ForeignKeyConstraint(['parent_id'],['parent.id'],
> > ondelete="CASCADE"),
> >         ForeignKeyConstraint(['current_id'],['child.id']), )
>
> > class Parent(object):
> >        pass
>
> > class Child(object):
> >        pass
>
> > mapper(Parent, parent);
>
> > mapper(Child, child,
> >     properties = { 'parent' : relation(Parent,
> >                                         primaryjoin =
> > (child.c.parent_id == parent.c.id) &
> >                                         (child.c.current_id ==
> > child.c.id),
> >                         backref = "child"),
> >                         'current' : relation(Child,
> >                         primaryjoin = child.c.current_id ==
> > child.c.id)
>
> > })
>
> > meta.create_all()
>
> > s = create_session()
> > c = Child()
> > c.parent = Parent()
> > s.save(c)
> > s.flush()
> > s.clear()
>
> > running that resulted in
>
> > Traceback (most recent call last):
> >   File "C:\powerforce\test_fk_relation.py", line 39, in <module>
> >     s.flush()
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\session.py", line 320, in flush
> >     self.uow.flush(self, objects)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 210, in flush
> >     flush_context.execute()
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 400, in execute
> >     UOWExecutor().execute(self, head)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 1018, in execute
> >     self.execute_save_steps(trans, task)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 1035, in
> > execute_save_steps
> >     self.execute_dependencies(trans, task, False)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 1048, in
> > execute_dependencies
> >     self.execute_dependency(trans, dep, False)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 1029, in
> > execute_dependency
> >     dep.execute(trans, isdelete)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\unitofwork.py", line 984, in execute
> >     self.processor.process_dependencies(self.targettask, [elem.obj for
> > elem in self.targettask.polymorphic_tosave_elements if elem.obj is not
> > None], trans, delete=False)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\dependency.py", line 275, in
> > process_dependencies
> >     self._synchronize(obj, child, None, False, uowcommit)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\dependency.py", line 310, in _synchronize
> >     self.syncrules.execute(source, dest, obj, child, clearkeys)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\sync.py", line 92, in execute
> >     rule.execute(source, dest, obj, child, clearkeys)
> >   File "C:\Python25\lib\site-packages\sqlalchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\sync.py", line 135, in execute
> >     value = self.source_mapper.get_attr_by_column(source,
> > self.source_column)
> >   File "C:\Python25\lib\site-packages\SQLAlchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\mapper.py", line 1017, in get_attr_by_column
> >     prop = self._getpropbycolumn(column, raiseerror)
> >   File "C:\Python25\lib\site-packages\SQLAlchemy-0.3.11dev_r3181-
> > py2.5.egg\sqlalchemy\orm\mapper.py", line 1007, in _getpropbycolumn
> >     raise exceptions.InvalidRequestError("Column '%s.%s' is not
> > available, due to conflicting property '%s':%s" % (column.table.name,
> > column.name, column.key, repr(prop)))
> > sqlalchemy.exceptions.InvalidRequestError: Column 'child.id' is not
> > available, d
> > ue to conflicting property
> > 'id':<sqlalchemy.orm.properties.ColumnProperty object at 0x016FB730>
>
> > If I had renamed the id column on child to '_id', I ended up with a
> > different error no child.id column configured on the maper Parent|
> > parent|
>
> > any clues?
>
> > Thanks in advance
>
> > Lei- Hide quoted text -
>
> - Show quoted text -


--~--~---------~--~----~------------~-------~--~----~
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