docs(data_store): document polymorphic for_id resolution pattern
Clarifies why v_data_store has no for_id_random JOIN column (for_type is runtime-variable), how get_id_random() resolves the integer FK at model validation time, and that Step 4 guarantees integers never leak into API responses. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -106,6 +106,10 @@ class Data_Store_Base(BaseModel):
|
|||||||
values[f'{field}_random'] = resolved_rid
|
values[f'{field}_random'] = resolved_rid
|
||||||
|
|
||||||
# 3. Handle Polymorphic for_id
|
# 3. Handle Polymorphic for_id
|
||||||
|
# v_data_store intentionally has no for_id_random JOIN column because for_type is
|
||||||
|
# runtime-variable (event, event_session, person, journal, etc.) — the target table
|
||||||
|
# is unknown at view-definition time. Resolution falls back to get_id_random() here.
|
||||||
|
# If resolution fails, Step 4 strips the raw integer to None — integers never leak.
|
||||||
if f_rid := values.get('for_id_random'):
|
if f_rid := values.get('for_id_random'):
|
||||||
values['for_id'] = f_rid
|
values['for_id'] = f_rid
|
||||||
elif values.get('for_id') and values.get('for_type'):
|
elif values.get('for_id') and values.get('for_type'):
|
||||||
|
|||||||
@@ -261,6 +261,14 @@ Fix: add a mapping to the special-case block in `sanitize_payload()` (same file,
|
|||||||
if obj_type_lookup == 'poc_person': obj_type_lookup = 'person'
|
if obj_type_lookup == 'poc_person': obj_type_lookup = 'person'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Polymorphic FK fields (`for_id` / `for_type`)
|
||||||
|
|
||||||
|
`data_store.for_id` is a polymorphic FK — `for_type` can be `event`, `event_session`, `person`, `journal`, or any other Aether object type, chosen at runtime. Because the target table is unknown at view-definition time, `v_data_store` intentionally **has no `for_id_random` JOIN column** (unlike `account_id_random`, which is a fixed JOIN to `account`).
|
||||||
|
|
||||||
|
Resolution happens in the `Data_Store_Base.map_v3_ids` root validator (Step 3): it calls `get_id_random(for_id_int, for_type)` which does `SELECT id_random FROM {for_type} WHERE id = :id`, with Redis caching. If resolution fails, Step 4 strips the raw integer to `None` — **integers never appear in API responses**.
|
||||||
|
|
||||||
|
> If you see `for_id: null` in a response where a value is expected, check that `for_type` matches a valid Aether table name and the referenced record exists.
|
||||||
|
|
||||||
#### Alt-view fields (in `tbl_alt` only)
|
#### Alt-view fields (in `tbl_alt` only)
|
||||||
Some objects have a richer alternate SQL view triggered by `?view=alt`. These fields
|
Some objects have a richer alternate SQL view triggered by `?view=alt`. These fields
|
||||||
**must still be declared in the Pydantic model and `searchable_fields`** even if they only
|
**must still be declared in the Pydantic model and `searchable_fields`** even if they only
|
||||||
|
|||||||
Reference in New Issue
Block a user