Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/data/model/designation.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ def layer1_table(cls) -> str:
def layer1_keys(cls) -> list[str]:
return ["design"]

@classmethod
def layer1_primary_keys(cls) -> list[str]:
return ["record_id", "design"]

@classmethod
def from_layer1(cls, data: dict[str, Any]) -> Self:
return cls(design=data["design"])
Expand Down
12 changes: 7 additions & 5 deletions app/data/repositories/layer1.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ def save_structured_data(
all_columns = ["record_id"] + columns
placeholders = ",".join(["%s"] * len(all_columns))
update_columns = [c for c in all_columns if c not in conflict_keys]
on_conflict_set = ", ".join(f"{c} = EXCLUDED.{c}" for c in update_columns)
query = (
f"INSERT INTO {table} ({', '.join(all_columns)}) VALUES ({placeholders}) "
f"ON CONFLICT ({', '.join(conflict_keys)}) DO UPDATE SET {on_conflict_set}"
)
conflict_clause = f"ON CONFLICT ({', '.join(conflict_keys)})"
if update_columns:
on_conflict_set = ", ".join(f"{c} = EXCLUDED.{c}" for c in update_columns)
conflict_action = f"{conflict_clause} DO UPDATE SET {on_conflict_set}"
else:
conflict_action = f"{conflict_clause} DO NOTHING"
query = f"INSERT INTO {table} ({', '.join(all_columns)}) VALUES ({placeholders}) {conflict_action}"
rows = [[rid] + vals for rid, vals in zip(ids, data, strict=True)]
with self.with_tx():
self._storage.execute_batch(query, rows)
Expand Down
5 changes: 5 additions & 0 deletions postgres/migrations/V039__designation_multi_name.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* pgmigrate-encoding: utf-8 */

ALTER TABLE designation.data DROP CONSTRAINT data_pkey;

ALTER TABLE designation.data ADD PRIMARY KEY (record_id, design);
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies = [
"opentelemetry-instrumentation-fastapi>=0.61b0",
"opentelemetry-instrumentation-psycopg>=0.61b0",
"opentelemetry-exporter-otlp>=1.40.0",
"click~=8.3.1",
"click~=8.0",
]

[project.scripts]
Expand Down
18 changes: 18 additions & 0 deletions tests/integration/layer1_repository_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,21 @@ def test_get_new_nature_records_returns_all_records_for_same_pgc_in_one_batch(
self.assertEqual({r.pgc for r in result}, {99})
type_names = {r.data.type_name for r in result}
self.assertEqual(type_names, {"G", "*"})

def test_designation_multiple_names_per_record(self) -> None:
self._get_table("desig_table")
self.layer0_repo.register_records("desig_table", ["r1"])
self.layer1_repo.save_structured_data(
model.DesignationCatalogObject.layer1_table(),
model.DesignationCatalogObject.layer1_keys(),
["r1", "r1"],
[["NGC 224"], ["M 31"]],
conflict_keys=model.DesignationCatalogObject.layer1_primary_keys(),
)

result = self.pg_storage.storage.query(
"SELECT design FROM designation.data WHERE record_id = %s ORDER BY design",
params=["r1"],
)

self.assertEqual(result, [{"design": "M 31"}, {"design": "NGC 224"}])
16 changes: 14 additions & 2 deletions tests/integration/layer2_import_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ def test_import_two_catalogs(self):
self.layer1_repo.save_structured_data(
"icrs.data", ["ra", "e_ra", "dec", "e_dec"], ["123", "124"], [[12, 0.2, 13, 0.2], [14, 0.2, 15, 0.2]]
)
self.layer1_repo.save_structured_data("designation.data", ["design"], ["123", "124"], [["test1"], ["test2"]])
self.layer1_repo.save_structured_data(
"designation.data",
["design"],
["123", "124"],
[["test1"], ["test2"]],
conflict_keys=model.DesignationCatalogObject.layer1_primary_keys(),
)

self.task.run()

Expand Down Expand Up @@ -75,7 +81,13 @@ def test_updated_objects(self):

last_update_dt = self.layer2_repo.get_last_update_time(model.RawCatalog.DESIGNATION)

self.layer1_repo.save_structured_data("designation.data", ["design"], ["125", "126"], [["test3"], ["test3"]])
self.layer1_repo.save_structured_data(
"designation.data",
["design"],
["125", "126"],
[["test3"], ["test3"]],
conflict_keys=model.DesignationCatalogObject.layer1_primary_keys(),
)

self.task.run()

Expand Down
16 changes: 14 additions & 2 deletions tests/integration/layer2_repository_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,13 @@ def test_get_orphaned_pgcs_returns_empty_when_layer1_present(self) -> None:
self.layer0_repo.register_records("t1", ["r1"])
self.common_repo.register_pgcs([100])
self.layer0_repo.upsert_pgc({"r1": 100})
self.layer1_repo.save_structured_data("designation.data", ["design"], ["r1"], [["x"]])
self.layer1_repo.save_structured_data(
"designation.data",
["design"],
["r1"],
[["x"]],
conflict_keys=model.DesignationCatalogObject.layer1_primary_keys(),
)
self._save_layer2_data([model.Layer2CatalogObject(100, [model.DesignationCatalogObject(design="x")])])

orphaned = self.layer2_repo.get_orphaned_pgcs([model.RawCatalog.DESIGNATION])
Expand All @@ -270,7 +276,13 @@ def test_get_orphaned_pgcs_returns_only_pgcs_without_layer1_data(self) -> None:
self.layer0_repo.register_records("t1", ["r1"])
self.common_repo.register_pgcs([100, 200])
self.layer0_repo.upsert_pgc({"r1": 100})
self.layer1_repo.save_structured_data("designation.data", ["design"], ["r1"], [["linked"]])
self.layer1_repo.save_structured_data(
"designation.data",
["design"],
["r1"],
[["linked"]],
conflict_keys=model.DesignationCatalogObject.layer1_primary_keys(),
)
self._save_layer2_data(
[
model.Layer2CatalogObject(100, [model.DesignationCatalogObject(design="linked")]),
Expand Down
Loading
Loading