diff --git a/crates/proof-of-sql-parser/Cargo.toml b/crates/proof-of-sql-parser/Cargo.toml index 228833b7e..29c23bc56 100644 --- a/crates/proof-of-sql-parser/Cargo.toml +++ b/crates/proof-of-sql-parser/Cargo.toml @@ -21,6 +21,7 @@ chrono = { workspace = true, features = ["serde"] } lalrpop-util = { workspace = true, features = ["lexer", "unicode"] } serde = { workspace = true, features = ["serde_derive", "alloc"] } snafu = { workspace = true } +sqlparser = { workspace = true } [build-dependencies] lalrpop = { workspace = true } diff --git a/crates/proof-of-sql-parser/src/identifier.rs b/crates/proof-of-sql-parser/src/identifier.rs index b11df6862..87ccc9de4 100644 --- a/crates/proof-of-sql-parser/src/identifier.rs +++ b/crates/proof-of-sql-parser/src/identifier.rs @@ -2,6 +2,7 @@ use crate::{sql::IdentifierParser, ParseError, ParseResult}; use alloc::{format, string::ToString}; use arrayvec::ArrayString; use core::{cmp::Ordering, fmt, ops::Deref, str::FromStr}; +use sqlparser::ast::Ident; /// Top-level unique identifier. #[derive(Debug, PartialEq, Eq, Clone, Hash, Ord, PartialOrd, Copy)] @@ -71,6 +72,16 @@ impl fmt::Display for Identifier { } } +// TryFrom for Identifier +impl TryFrom for Identifier { + type Error = ParseError; + + fn try_from(ident: Ident) -> ParseResult { + // Convert Ident's value to Identifier + Identifier::try_new(ident.value) + } +} + impl PartialEq for Identifier { fn eq(&self, other: &str) -> bool { other.eq_ignore_ascii_case(&self.name) @@ -278,4 +289,14 @@ mod tests { Identifier::new("t".repeat(64)); Identifier::new("茶".repeat(21)); } + + #[test] + fn try_from_ident() { + let ident = Ident::new("ValidIdentifier"); + let identifier = Identifier::try_from(ident).unwrap(); + assert_eq!(identifier.name(), "valididentifier"); + + let invalid_ident = Ident::new("INVALID$IDENTIFIER"); + assert!(Identifier::try_from(invalid_ident).is_err()); + } } diff --git a/crates/proof-of-sql-parser/src/resource_id.rs b/crates/proof-of-sql-parser/src/resource_id.rs index 2fe0d0848..10045d03b 100644 --- a/crates/proof-of-sql-parser/src/resource_id.rs +++ b/crates/proof-of-sql-parser/src/resource_id.rs @@ -3,11 +3,13 @@ use crate::{impl_serde_from_str, sql::ResourceIdParser, Identifier, ParseError, use alloc::{ format, string::{String, ToString}, + vec::Vec, }; use core::{ fmt::{self, Display}, str::FromStr, }; +use sqlparser::ast::Ident; /// Unique resource identifier, like `schema.object_name`. #[derive(Debug, PartialEq, Eq, Clone, Hash, Copy)] @@ -110,6 +112,22 @@ impl FromStr for ResourceId { } impl_serde_from_str!(ResourceId); +impl TryFrom> for ResourceId { + type Error = ParseError; + + fn try_from(identifiers: Vec) -> ParseResult { + if identifiers.len() != 2 { + return Err(ParseError::ResourceIdParseError { + error: "Expected exactly two identifiers for ResourceId".to_string(), + }); + } + + let schema = Identifier::try_from(identifiers[0].clone())?; + let object_name = Identifier::try_from(identifiers[1].clone())?; + Ok(ResourceId::new(schema, object_name)) + } +} + #[cfg(test)] mod tests { use super::*; @@ -233,4 +251,15 @@ mod tests { serde_json::from_str(r#""good_identifier.bad!identifier"#); assert!(deserialized.is_err()); } + + #[test] + fn test_try_from_vec_ident() { + let identifiers = alloc::vec![Ident::new("schema_name"), Ident::new("object_name")]; + let resource_id = ResourceId::try_from(identifiers).unwrap(); + assert_eq!(resource_id.schema().name(), "schema_name"); + assert_eq!(resource_id.object_name().name(), "object_name"); + + let invalid_identifiers = alloc::vec![Ident::new("only_one_ident")]; + assert!(ResourceId::try_from(invalid_identifiers).is_err()); + } }