Skip to content

Commit f99851a

Browse files
authored
fix(query): fix index out of bounds with constant expr (#16206)
* fix(query): fix index out of bounds with constant expr * fix(query): fix index out of bounds with constant expr * Revert "fix(query): fix index out of bounds with constant expr" This reverts commit 1486da6. * fix(query): fix index out of bounds with constant expr * fix(query): add short circuit test case * fix(query): fix index out of bounds with constant expr * fix(query): fix index out of bounds with constant expr
1 parent c5531ab commit f99851a

File tree

3 files changed

+40
-15
lines changed

3 files changed

+40
-15
lines changed

src/query/expression/src/evaluator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ impl<'a> Evaluator<'a> {
222222

223223
let (_, eval) = function.eval.as_scalar().unwrap();
224224
let result = (eval)(cols_ref.as_slice(), &mut ctx);
225+
225226
ctx.render_error(
226227
*span,
227228
id.params(),
@@ -852,6 +853,7 @@ impl<'a> Evaluator<'a> {
852853
Value::Scalar(_) => 1,
853854
Value::Column(col) => col.len(),
854855
});
856+
855857
let block = DataBlock::new(vec![BlockEntry::new(src_type.clone(), value)], num_rows);
856858
let evaluator = Evaluator::new(&block, self.func_ctx, self.fn_registry);
857859
Ok(Some(evaluator.partial_run(&cast_expr, validity, options)?))

src/query/expression/src/function.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use crate::FunctionDomain;
4848
use crate::Scalar;
4949

5050
pub type AutoCastRules<'a> = &'a [(DataType, DataType)];
51+
5152
/// A function to build function depending on the const parameters and the type of arguments (before coercion).
5253
///
5354
/// The first argument is the const parameters and the second argument is the types of arguments.
@@ -604,24 +605,26 @@ impl<'a> EvalContext<'a> {
604605
}
605606
match &self.errors {
606607
Some((valids, error)) => {
607-
let first_error_row = if let Some(selection) = selection {
608-
if let Some(first_invalid) =
609-
selection.iter().find(|idx| !valids.get(**idx as usize))
610-
{
608+
let first_error_row = match selection {
609+
None => valids.iter().enumerate().find(|(_, v)| !v).unwrap().0,
610+
Some(selection) if valids.len() == 1 => {
611+
if valids.get(0) || selection.is_empty() {
612+
return Ok(());
613+
}
614+
615+
selection.first().map(|x| *x as usize).unwrap()
616+
}
617+
Some(selection) => {
618+
let Some(first_invalid) =
619+
selection.iter().find(|idx| !valids.get(**idx as usize))
620+
else {
621+
return Ok(());
622+
};
623+
611624
*first_invalid as usize
612-
} else {
613-
return Ok(());
614625
}
615-
} else {
616-
valids
617-
.iter()
618-
.enumerate()
619-
.filter(|(_, valid)| !valid)
620-
.take(1)
621-
.next()
622-
.unwrap()
623-
.0
624626
};
627+
625628
let args = args
626629
.iter()
627630
.map(|arg| {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
statement ok
2+
DROP TABLE IF EXISTS test
3+
4+
statement ok
5+
CREATE TABLE test(test DATE NULL)
6+
7+
statement ok
8+
INSERT INTO test SELECT IF(number % 999=0 and number != 0,'2024-01-01', NULL) FROM numbers(10000)
9+
10+
statement error 1006
11+
SELECT count(1) FROM test WHERE test IS NOT NULL AND NOT test = ''
12+
13+
query ITIT
14+
SELECT count(1) FROM test WHERE test IS NOT NULL AND test != '2024-01-01' AND NOT test = ''
15+
----
16+
0
17+
18+
statement ok
19+
drop table test;
20+

0 commit comments

Comments
 (0)