Network: Export model network to sqlite db.

results
Pierre-Antoine Rouby 2023-06-29 11:33:59 +02:00
parent 2ed3254b46
commit 4978f20e29
7 changed files with 167 additions and 65 deletions

View File

@ -22,54 +22,65 @@ class SQLModel(SQL):
self._cur = self._db.cursor() self._cur = self._db.cursor()
if is_new: if is_new:
print("CREATE")
self._create() # Create db self._create() # Create db
self._save() # Save # self._save() # Save
else: else:
print("UPDATE")
self._update() # Update db scheme if necessary self._update() # Update db scheme if necessary
self._load() # Load data # self._load() # Load data
def __init__(self, filename = None):
self._db = None
def _create_submodel(self): def _create_submodel(self):
for cls in self._sub_classes: fn = lambda sql: self.execute(
requests = cls._sql_create(
lambda sql: self.execute(
sql, sql,
fetch_one = False, fetch_one = False,
commit = True commit = True
) )
)
for cls in self._sub_classes:
requests = cls._sql_create(fn)
def _create(self): def _create(self):
raise NotImplementedMethodeError(self, self._create) raise NotImplementedMethodeError(self, self._create)
def _update_submodel(self, version): def _update_submodel(self, version):
for cls in self._sub_classes: fn = lambda sql: self.execute(
requests = cls._sql_update(
lambda sql: self.execute(
sql, sql,
fetch_one = False, fetch_one = False,
commit = True commit = True
),
version
) )
ok = True
for cls in self._sub_classes:
ok &= cls._sql_update(fn, version)
return ok
def _update(self): def _update(self):
raise NotImplementedMethodeError(self, self._update) raise NotImplementedMethodeError(self, self._update)
def _save_submodel(self, objs): def _save_submodel(self, objs, data = None):
for obj in objs: fn = lambda sql: self.execute(
requests = obj._sql_save(
lambda sql: self.execute(
sql, sql,
fetch_one = False, fetch_one = False,
commit = True commit = True
) )
)
ok = True
for obj in objs:
ok &= obj._sql_save(fn)
return ok
def _save(self): def _save(self):
raise NotImplementedMethodeError(self, self._save) raise NotImplementedMethodeError(self, self._save)
@classmethod @classmethod
def _load(cls, filename): def _load(cls, filename = None):
raise NotImplementedMethodeError(cls, cls._load) raise NotImplementedMethodeError(cls, cls._load)
# Sub model class # Sub model class
@ -80,6 +91,8 @@ class SQLSubModel(object):
# Replace ''' by ''' to preserve SQL injection # Replace ''' by ''' to preserve SQL injection
if type(value) == str: if type(value) == str:
value = value.replace("'", "'") value = value.replace("'", "'")
elif type(value) == bool:
value = 'TRUE' if value else 'FALSE'
return value return value
@classmethod @classmethod
@ -130,9 +143,9 @@ class SQLSubModel(object):
""" """
raise NotImplementedMethodeError(cls, cls._sql_load) raise NotImplementedMethodeError(cls, cls._sql_load)
def _save_submodel(self, execute): def _save_submodel(self, execute, objs, data = None):
for sc in self._sub_classes: for o in objs:
sc._sql_update(execute) o._sql_save(execute, data = data)
def _sql_save(self, execute, data = None): def _sql_save(self, execute, data = None):
"""Save class data to data base """Save class data to data base

View File

@ -3,7 +3,9 @@
from Model.Network.Node import Node from Model.Network.Node import Node
class Edge(object): class Edge(object):
def __init__(self, id:str, name:str, _id_cnt = 0
def __init__(self, id:int, name:str,
node1:Node = None, node1:Node = None,
node2:Node = None, node2:Node = None,
status = None): status = None):
@ -11,7 +13,12 @@ class Edge(object):
self._status = status self._status = status
if id == -1:
type(self)._id_cnt += 1
self.id = type(self)._id_cnt
else:
self.id = id self.id = id
self._name = name self._name = name
self.node1 = node1 self.node1 = node1

View File

