Family references discriminate through the referenced row's type

Intention: make local <prop>_type columns optional denormalization instead
of an engine requirement — writers should only ever have to say WHO.

Outcomes:
- compile_one_of: a type-strategy family REFERENCE (payer, source, target)
  now selects its polymorphic branch via the referenced row's own type —
  CASE (SELECT type FROM agreego.entity WHERE id = <alias>.<prop>_id) —
  the truth itself, instead of requiring a <prop>_type column beside the
  id. kind-strategy STI and a row's self-discrimination still read locally
  (there is no referenced row to consult). All CASEs are now simple-form,
  so the operand is evaluated once even as a subquery.
- GUC readers guard against the empty string: a rolled-back transaction
  that FIRST-sets a custom GUC leaves it '' session-wide (not unset), and
  COALESCE alone never fires — auth.user_id and punc.external now NULLIF
  first, matching agreego.get_cue's own convention.
- Golden fixtures regenerated via UPDATE_EXPECT; 1286 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 18:21:44 -04:00
parent 90262fc82b
commit f60158564d
3 changed files with 71 additions and 42 deletions

View File

@ -1408,8 +1408,13 @@
" 'archived', entity_19.archived,",
" 'created_at', entity_19.created_at,",
" 'is_primary', contact_21.is_primary,",
" 'target', CASE",
" WHEN relationship_20.target_type = 'phone_number' THEN ((",
" 'target', CASE (",
" SELECT __fam.type",
" FROM agreego.entity __fam",
" WHERE",
" __fam.id = relationship_20.target_id",
" )",
" WHEN 'phone_number' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_22.id,",
" 'type', entity_22.type,",
@ -1423,7 +1428,7 @@
" NOT entity_22.archived",
" AND relationship_20.target_id = entity_22.id",
" ))",
" WHEN relationship_20.target_type = 'email_address' THEN ((",
" WHEN 'email_address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_24.id,",
" 'type', entity_24.type,",
@ -1437,7 +1442,7 @@
" NOT entity_24.archived",
" AND relationship_20.target_id = entity_24.id",
" ))",
" WHEN relationship_20.target_type = 'address' THEN ((",
" WHEN 'address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_26.id,",
" 'type', entity_26.type,",
@ -1659,8 +1664,13 @@
" 'archived', entity_19.archived,",
" 'created_at', entity_19.created_at,",
" 'is_primary', contact_21.is_primary,",
" 'target', CASE",
" WHEN relationship_20.target_type = 'phone_number' THEN ((",
" 'target', CASE (",
" SELECT __fam.type",
" FROM agreego.entity __fam",
" WHERE",
" __fam.id = relationship_20.target_id",
" )",
" WHEN 'phone_number' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_22.id,",
" 'type', entity_22.type,",
@ -1674,7 +1684,7 @@
" NOT entity_22.archived",
" AND relationship_20.target_id = entity_22.id",
" ))",
" WHEN relationship_20.target_type = 'email_address' THEN ((",
" WHEN 'email_address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_24.id,",
" 'type', entity_24.type,",
@ -1688,7 +1698,7 @@
" NOT entity_24.archived",
" AND relationship_20.target_id = entity_24.id",
" ))",
" WHEN relationship_20.target_type = 'address' THEN ((",
" WHEN 'address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_26.id,",
" 'type', entity_26.type,",
@ -1889,8 +1899,8 @@
"sql": [
[
"((SELECT jsonb_strip_nulls((",
" SELECT COALESCE(jsonb_agg(CASE",
" WHEN organization_2.type = 'bot' THEN ((",
" SELECT COALESCE(jsonb_agg(CASE organization_2.type",
" WHEN 'bot' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_3.id,",
" 'type', entity_3.type,",
@ -1907,7 +1917,7 @@
" NOT entity_3.archived",
" AND entity_3.id = entity_1.id",
" ))",
" WHEN organization_2.type = 'organization' THEN ((",
" WHEN 'organization' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_6.id,",
" 'type', entity_6.type,",
@ -1921,7 +1931,7 @@
" NOT entity_6.archived",
" AND entity_6.id = entity_1.id",
" ))",
" WHEN organization_2.type = 'person' THEN ((",
" WHEN 'person' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_8.id,",
" 'type', entity_8.type,",
@ -1959,8 +1969,8 @@
"sql": [
[
"((SELECT jsonb_strip_nulls((",
" SELECT CASE",
" WHEN organization_2.type = 'bot' THEN ((",
" SELECT CASE organization_2.type",
" WHEN 'bot' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_3.id,",
" 'type', entity_3.type,",
@ -1976,7 +1986,7 @@
" NOT entity_3.archived",
" AND entity_3.id = entity_1.id",
" ))",
" WHEN organization_2.type = 'person' THEN ((",
" WHEN 'person' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_6.id,",
" 'type', entity_6.type,",
@ -2013,8 +2023,8 @@
"sql": [
[
"((SELECT jsonb_strip_nulls((",
" SELECT CASE",
" WHEN organization_2.type = 'person' THEN ((",
" SELECT CASE organization_2.type",
" WHEN 'person' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_3.id,",
" 'type', entity_3.type,",
@ -2121,8 +2131,13 @@
" 'archived', entity_21.archived,",
" 'created_at', entity_21.created_at,",
" 'is_primary', contact_23.is_primary,",
" 'target', CASE",
" WHEN relationship_22.target_type = 'phone_number' THEN ((",
" 'target', CASE (",
" SELECT __fam.type",
" FROM agreego.entity __fam",
" WHERE",
" __fam.id = relationship_22.target_id",
" )",
" WHEN 'phone_number' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_24.id,",
" 'type', entity_24.type,",
@ -2136,7 +2151,7 @@
" NOT entity_24.archived",
" AND relationship_22.target_id = entity_24.id",
" ))",
" WHEN relationship_22.target_type = 'email_address' THEN ((",
" WHEN 'email_address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_26.id,",
" 'type', entity_26.type,",
@ -2150,7 +2165,7 @@
" NOT entity_26.archived",
" AND relationship_22.target_id = entity_26.id",
" ))",
" WHEN relationship_22.target_type = 'address' THEN ((",
" WHEN 'address' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_28.id,",
" 'type', entity_28.type,",
@ -2246,15 +2261,15 @@
"sql": [
[
"((SELECT jsonb_strip_nulls((",
" SELECT COALESCE(jsonb_agg(CASE",
" WHEN widget_2.kind = 'stock' THEN (jsonb_build_object(",
" SELECT COALESCE(jsonb_agg(CASE widget_2.kind",
" WHEN 'stock' THEN (jsonb_build_object(",
" 'id', entity_1.id,",
" 'type', entity_1.type,",
" 'archived', entity_1.archived,",
" 'created_at', entity_1.created_at,",
" 'kind', widget_2.kind",
" ))",
" WHEN widget_2.kind = 'tasks' THEN (jsonb_build_object(",
" WHEN 'tasks' THEN (jsonb_build_object(",
" 'id', entity_1.id,",
" 'type', entity_1.type,",
" 'archived', entity_1.archived,",
@ -2360,8 +2375,8 @@
" 'total', order_2.total,",
" 'customer_id', order_2.customer_id,",
" 'counterparty', (",
" SELECT CASE",
" WHEN organization_4.type = 'bot' THEN ((",
" SELECT CASE organization_4.type",
" WHEN 'bot' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_5.id,",
" 'type', entity_5.type,",
@ -2378,7 +2393,7 @@
" NOT entity_5.archived",
" AND entity_5.id = entity_3.id",
" ))",
" WHEN organization_4.type = 'organization' THEN ((",
" WHEN 'organization' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_8.id,",
" 'type', entity_8.type,",
@ -2392,7 +2407,7 @@
" NOT entity_8.archived",
" AND entity_8.id = entity_3.id",
" ))",
" WHEN organization_4.type = 'person' THEN ((",
" WHEN 'person' THEN ((",
" SELECT jsonb_build_object(",
" 'id', entity_10.id,",
" 'type', entity_10.type,",