Skip to content

[DO NOT MERGE] Research notes on extension types, Decimal and casts - #10633

Draft
connortsui20 wants to merge 8 commits into
developfrom
ct/ext-types-research
Draft

connortsui20 wants to merge 8 commits into
developfrom
ct/ext-types-research

Conversation

@connortsui20

Copy link
Copy Markdown
Member

Research notes on the Vortex type system: extension types, the Decimal rework, wide integers, FixedSizeBinary as a core type, and casts. This PR exists so the notes can be read and discussed on GitHub. It is not meant to merge.

For review, start with research/decisions.md. It records the settled decisions and the open questions, each with a recommendation, and the other notes follow it. Each topic then has a short summary (research/extension-types/, research/decimal/) and an agents/ directory with the detailed report, file and line references against develop at 5fc5cb8, and reproductions.

The main decisions so far:

  • Extension types are opaque by default. A type implements its behavior as rewrite rules on arrays, registered in the session with the type, and a rewrite rule lifts generic structural arrays such as Constant and Dict out from under the extension wrapper.
  • ExtensionArray::try_new checks values, and a new new_unchecked serves kernels.
  • Decimal stays a built-in leaf with one buffer. The precision fixes the buffer width, so each decimal dtype has exactly one canonical encoding, and a Narrow encoding stores a column at a lower precision with the same scale.
  • Vortex adds I128, I256, U128 and U256, and FixedSizeBinary becomes a core type.
  • A cast exists only where a rule for that pair of dtypes exists.

The notes also describe how the open Narrow PRs (#10223, #10332, #10333) and #10230 fit this plan.

🤖 Generated with Claude Code

claude and others added 6 commits October 18, 2026 08:16
Research notes on why extension types must be opaque, what is wrong on
develop, a proposed design, urgent changes, and an implementation plan.
The agents directory holds the detailed findings catalog, design notes,
and the throwaway probe that reproduced the findings.

Signed-off-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKSPCwTaE2gzKwpxokMGXb
Aligns the short-term nullability rule across the design documents, fixes
the count of typed wrappers in vortex-spatial, and uses a checked multiply
in the unit cast example.

Signed-off-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKSPCwTaE2gzKwpxokMGXb
Research notes on making Decimal an opaque wrapper over an integer
child, the choice between an integer child and a FixedSizeBinary
child, a wide-integer tier, FixedSizeBinary as its own type, and a
dependency graph for the type work. The agents directory holds the
full report and the call-site and PType inventories.

The extension type notes now link to the Decimal notes, record the
position of the wrapper relative to generic encodings as an open
question, and state which parts of the Decimal work wait for the
extension phases.

Signed-off-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BKSPCwTaE2gzKwpxokMGXb
Derives are now a property of one extension dtype. A derive applies
only when every operand in a derived position has that dtype.
Operations across dtypes or metadata need explicit compatibility,
coercion or rewrite rules, and the notes do not assume them.

The design notes now define these parts:

- A Rust contract for Scalar equality and order that keeps PartialEq
  and PartialOrd consistent.
- Exact rules for the removal of ext_storage and ext_wrap pairs, for
  checked and unchecked wraps.
- A validation model with validated and unvalidated arrays, and a
  default validate_array that checks each value.
- Function declarations that authorize type-aware behavior, and a
  precise storage-only invariant.
- The position of the wrapper relative to generic encodings, as an
  open decision with a labeled recommendation.

A follow-up probe ran in vortex-btrblocks. It confirms the
DateTimeParts compare bug (EXT-Q3), the Decimal to f32 cast
disagreement, and a new finding about scalar storage checks
(EXT-V7). The notes also correct the U5 and U6 node mapping, a claim
about float equality, and a claim about the decimal wire form.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
U1 now also removes the storage target case in ExtScalar::cast.
Without that change, constants and the row path still cast an
extension value to its storage dtype after the array path stops.

The Decimal rewrite of a cast to an integer keeps the current rule: a
value outside the target range fails before truncation. Only min and
max wrap their result again, because is_sorted and is_constant return
Bool.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
The new research/decisions.md records the decisions from the review
on 2026-10-19 and the questions that stay open. The other notes
follow it.

Extension types now implement their behavior as rewrite rules on
arrays. The rules are registered with the type, and there is no
ext_wrap expression. A lift rule pulls generic structural arrays,
such as Constant and Dict, out from under the extension wrapper.
ExtensionArray::try_new checks values, and a new new_unchecked
serves kernels.

Decimal stays a leaf with one buffer and no data child. The
precision fixes the buffer width, so each decimal dtype has one
canonical encoding. A Narrow encoding stores a column at a lower
precision with the same scale. A reader wraps the narrow most
significant part of an old DecimalByteParts array in an integer
Narrow, without a copy.

The notes also list two costs of the one-width rule: an old I128
leaf at precision 39 to 76 needs a widening copy, and an Arrow
import at another width copies its buffer.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@connortsui20 connortsui20 added the do not merge Pull requests that are not intended to merge label Oct 20, 2026
@vortex-data vortex-data deleted a comment from codspeed Bot Oct 23, 2026
Add decisions D21 to D24 and update D8, D9, D11, D16, D17 and D20
after a confirmation review of the decimal and Narrow design.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
@codspeed

codspeed Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Merging this PR will regress 4 benchmarks

3 warnings, 1 note

⚠️ Walltime results may be unreliable

Some benchmarks used the Walltime instrument outside CodSpeed Macro Runners, which can make the results inconsistent.

Learn more about Macro Runners

See affected benchmarks

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

⚠️ 18 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

ℹ️ 40 benchmarks have no flamegraph

The flamegraph wasn't generated: the symbols of the profiling trace could not be resolved, because no information about the language frames was collected.

See affected benchmarks

⚡ 2 improved benchmarks
❌ 4 regressed benchmarks
✅ 2402 untouched benchmarks
⏩ 12 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ CPU Simulation test_scan_filter_to_arrow_array[int_float] 3.5 ms 4.1 ms -13.67%
❌ Walltime bitpack_blocked_compress_avx2 6.7 µs 7.6 µs -12.02%
❌ CPU Simulation test_repeated_scan_filter[int_float] 3.4 ms 3.9 ms -10.93%
❌ CPU Simulation test_repeated_scan_filter[int] 2.4 ms 2.7 ms -10.18%
⚡ CPU Simulation decode_primitives[f32, (2000, 32)] 39.8 µs 26.5 µs +50.45%
⚡ Walltime threshold_neon[80] 4.1 µs 3.4 µs +21.9%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing ct/ext-types-research (77c9829) with develop (b702068)

Open in CodSpeed

Footnotes

  1. 12 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

#10223, #10332 and #10333 closed on 2026-10-23, and new PRs replace
them. Note that the local rewrite needs a rebase over #10681 and new
branch names.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do not merge Pull requests that are not intended to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants