Skip to content

Commit 55e9d82

Browse files
authored
Merge branch 'main' into reduce-copy
2 parents be939ef + 2eabb59 commit 55e9d82

125 files changed

Lines changed: 15307 additions & 4894 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/dev.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
runs-on: ubuntu-latest
5252
steps:
5353
- uses: actions/checkout@v5
54-
- uses: actions/setup-node@v5
54+
- uses: actions/setup-node@v6
5555
with:
5656
node-version: "14"
5757
- name: Prettier check

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
steps:
7272
- uses: actions/checkout@v5
7373
- name: Download crate docs
74-
uses: actions/download-artifact@v5
74+
uses: actions/download-artifact@v6
7575
with:
7676
name: crate-docs
7777
path: website/build

CHANGELOG-old.md

Lines changed: 414 additions & 0 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 228 additions & 124 deletions
Large diffs are not rendered by default.

Cargo.toml

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ exclude = [
6868
]
6969

7070
[workspace.package]
71-
version = "56.2.0"
71+
version = "57.0.0"
7272
homepage = "https://github.com/apache/arrow-rs"
7373
repository = "https://github.com/apache/arrow-rs"
7474
authors = ["Apache Arrow <dev@arrow.apache.org>"]
@@ -85,22 +85,22 @@ edition = "2024"
8585
rust-version = "1.85"
8686

8787
[workspace.dependencies]
88-
arrow = { version = "56.2.0", path = "./arrow", default-features = false }
89-
arrow-arith = { version = "56.2.0", path = "./arrow-arith" }
90-
arrow-array = { version = "56.2.0", path = "./arrow-array" }
91-
arrow-buffer = { version = "56.2.0", path = "./arrow-buffer" }
92-
arrow-cast = { version = "56.2.0", path = "./arrow-cast" }
93-
arrow-csv = { version = "56.2.0", path = "./arrow-csv" }
94-
arrow-data = { version = "56.2.0", path = "./arrow-data" }
95-
arrow-ipc = { version = "56.2.0", path = "./arrow-ipc" }
96-
arrow-json = { version = "56.2.0", path = "./arrow-json" }
97-
arrow-ord = { version = "56.2.0", path = "./arrow-ord" }
98-
arrow-pyarrow = { version = "56.2.0", path = "./arrow-pyarrow" }
99-
arrow-row = { version = "56.2.0", path = "./arrow-row" }
100-
arrow-schema = { version = "56.2.0", path = "./arrow-schema" }
101-
arrow-select = { version = "56.2.0", path = "./arrow-select" }
102-
arrow-string = { version = "56.2.0", path = "./arrow-string" }
103-
parquet = { version = "56.2.0", path = "./parquet", default-features = false }
88+
arrow = { version = "57.0.0", path = "./arrow", default-features = false }
89+
arrow-arith = { version = "57.0.0", path = "./arrow-arith" }
90+
arrow-array = { version = "57.0.0", path = "./arrow-array" }
91+
arrow-buffer = { version = "57.0.0", path = "./arrow-buffer" }
92+
arrow-cast = { version = "57.0.0", path = "./arrow-cast" }
93+
arrow-csv = { version = "57.0.0", path = "./arrow-csv" }
94+
arrow-data = { version = "57.0.0", path = "./arrow-data" }
95+
arrow-ipc = { version = "57.0.0", path = "./arrow-ipc" }
96+
arrow-json = { version = "57.0.0", path = "./arrow-json" }
97+
arrow-ord = { version = "57.0.0", path = "./arrow-ord" }
98+
arrow-pyarrow = { version = "57.0.0", path = "./arrow-pyarrow" }
99+
arrow-row = { version = "57.0.0", path = "./arrow-row" }
100+
arrow-schema = { version = "57.0.0", path = "./arrow-schema" }
101+
arrow-select = { version = "57.0.0", path = "./arrow-select" }
102+
arrow-string = { version = "57.0.0", path = "./arrow-string" }
103+
parquet = { version = "57.0.0", path = "./parquet", default-features = false }
104104

