Skip to content

Commit 6ee2320

Browse files
author
percious
committed
relations with composite keys should now work.
1 parent 97a0747 commit 6ee2320

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

sqlautocode/declarative.py

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from StringIO import StringIO
88

99
import sqlalchemy
10-
from sqlalchemy import exc
10+
from sqlalchemy import exc, and_
1111
from sqlalchemy import MetaData, ForeignKeyConstraint
1212
from sqlalchemy.ext.declarative import declarative_base
1313
try:
@@ -40,9 +40,6 @@
4040
handler.setFormatter(formatter)
4141
log.addHandler(handler)
4242

43-
def fk_repr(self):
44-
import ipdb; ipdb.set_trace()
45-
4643
def by_name(a, b):
4744
if a.name>b.name:
4845
return 1
@@ -232,14 +229,17 @@ def _relation_repr(cls, rel):
232229
target = target.__name__
233230
primaryjoin=''
234231
lookup = mtl()
235-
if rel.primaryjoin is not None:
232+
if rel.primaryjoin is not None and hasattr(rel.primaryjoin, 'right'):
236233
right_lookup = lookup.get(rel.primaryjoin.right.table.name, '%s.c'%rel.primaryjoin.right.table.name)
237234
left_lookup = lookup.get(rel.primaryjoin.left.table.name, '%s.c'%rel.primaryjoin.left.table.name)
238235

239236
primaryjoin = ", primaryjoin='%s.%s==%s.%s'"%(left_lookup,
240237
rel.primaryjoin.left.name,
241238
right_lookup,
242239
rel.primaryjoin.right.name)
240+
elif hasattr(rel, '_as_string'):
241+
primaryjoin=', primaryjoin="%s"'%rel._as_string
242+
243243
secondary = ''
244244
secondaryjoin = ''
245245
if rel.secondary is not None:
@@ -271,11 +271,11 @@ def __repr__(cls):
271271
else:
272272
s += " __tablename__ = '%s'\n\n"%table_name
273273
if hasattr(cls, '__table_args__'):
274-
if cls.__table_args__[0]:
275-
for fkc in cls.__table_args__[0]:
276-
fkc.__class__.__repr__ = foreignkeyconstraint_repr
277-
break
278-
s+=" __table_args__ = (%s, %s)\n\n"%(cls.__table_args__[0], cls.__table_args__[1])
274+
#if cls.__table_args__[0]:
275+
#for fkc in cls.__table_args__[0]:
276+
# fkc.__class__.__repr__ = foreignkeyconstraint_repr
277+
# break
278+
s+=" __table_args__ = %s\n\n"%cls.__table_args__
279279
s += " #column definitions\n"
280280
for column in sorted(cls.__table__.c, by_name):
281281
s += " %s = %s\n"%(column.name, column_repr(column))
@@ -297,7 +297,9 @@ def __repr__(cls):
297297

298298
#hack the class to have the right classname
299299
Temporal.__name__ = model_name
300-
Temporal.__table_args__ = ([], {})
300+
301+
#set up some blank table args
302+
Temporal.__table_args__ = {}
301303

302304
#add in the schema
303305
if self.config.schema:
@@ -322,18 +324,33 @@ def __repr__(cls):
322324

323325
setattr(Temporal, related_table.name, _deferred_relationship(Temporal, rel))
324326

325-
#add in composite foreign_keys
326-
for fk in self.get_composite_foreign_keys(table):
327-
log.info(' Adding composite FKs for: %s'%[item.column.name for item in fk])
328-
# import ipdb; ipdb.set_trace()
329-
Temporal.__table_args__[0].append(ForeignKeyConstraint([k.parent.name for k in fk],
330-
["%s.%s"%(k.column.table.name, k.column.name) for k in fk],
331-
use_alter=False,
332-
table=table
333-
))
334-
335-
#remove foreign keys from associated columns (they are likely wrong)
327+
#add in the relations for the composites
328+
for constraint in table.constraints:
329+
if isinstance(constraint, ForeignKeyConstraint):
330+
if len(constraint.elements) >1:
331+
related_table = constraint.elements[0].column.table
332+
related_classname = singular(name2label(related_table.name, related_table.schema))
333+
334+
print "and_(%s)"%', '.join(["%s.%s==%s.%s"%(model_name,
335+
k.parent.name,
336+
related_classname,
337+
k.column.name)
338+
for k in constraint.elements])
339+
340+
primary_join = "and_(%s)"%', '.join(["%s.%s==%s.%s"%(model_name,
341+
k.parent.name,
342+
related_classname,
343+
k.column.name)
344+
for k in constraint.elements])
345+
rel = relation(related_classname,
346+
primaryjoin=primary_join
347+
# foreign_keys=[k.parent for k in constraint.elements]
348+
)
349+
350+
rel._as_string = primary_join
351+
setattr(Temporal, related_table.name, rel) # _deferred_relationship(Temporal, rel))
336352

353+
337354
#add in many-to-many relations
338355
for join_table in self.get_related_many_to_many_tables(table.name):
339356

@@ -350,7 +367,6 @@ def __repr__(cls):
350367
if related_table not in self.tables:
351368
continue
352369
log.info(' Adding <secondary> foreign key(%s) for:%s'%(key, related_table.name))
353-
# import ipdb; ipdb.set_trace()
354370
setattr(Temporal, plural(related_table.name), _deferred_relationship(Temporal,
355371
relation(singular(name2label(related_table.name,
356372
related_table.schema)),

0 commit comments

Comments
 (0)