You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "alamb (via GitHub)" <gi...@apache.org> on 2023/06/01 10:42:56 UTC

[GitHub] [arrow-datafusion] alamb commented on a diff in pull request #6498: feat: datafusion-cli support executes sql with escaped characters

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-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org