mirror of
https://github.com/djrobstep/migra.git
synced 2024-09-11 13:56:05 +03:00
upgrade extensions with alter
This commit is contained in:
parent
86506ee3b5
commit
7077f74589
155
migra/changes.py
155
migra/changes.py
@ -28,9 +28,11 @@ def statements_for_changes(
|
||||
things_target,
|
||||
creations_only=False,
|
||||
drops_only=False,
|
||||
modifications_only=False,
|
||||
modifications=True,
|
||||
dependency_ordering=False,
|
||||
add_dependents_for_modified=False,
|
||||
modifications_as_alters=False
|
||||
):
|
||||
added, removed, modified, unmodified = differences(things_from, things_target)
|
||||
|
||||
@ -41,9 +43,11 @@ def statements_for_changes(
|
||||
replaceable=None,
|
||||
creations_only=creations_only,
|
||||
drops_only=drops_only,
|
||||
modifications_only=modifications_only,
|
||||
modifications=modifications,
|
||||
dependency_ordering=dependency_ordering,
|
||||
old=things_from,
|
||||
modifications_as_alters=modifications_as_alters
|
||||
)
|
||||
|
||||
|
||||
@ -57,21 +61,38 @@ def statements_from_differences(
|
||||
modifications=True,
|
||||
dependency_ordering=False,
|
||||
old=None,
|
||||
modifications_only=False,
|
||||
modifications_as_alters=False
|
||||
):
|
||||
replaceable = replaceable or set()
|
||||
statements = Statements()
|
||||
if not creations_only:
|
||||
pending_drops = set(removed)
|
||||
if modifications:
|
||||
|
||||
pending_creations = set()
|
||||
pending_drops = set()
|
||||
|
||||
creations = not (drops_only or modifications_only)
|
||||
drops = not (creations_only or modifications_only)
|
||||
modifications = modifications or modifications_only and not (creations_only or drops_only)
|
||||
|
||||
drop_and_recreate = modifications and not modifications_as_alters
|
||||
alters = modifications and modifications_as_alters
|
||||
|
||||
if drops:
|
||||
pending_drops |= set(removed)
|
||||
|
||||
if creations:
|
||||
pending_creations |= set(added)
|
||||
|
||||
if drop_and_recreate:
|
||||
if drops:
|
||||
pending_drops |= set(modified) - replaceable
|
||||
else:
|
||||
pending_drops = set()
|
||||
if not drops_only:
|
||||
pending_creations = set(added)
|
||||
if modifications:
|
||||
|
||||
if creations:
|
||||
pending_creations |= set(modified)
|
||||
else:
|
||||
pending_creations = set()
|
||||
|
||||
if alters:
|
||||
for k, v in modified.items():
|
||||
statements += v.alter_statements(old[k])
|
||||
|
||||
def has_remaining_dependents(v, pending_drops):
|
||||
if not dependency_ordering:
|
||||
@ -87,13 +108,13 @@ def statements_from_differences(
|
||||
|
||||
while True:
|
||||
before = pending_drops | pending_creations
|
||||
if not creations_only:
|
||||
if drops:
|
||||
for k, v in removed.items():
|
||||
if not has_remaining_dependents(v, pending_drops):
|
||||
if k in pending_drops:
|
||||
statements.append(old[k].drop_statement)
|
||||
pending_drops.remove(k)
|
||||
if not drops_only:
|
||||
if creations:
|
||||
for k, v in added.items():
|
||||
if not has_uncreated_dependencies(v, pending_creations):
|
||||
if k in pending_creations:
|
||||
@ -101,12 +122,12 @@ def statements_from_differences(
|
||||
pending_creations.remove(k)
|
||||
if modifications:
|
||||
for k, v in modified.items():
|
||||
if not creations_only:
|
||||
if drops:
|
||||
if not has_remaining_dependents(v, pending_drops):
|
||||
if k in pending_drops:
|
||||
statements.append(old[k].drop_statement)
|
||||
pending_drops.remove(k)
|
||||
if not drops_only:
|
||||
if creations:
|
||||
if not has_uncreated_dependencies(v, pending_creations):
|
||||
if k in pending_creations:
|
||||
statements.append(v.create_statement)
|
||||
@ -443,52 +464,68 @@ class Changes(object):
|
||||
self.i_from = i_from
|
||||
self.i_target = i_target
|
||||
|
||||
@property
|
||||
def extensions(self):
|
||||
return partial(
|
||||
statements_for_changes,
|
||||
self.i_from.extensions,
|
||||
self.i_target.extensions,
|
||||
modifications_as_alters=True
|
||||
)
|
||||
|
||||
@property
|
||||
def selectables(self):
|
||||
return partial(
|
||||
get_selectable_changes,
|
||||
od(sorted(self.i_from.selectables.items())),
|
||||
od(sorted(self.i_target.selectables.items())),
|
||||
self.i_from.enums,
|
||||
self.i_target.enums,
|
||||
self.i_from.sequences,
|
||||
self.i_target.sequences,
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def non_pk_constraints(self):
|
||||
a = self.i_from.constraints.items()
|
||||
b = self.i_target.constraints.items()
|
||||
a_od = od((k, v) for k, v in a if v.constraint_type != PK)
|
||||
b_od = od((k, v) for k, v in b if v.constraint_type != PK)
|
||||
return partial(statements_for_changes, a_od, b_od)
|
||||
|
||||
|
||||
@property
|
||||
def pk_constraints(self):
|
||||
a = self.i_from.constraints.items()
|
||||
b = self.i_target.constraints.items()
|
||||
a_od = od((k, v) for k, v in a if v.constraint_type == PK)
|
||||
b_od = od((k, v) for k, v in b if v.constraint_type == PK)
|
||||
return partial(statements_for_changes, a_od, b_od)
|
||||
|
||||
@property
|
||||
def triggers(self):
|
||||
return partial(
|
||||
get_trigger_changes,
|
||||
od(sorted(self.i_from.triggers.items())),
|
||||
od(sorted(self.i_target.triggers.items())),
|
||||
od(sorted(self.i_from.selectables.items())),
|
||||
od(sorted(self.i_target.selectables.items())),
|
||||
self.i_from.enums,
|
||||
self.i_target.enums,
|
||||
)
|
||||
|
||||
@property
|
||||
def sequences(self):
|
||||
return partial(
|
||||
statements_for_changes,
|
||||
self.i_from.sequences,
|
||||
self.i_target.sequences,
|
||||
modifications=False,
|
||||
)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == "non_pk_constraints":
|
||||
a = self.i_from.constraints.items()
|
||||
b = self.i_target.constraints.items()
|
||||
a_od = od((k, v) for k, v in a if v.constraint_type != PK)
|
||||
b_od = od((k, v) for k, v in b if v.constraint_type != PK)
|
||||
return partial(statements_for_changes, a_od, b_od)
|
||||
|
||||
elif name == "pk_constraints":
|
||||
a = self.i_from.constraints.items()
|
||||
b = self.i_target.constraints.items()
|
||||
a_od = od((k, v) for k, v in a if v.constraint_type == PK)
|
||||
b_od = od((k, v) for k, v in b if v.constraint_type == PK)
|
||||
return partial(statements_for_changes, a_od, b_od)
|
||||
|
||||
elif name == "selectables":
|
||||
return partial(
|
||||
get_selectable_changes,
|
||||
od(sorted(self.i_from.selectables.items())),
|
||||
od(sorted(self.i_target.selectables.items())),
|
||||
self.i_from.enums,
|
||||
self.i_target.enums,
|
||||
self.i_from.sequences,
|
||||
self.i_target.sequences,
|
||||
)
|
||||
|
||||
elif name == "triggers":
|
||||
return partial(
|
||||
get_trigger_changes,
|
||||
od(sorted(self.i_from.triggers.items())),
|
||||
od(sorted(self.i_target.triggers.items())),
|
||||
od(sorted(self.i_from.selectables.items())),
|
||||
od(sorted(self.i_target.selectables.items())),
|
||||
self.i_from.enums,
|
||||
self.i_target.enums,
|
||||
)
|
||||
|
||||
elif name == "sequences":
|
||||
return partial(
|
||||
statements_for_changes,
|
||||
getattr(self.i_from, name),
|
||||
getattr(self.i_target, name),
|
||||
modifications=False,
|
||||
)
|
||||
|
||||
elif name in THINGS:
|
||||
if name in THINGS:
|
||||
return partial(
|
||||
statements_for_changes,
|
||||
getattr(self.i_from, name),
|
||||
|
@ -64,7 +64,8 @@ class Migration(object):
|
||||
def add_all_changes(self, privileges=False):
|
||||
self.add(self.changes.schemas(creations_only=True))
|
||||
|
||||
self.add(self.changes.extensions(creations_only=True))
|
||||
self.add(self.changes.extensions(creations_only=True, modifications=False))
|
||||
self.add(self.changes.extensions(modifications_only=True, modifications=True))
|
||||
self.add(self.changes.collations(creations_only=True))
|
||||
self.add(self.changes.enums(creations_only=True, modifications=False))
|
||||
self.add(self.changes.sequences(creations_only=True))
|
||||
@ -80,7 +81,7 @@ class Migration(object):
|
||||
|
||||
self.add(self.changes.sequences(drops_only=True))
|
||||
self.add(self.changes.enums(drops_only=True, modifications=False))
|
||||
self.add(self.changes.extensions(drops_only=True))
|
||||
self.add(self.changes.extensions(drops_only=True, modifications=False))
|
||||
self.add(self.changes.indexes(creations_only=True))
|
||||
self.add(self.changes.pk_constraints(creations_only=True))
|
||||
self.add(self.changes.non_pk_constraints(creations_only=True))
|
||||
|
@ -13,8 +13,8 @@ homepage = "https://migra.djrobstep.com/"
|
||||
python = "*"
|
||||
sqlbag = "*"
|
||||
six = "*"
|
||||
#schemainspect = {path="../schemainspect"}
|
||||
schemainspect = ">=0.1.1595570852"
|
||||
# schemainspect = {path="../schemainspect"}
|
||||
schemainspect = ">=0.1.1595673757"
|
||||
psycopg2-binary = { version="*", optional = true }
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
3
tests/FIXTURES/extversions/a.sql
Normal file
3
tests/FIXTURES/extversions/a.sql
Normal file
@ -0,0 +1,3 @@
|
||||
create extension pg_trgm version '1.3';
|
||||
|
||||
create extension hstore;
|
0
tests/FIXTURES/extversions/additions.sql
Normal file
0
tests/FIXTURES/extversions/additions.sql
Normal file
3
tests/FIXTURES/extversions/b.sql
Normal file
3
tests/FIXTURES/extversions/b.sql
Normal file
@ -0,0 +1,3 @@
|
||||
create extension citext;
|
||||
|
||||
create extension pg_trgm version '1.4';
|
5
tests/FIXTURES/extversions/expected.sql
Normal file
5
tests/FIXTURES/extversions/expected.sql
Normal file
@ -0,0 +1,5 @@
|
||||
create extension if not exists "citext" with schema "public" version '1.6';
|
||||
|
||||
alter extension "pg_trgm" update to '1.4';
|
||||
|
||||
drop extension if exists "hstore";
|
0
tests/FIXTURES/extversions/expected2.sql
Normal file
0
tests/FIXTURES/extversions/expected2.sql
Normal file
@ -94,6 +94,11 @@ def test_enumdeps():
|
||||
do_fixture_test(FIXTURE_NAME, with_privileges=True)
|
||||
|
||||
|
||||
def test_extversions():
|
||||
for FIXTURE_NAME in ["extversions"]:
|
||||
do_fixture_test(FIXTURE_NAME, with_privileges=True)
|
||||
|
||||
|
||||
def test_sequences():
|
||||
for FIXTURE_NAME in ["seq"]:
|
||||
do_fixture_test(FIXTURE_NAME, with_privileges=True)
|
||||
|
Loading…
Reference in New Issue
Block a user