Skip to content

Commit 2184f2b

Browse files
committed
Merge main
2 parents c60ac44 + 8dbf3a7 commit 2184f2b

File tree

5 files changed

+144
-18
lines changed

5 files changed

+144
-18
lines changed

src/db_connector.py

+23
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,29 @@ def get_tables(self) -> list[str]:
3535
return tables
3636

3737

38+
def get_groups(self) -> list[dict]:
39+
groups = []
40+
tables = self.get_tables()
41+
for table in tables:
42+
group = {}
43+
split_table = table.split(".")
44+
fields = self.get_fields_for_table(split_table[0], split_table[1])
45+
for field in fields:
46+
if "__fgid" in field["name"]:
47+
try:
48+
group[split_table[1]]
49+
except KeyError:
50+
group[split_table[1]] = {}
51+
group[split_table[1]]["layers"] = []
52+
group[split_table[1]]["layers"].append(field["name"].split("__fgid")[0])
53+
54+
if group:
55+
groups.append(group)
56+
57+
return groups
58+
59+
60+
3861
def get_fields_for_table(self, schema: str, table: str) -> list[dict]:
3962
fields = []
4063
self.cursor.execute(f"""SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = '{schema}' AND table_name = '{table}' AND column_name != 'geom';""")

src/feature_group.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from tabor_layer import TaborLayer
2+
3+
4+
class FeatureGroup(object):
5+
def __init__(self, name: str) -> None:
6+
self.name = name
7+
self.schema = ""
8+
self.owner = ""
9+
self.layers = []
10+
11+
12+
def add_layer(self, layer: TaborLayer) -> list[TaborLayer]:
13+
if not layer.get_pk_field()[0]:
14+
raise Exception(f"{layer.name} has no primary key but it is in group {self.name}")
15+
16+
if not self.schema:
17+
self.schema = layer.schema
18+
19+
if not self.owner:
20+
self.owner = layer.owner
21+
22+
if layer.schema != self.schema:
23+
raise Exception(f"{layer.name} is in the wrong schema, expected {self.schema} but got {layer.schema}")
24+
25+
if layer.owner != self.owner:
26+
raise Exception(f"{layer.name} has the wrong owner, expected {self.owner} but got {layer.owner}")
27+
28+
self.layers.append(layer)
29+
return self.layers
30+
31+
32+
def gather_foreign_keys(self) -> str:
33+
foreign_keys = []
34+
35+
for layer in self.layers:
36+
pk_name, pk_type = layer.get_pk_field()
37+
foreign_keys.append(f"""{layer.name}__fgid {pk_type} references "{layer.schema}"."{layer.name}"({pk_name})""")
38+
return f"({", ".join(foreign_keys)})"
39+
40+
41+
def __str__(self) -> str:
42+
return f"""CREATE TABLE IF NOT EXISTS "{self.schema}"."{self.name}" {self.gather_foreign_keys()}; """

