fix several cases where sort-by was crashing engine-q (#836)

This commit is contained in:
Michael Angerman 2022-01-23 20:52:19 -08:00 committed by GitHub
parent d4fb95a98c
commit 8a1b2d0812
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 1 deletions

View File

@ -1,3 +1,4 @@
use nu_engine::column::column_does_not_exist;
use nu_engine::CallExt; use nu_engine::CallExt;
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
@ -101,10 +102,19 @@ impl Command for SortBy {
pub fn sort(vec: &mut [Value], columns: Vec<String>, call: &Call) -> Result<(), ShellError> { pub fn sort(vec: &mut [Value], columns: Vec<String>, call: &Call) -> Result<(), ShellError> {
match &vec[0] { match &vec[0] {
Value::Record { Value::Record {
cols: _cols, cols,
vals: _input_vals, vals: _input_vals,
.. ..
} => { } => {
if columns.is_empty() {
println!("sort-by requires a column name to sort table data");
return Err(ShellError::CantFindColumn(call.head, call.head));
}
if column_does_not_exist(columns.clone(), cols.to_vec()) {
return Err(ShellError::CantFindColumn(call.head, call.head));
}
vec.sort_by(|a, b| { vec.sort_by(|a, b| {
process(a, b, &columns[0], call) process(a, b, &columns[0], call)
.expect("sort_by Value::Record bug") .expect("sort_by Value::Record bug")

View File

@ -1,4 +1,5 @@
use nu_protocol::Value; use nu_protocol::Value;
use std::collections::HashSet;
pub fn get_columns(input: &[Value]) -> Vec<String> { pub fn get_columns(input: &[Value]) -> Vec<String> {
let mut columns = vec![]; let mut columns = vec![];
@ -15,3 +16,23 @@ pub fn get_columns(input: &[Value]) -> Vec<String> {
columns columns
} }
/*
* Check to see if any of the columns inside the input
* does not exist in a vec of columns
*/
pub fn column_does_not_exist(inputs: Vec<String>, columns: Vec<String>) -> bool {
let mut set = HashSet::new();
for column in columns {
set.insert(column);
}
for input in &inputs {
if set.contains(input) {
continue;
}
return true;
}
false
}