Skip to content

metadata

metadata

EAV metadata wrapper for visit_metadata and sample_metadata.

Both tables share the same shape: four typed value columns (value_int, value_numeric, value_bool, value_text) plus a value_type discriminator and a CHECK constraint that requires exactly one value column to be populated and to match value_type. This module hides the encoding behind a small key-value API:

metadata.set_visit(cur, visit_id, "bmi", 22.7)        # numeric
metadata.set_visit(cur, visit_id, "smoker", False)    # bool
metadata.get_visit(cur, visit_id, "bmi")              # -> Decimal('22.700000')
metadata.list_for_visit(cur, visit_id)                # -> dict[str, Any]
metadata.delete_visit(cur, visit_id, "bmi")           # -> bool

Equivalent _sample functions exist for sample_metadata.

Python types map to value columns as follows. Order matters: bool is a subclass of int, so it is checked first.

bool   -> value_bool      (value_type='bool')
int    -> value_int       (value_type='int')
float  -> value_numeric   (value_type='numeric')
str    -> value_text      (value_type='text')

Numeric values are stored as DECIMAL(20,6); the driver returns them as decimal.Decimal. Round-trips therefore convert float -> Decimal.

Writes use INSERT ... ON DUPLICATE KEY UPDATE against the existing UNIQUE on (parent_id, key_name), so :func:set_visit and :func:set_sample are idempotent. The function returns one of "inserted", "updated", or "unchanged" based on cur.rowcount.

set_visit

set_visit(cur, visit_id: int, key: str, value: Any) -> SetResult

Upsert a visit_metadata entry. Idempotent.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
visit_id int

Parent visit.

required
key str

Metadata key name (unique per visit).

required
value Any

bool / int / float / str. Float values round-trip as decimal.Decimal because the column type is DECIMAL(20,6).

required

Returns:

Type Description
SetResult

"inserted" on first write, "updated" when the value

SetResult

changed, "unchanged" when the row already had the same

SetResult

value.

Raises:

Type Description
ValueError

If value is None.

TypeError

If value is of an unsupported type.

Source code in src/noxdb/metadata.py
def set_visit(cur, visit_id: int, key: str, value: Any) -> SetResult:
    """Upsert a visit_metadata entry. Idempotent.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        visit_id: Parent visit.
        key: Metadata key name (unique per visit).
        value: ``bool`` / ``int`` / ``float`` / ``str``. Float values
            round-trip as ``decimal.Decimal`` because the column type is
            ``DECIMAL(20,6)``.

    Returns:
        ``"inserted"`` on first write, ``"updated"`` when the value
        changed, ``"unchanged"`` when the row already had the same
        value.

    Raises:
        ValueError: If ``value`` is ``None``.
        TypeError: If ``value`` is of an unsupported type.
    """
    return _set(cur, _VISIT, visit_id, key, value)

get_visit

get_visit(cur, visit_id: int, key: str) -> Any

Return the native value for (visit_id, key).

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
visit_id int

Parent visit.

required
key str

Metadata key name.

required

Returns:

Type Description
Any

The decoded value, or None if the key is not set.

Source code in src/noxdb/metadata.py
def get_visit(cur, visit_id: int, key: str) -> Any:
    """Return the native value for ``(visit_id, key)``.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        visit_id: Parent visit.
        key: Metadata key name.

    Returns:
        The decoded value, or ``None`` if the key is not set.
    """
    return _get(cur, _VISIT, visit_id, key)

list_for_visit

list_for_visit(cur, visit_id: int) -> dict[str, Any]

Return all metadata for a visit as a key/value dict.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
visit_id int

Parent visit.

required

Returns:

Type Description
dict[str, Any]

{key: value, ...} with native Python types.

Source code in src/noxdb/metadata.py
def list_for_visit(cur, visit_id: int) -> dict[str, Any]:
    """Return all metadata for a visit as a key/value dict.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        visit_id: Parent visit.

    Returns:
        ``{key: value, ...}`` with native Python types.
    """
    return _list(cur, _VISIT, visit_id)

delete_visit

delete_visit(cur, visit_id: int, key: str) -> bool

Delete (visit_id, key).

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
visit_id int

Parent visit.

required
key str

Metadata key name.

required

Returns:

Type Description
bool

True iff a row was removed.

Source code in src/noxdb/metadata.py
def delete_visit(cur, visit_id: int, key: str) -> bool:
    """Delete ``(visit_id, key)``.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        visit_id: Parent visit.
        key: Metadata key name.

    Returns:
        ``True`` iff a row was removed.
    """
    return _delete(cur, _VISIT, visit_id, key)

set_sample

set_sample(cur, sample_id: int, key: str, value: Any) -> SetResult

Upsert a sample_metadata entry. Idempotent.

See set_visit for the contract; this is the sample-keyed variant.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
sample_id int

Parent sample.

required
key str

Metadata key name (unique per sample).

required
value Any

bool / int / float / str.

required

Returns:

Type Description
SetResult

"inserted" / "updated" / "unchanged".

Source code in src/noxdb/metadata.py
def set_sample(cur, sample_id: int, key: str, value: Any) -> SetResult:
    """Upsert a sample_metadata entry. Idempotent.

    See [`set_visit`][noxdb.metadata.set_visit] for the
    contract; this is the sample-keyed variant.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        sample_id: Parent sample.
        key: Metadata key name (unique per sample).
        value: ``bool`` / ``int`` / ``float`` / ``str``.

    Returns:
        ``"inserted"`` / ``"updated"`` / ``"unchanged"``.
    """
    return _set(cur, _SAMPLE, sample_id, key, value)

get_sample

get_sample(cur, sample_id: int, key: str) -> Any

Return the native value for (sample_id, key).

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
sample_id int

Parent sample.

required
key str

Metadata key name.

required

Returns:

Type Description
Any

The decoded value, or None if the key is not set.

Source code in src/noxdb/metadata.py
def get_sample(cur, sample_id: int, key: str) -> Any:
    """Return the native value for ``(sample_id, key)``.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        sample_id: Parent sample.
        key: Metadata key name.

    Returns:
        The decoded value, or ``None`` if the key is not set.
    """
    return _get(cur, _SAMPLE, sample_id, key)

list_for_sample

list_for_sample(cur, sample_id: int) -> dict[str, Any]

Return all metadata for a sample as a key/value dict.

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
sample_id int

Parent sample.

required

Returns:

Type Description
dict[str, Any]

{key: value, ...} with native Python types.

Source code in src/noxdb/metadata.py
def list_for_sample(cur, sample_id: int) -> dict[str, Any]:
    """Return all metadata for a sample as a key/value dict.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        sample_id: Parent sample.

    Returns:
        ``{key: value, ...}`` with native Python types.
    """
    return _list(cur, _SAMPLE, sample_id)

delete_sample

delete_sample(cur, sample_id: int, key: str) -> bool

Delete (sample_id, key).

Parameters:

Name Type Description Default
cur

Audit-logging cursor from transaction().

required
sample_id int

Parent sample.

required
key str

Metadata key name.

required

Returns:

Type Description
bool

True iff a row was removed.

Source code in src/noxdb/metadata.py
def delete_sample(cur, sample_id: int, key: str) -> bool:
    """Delete ``(sample_id, key)``.

    Args:
        cur: Audit-logging cursor from `transaction()`.
        sample_id: Parent sample.
        key: Metadata key name.

    Returns:
        ``True`` iff a row was removed.
    """
    return _delete(cur, _SAMPLE, sample_id, key)