Skip to content

fix(arrow-cast): support unsafe casting with masked null values - #10726

Open
dhruvxvaishnav wants to merge 5 commits into
apache:mainfrom
dhruvxvaishnav:fix/cast-unsafe-masked-nulls
Open

dhruvxvaishnav wants to merge 5 commits into
apache:mainfrom
dhruvxvaishnav:fix/cast-unsafe-masked-nulls

Conversation

@dhruvxvaishnav

@dhruvxvaishnav dhruvxvaishnav commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

When casting with safe: false, errors were raised for invalid values even if those values were masked by nulls in the array's null bitmap or child offsets (e.g. invalid UTF-8 in a null binary slot, invalid castable child items in a null fixed-size list, list, list view, struct, or map). Because masked values are logically null, the cast should succeed and preserve the null mask.

What changes are included in this PR?

  • arrow-cast/src/cast/string.rs: In cast_binary_to_string and cast_binary_view_to_string_view, if fast-path UTF-8 conversion fails with safe: false and the array contains nulls, only validate non-null values for valid UTF-8.
  • arrow-cast/src/cast/list.rs: Propagate parent list nulls to child arrays before casting in cast_single_element_fixed_size_list_to_values, cast_list_values, cast_list_view_values, cast_list, cast_list_view, and cast_list_to_list_view when the target field is nullable.
  • arrow-cast/src/cast/mod.rs: Propagate parent nulls for FixedSizeList and StructArray columns before calling cast_with_options when the target field is nullable.
  • arrow-cast/src/cast/map.rs: Propagate parent nulls to map key and value child arrays when target fields are nullable.
  • Added comprehensive unit tests in arrow-cast covering all container types and binary-to-string casts with masked null values.
  • Removed a stale BufferBuilder import inherited from main that caused the Arrow, Parquet, and Flight Clippy jobs to fail.

Are these changes tested?

Yes, new unit tests added in arrow-cast/src/cast/mod.rs:

  • test_binary_to_string_unsafe_masked_nulls
  • test_binary_view_to_string_view_unsafe_masked_nulls
  • test_fixed_size_list_unsafe_masked_nulls
  • test_list_unsafe_masked_nulls
  • test_list_view_unsafe_masked_nulls
  • test_struct_unsafe_masked_nulls
  • test_map_unsafe_masked_nulls

The following checks pass:

  • cargo test -p arrow-cast — 382 unit tests and 11 doctests passed
  • cargo clippy -p arrow-string --all-targets --all-features -- -D warnings
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo +stable fmt --all -- --check
  • git diff --check

Are there any user-facing changes?

No breaking changes to public APIs. safe: false casting now correctly succeeds on arrays where unconvertible values are masked by nulls instead of erroneously failing.

AI assistance

OpenAI Codex assisted with codebase exploration, implementation support, test preparation, validation, review follow-up, and CI diagnosis. The contributor remains responsible for understanding and maintaining the changes.

@Jefffrey

Copy link
Copy Markdown
Contributor

run benchmark cast_kernels

@Jefffrey Jefffrey added the bug label Aug 19, 2026
@adriangbot

This comment was marked as duplicate.

Comment thread arrow-cast/src/cast/list.rs Outdated
return Arc::clone(array.values());
}

let mut builder = BooleanBufferBuilder::new(array.values().len());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we can use NullBuffer::expand here

@dhruvxvaishnav dhruvxvaishnav Aug 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use NullBuffer::expand in mask_fixed_size_list_values. Thanks!

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing fix/cast-unsafe-masked-nulls (df27155) to bb1e6cd (merge-base) diff

