cufflink_types/
sql_parse.rs1use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct Parsed {
10 pub tree: Value,
11 pub parser: String,
13 pub fingerprint: String,
15}
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19#[serde(tag = "kind", content = "message", rename_all = "snake_case")]
20pub enum ParseError {
21 Syntax(String),
22 TooLarge(String),
23 Unavailable(String),
24}
25
26impl std::fmt::Display for ParseError {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 match self {
29 Self::Syntax(message) => write!(f, "syntax: {message}"),
30 Self::TooLarge(message) => write!(f, "too large: {message}"),
31 Self::Unavailable(message) => write!(f, "unavailable: {message}"),
32 }
33 }
34}
35
36impl std::error::Error for ParseError {}
37
38impl ParseError {
39 pub fn syntax() -> Self {
40 Self::Syntax("the statement is not valid SQL".into())
41 }
42
43 pub fn unavailable() -> Self {
44 Self::Unavailable("the SQL parser is unavailable".into())
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50#[serde(rename_all = "snake_case")]
51pub enum ParseResponse {
52 Ok(Parsed),
53 Error(ParseError),
54}
55
56impl From<Result<Parsed, ParseError>> for ParseResponse {
57 fn from(result: Result<Parsed, ParseError>) -> Self {
58 result.map_or_else(Self::Error, Self::Ok)
59 }
60}
61
62impl From<ParseResponse> for Result<Parsed, ParseError> {
63 fn from(response: ParseResponse) -> Self {
64 match response {
65 ParseResponse::Ok(parsed) => Ok(parsed),
66 ParseResponse::Error(error) => Err(error),
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use serde_json::json;
75
76 #[test]
77 fn answers_match_the_wire_shapes() {
78 let parsed = Parsed {
79 tree: json!({"version": 170007, "stmts": []}),
80 parser: "6.2.1".into(),
81 fingerprint: "ab".into(),
82 };
83 for (result, wire) in [
84 (
85 Ok(parsed.clone()),
86 json!({"ok": {"tree": {"version": 170007, "stmts": []}, "parser": "6.2.1", "fingerprint": "ab"}}),
87 ),
88 (
89 Err(ParseError::syntax()),
90 json!({"error": {"kind": "syntax", "message": "the statement is not valid SQL"}}),
91 ),
92 (
93 Err(ParseError::TooLarge("over".into())),
94 json!({"error": {"kind": "too_large", "message": "over"}}),
95 ),
96 (
97 Err(ParseError::unavailable()),
98 json!({"error": {"kind": "unavailable", "message": "the SQL parser is unavailable"}}),
99 ),
100 ] {
101 let response = ParseResponse::from(result.clone());
102 assert_eq!(serde_json::to_value(&response).expect("encode"), wire);
103 let back: ParseResponse = serde_json::from_value(wire).expect("decode");
104 assert_eq!(Result::<Parsed, ParseError>::from(back), result);
105 }
106 assert!(serde_json::from_value::<ParseResponse>(
107 json!({"error": {"kind": "fault", "message": "x"}})
108 )
109 .is_err());
110 }
111}