105105
# These crates have not yet been released and thus do not use the workspace version
106106
parquet-geospatial = { version = "0.1.0", path = "./parquet-geospatial" }

arrow-array/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,7 @@ harness = false
8080
[[bench]]
8181
name = "union_array"
8282
harness = false
83+
84+
[[bench]]
85+
name = "record_batch"
86+
harness = false
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use arrow_array::{ArrayRef, Int64Array, RecordBatch, RecordBatchOptions};
19+
use arrow_schema::{DataType, Field, Schema, SchemaRef};
20+
use criterion::*;
21+
use num_integer::Integer;
22+
use std::sync::Arc;
23+
24+
fn make_record_batch(column_count: usize, row_count: usize) -> RecordBatch {
25+
let fields = (0..column_count)
26+
.map(|i| Field::new(format!("col_{}", i), DataType::Int64, i.is_even()))
27+
.collect::<Vec<_>>();
28+
29+
let columns = fields
30+
.iter()
31+
.map(|_| {
32+
let array_ref: ArrayRef = Arc::new(Int64Array::from_value(0, row_count));
33+
array_ref
34+
})
35+
.collect::<Vec<_>>();
36+
37+
let schema = Schema::new(fields);
38+
39+
let mut options = RecordBatchOptions::new();
40+
options.row_count = Some(row_count);
41+
42+
RecordBatch::try_new_with_options(SchemaRef::new(schema), columns, &options).unwrap()
43+
}
44+
45+
fn project_benchmark(
46+
c: &mut Criterion,
47+
column_count: usize,
48+
row_count: usize,
49+
projection_size: usize,
50+
) {
51+
let input = make_input(column_count, row_count, projection_size);
52+
53+
c.bench_with_input(
54+
BenchmarkId::new(
55+
"project",
56+
format!(
57+
"{:?}x{:?} -> {:?}x{:?}",
58+
input.0.num_columns(),
59+
input.0.num_rows(),
60+
input.1.len(),
61+
input.0.num_rows()
62+
),
63+
),
64+
&input,
65+
|b, (rb, projection)| {
66+
b.iter(|| black_box(rb.project(projection).unwrap()));
67+
},
68+
);
69+
}
70+
71+
fn make_input(
72+
column_count: usize,
73+
row_count: usize,
74+
projection_size: usize,
75+
) -> (RecordBatch, Vec<usize>) {
76+
let rb = make_record_batch(column_count, row_count);
77+
let projection = (0..projection_size).collect::<Vec<_>>();
78+
(rb, projection)
79+
}
80+
81+
fn criterion_benchmark(c: &mut Criterion) {
82+
[10, 100, 1000].iter().for_each(|&column_count| {
83+
[1, column_count / 2, column_count - 1]
84+
.iter()
85+
.for_each(|&projection_size| {
86+
project_benchmark(c, column_count, 8192, projection_size);
87+
})
88+
});
89+
}
90+
91+
criterion_group!(benches, criterion_benchmark);
92+
criterion_main!(benches);

arrow-array/src/array/list_array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl<OffsetSize: OffsetSizeTrait> From<FixedSizeListArray> for GenericListArray<
466466
_ => unreachable!(),
467467
};
468468

469-
let offsets = OffsetBuffer::from_lengths(std::iter::repeat_n(size, value.len()));
469+
let offsets = OffsetBuffer::from_repeated_length(size, value.len());
470470