Run configuration
run benchmark cast_kernels
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                              fix_cast-unsafe-masked-nulls           main
-----                                                              ----------------------------           ----
"cast decimal128 to float64"                                       1.00     27.1±0.01µs        ? ?/sec    1.00     27.1±0.02µs        ? ?/sec
"cast decimal128 to int64"                                         1.00     48.3±0.76µs        ? ?/sec    1.00     48.3±0.88µs        ? ?/sec
"cast decimal128 to int8"                                          1.00     60.5±0.63µs        ? ?/sec    1.01     60.8±0.73µs        ? ?/sec
"cast decimal256 to float64"                                       1.00     68.6±0.08µs        ? ?/sec    1.00     68.6±0.10µs        ? ?/sec
"cast decimal256 to int64"                                         1.00    153.0±0.34µs        ? ?/sec    1.02    155.4±0.82µs        ? ?/sec
"cast float64 to decimal128(32, 3)"                                1.00     35.4±0.28µs        ? ?/sec    1.00     35.3±0.28µs        ? ?/sec
"cast invalid float64 to to decimal128(32, 3)"                     1.01     23.7±1.15µs        ? ?/sec    1.00     23.4±1.13µs        ? ?/sec
"cast string to decimal128(38, 3)"                                 1.00    110.8±0.63µs        ? ?/sec    1.01    111.7±0.48µs        ? ?/sec
"cast string to decimal256(76, 3)"                                 1.00    148.5±0.35µs        ? ?/sec    1.00    148.5±0.37µs        ? ?/sec
cast binary dict to string view (sparse)                           1.00     46.2±0.10µs        ? ?/sec    1.08     49.9±1.38µs        ? ?/sec
cast binary view to string                                         1.00     70.6±1.04µs        ? ?/sec    1.01     71.6±0.76µs        ? ?/sec
cast binary view to string view                                    1.00     63.5±1.39µs        ? ?/sec    1.00     63.8±1.80µs        ? ?/sec
cast binary view to wide string                                    1.00     69.3±0.83µs        ? ?/sec    1.00     69.6±0.92µs        ? ?/sec
cast date32 to date64 512                                          1.01    336.8±0.46ns        ? ?/sec    1.00    332.4±0.84ns        ? ?/sec
cast date64 to date32 512                                          1.03   1496.8±5.06ns        ? ?/sec    1.00   1446.4±4.18ns        ? ?/sec
cast decimal128 to decimal128 512                                  1.00      6.9±0.00µs        ? ?/sec    1.00      6.9±0.00µs        ? ?/sec
cast decimal128 to decimal128 512 lower precision                  1.00     19.9±0.08µs        ? ?/sec    1.01     20.0±0.02µs        ? ?/sec
cast decimal128 to decimal128 512 with lower scale (infallible)    1.00     45.8±0.06µs        ? ?/sec    1.00     45.8±0.04µs        ? ?/sec
cast decimal128 to decimal128 512 with same scale                  1.00     75.0±0.25ns        ? ?/sec    1.00     74.7±0.27ns        ? ?/sec
cast decimal128 to decimal256 512                                  1.00     26.2±0.01µs        ? ?/sec    1.00     26.2±0.02µs        ? ?/sec
cast decimal256 to decimal128 512                                  1.00    317.9±0.24µs        ? ?/sec    1.00    317.8±0.91µs        ? ?/sec
cast decimal256 to decimal256 512                                  1.00     81.9±0.05µs        ? ?/sec    1.00     81.9±0.06µs        ? ?/sec
cast decimal256 to decimal256 512 with same scale                  1.01     76.6±2.12ns        ? ?/sec    1.00     76.0±1.11ns        ? ?/sec
cast dict to string view                                           1.02     15.3±0.20µs        ? ?/sec    1.00     15.0±0.14µs        ? ?/sec
cast dict to string view (sparse)                                  1.00      5.2±0.06µs        ? ?/sec    1.05      5.5±0.08µs        ? ?/sec
cast f32 to string 512                                             1.00     11.9±0.04µs        ? ?/sec    1.01     12.1±0.05µs        ? ?/sec
cast f64 to string 512                                             1.00     15.4±0.03µs        ? ?/sec    1.02     15.6±0.05µs        ? ?/sec
cast float32 to int32 512                                          1.02  1390.4±13.51ns        ? ?/sec    1.00   1357.1±5.61ns        ? ?/sec
cast float64 to float32 512                                        1.06    718.6±1.30ns        ? ?/sec    1.00    680.6±4.27ns        ? ?/sec
cast float64 to uint64 512                                         1.05  1496.5±56.36ns        ? ?/sec    1.00   1421.0±2.97ns        ? ?/sec
cast i64 to string 512                                             1.00      8.8±0.03µs        ? ?/sec    1.00      8.7±0.05µs        ? ?/sec
cast int32 to float32 512                                          1.06    746.6±8.86ns        ? ?/sec    1.00    704.9±3.85ns        ? ?/sec
cast int32 to float64 512                                          1.07    758.8±3.22ns        ? ?/sec    1.00    707.1±2.16ns        ? ?/sec
cast int32 to int32 512                                            1.00    173.8±2.09ns        ? ?/sec    1.02    176.5±3.20ns        ? ?/sec
cast int32 to int64 512                                            1.05    704.4±4.06ns        ? ?/sec    1.00    670.2±3.16ns        ? ?/sec
cast int32 to uint32 512                                           1.00   1394.0±0.97ns        ? ?/sec    1.00   1387.9±1.53ns        ? ?/sec
cast int64 to int32 512                                            1.04   1528.0±2.58ns        ? ?/sec    1.00   1468.8±1.41ns        ? ?/sec
cast nested dict to dict                                           1.00      4.5±0.03µs        ? ?/sec    1.02      4.6±0.02µs        ? ?/sec
cast no runs of int32s to ree<int32>                               1.01     58.7±1.84µs        ? ?/sec    1.00     58.0±0.92µs        ? ?/sec
cast runs of 10 string to ree<int32>                               1.00      8.8±0.08µs        ? ?/sec    1.00      8.8±0.02µs        ? ?/sec
cast runs of 1000 int32s to ree<int32>                             1.00      3.4±0.02µs        ? ?/sec    1.01      3.4±0.01µs        ? ?/sec
cast string single run to ree<int32>                               1.00     27.4±0.04µs        ? ?/sec    1.00     27.4±0.02µs        ? ?/sec
cast string to binary view 512                                     1.04      2.3±0.01µs        ? ?/sec    1.00      2.2±0.03µs        ? ?/sec
cast string view to binary view                                    1.00     83.8±0.90ns        ? ?/sec    1.00     83.7±1.26ns        ? ?/sec
cast string view to dict                                           1.01    155.6±0.42µs        ? ?/sec    1.00    154.8±0.43µs        ? ?/sec
cast string view to string                                         1.00     43.2±0.92µs        ? ?/sec    1.00     43.4±0.77µs        ? ?/sec
cast string view to wide string                                    1.00     43.0±0.79µs        ? ?/sec    1.01     43.2±0.88µs        ? ?/sec
cast time32s to time32ms 512                                       1.02   1485.0±3.10ns        ? ?/sec    1.00   1461.3±2.94ns        ? ?/sec
cast time32s to time64us 512                                       1.01    336.6±0.48ns        ? ?/sec    1.00    331.7±0.67ns        ? ?/sec
cast time64ns to time32s 512                                       1.02    421.1±0.27ns        ? ?/sec    1.00    412.1±0.37ns        ? ?/sec
cast timestamp_ms to i64 512                                       1.00    246.7±0.69ns        ? ?/sec    1.00    246.9±2.20ns        ? ?/sec
cast timestamp_ms to timestamp_ns 512                              1.00   1867.7±3.13ns        ? ?/sec    1.00   1862.2±2.56ns        ? ?/sec
cast timestamp_ns to timestamp_s 512                               1.00    170.6±1.34ns        ? ?/sec    1.01    173.1±0.87ns        ? ?/sec
cast utf8 to date32 512                                            1.01      7.0±0.05µs        ? ?/sec    1.00      6.9±0.03µs        ? ?/sec
cast utf8 to date64 512                                            1.01     32.2±0.11µs        ? ?/sec    1.00     32.0±0.12µs        ? ?/sec
cast utf8 to f32                                                   1.00      5.6±0.03µs        ? ?/sec    1.00      5.6±0.02µs        ? ?/sec
cast utf8 to i32                                                   1.00      5.3±0.05µs        ? ?/sec    1.00      5.3±0.04µs        ? ?/sec
cast wide string to binary view 512                                1.00      3.9±0.06µs        ? ?/sec    1.01      4.0±0.07µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 575.1s
Peak memory 15.5 MiB
Avg memory 10.2 MiB
CPU user 572.4s
CPU sys 0.1s
Peak spill 0 B

