Christoph Zwerschke wrote:

> But that expression needs to be parsed to SQL anyway, and doing so all
> involved columns could be tracked. Another clue is that the class for
> the relation object has been stated as 'Group' which is mapped to
> pg_group. Why do you actually need a Foreign*Key*, not a Foreign*Table*?

yes, i could absolutely parse it out.  you should dig around the source
code a little bit to see how that works, including the diffs for the
revsion i just made for this one which illustrate how its done.

with regards to "foreignkey", i am just not totally comfortable
throwing some more "automatic" behavior in there just yet, for reasons
already stated, since its easy enough to state it explicitly.

the "foreignkey" parameter is still undergoing an evolution and a
clarification, which is one reason its still a little murky as to what
its used for and what it needs to know.  it accomplishes multiple
things and i have not yet worked out a really good way to clarify its
individual roles.

currently, heres why its a list of columns:

- for a self-referential mapper or other self-referring table
relationship, where theres only one table anyway...we need to know
specific columns in that case in order to determine what kind of
relationship we are looking at.

- it can account for all the foreign key columns in a more complicated
join condition, where maybe only one of those columns actually points
to the target table and therefore has meaning.

- it is used in the determination of the "lazy clause" in a
self-referential table relationship so that it can determine what
columns in the clause get converted into a bind parameter for a lazy
load.

- i have recently stepped up its role to also indicate which
column-mapped attributes should actually be "synchronized" when objects
are connected together or detached during flush time.  here is a
snippet of the recent example someone had (which is also present in the
"relationships.py" unit test if you want to play with it):

 pageversions = Table("pageversions", metadata,
                        Column("jobno", Unicode(15), primary_key=True),
                        Column("pagename", Unicode(30),
primary_key=True),
                        Column("version", Integer, primary_key=True,
default=1),
                       )
                        )
pages = Table("pages", metadata,
                        Column("jobno", Unicode(15),
ForeignKey("jobs.jobno"), primary_key=True),
                        Column("pagename", Unicode(30),
primary_key=True),
                        Column("current_version", Integer))

 mapper(Page, pages, properties={
            'currentversion': relation(PageVersion,
                            foreignkey=pages.c.current_version,

primaryjoin=and_(pages.c.jobno==pageversions.c.jobno,

pages.c.pagename==pageversions.c.pagename,

pages.c.current_version==pageversions.c.version),
                            post_update=True),
            'versions': relation(PageVersion, cascade="all,
delete-orphan",

primaryjoin=and_(pages.c.jobno==pageversions.c.jobno,

pages.c.pagename==pageversions.c.pagename),
                            order_by=pageversions.c.version,
                            backref=backref('page', lazy=False,

primaryjoin=and_(pages.c.jobno==pageversions.c.jobno,

pages.c.pagename==pageversions.c.pagename)))
        })

above, the "Page" object points to a list of PageVersion objects, via
the "versions" relation.  however, there is also a second relationship
between them called "currentversion", which refers to the "current"
entry in the "versions" relation.  When a given PageVersion becomes the
"currentversion", the "current_version" column in Page gets set to its
"version" value, and when it is removed as the "currentversion", the
"version" value gets removed.  However, the other columns in the join
condition (jobno and pagename) do not change.  In this example they are
primary key columns, and nulling them out raises an error on flush.
the "foreignkey" here refers only to "current_version" and indicates
the only column that actually needs to be changed when
attaching/detaching the "currentversion" to "Page".

its pretty impressive to me how far SA has managed to go with its
current relationship-definition model, which is literally a SQL
expression and a list of columns...because it is so sparse yet it is
more powerful than any other system I have ever seen (including
hibernate by a mile).  it might be time for a less sparse approach to
the whole thing, for reasons of clarity, but it hasnt really dawned on
me yet what that might look like.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sqlalchemy
-~----------~----~----~----~------~----~------~--~---

Reply via email to