visits¶
visits
¶
CRUD wrapper for the visits table.
Same call style as the other table modules: cursor first, dict returns,
writes audit-logged via _LoggingCursor.
Natural key is the composite (subject_id, timepoint) — but
timepoint is nullable, and MariaDB's UNIQUE treats NULLs as
distinct, so multiple rows with timepoint IS NULL for the same
subject are permitted by the schema.
get_or_create rejects
timepoint=None for that reason.
create
¶
create(cur, subject_id: int, group_test: str, age: int | None, *, timepoint: str | None = None) -> int
Insert a visit and return its new visit_id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
subject_id
|
int
|
Parent subject. Must already exist. |
required |
group_test
|
str
|
Group/test label for this visit. |
required |
age
|
int | None
|
Subject age at visit, or |
required |
timepoint
|
str | None
|
Optional timepoint string; nullable. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
The newly inserted |
Raises:
| Type | Description |
|---|---|
IntegrityError
|
If |
Source code in src/noxdb/visits.py
get
¶
Return the visit row for a given id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Primary key to look up. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The row as |
Source code in src/noxdb/visits.py
get_by_subject_timepoint
¶
Return the visit row for the natural key.
When timepoint is None this matches via IS NULL. Because
NULL timepoints are not deduplicated by the UNIQUE, this lookup may
match an arbitrary row among several NULL-timepoint visits for the
same subject. Don't rely on it for idempotent inserts when timepoint
is None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
subject_id
|
int
|
Parent subject. |
required |
timepoint
|
str | None
|
Timepoint string, or |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any] | None
|
The row as |
Source code in src/noxdb/visits.py
get_or_create
¶
get_or_create(cur, subject_id: int, timepoint: str, group_test: str, age: int | None) -> tuple[int, bool]
Idempotently return the visit id, inserting if needed.
Existing rows are returned as-is; group_test and age are not used to update an existing row. Falls back to a re-fetch on the UNIQUE-violation race.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
subject_id
|
int
|
Parent subject. |
required |
timepoint
|
str
|
Timepoint string. Must not be |
required |
group_test
|
str
|
Used only on insert. |
required |
age
|
int | None
|
Used only on insert. |
required |
Returns:
| Type | Description |
|---|---|
int
|
|
bool
|
call inserted the row. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
IntegrityError
|
If the race-recovery fetch also misses. |
Source code in src/noxdb/visits.py
list_for_subject
¶
Return all visits belonging to a subject.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
subject_id
|
int
|
Subject to list. |
required |
order_by
|
str
|
Column name to order by. Must be a column of |
'visit_id'
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
All matching rows as |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/noxdb/visits.py
count_for_subject
¶
Return the number of visits for a subject.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
subject_id
|
int
|
Subject to count. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of visit rows. |
Source code in src/noxdb/visits.py
update
¶
update(cur, visit_id: int, *, timepoint: str | None = None, group_test: str | None = None, age: int | None = None) -> bool
Partial update of a visit row.
Only kwargs with non-None values are written. subject_id and
created_at are intentionally NOT updatable — re-parenting a
visit would corrupt downstream lineage. Setting timepoint to NULL
is also out of scope (the helper treats None as "skip"); use raw
SQL if you need that.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Row to update. |
required |
timepoint
|
str | None
|
New timepoint (if not None). |
None
|
group_test
|
str | None
|
New group/test label (if not None). |
None
|
age
|
int | None
|
New age (if not None). |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/noxdb/visits.py
delete
¶
Delete a visit.
samples.fk_samples_visit and
visit_metadata.fk_visit_metadata_visit are ON DELETE
CASCADE, so this also removes every sample (and its metadata) and
every visit_metadata row owned by the visit. sample_files uses
ON DELETE RESTRICT and will block the delete instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Row to delete. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/noxdb/visits.py
exists
¶
Return whether a visit with the given id exists.
For natural-key existence checks use
get_by_subject_timepoint(...) is not None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cur
|
Audit-logging cursor from |
required | |
visit_id
|
int
|
Id to check. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|