Skip to content

Commit 29561b9

Browse files
committed
Render the ondelete, onupdate and match options in foreign key constraints
1 parent a866435 commit 29561b9

4 files changed

Lines changed: 27 additions & 18 deletions

File tree

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ exclude = .tox
44

55
[pytest]
66
pep8maxlinelength = 120
7+
addopts = --tb=short
78

89
[wheel]
910
universal = 1

sqlacodegen/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version = '1.1.4'
1+
version = '1.1.4.post1'

sqlacodegen/codegen.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from sqlalchemy import (Enum, ForeignKeyConstraint, PrimaryKeyConstraint, CheckConstraint, UniqueConstraint, Table,
1111
Column)
12+
from sqlalchemy.schema import ForeignKey
1213
from sqlalchemy.util import OrderedDict
1314
from sqlalchemy.types import Boolean, String
1415
import sqlalchemy
@@ -109,15 +110,6 @@ def _render_column_type(coltype):
109110
return text
110111

111112

112-
def _render_fk(fk):
113-
text = "ForeignKey('%s.%s'" % (fk.column.table.fullname, fk.column.name)
114-
if fk.deferrable:
115-
text += ', deferrable=True'
116-
if fk.initially:
117-
text += ', initially=%r' % fk.initially
118-
return text + ')'
119-
120-
121113
def _render_column(column, show_name):
122114
kwarg = []
123115
is_sole_pk = column.primary_key and len(column.table.primary_key) == 1
@@ -149,17 +141,29 @@ def _render_column(column, show_name):
149141
return 'Column({0})'.format(', '.join(
150142
([repr(column.name)] if show_name else []) +
151143
([_render_column_type(column.type)] if render_coltype else []) +
152-
[_render_fk(x) for x in dedicated_fks] +
144+
[_render_constraint(x) for x in dedicated_fks] +
153145
[repr(x) for x in column.constraints] +
154146
['{0}={1}'.format(k, repr(getattr(column, k))) for k in kwarg]))
155147

156148

157149
def _render_constraint(constraint):
158-
if isinstance(constraint, ForeignKeyConstraint):
150+
def render_fk_options(*opts):
151+
opts = [repr(opt) for opt in opts]
152+
for attr in 'ondelete', 'onupdate', 'deferrable', 'initially', 'match':
153+
value = getattr(constraint, attr)
154+
if value:
155+
opts.append('{0}={1!r}'.format(attr, value))
156+
157+
return ', '.join(opts)
158+
159+
if isinstance(constraint, ForeignKey):
160+
remote_column = '{0}.{1}'.format(constraint.column.table.fullname, constraint.column.name)
161+
return 'ForeignKey({0})'.format(render_fk_options(remote_column))
162+
elif isinstance(constraint, ForeignKeyConstraint):
159163
local_columns = constraint.columns
160164
remote_columns = ['{0}.{1}'.format(fk.column.table.fullname, fk.column.name)
161165
for fk in constraint.elements]
162-
return 'ForeignKeyConstraint({0!r}, {1!r})'.format(local_columns, remote_columns)
166+
return 'ForeignKeyConstraint({0})'.format(render_fk_options(local_columns, remote_columns))
163167
elif isinstance(constraint, CheckConstraint):
164168
return 'CheckConstraint({0!r})'.format(_get_compiled_expression(constraint.sqltext))
165169
elif isinstance(constraint, UniqueConstraint):
@@ -465,7 +469,7 @@ def __init__(self, metadata, noindexes=False, noconstraints=False, nojoined=Fals
465469
for table in metadata.tables.values():
466470
# Link tables have exactly two foreign key constraints and all columns are involved in them
467471
fk_constraints = [constr for constr in table.constraints if isinstance(constr, ForeignKeyConstraint)]
468-
if (len(fk_constraints) == 2 and all(col.foreign_keys for col in table.columns)):
472+
if len(fk_constraints) == 2 and all(col.foreign_keys for col in table.columns):
469473
association_tables.add(table.name)
470474
tablename = sorted(fk_constraints, key=_get_constraint_sort_key)[0].elements[0].column.table.name
471475
links[tablename].append(table)

test/test_codegen.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,8 @@ def test_onetomany_composite(self):
414414
Column('id', INTEGER, primary_key=True),
415415
Column('container_id1', INTEGER),
416416
Column('container_id2', INTEGER),
417-
ForeignKeyConstraint(['container_id1', 'container_id2'], ['simple_containers.id1', 'simple_containers.id2'])
417+
ForeignKeyConstraint(['container_id1', 'container_id2'], ['simple_containers.id1', 'simple_containers.id2'],
418+
ondelete='CASCADE', onupdate='CASCADE', match='PARTIAL')
418419
)
419420
Table(
420421
'simple_containers', self.metadata,
@@ -443,7 +444,8 @@ class SimpleContainer(Base):
443444
class SimpleItem(Base):
444445
__tablename__ = 'simple_items'
445446
__table_args__ = (
446-
ForeignKeyConstraint(['container_id1', 'container_id2'], ['simple_containers.id1', 'simple_containers.id2']),
447+
ForeignKeyConstraint(['container_id1', 'container_id2'], ['simple_containers.id1', 'simple_containers.id2'], \
448+
ondelete='CASCADE', onupdate='CASCADE', match='PARTIAL'),
447449
)
448450
449451
id = Column(Integer, primary_key=True)
@@ -899,7 +901,8 @@ def test_schema_boolean(self):
899901
def test_foreign_key_options(self):
900902
Table(
901903
'simple_items', self.metadata,
902-
Column('name', VARCHAR, ForeignKey('simple_items.name', deferrable=True, initially='DEFERRED'))
904+
Column('name', VARCHAR, ForeignKey('simple_items.name', ondelete='CASCADE', onupdate='CASCADE',
905+
deferrable=True, initially='DEFERRED', match='PARTIAL'))
903906
)
904907

905908
assert self.generate_code() == """\
@@ -912,7 +915,8 @@ def test_foreign_key_options(self):
912915
913916
t_simple_items = Table(
914917
'simple_items', metadata,
915-
Column('name', String, ForeignKey('simple_items.name', deferrable=True, initially='DEFERRED'))
918+
Column('name', String, ForeignKey('simple_items.name', ondelete='CASCADE', onupdate='CASCADE', \
919+
deferrable=True, initially='DEFERRED', match='PARTIAL'))
916920
)
917921
"""
918922

0 commit comments

Comments
 (0)