Summary
The cached EXISTS subject-probe fast path (fluree-db-query/src/filter.rs ~line 350, mirrored in optional.rs) only handles decoded subjects:
let Binding::Sid { sid, .. } = binding else {
// Only handle the common single-ledger SID binding here.
return Ok(None);
};
On a fully-indexed ledger with late materialization, scan-produced subjects are Binding::EncodedSid — so the probe declines every row and the query falls back to the generic correlated-EXISTS evaluation. Correctness is unaffected (the generic path is correct); this is purely a missed optimization, and arguably the common case on indexed reads.
Suggested fix
Handle Binding::EncodedSid { s_id, .. } directly — the cached subject set is keyed by s_id, so the encoded case needs no dictionary lookup at all (cheaper than the existing Sid arm, which does find_subject_id_by_parts). Both copies (filter.rs, optional.rs) need the same change.
Found during the mixed-representation equality audit (fixed separately); this site was verified correctness-safe.
Summary
The cached EXISTS subject-probe fast path (
fluree-db-query/src/filter.rs~line 350, mirrored inoptional.rs) only handles decoded subjects:On a fully-indexed ledger with late materialization, scan-produced subjects are
Binding::EncodedSid— so the probe declines every row and the query falls back to the generic correlated-EXISTS evaluation. Correctness is unaffected (the generic path is correct); this is purely a missed optimization, and arguably the common case on indexed reads.Suggested fix
Handle
Binding::EncodedSid { s_id, .. }directly — the cached subject set is keyed bys_id, so the encoded case needs no dictionary lookup at all (cheaper than the existingSidarm, which doesfind_subject_id_by_parts). Both copies (filter.rs,optional.rs) need the same change.Found during the mixed-representation equality audit (fixed separately); this site was verified correctness-safe.