alamb commented on code in PR #6498: URL: https://github.com/apache/arrow-datafusion/pull/6498#discussion_r1212953521
########## datafusion-cli/src/helper.rs: ########## @@ -76,27 +110,117 @@ impl Completer for CliHelper { impl Validator for CliHelper { fn validate(&self, ctx: &mut ValidationContext<'_>) -> Result<ValidationResult> { let input = ctx.input().trim_end(); - if let Some(sql) = input.strip_suffix(';') { - match DFParser::parse_sql(sql) { - Ok(statements) if statements.is_empty() => Ok(ValidationResult::Invalid( - Some(" 🤔 You entered an empty statement".to_string()), - )), - Ok(statements) if statements.len() > 1 => Ok(ValidationResult::Invalid( - Some(" 🤔 You entered more than one statement".to_string()), - )), - Ok(_statements) => Ok(ValidationResult::Valid(None)), - Err(err) => Ok(ValidationResult::Invalid(Some(format!( - " 🤔 Invalid statement: {}", - err - )))), + self.validate_input(input) + } +} + +impl Helper for CliHelper {} + +/// Unescape input string from readline. +/// +/// The data read from stdio will be escaped, so we need to unescape the input before executing the input +pub fn unescape_input(input: &str) -> datafusion::error::Result<String> { + let mut chars = input.chars(); + + let mut result = String::with_capacity(input.len()); + while let Some(char) = chars.next() { + if char == '\\' { + if let Some(next_char) = chars.next() { + // https://static.rust-lang.org/doc/master/reference.html#literals + result.push(match next_char { + '0' => '\0', + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + '\\' => '\\', + _ => { + return Err(DataFusionError::SQL(ParserError::TokenizerError( + format!("unsupported escape char: '\\{}'", next_char), + ))) + } + }); } - } else if input.starts_with('\\') { - // command - Ok(ValidationResult::Valid(None)) } else { - Ok(ValidationResult::Incomplete) + result.push(char); } } + + Ok(result) } -impl Helper for CliHelper {} +#[cfg(test)] +mod tests { + use std::io::{BufRead, Cursor}; + + use super::*; + + fn readline_direct( + mut reader: impl BufRead, + validator: &CliHelper, + ) -> Result<ValidationResult> { + let mut input = String::new(); + + if reader.read_line(&mut input)? == 0 { + return Err(ReadlineError::Eof); + } + + validator.validate_input(&input) + } + + #[test] + fn unescape_readline_input() -> Result<()> { Review Comment: ❤️ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@arrow.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org