From d08c072f1995577e2e5ff628068a0605ae6b38f1 Mon Sep 17 00:00:00 2001 From: Justin Ma Date: Sun, 8 May 2022 04:04:31 +0800 Subject: [PATCH] feat: add disable field type inferencing for `from csv` and `from tsv`, fix: #3485 and #4217 (#5467) --- crates/nu-command/src/formats/from/csv.rs | 4 +++- crates/nu-command/src/formats/from/delimited.rs | 12 +++++++++++- crates/nu-command/src/formats/from/tsv.rs | 3 +++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/nu-command/src/formats/from/csv.rs b/crates/nu-command/src/formats/from/csv.rs index 2c1984636..6da84f0be 100644 --- a/crates/nu-command/src/formats/from/csv.rs +++ b/crates/nu-command/src/formats/from/csv.rs @@ -26,6 +26,7 @@ impl Command for FromCsv { "don't treat the first row as column names", Some('n'), ) + .switch("no-infer", "no field type inferencing", None) .named( "trim", SyntaxShape::String, @@ -98,6 +99,7 @@ fn from_csv( ) -> Result { let name = call.head; + let no_infer = call.has_flag("no-infer"); let noheaders = call.has_flag("noheaders"); let separator: Option = call.get_flag(engine_state, stack, "separator")?; let trim: Option = call.get_flag(engine_state, stack, "trim")?; @@ -123,7 +125,7 @@ fn from_csv( let trim = trim_from_str(trim)?; - from_delimited_data(noheaders, sep, trim, input, name, config) + from_delimited_data(noheaders, no_infer, sep, trim, input, name, config) } #[cfg(test)] diff --git a/crates/nu-command/src/formats/from/delimited.rs b/crates/nu-command/src/formats/from/delimited.rs index 46b028ec7..c95159858 100644 --- a/crates/nu-command/src/formats/from/delimited.rs +++ b/crates/nu-command/src/formats/from/delimited.rs @@ -4,6 +4,7 @@ use nu_protocol::{Config, IntoPipelineData, PipelineData, ShellError, Span, Valu fn from_delimited_string_to_value( s: String, noheaders: bool, + no_infer: bool, separator: char, trim: Trim, span: Span, @@ -26,6 +27,14 @@ fn from_delimited_string_to_value( for row in reader.records() { let mut output_row = vec![]; for value in row?.iter() { + if no_infer { + output_row.push(Value::String { + span, + val: value.into(), + }); + continue; + } + if let Ok(i) = value.parse::() { output_row.push(Value::Int { val: i, span }); } else if let Ok(f) = value.parse::() { @@ -49,6 +58,7 @@ fn from_delimited_string_to_value( pub fn from_delimited_data( noheaders: bool, + no_infer: bool, sep: char, trim: Trim, input: PipelineData, @@ -58,7 +68,7 @@ pub fn from_delimited_data( let concat_string = input.collect_string("", config)?; Ok( - from_delimited_string_to_value(concat_string, noheaders, sep, trim, name) + from_delimited_string_to_value(concat_string, noheaders, no_infer, sep, trim, name) .map_err(|x| ShellError::DelimiterError(x.to_string(), name))? .into_pipeline_data(), ) diff --git a/crates/nu-command/src/formats/from/tsv.rs b/crates/nu-command/src/formats/from/tsv.rs index 888314248..32de54c98 100644 --- a/crates/nu-command/src/formats/from/tsv.rs +++ b/crates/nu-command/src/formats/from/tsv.rs @@ -20,6 +20,7 @@ impl Command for FromTsv { "don't treat the first row as column names", Some('n'), ) + .switch("no-infer", "no field type inferencing", None) .named( "trim", SyntaxShape::String, @@ -82,12 +83,14 @@ fn from_tsv( ) -> Result { let name = call.head; + let no_infer = call.has_flag("no-infer"); let noheaders = call.has_flag("noheaders"); let trim: Option = call.get_flag(engine_state, stack, "trim")?; let trim = trim_from_str(trim)?; from_delimited_data( noheaders, + no_infer, '\t', trim, input,