Skip to content

Commit

Permalink
Merge pull request #329 from seattleflu/sample-api-update
Browse files Browse the repository at this point in the history
Sample API update
  • Loading branch information
davereinhart authored Sep 1, 2023
2 parents 76a7f7e + c2126ad commit 7b1b4ac
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
5 changes: 4 additions & 1 deletion lib/id3c/api/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ def store_sample(session: DatabaseSession, sample: dict) -> Any:
collection_barcode = sample.pop("collection_id", None)
collection_identifier = find_identifier(session, collection_barcode) if collection_barcode else None

access_role = sample.pop("access_role", None)

result = {
"sample_barcode": sample_barcode,
"collection_barcode": collection_barcode
Expand Down Expand Up @@ -517,7 +519,8 @@ def store_sample(session: DatabaseSession, sample: dict) -> Any:
collection_identifier = collection_identifier.uuid if collection_identifier else None,
collection_date = collected_date,
encounter_id = None,
additional_details = sample)
additional_details = sample,
access_role = access_role)

result["sample"] = sample
result["status"] = status
Expand Down
5 changes: 4 additions & 1 deletion lib/id3c/api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@
},
"notes": {
"type": "string"
}
},
"access_role": {
"type": "string"
},
},
"anyOf": [
{ "required":
Expand Down
9 changes: 8 additions & 1 deletion lib/id3c/api/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,14 @@ <h3 class="code">POST /v1/warehouse/sample</h3>
"collection_matrix": "dry"
}
</pre>

<p>An "access_role" value is required for samples from specific projects to enable row-level security:
<pre>
{
...
"access_role": "some_db_role"
...
}
</pre>
<h3 class="code">GET /v1/warehouse/identifier-set-uses</h3>
<p>Retrieve metadata about all identifier set uses.

Expand Down
26 changes: 19 additions & 7 deletions lib/id3c/db/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ def upsert_sample(db: DatabaseSession,
collection_identifier: Optional[str],
collection_date: Optional[str],
encounter_id: Optional[int],
additional_details: dict) -> Tuple[Any, str]:
additional_details: dict,
access_role: Optional[str] = None) -> Tuple[Any, str]:
"""
Upsert sample by its *identifier* and/or *collection_identifier*.
An existing sample has its *identifier*, *collection_identifier*,
Expand All @@ -200,13 +201,15 @@ def upsert_sample(db: DatabaseSession,
"collection_date": collection_date,
"encounter_id": encounter_id,
"additional_details": Json(additional_details) if additional_details else None,
"additional_details_without_prov": Json({k: additional_details[k] for k in additional_details if k != '_provenance'}) if additional_details else None,
"access_role": access_role,
}

# Look for existing sample(s)
with db.cursor() as cursor:
cursor.execute("""
select
sample_id as id, identifier, collection_identifier, encounter_id, details,
sample_id as id, identifier, collection_identifier, encounter_id, details, access_role,
row (
identifier,
collection_identifier
Expand All @@ -223,8 +226,9 @@ def upsert_sample(db: DatabaseSession,
row(
coalesce(%(collection_date)s, collected)::timestamp,
coalesce(%(encounter_id)s::integer, encounter_id),
coalesce(details, '{}'::jsonb) || coalesce(%(additional_details)s, '{}')::jsonb
)::text as metadata_changed
coalesce(details, '{}'::jsonb) || coalesce(%(additional_details_without_prov)s, '{}')::jsonb
)::text as metadata_changed,
row(access_role)::text != row(coalesce(%(access_role)s, access_role))::text as access_role_changed
from warehouse.sample
where identifier = %(identifier)s
or collection_identifier = %(collection_identifier)s
Expand All @@ -239,12 +243,13 @@ def upsert_sample(db: DatabaseSession,
status = 'created'

sample = db.fetch_row("""
insert into warehouse.sample (identifier, collection_identifier, collected, encounter_id, details)
insert into warehouse.sample (identifier, collection_identifier, collected, encounter_id, details, access_role)
values (%(identifier)s,
%(collection_identifier)s,
date_or_null(%(collection_date)s),
%(encounter_id)s,
%(additional_details)s)
%(additional_details)s,
%(access_role)s)
returning sample_id as id, identifier, collection_identifier, encounter_id
""", data)

Expand All @@ -256,9 +261,10 @@ def upsert_sample(db: DatabaseSession,
LOG.info(f"Updating existing sample {sample.id}")
LOG.info(f"Sample.identifiers_changed is «{sample.identifiers_changed}» ")
LOG.info(f"Sample.metadata_changed is «{sample.metadata_changed}» ")
LOG.info(f"Sample.access_role_changed is «{sample.access_role_changed}» ")

# can safely skip upsert if metadata is unchanged and not updating identifiers or if all data is unchanged
if sample.metadata_changed == False and (not update_identifiers or sample.identifiers_changed == False):
if sample.metadata_changed == False and sample.access_role_changed == False and (not update_identifiers or sample.identifiers_changed == False):
LOG.info(f"Skipping upsert for sample {sample.id} «{sample.identifier}» (no change).")
return sample, status

Expand Down Expand Up @@ -286,16 +292,22 @@ def upsert_sample(db: DatabaseSession,
if overwrite_collection_date else SQL("""
collected = coalesce(collected, date_or_null(%(collection_date)s)), """)

# Update access_role if value changed
access_role_update_composable = SQL("""
access_role = %(access_role)s, """) if sample.access_role_changed else SQL("")

sample = db.fetch_row(SQL("""
update warehouse.sample
set {}
{}
{}
encounter_id = coalesce(%(encounter_id)s, encounter_id),
details = coalesce(details, {}) || %(additional_details)s
where sample_id = %(sample_id)s
returning sample_id as id, identifier, collection_identifier, encounter_id
""").format(identifiers_update_composable,
collected_update_composable,
access_role_update_composable,
Literal(Json({}))),
{ **data, "sample_id": sample.id })

Expand Down

0 comments on commit 7b1b4ac

Please sign in to comment.