@ -14,9 +14,6 @@ class Graph(object):
self._node_ctor = Node self._node_ctor = Node
self._edge_ctor = Edge self._edge_ctor = Edge
self._nodes_ids = 0
self._edges_ids = 0
self._nodes = [] self._nodes = []
self._edges = [] self._edges = []
@ -83,12 +80,11 @@ class Graph(object):
def _create_node(self, x:float, y:float): def _create_node(self, x:float, y:float):
node = self._node_ctor( node = self._node_ctor(
self._nodes_ids, -1,
f"Node {self._nodes_ids}", "",
x = x, y = y, x = x, y = y,
status = self._status status = self._status
) )
self._nodes_ids += 1
return node return node
def _add_node(self, node): def _add_node(self, node):
@ -118,11 +114,10 @@ class Graph(object):
def _create_edge(self, n1:Node, n2:Node): def _create_edge(self, n1:Node, n2:Node):
edge = self._edge_ctor( edge = self._edge_ctor(
self._edges_ids, -1,
"", n1, n2, "", n1, n2,
status = self._status status = self._status
) )
self._edges_ids += 1
return edge return edge

View File

@ -3,33 +3,44 @@
from Model.Network.Point import Point from Model.Network.Point import Point
class Node(object): class Node(object):
def __init__(self, id:str, name:str, _id_cnt = 0
def __init__(self, id:int, name:str,
x:float = 0.0, y:float = 0.0, x:float = 0.0, y:float = 0.0,
status = None): status = None):
super(Node, self).__init__() super(Node, self).__init__()
self._status = status self._status = status
if id == -1:
type(self)._id_cnt += 1
self.id = type(self)._id_cnt
else:
self.id = id self.id = id
if name == "":
self._name = f"Node {self.id}"
else:
self._name = name self._name = name
self.pos = Point(x, y) self.pos = Point(x, y)
def __getitem__(self, name): def __getitem__(self, key):
ret = None ret = None
if name == "name": if key == "name":
ret = self._name ret = self._name
elif name == "id": elif key == "id":
ret = self.id ret = self.id
elif name == "pos": elif key == "pos":
ret = f"({self.pos.x},{self.pos.y})" ret = f"({self.pos.x},{self.pos.y})"
return ret return ret
def __setitem__(self, name, value): def __setitem__(self, key, value):
if name == "name": if key == "name":
self._name = value self._name = value
elif name == "id": elif key == "id":
self.id = value self.id = value
self._status.modified() self._status.modified()

View File