src/tabor.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@ def load(file_path: str, db: str, username: str, password: str, host: str, port:
1717

1818
tabor_src = TaborFile(file_path)
1919
psql = tabor_src.to_psql()
20+
layers = psql["layers"]
21+
groups = psql["groups"]
2022

21-
for _,layer in psql.items():
23+
for _,layer in layers.items():
2224
for _,value in layer.items():
2325
if type(value) is list:
2426
for query in value:
2527
db_connector.execute_commit_query(query)
2628
else:
2729
db_connector.execute_commit_query(value)
2830

31+
for _,group in groups.items():
32+
for _,value in group.items():
33+
db_connector.execute_commit_query(value)
34+
2935
print(f"Loaded {file_path} to {db}")
3036
except:
3137
raise Exception("Failed to load .tabor file to PostGIS database")
@@ -45,12 +51,14 @@ def write(file_path: str, db: str, username: str, password: str, host: str, port
4551
data = {}
4652
db_connector = DBConnector(db, username, password, host, port)
4753
tables = db_connector.get_tables()
54+
groups = db_connector.get_groups()
55+
group_names = [list(group)[0] for group in groups]
4856

4957
for table in tables:
5058
schema = table.split(".")[0]
5159
table_name = table.split(".")[1]
5260

53-
if table_name in ignore_tables:
61+
if table_name in ignore_tables or table_name in group_names:
5462
continue
5563

5664
data[table] = {}
@@ -63,6 +71,11 @@ def write(file_path: str, db: str, username: str, password: str, host: str, port
6371

6472
data[table]["owner"] = username
6573

74+
for group in groups:
75+
for group_name,layers in group.items():
76+
if table_name in layers["layers"]:
77+
data[table]["group"] = group_name
78+
6679
tabor_src = TaborFile(file_path, psql_data=data)
6780
tabor_src.write()
6881
print(f"Wrote .tabor file to {file_path}")

src/tabor_file.py

+47-12
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
from yaml import safe_dump, safe_load
33

44
from constraint import Constraint, Trigger
5+
from feature_group import FeatureGroup
56
from tabor_layer import TaborLayer
67
from consts import VERSION
78

89

910
class TaborFile(object):
11+
# TODO: Use hashmaps!
12+
groups: list[FeatureGroup] = []
1013
layers: list[TaborLayer] = []
1114

1215
def __init__(self, path: str, psql_data: dict | None = None) -> None:
@@ -31,7 +34,14 @@ def __init__(self, path: str, psql_data: dict | None = None) -> None:
3134
except KeyError:
3235
pass
3336

34-
self.add_layer(layer["name"], layer["schema"], geometry, layer["owner"], layer["fields"], constraints)
37+
38+
group = ""
39+
try:
40+
group = layer["group"]
41+
except KeyError:
42+
pass
43+
44+
self.add_layer(layer["name"], layer["schema"], geometry, layer["owner"], layer["fields"], constraints, group)
3545

3646
except FileNotFoundError:
3747
raise Exception(f"Failed to read .tabor file at {self.path}, does that path exist?")
@@ -51,24 +61,43 @@ def __init__(self, path: str, psql_data: dict | None = None) -> None:
5161
except KeyError:
5262
pass
5363

54-
self.add_layer(table.split(".")[1], table.split(".")[0], geom, values["owner"], values["fields"], derived_constraints)
64+
derived_group = None
65+
try:
66+
derived_group = values["group"]
67+
except KeyError:
68+
pass
69+
self.add_layer(table.split(".")[1], table.split(".")[0], geom, values["owner"], values["fields"], derived_constraints, derived_group)
5570

5671

57-
def add_layer(self, name: str, schema: str, geometry: str | None, owner: str, fields: dict, constraints: list[dict]) -> TaborLayer:
58-
self.layers.append(TaborLayer(name, schema, geometry, owner, fields, constraints))
72+
def add_layer(self, name: str, schema: str, geometry: str | None, owner: str, fields: dict, constraints: list[dict], group: str | None) -> TaborLayer:
73+
layer = TaborLayer(name, schema, geometry, owner, fields, constraints, group)
74+
if group:
75+
feature_group = self.add_or_get_group(group)
76+
feature_group.add_layer(layer)
77+
self.layers.append(layer)
5978
return self.layers[len(self.layers) - 1]
6079

6180

81+
def add_or_get_group(self, name: str) -> FeatureGroup:
82+
for group in self.groups:
83+
if group.name == name:
84+
return group
85+
86+
self.groups.append(FeatureGroup(name))
87+
return self.groups[len(self.groups) - 1]
88+
89+
6290
def to_psql(self) -> dict:
6391
result = {}
92+
result["layers"] = {}
6493
for layer in self.layers:
65-
result[layer.name] = {}
94+
result["layers"][layer.name] = {}
6695
fields = []
6796
for field in layer.fields:
6897
fields.append(field.as_psql())
6998

70-
if layer.get_pk_field():
71-
pk_query = f""", PRIMARY KEY ({layer.get_pk_field()})"""
99+
if layer.get_pk_field()[0]:
100+
pk_query = f""", PRIMARY KEY ({layer.get_pk_field()[0]})"""
72101
else:
73102
pk_query = ""
74103

@@ -77,15 +106,21 @@ def to_psql(self) -> dict:
77106
else:
78107
geom_query = ""
79108

80-
result[layer.name]["schema"] = f"""CREATE TABLE IF NOT EXISTS "{layer.schema}"."{layer.name}" ({", ".join(fields)}{geom_query}{pk_query});"""
81-
result[layer.name]["owner"] = f"""ALTER TABLE "{layer.schema}"."{layer.name}" OWNER TO {layer.owner};"""
109+
result["layers"][layer.name]["schema"] = f"""CREATE TABLE IF NOT EXISTS "{layer.schema}"."{layer.name}" ({", ".join(fields)}{geom_query}{pk_query});"""
110+
result["layers"][layer.name]["owner"] = f"""ALTER TABLE "{layer.schema}"."{layer.name}" OWNER TO {layer.owner};"""
82111

83-
result[layer.name]["constraints"] = []
112+
result["layers"][layer.name]["constraints"] = []
84113
for constraint in layer.constraints:
85-
result[layer.name]["constraints"].append(str(constraint))
114+
result["layers"][layer.name]["constraints"].append(str(constraint))
86115

87116
if layer.geometry:
88-
result[layer.name]["geometry"] = f"""ALTER TABLE "{layer.schema}"."{layer.name}" ALTER COLUMN geom TYPE Geometry({layer.derive_geometry_type()});"""
117+
result["layers"][layer.name]["geometry"] = f"""ALTER TABLE "{layer.schema}"."{layer.name}" ALTER COLUMN geom TYPE Geometry({layer.derive_geometry_type()});"""
118+
119+
result["groups"] = {}
120+
for group in self.groups:
121+
result["groups"][group.name] = {}
122+
result["groups"][group.name]["schema"] = str(group)
123+
result["groups"][group.name]["owner"] = f"""ALTER TABLE "{group.schema}"."{group.name}" OWNER TO {group.owner};"""
89124

90125
return result
91126

src/tabor_layer.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from geometry_type import GeometryType
22
from constraint import Constraint
3+
from tabor_field_type import TaborFieldType
34
from tabor_field import TaborField
45

56

67
class TaborLayer(object):
7-
def __init__(self, name: str, schema: str, geometry: str | None, owner: str, fields: dict, constraints: list[dict]) -> None:
8+
def __init__(self, name: str, schema: str, geometry: str | None, owner: str, fields: dict, constraints: list[dict], group: str | None) -> None:
89
self.name = name
910
self.schema = schema
1011

@@ -13,6 +14,11 @@ def __init__(self, name: str, schema: str, geometry: str | None, owner: str, fie
1314
else:
1415
self.geometry = None
1516

17+
if group:
18+
self.group = group
19+
else:
20+
self.group = None
21+
1622
self.constraints: list[Constraint] = []
1723
if constraints:
1824
for constraint in constraints:
@@ -37,11 +43,11 @@ def add_field(self, name: str, type: str, pk: bool) -> None:
3743
self.fields.append(TaborField(name, type, pk))
3844

3945

40-
def get_pk_field(self) -> str:
46+
def get_pk_field(self) -> tuple[str, TaborFieldType]:
4147
for field in self.fields:
4248
if field.pk:
43-
return field.name
44-
return ""
49+
return (field.name, field.type)
50+
return ("", TaborFieldType(""))
4551

4652

4753
def as_dict(self) -> dict:
@@ -58,6 +64,9 @@ def as_dict(self) -> dict:
5864
if self.geometry:
5965
var_dict["geometry"] = str(self.geometry)
6066

67+
if self.group:
68+
var_dict["group"] = self.group
69+
6170
return var_dict
6271

6372

@@ -72,3 +81,7 @@ def derive_geometry_type(self) -> str:
7281
"multi polygon": "Multipolygon"
7382
}
7483
return postgis_geometry_types[self.geometry.type]
84+
85+
86+
def __str__(self) -> str:
87+
return f"{self.schema}.{self.name}"

0 commit comments

Comments
 (0)