Ray's Knowledge Base

Pruning must key a literal the way the index stored the value

PitfallVerified 28 Sep 2026Holds anywhere
Pitfall. The symptom, what causes it, and the fix that was run and seen to work.

Symptom#

A filter on a bool field returns no rows on every path that uses the index (View scan, reader), while the same filter over the JSON records keeps the matching ones:

  • ok == true over records with "ok": true returned nothing in View collect, group/count, sink_json, read_lines and read_json.

Cause#

The index build had stored the bool as the integer 1 (the fold event keeps a bool as int64 1/0, and the bloom and zone-map builders saw that integer). Pruning turned the query literal true into the text "true" and looked that up. No chunk's evidence held "true", so every chunk was skipped.

Fix#

Convert each literal to the exact form the build stored before any bloom, postings or zone-map lookup: in dftracer-utils a bool literal becomes "1" or "0" in literal_to_string (index/plan/conditions.cpp). This only widens what a chunk may match; the evaluator still decides the rows. Test every literal type through each pruning path against a scan with the index off.

Evidence#

  • dftracer-utils cross-path test tests/trace/views/test_duql_paths.cpp (2026-09-27) found it: the filter returned 0 of 1 expected rows on all index-backed paths. After the change it returned the expected row on every path, and the prefilter fuzz and prune oracle tests still passed.