Skip to content

Update item transactions in SQLAlchemy #303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Dec 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6de07ec
query by item and collection id
jonhealy1 Oct 8, 2021
a007828
add get item test
jonhealy1 Oct 8, 2021
be29b23
add parameters
jonhealy1 Oct 8, 2021
c48a816
run pre-commit
jonhealy1 Oct 8, 2021
9efd11a
Alter items table to have primary key on both id and collection_id
robintw Oct 11, 2021
5178f15
Merge pull request #1 from robintw/update_get_item
jonhealy1 Oct 18, 2021
893e7d1
update update_item route
jonhealy1 Nov 29, 2021
a229c3e
add delete_item changes
jonhealy1 Nov 29, 2021
75616b0
run pre-commit
jonhealy1 Nov 29, 2021
aa690fa
run pre-commit
jonhealy1 Nov 29, 2021
832df22
Merge branch 'master' into update_item_transactions
jonhealy1 Nov 29, 2021
fa8e6c3
clean up
jonhealy1 Nov 29, 2021
8ac720f
fix query in update/delete items
jonhealy1 Nov 30, 2021
aa02658
merge
jonhealy1 Nov 30, 2021
a24f4bc
Merge branch 'master' into update_item_transactions
jonhealy1 Nov 30, 2021
3ce88b6
run pre commit
jonhealy1 Nov 30, 2021
21468d8
pre commit
jonhealy1 Nov 30, 2021
1fe00ae
create duplicate item ids, different collections test
jonhealy1 Nov 30, 2021
7875523
create duplicate item ids, delete item test
jonhealy1 Nov 30, 2021
c071d87
create duplicate item ids, update item test
jonhealy1 Nov 30, 2021
2977d63
clarify tests
jonhealy1 Dec 6, 2021
92f92ed
create duplicate item, different collections test in postgres
jonhealy1 Dec 6, 2021
ee2e59d
Merge branch 'master' into update_item_transactions
jonhealy1 Dec 6, 2021
94e1c90
Merge branch 'master' into update_item_transactions
jonhealy1 Dec 7, 2021
c4e2f90
Merge branch 'master' into update_item_transactions
geospatial-jeff Dec 8, 2021
4ea5ec8
remove app client 2 in conftest
jonhealy1 Dec 8, 2021
52a8c2c
merge master
jonhealy1 Dec 8, 2021
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
14 changes: 11 additions & 3 deletions stac_fastapi/sqlalchemy/stac_fastapi/sqlalchemy/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ def update_item(self, model: stac_types.Item, **kwargs) -> stac_types.Item:
query = session.query(self.item_table).filter(
self.item_table.id == model["id"]
)
query = query.filter(self.item_table.collection_id == model["collection"])
if not query.scalar():
raise NotFoundError(f"Item {model['id']} not found")
raise NotFoundError(
f"Item {model['id']} in collection {model['collection']}"
)
# SQLAlchemy orm updates don't seem to like geoalchemy types
db_model = self.item_serializer.stac_to_db(model)
query.update(self.item_serializer.row_to_dict(db_model))
Expand Down Expand Up @@ -91,10 +94,15 @@ def delete_item(
"""Delete item."""
base_url = str(kwargs["request"].base_url)
with self.session.writer.context_session() as session:
query = session.query(self.item_table).filter(self.item_table.id == item_id)
query = session.query(self.item_table).filter(
self.item_table.collection_id == collection_id
)
query = query.filter(self.item_table.id == item_id)
data = query.first()
if not data:
raise NotFoundError(f"Item {item_id} not found")
raise NotFoundError(
f"Item {item_id} not found in collection {collection_id}"
)
query.delete()
return self.item_serializer.db_to_stac(data, base_url=base_url)

Expand Down
38 changes: 38 additions & 0 deletions stac_fastapi/sqlalchemy/tests/clients/test_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,44 @@ def test_create_item_already_exists(
postgres_transactions.create_item(item, request=MockStarletteRequest)


def test_create_duplicate_item_different_collections(
postgres_core: CoreCrudClient,
postgres_transactions: TransactionsClient,
load_test_data: Callable,
):
# create test-collection
coll = load_test_data("test_collection.json")
postgres_transactions.create_collection(coll, request=MockStarletteRequest)

# create test-collection-2
coll["id"] = "test-collection-2"
postgres_transactions.create_collection(coll, request=MockStarletteRequest)

# add item to test-collection
item = load_test_data("test_item.json")
postgres_transactions.create_item(item, request=MockStarletteRequest)

# get item from test-collection
resp = postgres_core.get_item(
item["id"], item["collection"], request=MockStarletteRequest
)
assert Item(**item).dict(
exclude={"links": ..., "properties": {"created", "updated"}}
) == Item(**resp).dict(exclude={"links": ..., "properties": {"created", "updated"}})

# add item to test-collection-2
item["collection"] = "test-collection-2"
postgres_transactions.create_item(item, request=MockStarletteRequest)

# get item with same id from test-collection-2
resp = postgres_core.get_item(
item["id"], item["collection"], request=MockStarletteRequest
)
assert Item(**item).dict(
exclude={"links": ..., "properties": {"created", "updated"}}
) == Item(**resp).dict(exclude={"links": ..., "properties": {"created", "updated"}})


def test_update_item(
postgres_core: CoreCrudClient,
postgres_transactions: TransactionsClient,
Expand Down
137 changes: 136 additions & 1 deletion stac_fastapi/sqlalchemy/tests/resources/test_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,141 @@ def test_create_item_conflict(app_client, load_test_data):
assert resp.status_code == 409


def test_create_item_duplicate(app_client, load_test_data):
"""Test creation of an item id which already exists but in a different collection(transactions extension)"""

# add test_item to test-collection
test_item = load_test_data("test_item.json")
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200

# add test_item to test-collection again, resource already exists
test_item = load_test_data("test_item.json")
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 409

# create "test-collection-2"
collection_2 = load_test_data("test_collection.json")
collection_2["id"] = "test-collection-2"
resp = app_client.post("/collections", json=collection_2)
assert resp.status_code == 200

# add test_item to test-collection-2, posts successfully
test_item["collection"] = "test-collection-2"
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200


def test_delete_item_duplicate(app_client, load_test_data):
"""Test creation of an item id which already exists but in a different collection(transactions extension)"""

# add test_item to test-collection
test_item = load_test_data("test_item.json")
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200

# create "test-collection-2"
collection_2 = load_test_data("test_collection.json")
collection_2["id"] = "test-collection-2"
resp = app_client.post("/collections", json=collection_2)
assert resp.status_code == 200

# add test_item to test-collection-2
test_item["collection"] = "test-collection-2"
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200

# delete test_item from test-collection
test_item["collection"] = "test-collection"
resp = app_client.delete(
f"/collections/{test_item['collection']}/items/{test_item['id']}"
)
assert resp.status_code == 200

# test-item in test-collection has already been deleted
resp = app_client.delete(
f"/collections/{test_item['collection']}/items/{test_item['id']}"
)
assert resp.status_code == 404

# test-item in test-collection-2 still exists, was not deleted
test_item["collection"] = "test-collection-2"
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 409


def test_update_item_duplicate(app_client, load_test_data):
"""Test creation of an item id which already exists but in a different collection(transactions extension)"""

# add test_item to test-collection
test_item = load_test_data("test_item.json")
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200

# create "test-collection-2"
collection_2 = load_test_data("test_collection.json")
collection_2["id"] = "test-collection-2"
resp = app_client.post("/collections", json=collection_2)
assert resp.status_code == 200

# add test_item to test-collection-2
test_item["collection"] = "test-collection-2"
resp = app_client.post(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200

# update gsd in test_item, test-collection-2
test_item["properties"]["gsd"] = 16
resp = app_client.put(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200
updated_item = resp.json()
assert updated_item["properties"]["gsd"] == 16

# update gsd in test_item, test-collection
test_item["collection"] = "test-collection"
test_item["properties"]["gsd"] = 17
resp = app_client.put(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 200
updated_item = resp.json()
assert updated_item["properties"]["gsd"] == 17

# test_item in test-collection, updated gsd = 17
resp = app_client.get(
f"/collections/{test_item['collection']}/items/{test_item['id']}"
)
assert resp.status_code == 200
item = resp.json()
assert item["properties"]["gsd"] == 17

# test_item in test-collection-2, updated gsd = 16
test_item["collection"] = "test-collection-2"
resp = app_client.get(
f"/collections/{test_item['collection']}/items/{test_item['id']}"
)
assert resp.status_code == 200
item = resp.json()
assert item["properties"]["gsd"] == 16


def test_delete_missing_item(app_client, load_test_data):
"""Test deletion of an item which does not exist (transactions extension)"""
test_item = load_test_data("test_item.json")
Expand Down Expand Up @@ -102,7 +237,7 @@ def test_update_item_missing_collection(app_client, load_test_data):
resp = app_client.put(
f"/collections/{test_item['collection']}/items", json=test_item
)
assert resp.status_code == 422
assert resp.status_code == 404


def test_update_item_geometry(app_client, load_test_data):
Expand Down