From ea2287215e2fcb15a6bcf91d3679fdb76fa61548 Mon Sep 17 00:00:00 2001 From: Dylan Jeannin Date: Mon, 18 May 2026 15:33:36 +0200 Subject: [PATCH 1/7] fix pep8 before push --- src/Model/Pollutants/Pollutants.py | 4 ---- src/Solver/AdisTS.py | 4 +++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Model/Pollutants/Pollutants.py b/src/Model/Pollutants/Pollutants.py index 51872f1d..72681f40 100644 --- a/src/Model/Pollutants/Pollutants.py +++ b/src/Model/Pollutants/Pollutants.py @@ -424,10 +424,6 @@ class Pollutants(SQLSubModel): new_pollutant._data = PollutantCharacteristics._db_load( execute, data=data ) - - new_pollutant._boundary_conditions_adists = BoundaryConditionAdisTS._db_load( - execute, data=data - ) new_pollutant._boundary_conditions_adists = ( BoundaryConditionAdisTS._db_load( diff --git a/src/Solver/AdisTS.py b/src/Solver/AdisTS.py index a8225a64..b8310dfb 100644 --- a/src/Solver/AdisTS.py +++ b/src/Solver/AdisTS.py @@ -845,7 +845,9 @@ class AdisTSwc(AdisTS): # seventh line (useless) for k in range(0, ismax, kbl): data = np.fromfile(f, dtype=np.int32, count=1) # (start) - zero = np.fromfile(f, dtype=np.int32, count=min(k + kbl, ismax) - k) + zero = np.fromfile( + f, dtype=np.int32, count=min(k + kbl, ismax) - k + ) data = np.fromfile(f, dtype=np.int32, count=1) # (end) # end header # data From a6915020cb18d759523da2ee96abd6279ba5c8df Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 09:28:16 +0200 Subject: [PATCH 2/7] BC: Minor change. --- src/Model/BoundaryConditionsAdisTS/BoundaryConditionAdisTS.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/BoundaryConditionsAdisTS/BoundaryConditionAdisTS.py b/src/Model/BoundaryConditionsAdisTS/BoundaryConditionAdisTS.py index 5376cba1..b33c1a03 100644 --- a/src/Model/BoundaryConditionsAdisTS/BoundaryConditionAdisTS.py +++ b/src/Model/BoundaryConditionsAdisTS/BoundaryConditionAdisTS.py @@ -71,7 +71,7 @@ class Data(SQLSubModel): major, minor, release = version.strip().split(".") created = False - if major == "0" and int(minor) <= 1: + if major == "0" and minor == "0": if int(release) < 7: cls._db_create(execute) created = True @@ -249,7 +249,7 @@ class BoundaryConditionAdisTS(SQLSubModel): major, minor, release = version.strip().split(".") created = False - if major == "0" and int(minor) <= 1: + if major == "0" and minor == "0": if int(release) < 7: cls._db_create(execute) created = True From fa88e05d913fe2c1512a35a462f303fb7609ec84 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 10:15:23 +0200 Subject: [PATCH 3/7] AdisTS: BC: Fix dual sub classes dependencies. --- src/Model/Pollutants/Pollutants.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Model/Pollutants/Pollutants.py b/src/Model/Pollutants/Pollutants.py index 72681f40..67818bc6 100644 --- a/src/Model/Pollutants/Pollutants.py +++ b/src/Model/Pollutants/Pollutants.py @@ -278,8 +278,10 @@ class PollutantCharacteristics(SQLSubModel): class Pollutants(SQLSubModel): - _sub_classes = [PollutantCharacteristics, - BoundaryConditionAdisTS] + _sub_classes = [ + PollutantCharacteristics, + # BoundaryConditionAdisTS + ] def __init__(self, id: int = -1, name: str = "", status=None, owner_scenario=-1): From 914a1f886649543cad25a62fa4f13cf65011277b Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 12:22:20 +0200 Subject: [PATCH 4/7] Scenario: Add DB clean methode (not tested yet). --- src/Model/Scenario.py | 100 ++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/src/Model/Scenario.py b/src/Model/Scenario.py index 9139cb25..39df1d70 100644 --- a/src/Model/Scenario.py +++ b/src/Model/Scenario.py @@ -17,16 +17,43 @@ # -*- coding: utf-8 -*- import os +import logging from tools import logger_exception from Model.Tools.PamhyrDB import SQLSubModel +logger = logging.getLogger() + class Scenario(SQLSubModel): _id_cnt = 0 _sub_classes = [] + related_tables = [ + # Adists + "output_rk_adists", + "boundary_condition_adists", "boundary_condition_data_adists", + "lateral_contribution_adists", "lateral_contribution_data_adists", + "initial_conditions_adists", + "d90_adists", "dif_adists", + "pollutants", "pollutants_characteristics", + # Hydraulic + "additional_files", + "boundary_condition", "boundary_condition_data", + "lateral_contribution", "lateral_contribution_data", + "friction", "stricklers", + "hydraulic_structures", + "hydraulic_structures_basic", "hydraulic_structures_basic_value", + "initial_conditions", + "sedimentary_layer", "sedimentary_layer_layer", + "reservoir", "reservoir_data", + "rep_lines", + "solver_parameter", + "geometry_pointXYZ", "geometry_profileXYZ", + "river_reach", "river_node", + ] + def __init__(self, id: int = -1, name: str = "", @@ -171,29 +198,7 @@ class Scenario(SQLSubModel): def drop_all(self, execute): execute(f"DELETE FROM scenario WHERE id = {self.id}") - tables = [ - # Adists - "output_rk_adists", - "boundary_condition_adists", "boundary_condition_data_adists", - "lateral_contribution_adists", "lateral_contribution_data_adists", - "initial_conditions_adists", - "d90_adists", "dif_adists", - "pollutants", "pollutants_characteristics", - # Hydraulic - "additional_files", - "boundary_condition", "boundary_condition_data", - "lateral_contribution", "lateral_contribution_data", - "friction", "stricklers", - "hydraulic_structures", - "hydraulic_structures_basic", "hydraulic_structures_basic_value", - "initial_conditions", - "sedimentary_layer", "sedimentary_layer_layer", - "reservoir", "reservoir_data", - "rep_lines", - "solver_parameter", - "geometry_pointXYZ", "geometry_profileXYZ", - "river_reach", "river_node", - ] + tables = self.related_tables for table in tables: execute( @@ -203,6 +208,55 @@ class Scenario(SQLSubModel): return True + def get_parent_branch(self): + def aux(scenario, acc): + if scenario.parent == None: + return [scenario.id] + acc + + return aux(scenario.parent, [scenario.id] + acc) + + return aux(self, []) + + def drop_deleted_data(self, execute): + tables = self.related_tables + branch = self.get_parent_branch() + + for table in tables: + if self.parent == None: + execute( + f"DELETE FROM {table} " + + f"WHERE scenario = {self.id} " + + "AND deleted = TRUE" + ) + continue + + ids = execute( + f""" + SELECT pamhyr_id FROM {table} + WHERE deleted = TRUE + AND scenario = {self.id} + AND pamhyr_id NOT IN ( + SELECT pamhyr_id FROM {table} + WHERE scenario IN + ({', '.join(map(str, branch[:-1]))}) + ) + """, fetch_one=False + ) + if ids == None or len(ids) == 0: + continue + + logger.debug( + f"Drop deleted data into '{table}' : {ids}" + ) + + execute( + f"DELETE FROM {table} " + + f"WHERE scenario = {self.id} " + + f"AND pamhyr_id IN ({', '.join(map(lambda x: str(x[0]), ids))})" + ) + + return True + @property def id(self): return self._id From 0df4cf0fd5f10ce3010d8edf78d4306b984719f6 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 16:08:20 +0200 Subject: [PATCH 5/7] Scenario: Clean DB. --- src/Model/Scenario.py | 30 +++++++++++++++++------------- src/Model/Study.py | 5 +++++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/Model/Scenario.py b/src/Model/Scenario.py index 39df1d70..46285b45 100644 --- a/src/Model/Scenario.py +++ b/src/Model/Scenario.py @@ -30,13 +30,13 @@ class Scenario(SQLSubModel): _id_cnt = 0 _sub_classes = [] - related_tables = [ + tables_with_deleted_column = [ # Adists "output_rk_adists", "boundary_condition_adists", "boundary_condition_data_adists", "lateral_contribution_adists", "lateral_contribution_data_adists", "initial_conditions_adists", - "d90_adists", "dif_adists", + "d90_adists", "pollutants", "pollutants_characteristics", # Hydraulic "additional_files", @@ -44,16 +44,21 @@ class Scenario(SQLSubModel): "lateral_contribution", "lateral_contribution_data", "friction", "stricklers", "hydraulic_structures", - "hydraulic_structures_basic", "hydraulic_structures_basic_value", + "hydraulic_structures_basic", "initial_conditions", "sedimentary_layer", "sedimentary_layer_layer", "reservoir", "reservoir_data", "rep_lines", - "solver_parameter", "geometry_pointXYZ", "geometry_profileXYZ", "river_reach", "river_node", ] + related_tables = tables_with_deleted_column + [ + "dif_adists", + "solver_parameter", + "hydraulic_structures_basic_value", + ] + def __init__(self, id: int = -1, name: str = "", @@ -210,19 +215,19 @@ class Scenario(SQLSubModel): def get_parent_branch(self): def aux(scenario, acc): - if scenario.parent == None: - return [scenario.id] + acc + if scenario is None: + return acc return aux(scenario.parent, [scenario.id] + acc) return aux(self, []) def drop_deleted_data(self, execute): - tables = self.related_tables + tables = self.tables_with_deleted_column branch = self.get_parent_branch() for table in tables: - if self.parent == None: + if self.parent is None: execute( f"DELETE FROM {table} " + f"WHERE scenario = {self.id} " + @@ -242,21 +247,20 @@ class Scenario(SQLSubModel): ) """, fetch_one=False ) - if ids == None or len(ids) == 0: + if ids is None or len(ids) == 0: continue logger.debug( - f"Drop deleted data into '{table}' : {ids}" + f"(s{self.id}) Drop deleted data into '{table}' : {ids}" ) execute( f"DELETE FROM {table} " + f"WHERE scenario = {self.id} " + - f"AND pamhyr_id IN ({', '.join(map(lambda x: str(x[0]), ids))})" + "AND pamhyr_id IN " + + f"({', '.join(map(lambda x: str(x[0]), ids))})" ) - return True - @property def id(self): return self._id diff --git a/src/Model/Study.py b/src/Model/Study.py index 23113ab9..d0746c39 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -449,6 +449,11 @@ class Study(SQLModel): [self.scenarios, self._river], data=progress ) + + # Clear DB for each scenarios + for scenar in self.scenarios.lst: + scenar.drop_deleted_data(self.execute) + self.commit() def sql_save_request_count(self, *args, **kargs): From 42ea50d62e4e9ef5c9c089a936bb0f074fbb5bd3 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 16:51:57 +0200 Subject: [PATCH 6/7] Study: Minor change. --- src/Model/Study.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Model/Study.py b/src/Model/Study.py index d0746c39..2ec031a7 100644 --- a/src/Model/Study.py +++ b/src/Model/Study.py @@ -454,6 +454,8 @@ class Study(SQLModel): for scenar in self.scenarios.lst: scenar.drop_deleted_data(self.execute) + progress() + self.commit() def sql_save_request_count(self, *args, **kargs): @@ -464,7 +466,7 @@ class Study(SQLModel): [self.scenarios, self._river] ) logger.debug(cnt) - return cnt + 7 + return cnt + 8 def close(self): """Close db connection @@ -523,7 +525,8 @@ class Study(SQLModel): data["study"] = self river._db_load_results(sql_exec, data=data) - self._river_scenario_cache[scenario] = river + # FIXME: Disable scenario cache to save memory usage + # self._river_scenario_cache[scenario] = river self.status.scenario = old_scenario return river From 5ce94a63d3702ade593ea160b23113786ee531f7 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby Date: Tue, 19 May 2026 17:54:28 +0200 Subject: [PATCH 7/7] Scenario: Clean DB add minimal comment. --- src/Model/Scenario.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Model/Scenario.py b/src/Model/Scenario.py index 46285b45..2fdde4a6 100644 --- a/src/Model/Scenario.py +++ b/src/Model/Scenario.py @@ -228,6 +228,8 @@ class Scenario(SQLSubModel): for table in tables: if self.parent is None: + # This scenario is the default scenario, so we can + # delete all data marked as deleted execute( f"DELETE FROM {table} " + f"WHERE scenario = {self.id} " + @@ -235,6 +237,8 @@ class Scenario(SQLSubModel): ) continue + # Select pamhyr_id for each deleted data in this scenario + # who do not exists into parents scenarios ids = execute( f""" SELECT pamhyr_id FROM {table}