Skip to content

Commit 8de2e60

Browse files
authored
fix(query): handle sub_bitmap offset beyond cardinality (#19894)
1 parent 0290337 commit 8de2e60

4 files changed

Lines changed: 24 additions & 5 deletions

File tree

src/query/functions/src/scalars/bitmap.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,18 @@ pub fn register(registry: &mut FunctionRegistry) {
346346
Ok(rb) => {
347347
let subset_start = offset;
348348
let subset_length = length;
349-
if subset_start >= b.len() as u64 {
349+
let bitmap_len = rb.len();
350+
if subset_start >= bitmap_len {
350351
let rb = HybridBitmap::new();
351352
rb.serialize_into(&mut builder.data).unwrap();
352353
} else {
353-
let adjusted_length = (subset_start + subset_length).min(b.len() as u64) - subset_start;
354-
let subset_bitmap = &rb.into_iter().collect::<Vec<_>>()[subset_start as usize..(subset_start + adjusted_length) as usize];
355-
let rb = HybridBitmap::from_iter(subset_bitmap.iter());
354+
let subset_end = subset_start.saturating_add(subset_length).min(bitmap_len);
355+
let subset_bitmap = (0_u64..)
356+
.zip(rb)
357+
.skip_while(|(index, _)| *index < subset_start)
358+
.take_while(|(index, _)| *index < subset_end)
359+
.map(|(_, value)| value);
360+
let rb = HybridBitmap::from_iter(subset_bitmap);
356361
rb.serialize_into(&mut builder.data).unwrap();
357362
}
358363
}

src/query/functions/tests/it/scalars/bitmap.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ fn test_bitmap_min(file: &mut impl Write) {
9999

100100
fn test_sub_bitmap(file: &mut impl Write) {
101101
run_ast(file, "sub_bitmap(build_bitmap([1, 2, 3, 4, 5]), 1, 3)", &[]);
102+
run_ast(file, "sub_bitmap(build_bitmap([1]), 2, 1)", &[]);
102103
}
103104

104105
fn test_bitmap_subset_limit(file: &mut impl Write) {

src/query/functions/tests/it/scalars/testdata/bitmap.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,15 @@ output domain : Undefined
146146
output : '2,3,4'
147147

148148

149+
ast : sub_bitmap(build_bitmap([1]), 2, 1)
150+
raw expr : sub_bitmap(build_bitmap(array(1)), 2, 1)
151+
checked expr : sub_bitmap<Bitmap, UInt64, UInt64>(build_bitmap<Array(UInt8 NULL)>(CAST<Array(UInt8)>(array<T0=UInt8><T0>(1_u8) AS Array(UInt8 NULL))), CAST<UInt8>(2_u8 AS UInt64), CAST<UInt8>(1_u8 AS UInt64))
152+
optimized expr : HybridBitmap<[]>
153+
output type : Bitmap
154+
output domain : Undefined
155+
output : ''
156+
157+
149158
ast : bitmap_subset_limit(build_bitmap([3,5,7]), 4, 2)
150159
raw expr : bitmap_subset_limit(build_bitmap(array(3, 5, 7)), 4, 2)
151160
checked expr : bitmap_subset_limit<Bitmap, UInt64, UInt64>(build_bitmap<Array(UInt8 NULL)>(CAST<Array(UInt8)>(array<T0=UInt8><T0, T0, T0>(3_u8, 5_u8, 7_u8) AS Array(UInt8 NULL))), CAST<UInt8>(4_u8 AS UInt64), CAST<UInt8>(2_u8 AS UInt64))

tests/sqllogictests/suites/query/functions/02_0064_function_bitmap.test

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ SELECT sub_bitmap(build_bitmap([1, 2, 3, 4, 5]), 1, 3)::String;
7272
----
7373
2,3,4
7474

75+
query T
76+
SELECT sub_bitmap(build_bitmap([1]), 2, 1)::String;
77+
----
78+
(empty)
79+
7580
query T
7681
SELECT bitmap_subset_limit(build_bitmap([3,5,7]), 4, 2)::String;
7782
----
@@ -86,4 +91,3 @@ query T
8691
SELECT bitmap_to_array(build_bitmap([1, 2, 3, 100, 10000]));
8792
----
8893
[1,2,3,100,10000]
89-

0 commit comments

Comments
 (0)