Skip to content

Read non-strict values without dispatching on the column type - #372

Merged
quinnj merged 4 commits into
masterfrom
claude/nonstrict-getvalue
Oct 27, 2026
Merged

quinnj merged 4 commits into
masterfrom
claude/nonstrict-getvalue

Conversation

@quinnj

@quinnj quinnj commented Oct 22, 2026

Copy link
Copy Markdown
Member

Non-strict queries (the default) decide each value's Julia type from its SQLite storage class, but every cell went through two dynamic dispatches: Tables.getcolumn on the column's declared Type, then sqlitevalue on the storage class's type. getvalue now branches on the storage class and calls the matching reader directly, and getcolumn(::Row{false}, i) skips dispatching on the declared type, which never changes a non-strict value. Values are unchanged: integers, floats, and text use the same readers, and blobs keep the existing type rule.

Benchmarks (Chairmarks @b, 200k rows; columns INTEGER, REAL, TEXT, all-NULL INTEGER, half-NULL REAL):

Julia 1.12 master this PR Julia 1.10 master this PR
Tables.columntable (non-strict) 470 ms, 3.40M allocs, 128.6 MB 86 ms, 1.70M allocs, 53.4 MB 446 ms, 3.40M allocs 69 ms, 1.70M allocs
row loop summing one INTEGER column 66 ms, 1.40M allocs 29 ms, 1.00M allocs 67 ms 26 ms
Tables.columntable (strict) 63 ms 63-77 ms (noise) 62 ms 61 ms

Verification: new testset reading INTEGER, REAL, TEXT, serialized-Symbol, raw-BLOB, and NULL values from one column through both row access and columntable (passes before and after); full Pkg.test() passes locally (SQLite 499/499).

This touches the function next to the one #370 changes; they don't overlap.

🤖 Generated with Claude Code

Non-strict queries decide each value's Julia type from its storage class,
but the read went through two dynamic dispatches: `getcolumn` on the
column's declared `Type` and `sqlitevalue` on the storage class's type.
`getvalue` now branches on the storage class and calls the reader for it
directly, and `getcolumn(::Row{false}, i)` no longer dispatches on the
declared type, which never changes a non-strict value.

200k rows x 5 columns into `Tables.columntable` (Julia 1.12): 470 ms ->
86 ms, 3.40M -> 1.70M allocations; a row loop reading one integer column:
66 ms -> 29 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.81%. Comparing base (65f2de4) to head (0b51ed7).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #372   +/-   ##
=======================================
  Coverage   96.80%   96.81%           
=======================================
  Files           5        5           
  Lines         782      784    +2     
=======================================
+ Hits          757      759    +2     
  Misses         25       25           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

quinnj and others added 3 commits October 22, 2026 09:55
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@quinnj
quinnj merged commit c36ac0f into master Oct 27, 2026
9 checks passed
@quinnj
quinnj deleted the claude/nonstrict-getvalue branch October 27, 2026 09:11
quinnj referenced this pull request Oct 27, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant