- [ticket:257] - oracle boolean type
- custom primary/secondary join conditions in a relation *will* be propigated
to backrefs by default. specifying a backref() will override this behavior.
+- better check for ambiguous join conditions in sql.Join; propigates to a
+better error message in PropertyLoader (i.e. relation()/backref()) for when
+the join condition can't be reasonably determined.
+- sqlite creates ForeignKeyConstraint objects properly upon table
+reflection.
0.2.6
- big overhaul to schema to allow truly composite primary and foreign
raise exceptions.NoSuchTableError(table.name)
c = connection.execute("PRAGMA foreign_key_list(" + table.name + ")", {})
+ fks = {}
while True:
row = c.fetchone()
if row is None:
break
- (tablename, localcol, remotecol) = (row[2], row[3], row[4])
- #print "row! " + repr(row)
+ (constraint_name, tablename, localcol, remotecol) = (row[0], row[2], row[3], row[4])
+ try:
+ fk = fks[constraint_name]
+ except KeyError:
+ fk = ([],[])
+ fks[constraint_name] = fk
+
+ print "row! " + repr([key for key in row.keys()]), repr(row)
# look up the table based on the given table's engine, not 'self',
# since it could be a ProxyEngine
remotetable = schema.Table(tablename, table.metadata, autoload=True, autoload_with=connection)
- table.c[localcol].append_item(schema.ForeignKey(remotetable.c[remotecol]))
+ constrained_column = table.c[localcol].name
+ refspec = ".".join([tablename, remotecol])
+ if constrained_column not in fk[0]:
+ fk[0].append(constrained_column)
+ if refspec not in fk[1]:
+ fk[1].append(refspec)
+ for name, value in fks.iteritems():
+ table.append_item(schema.ForeignKeyConstraint(value[0], value[1]))
# check for UNIQUE indexes
c = connection.execute("PRAGMA index_list(" + table.name + ")", {})
unique_indexes = []
else:
return self
+ def common_parent(self, other):
+ """return true if the given mapper shares a common inherited parent as this mapper"""
+ return self.base_mapper() is other.base_mapper()
+
def isa(self, other):
"""return True if the given mapper inherits from this mapper"""
m = other
if self.secondaryjoin is not None and self.secondary is None:
raise exceptions.ArgumentError("Property '" + self.key + "' specified with secondary join condition but no secondary argument")
# if join conditions were not specified, figure them out based on foreign keys
- if self.secondary is not None:
- if self.secondaryjoin is None:
- self.secondaryjoin = sql.join(self.mapper.unjoined_table, self.secondary).onclause
- if self.primaryjoin is None:
- self.primaryjoin = sql.join(self.parent.unjoined_table, self.secondary).onclause
- else:
- if self.primaryjoin is None:
- self.primaryjoin = sql.join(self.parent.unjoined_table, self.target).onclause
-
+ try:
+ if self.secondary is not None:
+ if self.secondaryjoin is None:
+ self.secondaryjoin = sql.join(self.mapper.unjoined_table, self.secondary).onclause
+ if self.primaryjoin is None:
+ self.primaryjoin = sql.join(self.parent.unjoined_table, self.secondary).onclause
+ else:
+ if self.primaryjoin is None:
+ self.primaryjoin = sql.join(self.parent.unjoined_table, self.target).onclause
+ except exceptions.ArgumentError, e:
+ raise exceptions.ArgumentError("Error determining primary and/or secondary join for relationship '%s' between mappers '%s' and '%s'. You should specify the 'primaryjoin' (and 'secondaryjoin', if there is an association table present) keyword arguments to the relation() function (or for backrefs, by specifying the backref using the backref() function with keyword arguments) to explicitly specify the join conditions. Nested error is \"%s\"" % (self.key, self.localparent, self.mapper, str(e)))
# if the foreign key wasnt specified and theres no assocaition table, try to figure
# out who is dependent on who. we dont need all the foreign keys represented in the join,
# just one of them.
return column
def _match_primaries(self, primary, secondary):
crit = []
+ constraints = util.Set()
for fk in secondary.foreign_keys:
if fk.references(primary):
crit.append(primary.corresponding_column(fk.column) == fk.parent)
+ constraints.add(fk.constraint)
self.foreignkey = fk.parent
if primary is not secondary:
for fk in primary.foreign_keys:
if fk.references(secondary):
crit.append(secondary.corresponding_column(fk.column) == fk.parent)
+ constraints.add(fk.constraint)
self.foreignkey = fk.parent
if len(crit) == 0:
raise exceptions.ArgumentError("Cant find any foreign key relationships between '%s' and '%s'" % (primary.name, secondary.name))
+# elif len(constraints) > 1:
+# raise exceptions.ArgumentError("Cant determine join between '%s' and '%s'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly. %s" % (primary.name, secondary.name, constraints))
elif len(crit) == 1:
return (crit[0])
else:
self.assert_(and_(table.c.multi_id==table2.c.foo, table.c.multi_rev==table2.c.bar).compare(j.onclause))
finally:
- meta.drop_all()
+ pass
+# meta.drop_all()
def testcheckfirst(self):
meta = BoundMetaData(testbase.db)