471471
Self {
472472
data_type: Self::DATA_TYPE_CONSTRUCTOR(field.clone()),

arrow-array/src/builder/generic_bytes_view_builder.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,15 +306,30 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
306306
/// - String length exceeds `u32::MAX`
307307
#[inline]
308308
pub fn append_value(&mut self, value: impl AsRef<T::Native>) {
309+
self.try_append_value(value).unwrap()
310+
}
311+
312+
/// Appends a value into the builder
313+
///
314+
/// # Errors
315+
///
316+
/// Returns an error if:
317+
/// - String buffer count exceeds `u32::MAX`
318+
/// - String length exceeds `u32::MAX`
319+
#[inline]
320+
pub fn try_append_value(&mut self, value: impl AsRef<T::Native>) -> Result<(), ArrowError> {
309321
let v: &[u8] = value.as_ref().as_ref();
310-
let length: u32 = v.len().try_into().unwrap();
322+
let length: u32 = v.len().try_into().map_err(|_| {
323+
ArrowError::InvalidArgumentError(format!("String length {} exceeds u32::MAX", v.len()))
324+
})?;
325+
311326
if length <= MAX_INLINE_VIEW_LEN {
312327
let mut view_buffer = [0; 16];
313328
view_buffer[0..4].copy_from_slice(&length.to_le_bytes());
314329
view_buffer[4..4 + v.len()].copy_from_slice(v);
315330
self.views_buffer.push(u128::from_le_bytes(view_buffer));
316331
self.null_buffer_builder.append_non_null();
317-
return;
332+
return Ok(());
318333
}
319334

320335
// Deduplication if:
@@ -339,7 +354,7 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
339354
self.views_buffer.push(self.views_buffer[*idx]);
340355
self.null_buffer_builder.append_non_null();
341356
self.string_tracker = Some((ht, hasher));
342-
return;
357+
return Ok(());
343358
}
344359
Entry::Vacant(vacant) => {
345360
// o.w. we insert the (string hash -> view index)
@@ -356,17 +371,28 @@ impl<T: ByteViewType + ?Sized> GenericByteViewBuilder<T> {
356371
let to_reserve = v.len().max(self.block_size.next_size() as usize);
357372
self.in_progress.reserve(to_reserve);
358373
};
374+
359375
let offset = self.in_progress.len() as u32;
360376
self.in_progress.extend_from_slice(v);
361377

378+
let buffer_index: u32 = self.completed.len().try_into().map_err(|_| {
379+
ArrowError::InvalidArgumentError(format!(
380+
"Buffer count {} exceeds u32::MAX",
381+
self.completed.len()
382+
))
383+
})?;
384+
362385
let view = ByteView {
363386
length,
387+
// This won't panic as we checked the length of prefix earlier.
364388
prefix: u32::from_le_bytes(v[0..4].try_into().unwrap()),
365-
buffer_index: self.completed.len() as u32,
389+
buffer_index,
366390
offset,
367391
};
368392
self.views_buffer.push(view.into());
369393
self.null_buffer_builder.append_non_null();
394+
395+
Ok(())
370396
}
371397

372398
/// Append an `Option` value into the builder
@@ -581,7 +607,6 @@ mod tests {
581607
use core::str;
582608

583609
use super::*;
584-
use crate::Array;
585610

586611
#[test]
587612
fn test_string_view_deduplicate() {

arrow-array/src/record_batch.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -445,14 +445,16 @@ impl RecordBatch {
445445
})
446446
.collect::<Result<Vec<_>, _>>()?;
447447

448-
RecordBatch::try_new_with_options(
449-
SchemaRef::new(projected_schema),
450-
batch_fields,
451-
&RecordBatchOptions {
452-
match_field_names: true,
453-
row_count: Some(self.row_count),
454-
},
455-
)
448+
unsafe {
449+
// Since we're starting from a valid RecordBatch and project
450+
// creates a strict subset of the original, there's no need to
451+
// redo the validation checks in `try_new_with_options`.
452+
Ok(RecordBatch::new_unchecked(
453+
SchemaRef::new(projected_schema),
454+
batch_fields,
455+
self.row_count,
456+
))
457+
}
456458
}
457459

458460
/// Normalize a semi-structured [`RecordBatch`] into a flat table.

0 commit comments

Comments
 (0)