@ -52,9 +52,26 @@ class RiverNode(Node, SQLSubModel):
@classmethod @classmethod
def _sql_load(cls, execute, data = None): def _sql_load(cls, execute, data = None):
return True nodes = []
table = execute("SELECT id, name, x, y FROM river_node")
for row in table:
# Update id counter
cls._id_cnt = max(cls._id_cnt, row[0])
# Create new node
nodes.append(cls(*row, **data))
return nodes
def _sql_save(self, execute, data = None): def _sql_save(self, execute, data = None):
sql = (
"INSERT OR REPLACE INTO river_node(id, name, x, y) VALUES (" +
f"{self.id}, '{self._sql_format(self.name)}', " +
f"{self.x}, {self.y}"+
")"
)
execute(sql)
return True return True
@property @property
@ -91,6 +108,7 @@ class RiverReach(Edge, SQLSubModel):
CREATE TABLE river_reach( CREATE TABLE river_reach(
id INTEGER NOT NULL PRIMARY KEY, id INTEGER NOT NULL PRIMARY KEY,
name TEXT NOT NULL, name TEXT NOT NULL,
enable BOOLEAN NOT NULL,
node1 INTEGER, node1 INTEGER,
node2 INTEGER, node2 INTEGER,
FOREIGN KEY(node1) REFERENCES river_node(id), FOREIGN KEY(node1) REFERENCES river_node(id),
@ -107,9 +125,38 @@ class RiverReach(Edge, SQLSubModel):
@classmethod @classmethod
def _sql_load(cls, execute, data = None): def _sql_load(cls, execute, data = None):
return None reachs = []
table = execute("SELECT id, name, enable, node1, node2 FROM river_reach")
for row in table:
# Update id counter
cls._id_cnt = max(cls._id_cnt, row[0])
# Create new reach
id = row[0]
name = row[1]
enable = (row[2] == 1)
# Get nodes corresponding to db foreign key id
node1 = next(filter(lambda n: n.id == row[3], data["nodes"]))
node2 = next(filter(lambda n: n.id == row[4], data["nodes"]))
new = cls(id, name, node1, node2, status = data["status"])
new.enable(enable = enable)
reachs.append(new)
return reachs
def _sql_save(self, execute, data = None): def _sql_save(self, execute, data = None):
sql = (
"INSERT OR REPLACE INTO " +
"river_reach(id, name, enable, node1, node2) "+
"VALUES (" +
f"{self.id}, '{self._sql_format(self._name)}', " +
f"{self._sql_format(self.is_enable())},"
f"{self.node1.id}, {self.node2.id}"+
")"
)
execute(sql)
return True return True
@property @property
@ -152,13 +199,27 @@ class River(Graph, SQLSubModel):
@classmethod @classmethod
def _sql_update(cls, execute, version): def _sql_update(cls, execute, version):
cls._update_submodel(execute, version)
return True return True
@classmethod @classmethod
def _sql_load(cls, execute, data = None): def _sql_load(cls, execute, data = None):
return None new = cls(data["status"])
new._nodes = RiverNode._sql_load(
execute,
data
)
data["nodes"] = new.nodes()
new._edges = RiverReach._sql_load(
execute,
data
)
return new
def _sql_save(self, execute, data = None): def _sql_save(self, execute, data = None):
objs = self._nodes + self._edges
self._save_submodel(execute, objs, data)
return True return True
@property @property
@ -169,7 +230,6 @@ class River(Graph, SQLSubModel):
def sections(self): def sections(self):
return self._sections return self._sections
@property @property
def boundary_condition(self): def boundary_condition(self):
return self._boundary_condition return self._boundary_condition

View File

@ -38,6 +38,8 @@ class Study(SQLModel):
if init_new: if init_new:
# Study data # Study data
self._river = River(status = self.status) self._river = River(status = self.status)
else:
self._init_db_file(filename, is_new = False)
@classmethod @classmethod
def checkers(cls): def checkers(cls):
@ -141,22 +143,36 @@ class Study(SQLModel):
def _update(self): def _update(self):
version = self.execute(f"SELECT value FROM info WHERE key='version'") version = self.execute(f"SELECT value FROM info WHERE key='version'")
print(f"{version} == {self._version}") print(f"{version[0]} == {self._version}")
if version == self._version: if version[0] == self._version:
return True return True
print("TODO: update") if self._update_submodel(version):
self.execute(f"UPDATE info SET value='{self._version}' WHERE key='version'")
return True
print("TODO: update failed")
raise NotImplementedMethodeError(self, self._update) raise NotImplementedMethodeError(self, self._update)
@classmethod @classmethod
def _load(cls, filename): def _load(cls, filename):
new = cls(init_new = False) new = cls(init_new = False, filename = filename)
# TODO: Load metadata
print("TODO: Load metadata")
# Load river data # Load river data
self._river = River.load() new._river = River._sql_load(
lambda sql: new.execute(
sql,
fetch_one = False,
commit = True
),
data = {"status": new.status}
)
return new return new
def _save(self): def _save(self):
self._save_submodel([self._river])
self.commit() self.commit()

View File

@ -216,13 +216,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
if self.model.filename is None or self.model.filename == "": if self.model.filename is None or self.model.filename == "":
file_name, _ = QFileDialog.getSaveFileName( file_name, _ = QFileDialog.getSaveFileName(
self, "Save File", self, "Save File",
"", "Pamhyr(*.pkl)" "", "Pamhyr(*.pamhyr)"
) )
if file_name[-4:] == ".pkl": if file_name[-4:] == ".pamhyr":
self.model.filename = file_name self.model.filename = file_name
else: else:
self.model.filename = file_name + ".pkl" self.model.filename = file_name + ".pamhyr"
self.model.save() self.model.save()
@ -237,13 +237,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
""" """
file_name, _ = QFileDialog.getSaveFileName( file_name, _ = QFileDialog.getSaveFileName(
self, "Save File", self, "Save File",
"", "Pamhyr(*.pkl)" "", "Pamhyr(*.pamhyr)"
) )
if file_name[-4:] == ".pkl": if file_name[-4:] == ".pamhyr":
self.model.filename = file_name self.model.filename = file_name
else: else:
self.model.filename = file_name + ".pkl" self.model.filename = file_name + ".pamhyr"
self.model.save() self.model.save()