refactor(db)!: finalize pooled WNDB v2 migration
This commit is contained in:
@@ -94,16 +94,3 @@ def delete_demand_by_junction(name: str, junction: str) -> ChangeSet:
|
||||
if row is None:
|
||||
return ChangeSet()
|
||||
return ChangeSet(g_update_prefix | {'type': 'demand', 'junction': junction, 'demands': []})
|
||||
|
||||
|
||||
def unset_demand_by_pattern(name: str, pattern: str) -> ChangeSet:
|
||||
cs = ChangeSet()
|
||||
|
||||
rows = read_all(name, "select distinct junction_id as junction from network.demands where pattern_id = %s", (pattern,))
|
||||
for row in rows:
|
||||
ds = get_demand(name, row['junction'])
|
||||
for d in ds['demands']:
|
||||
d['pattern'] = None
|
||||
cs.append(g_update_prefix | {'type': 'demand', 'junction': row['junction'], 'demands': ds['demands']})
|
||||
|
||||
return cs
|
||||
|
||||
@@ -159,26 +159,6 @@ def get_nodes(name: str) -> list[str]:
|
||||
return _get_all(name, _NODE)
|
||||
|
||||
|
||||
def get_nodes_id_and_type(name: str) -> dict[str, str]:
|
||||
rows = read_all_typed(name, "SELECT id, node_type FROM network.nodes", ())
|
||||
return {row["id"]: row["node_type"] for row in rows}
|
||||
|
||||
|
||||
def get_major_nodes(name: str, diameter: int) -> list[str]:
|
||||
rows = read_all_typed(
|
||||
name,
|
||||
"""
|
||||
SELECT DISTINCT endpoint
|
||||
FROM network.links AS l
|
||||
JOIN network.pipes AS p ON p.link_id = l.id
|
||||
CROSS JOIN LATERAL (VALUES (l.start_node_id), (l.end_node_id)) AS e(endpoint)
|
||||
WHERE p.diameter > %s
|
||||
""",
|
||||
(diameter,),
|
||||
)
|
||||
return [row["endpoint"] for row in rows]
|
||||
|
||||
|
||||
def get_junctions(name: str) -> list[str]:
|
||||
return _get_nodes_by_type(name, JUNCTION)
|
||||
|
||||
@@ -195,20 +175,6 @@ def get_links(name: str) -> list[str]:
|
||||
return _get_all(name, _LINK)
|
||||
|
||||
|
||||
def get_links_id_and_type(name: str) -> dict[str, str]:
|
||||
rows = read_all_typed(name, "SELECT id, link_type FROM network.links", ())
|
||||
return {row["id"]: row["link_type"] for row in rows}
|
||||
|
||||
|
||||
def get_major_pipes(name: str, diameter: int) -> list[str]:
|
||||
rows = read_all_typed(
|
||||
name,
|
||||
"SELECT link_id FROM network.pipes WHERE diameter > %s ORDER BY link_id",
|
||||
(diameter,),
|
||||
)
|
||||
return [row["link_id"] for row in rows]
|
||||
|
||||
|
||||
def get_pipes(name: str) -> list[str]:
|
||||
return _get_links_by_type(name, PIPE)
|
||||
|
||||
@@ -247,10 +213,10 @@ def get_node_links(name: str, node_id: str) -> list[str]:
|
||||
|
||||
|
||||
def get_all_node_links(name: str) -> dict[str, list[str]]:
|
||||
"""Build the node adjacency map with one scan of the link table."""
|
||||
"""Build the node adjacency map with one scan of the unified GIS view."""
|
||||
rows = read_all_typed(
|
||||
name,
|
||||
"SELECT id, start_node_id, end_node_id FROM network.links ORDER BY id",
|
||||
"SELECT id, start_node_id, end_node_id FROM gis.network_links ORDER BY id",
|
||||
(),
|
||||
)
|
||||
result: dict[str, list[str]] = {}
|
||||
|
||||
@@ -6,6 +6,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -94,8 +95,12 @@ class Junction(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'x': self.x, 'y': self.y, 'elevation': self.elevation }
|
||||
|
||||
def _set_junction(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_junction(name, cs.operations[0]['id'])
|
||||
def _set_junction(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_junction(name, cs.operations[0]['id'])
|
||||
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_junction_schema(name)
|
||||
@@ -113,11 +118,15 @@ def _set_junction(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
|
||||
def set_junction(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_junction(name, cs.operations[0]['id']) == {}:
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_junction(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_junction(name, operation['id'])
|
||||
return None if current == {} else _set_junction(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_junction(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
from psycopg import sql
|
||||
|
||||
from ..core.database import ChangeSet, g_update_prefix, read_all, sql_literal
|
||||
from .options import get_option_schema, generate_v3
|
||||
|
||||
|
||||
def _inp_in_option(section: list[str]) -> ChangeSet:
|
||||
def _inp_in_option_v2(section: list[str]) -> ChangeSet:
|
||||
if len(section) <= 0:
|
||||
return ChangeSet()
|
||||
|
||||
@@ -34,9 +32,9 @@ def _inp_in_option(section: list[str]) -> ChangeSet:
|
||||
return result
|
||||
|
||||
|
||||
def inp_in_option(section: list[str]) -> str:
|
||||
def inp_in_option_v2(section: list[str]) -> str:
|
||||
sql = ''
|
||||
result = _inp_in_option(section)
|
||||
result = _inp_in_option_v2(section)
|
||||
for op in result.operations:
|
||||
for key in op.keys():
|
||||
if key == 'operation' or key == 'type':
|
||||
@@ -48,7 +46,7 @@ def inp_in_option(section: list[str]) -> str:
|
||||
return sql
|
||||
|
||||
|
||||
def inp_out_option(name: str) -> list[str]:
|
||||
def inp_out_option_v2(name: str) -> list[str]:
|
||||
lines = []
|
||||
objs = read_all(name, "select key, value from network.simulation_settings where engine_version = 'legacy' order by key")
|
||||
|
||||
@@ -71,7 +69,7 @@ def inp_out_option(name: str) -> list[str]:
|
||||
# why write this ?
|
||||
if key == 'PRESSURE':
|
||||
continue
|
||||
# release version does not support new keys and has error message
|
||||
# EPANET V2 does not support these newer keys.
|
||||
if key == 'HTOL' or key == 'QTOL' or key == 'RQTOL':
|
||||
continue
|
||||
# ignore some weird settings for DDA
|
||||
@@ -1,5 +1,3 @@
|
||||
from psycopg import sql
|
||||
|
||||
from ..core.database import ChangeSet, g_update_prefix, read_all, sql_literal
|
||||
from .options import get_option_schema, get_option_v3_schema, generate_v2, generate_v3
|
||||
|
||||
|
||||
@@ -93,7 +93,10 @@ def _delete_pattern(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
id = cs.operations[0]['id']
|
||||
f_id = sql_literal(id)
|
||||
|
||||
statement = f"delete from network.patterns where id = {f_id};"
|
||||
statement = (
|
||||
f"update network.demands set pattern_id = null where pattern_id = {f_id};"
|
||||
f"\ndelete from network.patterns where id = {f_id};"
|
||||
)
|
||||
|
||||
change = g_delete_prefix | { 'type': 'pattern' } | { 'id': id }
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -144,9 +145,12 @@ class Pipe(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'node1': self.node1, 'node2': self.node2, 'length': self.length, 'diameter': self.diameter, 'roughness': self.roughness, 'minor_loss': self.minor_loss, 'status': self.status }
|
||||
|
||||
def _set_pipe(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_pipe(name, cs.operations[0]['id'])
|
||||
|
||||
def _set_pipe(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_pipe(name, cs.operations[0]['id'])
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_pipe_schema(name)
|
||||
for key, value in schema.items():
|
||||
@@ -154,19 +158,59 @@ def _set_pipe(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new[key] = new_dict[key]
|
||||
new = Pipe(raw_new)
|
||||
|
||||
statement = f"update network.links set start_node_id = {new.f_node1}, end_node_id = {new.f_node2} where id = {new.f_id};"
|
||||
statement += f"\nupdate network.pipes set length = {new.f_length}, diameter = {new.f_diameter}, roughness = {new.f_roughness}, minor_loss = {new.f_minor_loss}, status = {new.f_status} where link_id = {new.f_id};"
|
||||
link_columns = {
|
||||
'node1': ('start_node_id', new.f_node1),
|
||||
'node2': ('end_node_id', new.f_node2),
|
||||
}
|
||||
pipe_columns = {
|
||||
'length': ('length', new.f_length),
|
||||
'diameter': ('diameter', new.f_diameter),
|
||||
'roughness': ('roughness', new.f_roughness),
|
||||
'minor_loss': ('minor_loss', new.f_minor_loss),
|
||||
'status': ('status', new.f_status),
|
||||
}
|
||||
statements = []
|
||||
link_assignments = [
|
||||
f"{column} = {value}"
|
||||
for field, (column, value) in link_columns.items()
|
||||
if field in new_dict
|
||||
]
|
||||
if link_assignments:
|
||||
statements.append(
|
||||
f"update network.links set {', '.join(link_assignments)} where id = {new.f_id};"
|
||||
)
|
||||
pipe_assignments = [
|
||||
f"{column} = {value}"
|
||||
for field, (column, value) in pipe_columns.items()
|
||||
if field in new_dict
|
||||
]
|
||||
if pipe_assignments:
|
||||
statements.append(
|
||||
f"update network.pipes set {', '.join(pipe_assignments)} where link_id = {new.f_id};"
|
||||
)
|
||||
statement = "\n".join(statements)
|
||||
change = g_update_prefix | new.as_dict()
|
||||
|
||||
return DatabaseCommand(statement, [change])
|
||||
|
||||
|
||||
def set_pipe(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_pipe(name, cs.operations[0]['id']) == {}:
|
||||
mutable_fields = {
|
||||
'node1', 'node2', 'length', 'diameter', 'roughness', 'minor_loss', 'status'
|
||||
}
|
||||
if not mutable_fields.intersection(operation):
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_pipe(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_pipe(name, operation['id'])
|
||||
if current == {}:
|
||||
return None
|
||||
return _set_pipe(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_pipe(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
@@ -4,6 +4,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -87,8 +88,12 @@ class Pump(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'node1': self.node1, 'node2': self.node2, 'power': self.power, 'head': self.head, 'speed': self.speed, 'pattern': self.pattern }
|
||||
|
||||
def _set_pump(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_pump(name, cs.operations[0]['id'])
|
||||
def _set_pump(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_pump(name, cs.operations[0]['id'])
|
||||
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_pump_schema(name)
|
||||
@@ -105,11 +110,15 @@ def _set_pump(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
|
||||
def set_pump(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_pump(name, cs.operations[0]['id']) == {}:
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_pump(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_pump(name, operation['id'])
|
||||
return None if current == {} else _set_pump(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_pump(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
@@ -4,6 +4,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -85,8 +86,12 @@ class Reservoir(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'x': self.x, 'y': self.y, 'head': self.head, 'pattern': self.pattern }
|
||||
|
||||
def _set_reservoir(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_reservoir(name, cs.operations[0]['id'])
|
||||
def _set_reservoir(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_reservoir(name, cs.operations[0]['id'])
|
||||
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_reservoir_schema(name)
|
||||
@@ -104,11 +109,15 @@ def _set_reservoir(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
|
||||
def set_reservoir(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_reservoir(name, cs.operations[0]['id']) == {}:
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_reservoir(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_reservoir(name, operation['id'])
|
||||
return None if current == {} else _set_reservoir(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_reservoir(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
@@ -4,6 +4,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -121,8 +122,12 @@ class Tank(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'x': self.x, 'y': self.y, 'elevation': self.elevation, 'init_level': self.init_level, 'min_level': self.min_level, 'max_level': self.max_level, 'diameter': self.diameter, 'min_vol': self.min_vol, 'vol_curve': self.vol_curve, 'overflow': self.overflow }
|
||||
|
||||
def _set_tank(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_tank(name, cs.operations[0]['id'])
|
||||
def _set_tank(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_tank(name, cs.operations[0]['id'])
|
||||
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_tank_schema(name)
|
||||
@@ -140,11 +145,15 @@ def _set_tank(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
|
||||
def set_tank(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_tank(name, cs.operations[0]['id']) == {}:
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_tank(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_tank(name, operation['id'])
|
||||
return None if current == {} else _set_tank(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_tank(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
@@ -4,6 +4,7 @@ from ..core.database import (
|
||||
ChangeSet,
|
||||
DatabaseCommand,
|
||||
execute_command,
|
||||
execute_locked_command,
|
||||
g_add_prefix,
|
||||
g_delete_prefix,
|
||||
g_update_prefix,
|
||||
@@ -94,8 +95,12 @@ class Valve(object):
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return { 'type': self.type, 'id': self.id, 'node1': self.node1, 'node2': self.node2, 'diameter': self.diameter, 'v_type': self.v_type, 'setting': self.setting, 'minor_loss': self.minor_loss }
|
||||
|
||||
def _set_valve(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
raw_new = get_valve(name, cs.operations[0]['id'])
|
||||
def _set_valve(
|
||||
name: str,
|
||||
cs: ChangeSet,
|
||||
current: dict[str, Any] | None = None,
|
||||
) -> DatabaseCommand:
|
||||
raw_new = current if current is not None else get_valve(name, cs.operations[0]['id'])
|
||||
|
||||
new_dict = cs.operations[0]
|
||||
schema = get_valve_schema(name)
|
||||
@@ -112,11 +117,15 @@ def _set_valve(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
|
||||
def set_valve(name: str, cs: ChangeSet) -> ChangeSet:
|
||||
if 'id' not in cs.operations[0]:
|
||||
operation = cs.operations[0]
|
||||
if 'id' not in operation:
|
||||
return ChangeSet()
|
||||
if get_valve(name, cs.operations[0]['id']) == {}:
|
||||
return ChangeSet()
|
||||
return execute_command(name, _set_valve(name, cs))
|
||||
|
||||
def build_command() -> DatabaseCommand | None:
|
||||
current = get_valve(name, operation['id'])
|
||||
return None if current == {} else _set_valve(name, cs, current)
|
||||
|
||||
return execute_locked_command(name, build_command)
|
||||
|
||||
|
||||
def _add_valve(name: str, cs: ChangeSet) -> DatabaseCommand:
|
||||
|
||||
Reference in New Issue
Block a user