Repository navigation
fix(r13): make the value evaluator three-valued (R13 slice 2; P48, P50) - #84
Merged
TimelordUK merged 3 commits intoSep 13, 2026
Merged
Conversation
A simple CASE compares with =, so CASE x WHEN NULL never matches. Ours treats (Null, Null) as equal. Not a predicate, so outside the evaluator matrix; pinned as a corpus case before the slice 2 change. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01GpuTexUeuyuAdmDsukMTRW
ArithmeticEvaluator - serving SELECT, HAVING and join conditions - now evaluates predicates in three-valued logic, with NULL standing for UNKNOWN: - comparisons yield NULL for a NULL operand, via a predicate-layer compare_trilean; compare_values keeps NULL = NULL equal for ORDER BY - AND / OR / NOT use Trilean's truth tables instead of to_bool (removed) - IN / NOT IN take OR's truth table, so a NULL probe or NULL item is UNKNOWN - BETWEEN takes AND's truth table; LIKE yields NULL for a NULL operand - simple CASE x WHEN NULL no longer matches a NULL x Trilean gains from_value / to_value, the single crossing between the value evaluator's DataValue and the truth tables. Acceptance, as set by slice 1: all 32 value-evaluator KNOWN entries in the evaluator matrix went FIXED in this one change and the WHERE column did not move, so KNOWN is now empty. Parity moved by exactly the six P48/P50 cases, 168 -> 174 AGREE over 204. FORMAL examples unchanged; Rust, Python and example suites green. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01GpuTexUeuyuAdmDsukMTRW
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01GpuTexUeuyuAdmDsukMTRW
IgorOffline
pushed a commit
to IgorOffline/TimelordUK-sql-cli
that referenced
this pull request
Oct 10, 2026
Adds data/frankenstein_excerpt.txt — Letter 1 and Chapter 5 from Mary Shelley's Frankenstein (Project Gutenberg TimelordUK#84, public domain, 1818). 366 lines / ~20KB of real prose for deterministic demos. Adds examples/text_processing_demo.sql walking through READ_TEXT and GREP over real content, in six sections: basic ingestion, read-time regex pre-filter, composable GREP with CTE, line-level analytics (longest lines, length bucket distribution via x - (x % 10)), scoped queries by line_num, and a "sentiment palette" pattern using scalar subqueries over READ_TEXT with different regexes per category. All 9 statements complete in <100ms over the excerpt. Demonstrates that text ingestion + SQL composition covers non-trivial corpus exploration without new type machinery. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
R13 slice 2, the one slice in the plan that changes answers.
ArithmeticEvaluator, which serves SELECT, HAVING and join conditions, now evaluates predicates in three-valued logic, with NULL standing for UNKNOWN. Closes P48 and P50.What changed
compare_with_op, no NULL guard: NULL vs value was false, NULL vs NULL was equalcompare_trilean: NULL on either side gives NULLAND/OR/NOTto_bool(NULL → false)Trileantruth tables;to_booldeletedIN/NOT INNOT INis its negationBETWEEN&&LIKECASE x WHEN NULLxcompare_valuesstill reportsNULL = NULLas equal. ORDER BY needs that, so the NULL test sits at the predicate layer, as R10 did for WHERE.Trilean::from_value/to_valueare now the single crossing betweenDataValueand the truth tables.Acceptance, as slice 1 set it
KNOWNentries went FIXED in this one change, and the WHERE column did not move. The value evaluator went from 4/36 to 36/36, andKNOWNis now empty (the mechanism stays).falsefor NULL.expander_rewritersquery 7) is identical on main.Scoping
Before editing, every consumer of predicate output was checked:
is_truthytreats NULL as not-true, which is correct;IIF(NULL, …)already took the false branch.So nothing downstream had to change.
Commits
test(parity): pin simpleCASE x WHEN NULL. It isn't a predicate, so the matrix can't see it.fix(r13): the evaluator change,Trileanconversions and their unit test, matrixKNOWNcleared, corpus expects dropped.docs(parity): P48 and P50 closed; R13 slice 2 result recorded.Not in this slice
ANDin a SELECT item doesn't parse. A parser fix, outside R13.🤖 Generated with Claude Code
https://claude.ai/code/session_01GpuTexUeuyuAdmDsukMTRW