Skip to content

Commit

Permalink
Merge pull request #7 from keredson/3-circular-fk-dep-error
Browse files Browse the repository at this point in the history
fix for tries to create table referencing foreign key when table does…
  • Loading branch information
keredson authored Nov 21, 2016
2 parents 5cebc45 + 25486b3 commit 6e78111
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
22 changes: 15 additions & 7 deletions peeweedbevolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# peewee doesn't do defaults in the database - doh!
DIFF_DEFAULTS = False

__version__ = '0.4.5'
__version__ = '0.4.6'


try:
Expand All @@ -26,10 +26,15 @@
unicode = lambda s: str(s)


def sort_by_fk_deps(table_names):
def mark_fks_as_deferred(table_names):
add_fks = []
table_names_to_models = {cls._meta.db_table:cls for cls in all_models.keys() if cls._meta.db_table in table_names}
models = pw.sort_models_topologically(table_names_to_models.values())
return [model._meta.db_table for model in models]
for model in table_names_to_models.values():
for field in model._meta.sorted_fields:
if isinstance(field, pw.ForeignKeyField):
add_fks.append(field)
field.deferred = True
return add_fks

def calc_table_changes(existing_tables):
existing_tables = set(existing_tables)
Expand All @@ -51,8 +56,8 @@ def calc_table_changes(existing_tables):
adds.remove(to_add)
deletes.remove(a)
break
adds = sort_by_fk_deps(adds)
return adds, deletes, renames
add_fks = mark_fks_as_deferred(adds)
return adds, add_fks, deletes, renames

def is_postgres(db):
return db.__class__.__name__ in ['PostgresqlDatabase','PooledPostgresqlDatabase','PostgresqlExtDatabase']
Expand Down Expand Up @@ -311,9 +316,12 @@ def calc_changes(db):
qc = db.compiler()
to_run = []

table_adds, table_deletes, table_renames = calc_table_changes(existing_tables)
table_adds, add_fks, table_deletes, table_renames = calc_table_changes(existing_tables)
table_renamed_from = {v:k for k,v in table_renames.items()}
to_run += [qc.create_table(table_names_to_models[tbl]) for tbl in table_adds]
for field in add_fks:
op = qc._create_foreign_key(field.model_class, field)
to_run.append(qc.parse_node(op))
for k,v in table_renames.items():
ops = migrator.rename_table(k,v, generate=True)
if not hasattr(ops, '__iter__'): ops = [ops] # sometimes pw return arrays, sometimes not
Expand Down
11 changes: 11 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,17 @@ class Meta:
self.evolve_and_check_noop()
self.assertEqual(SomeModel.select().first().some_field, 'woot')

def test_circular_deps(self):
class SomeModel(pw.Model):
some_model2 = pw.ForeignKeyField(pw.DeferredRelation('SomeModel2'))
class Meta:
database = self.db
class SomeModel2(pw.Model):
some_model = pw.ForeignKeyField(SomeModel)
class Meta:
database = self.db
self.evolve_and_check_noop()



## SQLite doesn't work
Expand Down

0 comments on commit 6e78111

Please sign in to comment.