Error out when Select gets same row (#8200)

# Description
Fixes #8145, by disallowing any rows that are duplicated.

```
❯ ls | select 0 0
Error: 
  × Select only allows unique rows
   ╭─[entry #1:1:1]
 1 │ ls | select 0 0
   ·               ┬
   ·               ╰── duplicated row
   ╰────

```

# User-Facing Changes


# Tests + Formatting

Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- [X] `cargo fmt --all -- --check` to check standard code formatting
(`cargo fmt --all` applies these changes)
- [X] `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used -A
clippy::needless_collect` to check that you're using the standard code
style
- [X] `cargo test --workspace` to check that all tests pass

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.

---------

Co-authored-by: Reilly Wood <reilly.wood@icloud.com>
This commit is contained in:
David Matos 2023-02-27 03:14:15 +01:00 committed by GitHub
parent 2aa5c2c41f
commit 96e3a3de68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 6 deletions

View File

@ -5,6 +5,7 @@ use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData,
PipelineIterator, ShellError, Signature, Span, SyntaxShape, Type, Value,
};
use std::collections::HashSet;
#[derive(Clone)]
pub struct Select;
@ -98,7 +99,7 @@ fn select(
input: PipelineData,
ignore_errors: bool,
) -> Result<PipelineData, ShellError> {
let mut rows = vec![];
let mut unique_rows: HashSet<usize> = HashSet::new();
let mut new_columns = vec![];
@ -118,23 +119,32 @@ fn select(
Vec::new(),
));
}
rows.push(*val);
if unique_rows.contains(val) {
return Err(ShellError::GenericError(
"Select can't get the same row twice".into(),
"duplicated row index".into(),
Some(*span),
None,
Vec::new(),
));
}
unique_rows.insert(*val);
}
_ => new_columns.push(column),
};
}
let columns = new_columns;
let mut unique_rows: Vec<usize> = unique_rows.into_iter().collect();
let input = if !rows.is_empty() {
rows.sort_unstable();
let input = if !unique_rows.is_empty() {
unique_rows.sort_unstable();
// let skip = call.has_flag("skip");
let metadata = input.metadata();
let pipeline_iter: PipelineIterator = input.into_iter();
NthIterator {
input: pipeline_iter,
rows,
rows: unique_rows,
skip: false,
current: 0,
}

View File

@ -272,3 +272,15 @@ fn select_failed3() {
assert!(actual.out.is_empty());
assert!(actual.err.contains("cannot find column"));
}
#[test]
fn select_failed4() {
let actual = nu!(
cwd: ".", pipeline(
r#"
[{a: 1 b: 10}, {a:2, b:11}] | select 0 0
"#
));
assert!(actual.err.contains("Select can't get the same row twice"));
}