luplo.core.id_resolve¶
UUID prefix resolution for human-typed identifiers.
luplo identifies most rows by UUIDv4 primary keys; the CLI displays them
as 8-character prefixes (id[:8]) and accepts the same prefixes back
on input. This module is the single place where prefix → full UUID
resolution happens.
Behaviour:
A 36-character canonical UUID is returned as-is (fast path; no DB call).
A hex prefix of at least
MIN_PREFIX_LENGTHcharacters is looked up against<table>.id::text LIKE prefix || '%'withLIMIT 2. Dashes in the input are ignored so users can paste partially-formatted ids.Zero matches →
NotFoundErroris the caller’s job; this function returnsNoneinstead so callers keep their existing not-found shapes.One match → the full UUID is returned.
Two or more matches →
AmbiguousIdErroris raised carrying the sampled rows. The caller never has to choose silently.
The module is intentionally generic: it takes a table name, an optional
project scope, and a label column used only for ambiguity messages. Each
domain module wraps this with its own resolve_*_id helper.
Attributes¶
Minimum hex characters required for a prefix lookup. |
Functions¶
|
Resolve a UUID or hex prefix against |
|
Build a SQL fragment that selects rows matching value by id. |
Module Contents¶
- luplo.core.id_resolve.MIN_PREFIX_LENGTH = 8¶
Minimum hex characters required for a prefix lookup.
8 hex characters = 32 bits, which keeps birthday-paradox collision probability under ~1% for project-scoped tables holding fewer than ~10,000 rows. Below this threshold, requiring more characters is cheaper than relying on collision luck.
- async luplo.core.id_resolve.resolve_uuid_prefix(conn: psycopg.AsyncConnection[Any], table: str, value: str, *, project_id: str | None = None, label_column: str = 'title', project_column: str = 'project_id') str | None¶
Resolve a UUID or hex prefix against
<table>.id.- Parameters:
conn – Open async connection.
table – Unquoted table name (e.g.
"items").value – Either a full canonical UUID string or a hex prefix.
project_id – Optional project scope. If supplied, the lookup is constrained to
project_column = project_idso prefixes from other projects do not collide.label_column – Column used to label sampled rows in the
AmbiguousIdErrormessage. Tables without a useful label can pass"id"to get the id back as the label.project_column – Column name to scope by; defaults to
"project_id".
- Returns:
The full UUID string when exactly one row matches, or
Nonewhen no row matches.- Raises:
InvalidIdFormatError – When value is neither a full UUID nor a valid hex prefix (after stripping dashes).
IdTooShortError – When value is a hex prefix shorter than
MIN_PREFIX_LENGTH.AmbiguousIdError – When the prefix matches more than one row.
- luplo.core.id_resolve.build_seed_clause(value: str, params: dict[str, Any]) psycopg.sql.Composable¶
Build a SQL fragment that selects rows matching value by id.
Returns a clause suitable for a WHERE position (no leading
WHERE). Mutates params in place: adds the binding under the key"seed".Use this when the caller needs to embed prefix matching inside a larger query (e.g. a recursive CTE that walks a supersede chain forward from any matching seed). For standalone lookups, prefer
resolve_uuid_prefix().- Raises:
InvalidIdFormatError – When value is not a UUID or hex prefix.
IdTooShortError – When the hex prefix is shorter than the minimum.