From: Mike Bayer Date: Fri, 13 Jul 2007 07:36:39 +0000 (+0000) Subject: - composite primary key is represented as a non-keyed set to allow for X-Git-Tag: rel_0_3_9~23 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de220677418653257b0068c71e87698e8978796b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - composite primary key is represented as a non-keyed set to allow for composite keys consisting of cols with the same name; occurs within a Join. helps inheritance scenarios formulate correct PK. - ticket #185 reopened. still need to get Join to produce a minmal PK for fk'ed columns --- diff --git a/CHANGES b/CHANGES index 3cdb3cce0b..bd71fe1b1f 100644 --- a/CHANGES +++ b/CHANGES @@ -50,6 +50,9 @@ - DynamicMetaData has been renamed to ThreadLocalMetaData. the DynamicMetaData name is deprecated and is an alias for ThreadLocalMetaData or a regular MetaData if threadlocal=False + - composite primary key is represented as a non-keyed set to allow for + composite keys consisting of cols with the same name; occurs within a + Join. helps inheritance scenarios formulate correct PK. - some enhancements to "column targeting", the ability to match a column to a "corresponding" column in another selectable. this affects mostly ORM ability to map to complex joins diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index ff6aa5e2c1..d1fc3fef17 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -1618,6 +1618,25 @@ class ColumnCollection(util.OrderedProperties): # "True" value (i.e. a BinaryClause...) return col in util.Set(self) +class ColumnSet(util.OrderedSet): + def contains_column(self, col): + return col in self + + def extend(self, cols): + for col in cols: + self.add(col) + + def __add__(self, other): + return list(self) + list(other) + + def __eq__(self, other): + l = [] + for c in other: + for local in self: + if c.shares_lineage(local): + l.append(c==local) + return and_(*l) + class FromClause(Selectable): """Represent an element that can be used within the ``FROM`` clause of a ``SELECT`` statement. @@ -1762,7 +1781,7 @@ class FromClause(Selectable): # TODO: put a mutex here ? this is a key place for threading probs return self._columns = ColumnCollection() - self._primary_key = ColumnCollection() + self._primary_key = ColumnSet() self._foreign_keys = util.Set() self._orig_cols = {} for co in self._adjusted_exportable_columns(): diff --git a/test/orm/abc_inheritance.py b/test/orm/abc_inheritance.py index 766bbc5df1..9b2928fbec 100644 --- a/test/orm/abc_inheritance.py +++ b/test/orm/abc_inheritance.py @@ -84,9 +84,14 @@ def produce_test(parent, child, direction): class B(A):pass class C(B):pass - mapper(A, ta, polymorphic_on=abcjoin.c.type, select_table=abcjoin, polymorphic_identity="a") - mapper(B, tb, polymorphic_on=bcjoin.c.type, select_table=bcjoin, polymorphic_identity="b", inherits=A, inherit_condition=atob) - mapper(C, tc, polymorphic_identity="c", inherits=B, inherit_condition=btoc) + mapper(A, ta, polymorphic_on=abcjoin.c.type, select_table=abcjoin, polymorphic_identity="a", ) + mapper(B, tb, polymorphic_on=bcjoin.c.type, select_table=bcjoin, polymorphic_identity="b", inherits=A, inherit_condition=atob,) + mapper(C, tc, polymorphic_identity="c", inherits=B, inherit_condition=btoc, ) + + #print "KEYS:" + #print [c.key for c in class_mapper(A).primary_key] + #print [c.key for c in class_mapper(B).primary_key] + #print [c.key for c in class_mapper(C).primary_key] parent_mapper = class_mapper({ta:A, tb:B, tc:C}[parent_table]) child_mapper = class_mapper({ta:A, tb:B, tc:C}[child_table]) @@ -121,13 +126,14 @@ def produce_test(parent, child, direction): sess.clear() # assert result via direct get() of parent object - result = sess.query(parent_class).get(parent_obj.id) + # TODO: dual PK here is a temporary workaround until #185 is fixed again + result = sess.query(parent_class).get([parent_obj.id, parent_obj.id]) assert result.id == parent_obj.id assert result.collection[0].id == child_obj.id if direction == ONETOMANY: assert result.collection[1].id == child2.id elif direction == MANYTOONE: - result2 = sess.query(parent_class).get(parent2.id) + result2 = sess.query(parent_class).get([parent2.id, parent2.id]) assert result2.id == parent2.id assert result2.collection[0].id == child_obj.id