aboutsummaryrefslogtreecommitdiff
path: root/src/hydrilla/proxy/state_impl
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-09-03 17:41:16 +0200
committerWojtek Kosior <koszko@koszko.org>2022-09-28 12:54:55 +0200
commit699c949d8ec1260ca12dfbfa05c404be7395c9cc (patch)
treef8b1b9dad24269a99a3e54cf85c04434ffc2c250 /src/hydrilla/proxy/state_impl
parentccf3ce18220f3256a7cf96ed32f26511a5d01337 (diff)
downloadhaketilo-hydrilla-699c949d8ec1260ca12dfbfa05c404be7395c9cc.tar.gz
haketilo-hydrilla-699c949d8ec1260ca12dfbfa05c404be7395c9cc.zip
[proxy] fix a bug that caused mappings to be marked as required even after they stopped being required
Diffstat (limited to 'src/hydrilla/proxy/state_impl')
-rw-r--r--src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py97
-rw-r--r--src/hydrilla/proxy/state_impl/base.py24
2 files changed, 104 insertions, 17 deletions
diff --git a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
index 9419f91..7539e29 100644
--- a/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
+++ b/src/hydrilla/proxy/state_impl/_operations/recompute_dependencies.py
@@ -88,11 +88,79 @@ def _get_current_required_state(
# recursively depend on) let's make sure that their exact same versions will
# be enabled after the change. Make exception for mappings specified by the
# caller.
- with base.temporary_ids_table(
- cursor = cursor,
- ids = unlocked_required_mappings,
- table_name = '__unlocked_ids'
+ # The mappings to make exception for are passed by their item_id's. First,
+ # we compute a set of their corresponding item_version_id's.
+ with base.temporary_ids_tables(
+ cursor = cursor,
+ tables = [
+ ('__work_ids_0', unlocked_required_mappings),
+ ('__work_ids_1', []),
+ ('__unlocked_ids', [])
+ ]
):
+ cursor.execute(
+ '''
+ INSERT INTO
+ __work_ids_1
+ SELECT
+ item_version_id
+ FROM
+ item_versions
+ WHERE
+ item_id IN __work_ids_0;
+ '''
+ )
+
+ # Recursively update the our unlocked ids collection with all mapping
+ # version ids that are required by mapping versions already referenced
+ # there.
+ work_tab = '__work_ids_1'
+ next_tab = '__work_ids_0'
+
+ while True:
+ cursor.execute(f'SELECT COUNT(*) FROM {work_tab};')
+
+ (count,), = cursor.fetchall()
+
+ if count == 0:
+ break
+
+ cursor.execute(f'DELETE FROM {next_tab};')
+
+ cursor.execute(
+ f'''
+ INSERT INTO
+ {next_tab}
+ SELECT
+ item_version_id
+ FROM
+ item_versions AS iv
+ JOIN items AS i
+ USING (item_id)
+ JOIN mapping_statuses AS ms
+ USING (item_id)
+ JOIN resolved_required_mappings AS rrm
+ ON iv.item_version_id = rrm.required_mapping_id
+ WHERE
+ ms.enabled != 'E' AND
+ rrm.requiring_mapping_id IN {work_tab} AND
+ rrm.requiring_mapping_id NOT IN __unlocked_ids;
+ '''
+ )
+
+ cursor.execute(
+ f'''
+ INSERT OR IGNORE INTO
+ __unlocked_ids
+ SELECT
+ id
+ FROM
+ {work_tab};
+ '''
+ )
+
+ work_tab, next_tab = next_tab, work_tab
+
# Describe all required mappings using requirement objects.
cursor.execute(
'''
@@ -102,8 +170,8 @@ def _get_current_required_state(
item_versions_extra AS ive
JOIN items AS i USING (item_id)
WHERE
- i.type = 'M' AND
- item_id NOT IN __unlocked_ids AND
+ i.type = 'M' AND
+ ive.item_version_id NOT IN __unlocked_ids AND
ive.active = 'R';
''',
)
@@ -138,7 +206,8 @@ def _get_current_required_state(
JOIN items AS i_m
ON iv_m.item_id = i_m.item_id
WHERE
- i_m.item_id NOT IN __unlocked_ids AND iv_m.active = 'R';
+ iv_m.item_version_id NOT IN __unlocked_ids AND
+ iv_m.active = 'R';
''',
)
@@ -250,6 +319,8 @@ def _recompute_dependencies_no_state_update_no_pull_files(
cursor.execute('DELETE FROM payloads;')
+ cursor.execute('DELETE FROM resolved_required_mappings;')
+
for choice in mapping_choices.values():
mapping_ver_id = mappings_to_ids[choice.info]
@@ -294,6 +365,18 @@ def _recompute_dependencies_no_state_update_no_pull_files(
('R' if choice.required else 'A', mapping_ver_id)
)
+ for depended_mapping_info in choice.mapping_dependencies:
+ cursor.execute(
+ '''
+ INSERT INTO resolved_required_mappings(
+ requiring_mapping_id,
+ required_mapping_id
+ )
+ VALUES (?, ?);
+ ''',
+ (mapping_ver_id, mappings_to_ids[depended_mapping_info])
+ )
+
for num, (pattern, payload) in enumerate(choice.payloads.items()):
cursor.execute(
'''
diff --git a/src/hydrilla/proxy/state_impl/base.py b/src/hydrilla/proxy/state_impl/base.py
index e5a9898..82b8734 100644
--- a/src/hydrilla/proxy/state_impl/base.py
+++ b/src/hydrilla/proxy/state_impl/base.py
@@ -50,22 +50,26 @@ from .. import policies
@contextmanager
-def temporary_ids_table(
- cursor: sqlite3.Cursor,
- ids: t.Iterable[int],
- table_name: str = '__helper_ids'
+def temporary_ids_tables(
+ cursor: sqlite3.Cursor,
+ tables: t.Iterable[tuple[str, t.Iterable[int]]]
) -> t.Iterator[None]:
- cursor.execute(
- f'CREATE TEMPORARY TABLE "{table_name}"(id INTEGER PRIMARY KEY);'
- )
+ created: set[str] = set()
try:
- for id in ids:
- cursor.execute(f'INSERT INTO "{table_name}" VALUES(?);', (id,))
+ for name, ids in tables:
+ cursor.execute(
+ f'CREATE TEMPORARY TABLE "{name}"(id INTEGER PRIMARY KEY);'
+ )
+ created.add(name)
+
+ for id in ids:
+ cursor.execute(f'INSERT INTO "{name}" VALUES(?);', (id,))
yield
finally:
- cursor.execute(f'DROP TABLE "{table_name}";')
+ for name in created:
+ cursor.execute(f'DROP TABLE "{name}";')
@dc.dataclass(frozen=True)