branch

Metric Value
Wall time 565.1s
Peak memory 16.8 MiB
Avg memory 14.3 MiB
CPU user 562.6s
CPU sys 0.1s
Peak spill 0 B

File an issue against this benchmark runner

@github-actions github-actions Bot added arrow Changes to the arrow crate arrow-cast labels Aug 20, 2026
Do not fail safe: false casts on unconvertible values that are masked as nulls in binary, string, list, struct, and map arrays.

Fixes apache#10711
@dhruvxvaishnav
dhruvxvaishnav force-pushed the fix/cast-unsafe-masked-nulls branch from 77ba73c to 759bb33 Compare August 20, 2026 05:35
@Rich-T-kid

Copy link
Copy Markdown
Contributor

run benchmark cast_kernels

@adriangbot

This comment was marked as duplicate.

@adriangbot

Copy link
Copy Markdown

🤖 Arrow criterion benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing fix/cast-unsafe-masked-nulls (2537e2a) to db915ec (merge-base) diff

Run configuration
run benchmark cast_kernels
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                                              fix_cast-unsafe-masked-nulls           main
-----                                                              ----------------------------           ----
"cast decimal128 to float64"                                       1.00     27.1±0.01µs        ? ?/sec    1.00     27.1±0.01µs        ? ?/sec
"cast decimal128 to int64"                                         1.00     48.2±0.66µs        ? ?/sec    1.01     48.4±0.83µs        ? ?/sec
"cast decimal128 to int8"                                          1.00     60.6±0.74µs        ? ?/sec    1.01     61.0±0.54µs        ? ?/sec
"cast decimal256 to float64"                                       1.00     68.7±0.08µs        ? ?/sec    1.00     68.7±0.10µs        ? ?/sec
"cast decimal256 to int64"                                         1.00    152.2±0.67µs        ? ?/sec    1.00    151.7±0.68µs        ? ?/sec
"cast float64 to decimal128(32, 3)"                                1.00     35.4±0.48µs        ? ?/sec    1.00     35.4±0.35µs        ? ?/sec
"cast invalid float64 to to decimal128(32, 3)"                     1.01     23.7±1.11µs        ? ?/sec    1.00     23.4±0.93µs        ? ?/sec
"cast string to decimal128(38, 3)"                                 1.00    110.2±0.52µs        ? ?/sec    1.06    116.7±0.47µs        ? ?/sec
"cast string to decimal256(76, 3)"                                 1.00    150.0±0.42µs        ? ?/sec    1.01    151.4±0.58µs        ? ?/sec
cast binary dict to string view (sparse)                           1.02     46.0±2.14µs        ? ?/sec    1.00     45.0±0.10µs        ? ?/sec
cast binary to dict high cardinality                               1.00    211.4±0.36µs        ? ?/sec    1.01    212.5±0.35µs        ? ?/sec
cast binary to dict high cardinality no nulls                      1.00    196.0±0.56µs        ? ?/sec    1.00    195.1±0.33µs        ? ?/sec
cast binary to dict low cardinality                                1.00    180.8±0.34µs        ? ?/sec    1.00    181.3±0.22µs        ? ?/sec
cast binary to dict low cardinality no nulls                       1.01    165.1±0.55µs        ? ?/sec    1.00    164.1±0.29µs        ? ?/sec
cast binary to dict medium cardinality                             1.00    182.0±0.33µs        ? ?/sec    1.00    182.1±0.27µs        ? ?/sec
cast binary to dict medium cardinality no nulls                    1.01    166.6±0.61µs        ? ?/sec    1.00    165.1±0.36µs        ? ?/sec
cast binary view to string                                         1.00     68.7±0.78µs        ? ?/sec    1.01     69.1±0.86µs        ? ?/sec
cast binary view to string view                                    1.04     64.8±2.79µs        ? ?/sec    1.00     62.4±1.21µs        ? ?/sec
cast binary view to wide string                                    1.00     68.5±0.73µs        ? ?/sec    1.00     68.8±0.81µs        ? ?/sec
cast date32 to date64 512                                          1.04    338.3±0.46ns        ? ?/sec    1.00    325.4±2.34ns        ? ?/sec
cast date64 to date32 512                                          1.00   1449.1±4.78ns        ? ?/sec    1.02  1479.6±15.37ns        ? ?/sec
cast decimal128 to decimal128 512                                  1.00      6.9±0.01µs        ? ?/sec    1.00      6.9±0.01µs        ? ?/sec
cast decimal128 to decimal128 512 lower precision                  1.00     20.0±0.02µs        ? ?/sec    1.00     20.0±0.02µs        ? ?/sec
cast decimal128 to decimal128 512 with lower scale (infallible)    1.00     45.8±0.07µs        ? ?/sec    1.00     45.9±0.06µs        ? ?/sec
cast decimal128 to decimal128 512 with same scale                  1.00     75.2±0.27ns        ? ?/sec    1.00     75.4±0.37ns        ? ?/sec
cast decimal128 to decimal256 512                                  1.00     26.2±0.01µs        ? ?/sec    1.00     26.2±0.02µs        ? ?/sec
cast decimal256 to decimal128 512                                  1.00    318.3±0.13µs        ? ?/sec    1.01    321.7±0.16µs        ? ?/sec
cast decimal256 to decimal256 512                                  1.00     82.0±0.10µs        ? ?/sec    1.00     82.1±0.07µs        ? ?/sec
cast decimal256 to decimal256 512 with same scale                  1.00     75.8±1.43ns        ? ?/sec    1.02     77.1±1.89ns        ? ?/sec
cast dict to string view                                           1.00     15.0±0.20µs        ? ?/sec    1.03     15.5±0.03µs        ? ?/sec
cast dict to string view (sparse)                                  1.00      5.3±0.06µs        ? ?/sec    1.00      5.3±0.06µs        ? ?/sec
cast f32 to string 512                                             1.00     12.0±0.05µs        ? ?/sec    1.00     12.0±0.06µs        ? ?/sec
cast f64 to string 512                                             1.00     15.5±0.03µs        ? ?/sec    1.00     15.5±0.04µs        ? ?/sec
cast float32 to int32 512                                          1.02   1384.9±6.49ns        ? ?/sec    1.00   1364.0±6.36ns        ? ?/sec
cast float64 to float32 512                                        1.01    685.0±4.17ns        ? ?/sec    1.00    678.2±4.11ns        ? ?/sec
cast float64 to uint64 512                                         1.01  1466.3±13.64ns        ? ?/sec    1.00   1457.4±9.18ns        ? ?/sec
cast i64 to string 512                                             1.00      8.7±0.03µs        ? ?/sec    1.01      8.8±0.03µs        ? ?/sec
cast int32 to float32 512                                          1.03    716.5±6.16ns        ? ?/sec    1.00    694.5±2.94ns        ? ?/sec
cast int32 to float64 512                                          1.03    743.4±3.11ns        ? ?/sec    1.00    724.6±3.32ns        ? ?/sec
cast int32 to int32 512                                            1.00    171.7±1.15ns        ? ?/sec    1.01    172.8±1.45ns        ? ?/sec
cast int32 to int64 512                                            1.02    701.4±3.49ns        ? ?/sec    1.00    684.6±4.57ns        ? ?/sec
cast int32 to uint32 512                                           1.00   1397.7±1.50ns        ? ?/sec    1.00   1404.2±6.30ns        ? ?/sec
cast int64 to decimal32(9, -1) 512                                 1.01      3.4±0.00µs        ? ?/sec    1.00      3.4±0.00µs        ? ?/sec
cast int64 to decimal32(9, 0) 512                                  1.00   1555.8±1.68ns        ? ?/sec    1.01   1578.8±3.11ns        ? ?/sec
cast int64 to int32 512                                            1.00   1463.0±2.18ns        ? ?/sec    1.03   1503.3±2.82ns        ? ?/sec
cast nested dict to dict                                           1.01      4.6±0.02µs        ? ?/sec    1.00      4.6±0.10µs        ? ?/sec
cast no runs of int32s to ree<int32>                               1.00     56.6±1.30µs        ? ?/sec    1.02     57.9±1.28µs        ? ?/sec
cast runs of 10 string to ree<int32>                               1.00      8.7±0.07µs        ? ?/sec    1.00      8.7±0.06µs        ? ?/sec
cast runs of 1000 int32s to ree<int32>                             1.01      3.5±0.01µs        ? ?/sec    1.00      3.4±0.01µs        ? ?/sec
cast string single run to ree<int32>                               1.00     27.5±0.02µs        ? ?/sec    1.00     27.5±0.33µs        ? ?/sec
cast string to binary view 512                                     1.00      2.3±0.01µs        ? ?/sec    1.00      2.3±0.04µs        ? ?/sec
cast string view to binary view                                    1.00     83.5±0.81ns        ? ?/sec    1.02     85.5±1.93ns        ? ?/sec
cast string view to dict                                           1.00    155.1±0.37µs        ? ?/sec    1.00    155.1±0.42µs        ? ?/sec
cast string view to string                                         1.00     43.3±0.80µs        ? ?/sec    1.01     43.7±0.72µs        ? ?/sec
cast string view to wide string                                    1.00     43.3±0.74µs        ? ?/sec    1.00     43.4±0.77µs        ? ?/sec
cast time32s to time32ms 512                                       1.01   1473.7±2.97ns        ? ?/sec    1.00   1460.7±2.91ns        ? ?/sec
cast time32s to time64us 512                                       1.00    336.5±0.65ns        ? ?/sec    1.00    337.6±2.29ns        ? ?/sec
cast time64ns to time32s 512                                       1.00    422.2±0.45ns        ? ?/sec    1.01    426.6±3.97ns        ? ?/sec
cast timestamp_ms to i64 512                                       1.00    245.1±0.99ns        ? ?/sec    1.00    245.3±1.36ns        ? ?/sec
cast timestamp_ms to timestamp_ns 512                              1.00   1852.4±2.76ns        ? ?/sec    1.00   1852.3±3.41ns        ? ?/sec
cast timestamp_ns to timestamp_s 512                               1.00    169.8±1.47ns        ? ?/sec    1.02    172.7±1.89ns        ? ?/sec
cast utf8 to date32 512                                            1.00      6.9±0.06µs        ? ?/sec    1.01      7.0±0.05µs        ? ?/sec
cast utf8 to date64 512                                            1.00     31.9±0.16µs        ? ?/sec    1.00     32.0±0.12µs        ? ?/sec
cast utf8 to f32                                                   1.00      5.6±0.03µs        ? ?/sec    1.00      5.6±0.04µs        ? ?/sec
cast utf8 to i32                                                   1.00      5.4±0.06µs        ? ?/sec    1.00      5.3±0.05µs        ? ?/sec
cast wide string to binary view 512                                1.01      4.0±0.07µs        ? ?/sec    1.00      4.0±0.07µs        ? ?/sec

