From 6db4621ff4bfcdecf93ae164972f2837f4a787c1 Mon Sep 17 00:00:00 2001 From: Jiayu Liu Date: Thu, 15 Jul 2021 13:23:56 +0800 Subject: [PATCH] implement FromStr for FileType --- datafusion/src/sql/parser.rs | 40 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/datafusion/src/sql/parser.rs b/datafusion/src/sql/parser.rs index 3637e882d2fd..bb2f9e6bbb24 100644 --- a/datafusion/src/sql/parser.rs +++ b/datafusion/src/sql/parser.rs @@ -25,6 +25,7 @@ use sqlparser::{ parser::{Parser, ParserError}, tokenizer::{Token, Tokenizer}, }; +use std::str::FromStr; // Use `Parser::expected` instead, if possible macro_rules! parser_err { @@ -44,6 +45,22 @@ pub enum FileType { CSV, } +impl FromStr for FileType { + type Err = ParserError; + + fn from_str(s: &str) -> Result { + match s.to_uppercase().as_str() { + "PARQUET" => Ok(Self::Parquet), + "NDJSON" => Ok(Self::NdJson), + "CSV" => Ok(Self::CSV), + other => Err(ParserError::ParserError(format!( + "expect one of PARQUET, NDJSON, or CSV, found: {}", + other + ))), + } + } +} + /// DataFusion extension DDL for `CREATE EXTERNAL TABLE` #[derive(Debug, Clone, PartialEq)] pub struct CreateExternalTable { @@ -268,12 +285,7 @@ impl<'a> DFParser<'a> { /// Parses the set of valid formats fn parse_file_format(&mut self) -> Result { match self.parser.next_token() { - Token::Word(w) => match &*w.value { - "PARQUET" => Ok(FileType::Parquet), - "NDJSON" => Ok(FileType::NdJson), - "CSV" => Ok(FileType::CSV), - _ => self.expected("one of PARQUET, NDJSON, or CSV", Token::Word(w)), - }, + Token::Word(w) => w.value.parse(), unexpected => self.expected("one of PARQUET, NDJSON, or CSV", unexpected), } } @@ -367,13 +379,21 @@ mod tests { }); expect_parse_ok(sql, expected)?; + // positive case: it is ok for parquet files to be other than upper case + let sql = "CREATE EXTERNAL TABLE t STORED AS parqueT LOCATION 'foo.parquet'"; + let expected = Statement::CreateExternalTable(CreateExternalTable { + name: "t".into(), + columns: vec![], + file_type: FileType::Parquet, + has_header: false, + location: "foo.parquet".into(), + }); + expect_parse_ok(sql, expected)?; + // Error cases: Invalid type let sql = "CREATE EXTERNAL TABLE t(c1 int) STORED AS UNKNOWN_TYPE LOCATION 'foo.csv'"; - expect_parse_error( - sql, - "Expected one of PARQUET, NDJSON, or CSV, found: UNKNOWN_TYPE", - ); + expect_parse_error(sql, "expect one of PARQUET, NDJSON, or CSV"); Ok(()) }