Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: wrong result of range function #8313

Merged
merged 6 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions datafusion/physical-expr/src/array_expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,14 @@ pub fn gen_range(args: &[ArrayRef]) -> Result<ArrayRef> {
if step == 0 {
return exec_err!("step can't be 0 for function range(start [, stop, step]");
}
let value = (start..stop).step_by(step as usize);
values.extend(value);
if step < 0 {
// Decreasing range
values.extend((stop + 1..start + 1).rev().step_by((-step) as usize));
} else {
// Increasing range
values.extend((start..stop).step_by(step as usize));
}

offsets.push(values.len() as i32);
}
let arr = Arc::new(ListArray::try_new(
Expand Down Expand Up @@ -2514,6 +2520,67 @@ mod tests {
.is_null(0));
}

#[test]
fn test_array_range() {
Copy link
Contributor

Choose a reason for hiding this comment

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

remove test here

Copy link
Contributor

Choose a reason for hiding this comment

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

@jayzhan211 and @Weijun-H I think what is happening is that people follow the model of the existing code -- so as long as there are tests in array_expressions (rather than .slt) that is what people will model.

What do you think about migrating (as part of another PR) all the existing tests to sqllogictests -- this would likely result in all subsequent PRs following the sqllogictests model

Copy link
Member

Choose a reason for hiding this comment

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

I endorse this proposal as it promises to enhance convenience in directing individuals to incorporate new tests, thereby minimizing potential misunderstandings.

Copy link
Contributor

Choose a reason for hiding this comment

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

@alamb @Weijun-H
There is one problem actually, function like align_array_dimensions we have a unit test for it but it is not possible to port to slt file. We should either not test it directly but rely on array function test that call it or port it to datafusion::common::utils, and test it there. I think the latter is better so we can check the coverage more easily.

btw, should we introduce array_utils in common. I think it will grow larger and larger quickly.

// range(1, 5, 1) = [1, 2, 3, 4]
let args1 = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
let args2 = Arc::new(Int64Array::from(vec![Some(5)])) as ArrayRef;
let args3 = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
let arr = gen_range(&[args1, args2, args3]).unwrap();

let result = as_list_array(&arr).expect("failed to initialize function range");
assert_eq!(
&[1, 2, 3, 4],
result
.value(0)
.as_any()
.downcast_ref::<Int64Array>()
.unwrap()
.values()
);

// range(1, -5, -1) = [1, 0, -1, -2, -3, -4]
let args1 = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
let args2 = Arc::new(Int64Array::from(vec![Some(-5)])) as ArrayRef;
let args3 = Arc::new(Int64Array::from(vec![Some(-1)])) as ArrayRef;
let arr = gen_range(&[args1, args2, args3]).unwrap();

let result = as_list_array(&arr).expect("failed to initialize function range");
assert_eq!(
&[1, 0, -1, -2, -3, -4],
result
.value(0)
.as_any()
.downcast_ref::<Int64Array>()
.unwrap()
.values()
);

// range(1, 5, -1) = []
let args1 = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
let args2 = Arc::new(Int64Array::from(vec![Some(5)])) as ArrayRef;
let args3 = Arc::new(Int64Array::from(vec![Some(-1)])) as ArrayRef;
let arr = gen_range(&[args1, args2, args3]).unwrap();

let result = as_list_array(&arr).expect("failed to initialize function range");
assert_eq!(
&[],
result
.value(0)
.as_any()
.downcast_ref::<Int64Array>()
.unwrap()
.values()
);

// range(1, 5, 0) = []
let args1 = Arc::new(Int64Array::from(vec![Some(1)])) as ArrayRef;
let args2 = Arc::new(Int64Array::from(vec![Some(5)])) as ArrayRef;
let args3 = Arc::new(Int64Array::from(vec![Some(0)])) as ArrayRef;
let is_err = gen_range(&[args1, args2, args3]).is_err();
assert!(is_err)
}

#[test]
fn test_nested_array_slice() {
// array_slice([[1, 2, 3, 4], [5, 6, 7, 8]], 1, 1) = [[1, 2, 3, 4]]
Expand Down
7 changes: 4 additions & 3 deletions datafusion/sqllogictest/test_files/array.slt
Original file line number Diff line number Diff line change
Expand Up @@ -2744,15 +2744,16 @@ from arrays_range;
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [3, 4, 5, 6, 7, 8, 9] [3, 5, 7, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] [4, 5, 6, 7, 8, 9, 10, 11, 12] [4, 7, 10]

query ?????
query ??????
select range(5),
range(2, 5),
range(2, 10, 3),
range(1, 5, -1),
range(1, -5, 1)
range(1, -5, 1),
range(1, -5, -1)
;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
;
range(1, -5, -1)
;

Copy link
Member

Choose a reason for hiding this comment

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

move the test to the sqllogistest, overall LGTM 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated~

----
[0, 1, 2, 3, 4] [2, 3, 4] [2, 5, 8] [1] []
[0, 1, 2, 3, 4] [2, 3, 4] [2, 5, 8] [] [] [1, 0, -1, -2, -3, -4]

query ???
select generate_series(5),
Expand Down