Resource Usage

base (merge-base)

Metric Value
Wall time 660.2s
Peak memory 16.6 MiB
Avg memory 11.3 MiB
CPU user 653.3s
CPU sys 0.2s
Peak spill 0 B

branch

Metric Value
Wall time 655.1s
Peak memory 16.6 MiB
Avg memory 11.3 MiB
CPU user 649.6s
CPU sys 0.1s
Peak spill 0 B

File an issue against this benchmark runner

@Jefffrey Jefffrey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry it took me a while to get back to reviewing this

.build();
match data {
Ok(d) => make_array(d),
Err(_) => Arc::clone(array.values()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we should propagate the error here instead of silently returning original

Comment on lines +56 to +71
let mut builder = BooleanBufferBuilder::new(array.values().len());
let offsets = array.value_offsets();
for i in 0..array.len() {
let is_valid = array.is_valid(i);
let len = offsets[i + 1].as_usize() - offsets[i].as_usize();
builder.append_n(len, is_valid);
}
if builder.len() < array.values().len() {
builder.append_n(array.values().len() - builder.len(), false);
}
let parent_nulls = NullBuffer::from(builder.finish());
let combined_nulls = NullBuffer::union(Some(&parent_nulls), array.values().nulls());
if combined_nulls.as_ref() != array.values().nulls() {
let data = array
.values()
.to_data()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wonder if we can use the nullif kernel here actually. we can skip it for fixedsizelist since that is a simple nullbuffer replacement

and if we can use nullif here we can probably use it for list view, maps, structs, etc.

let values = array.as_fixed_size_list().values();
cast_with_options(values, to, cast_options)
let array = array.as_fixed_size_list();
let values = mask_fixed_size_list_values(array);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably mask only on cast failure (and then retry the cast); this avoids affecting the fast (optimistic) path

and consider we only need to do this masking for safe: false casting

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

arrow Changes to the arrow crate arrow-cast bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

safe: false casting doesn't account for masked null values

4 participants