sql/parsers/create_parser/
json.rs1use snafu::ResultExt;
16use sqlparser::parser::Parser;
17use sqlparser::tokenizer::Token;
18
19use crate::error::{Result, SyntaxSnafu};
20use crate::statements::OptionMap;
21use crate::util;
22
23pub(super) fn parse_json_datatype_options(parser: &mut Parser<'_>) -> Result<Option<OptionMap>> {
24 if parser.consume_token(&Token::LParen) {
25 let result = parser
26 .parse_comma_separated0(Parser::parse_sql_option, Token::RParen)
27 .context(SyntaxSnafu)
28 .and_then(|options| {
29 options
30 .into_iter()
31 .map(util::parse_option_string)
32 .collect::<Result<Vec<_>>>()
33 })?;
34 parser.expect_token(&Token::RParen).context(SyntaxSnafu)?;
35 Ok(Some(OptionMap::new(result)))
36 } else {
37 Ok(None)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use sqlparser::ast::DataType;
44
45 use crate::dialect::GreptimeDbDialect;
46 use crate::parser::{ParseOptions, ParserContext};
47 use crate::statements::OptionMap;
48 use crate::statements::create::{
49 Column, JSON_FORMAT_FULL_STRUCTURED, JSON_FORMAT_PARTIAL, JSON_FORMAT_RAW, JSON_OPT_FORMAT,
50 JSON_OPT_UNSTRUCTURED_KEYS,
51 };
52 use crate::statements::statement::Statement;
53
54 #[test]
55 fn test_parse_json_datatype_options() {
56 fn parse(sql: &str) -> Option<OptionMap> {
57 let Statement::CreateTable(mut create_table) = ParserContext::create_with_dialect(
58 sql,
59 &GreptimeDbDialect {},
60 ParseOptions::default(),
61 )
62 .unwrap()
63 .remove(0) else {
64 unreachable!()
65 };
66
67 let Column {
68 column_def,
69 extensions,
70 } = create_table.columns.remove(0);
71 assert_eq!(column_def.name.to_string(), "my_json");
72 assert_eq!(column_def.data_type, DataType::JSON);
73 assert!(column_def.options.is_empty());
74
75 extensions.json_datatype_options
76 }
77
78 let sql = r#"
79CREATE TABLE json_data (
80 my_json JSON(format = "partial", unstructured_keys = ["k", "foo.bar", "a.b.c"]),
81 ts TIMESTAMP TIME INDEX,
82)"#;
83 let options = parse(sql).unwrap();
84 assert_eq!(options.len(), 2);
85 assert_eq!(
86 options.value(JSON_OPT_FORMAT).and_then(|x| x.as_string()),
87 Some(JSON_FORMAT_PARTIAL)
88 );
89 let expected = vec!["k", "foo.bar", "a.b.c"];
90 assert_eq!(
91 options
92 .value(JSON_OPT_UNSTRUCTURED_KEYS)
93 .and_then(|x| x.as_list()),
94 Some(expected)
95 );
96
97 let sql = r#"
98CREATE TABLE json_data (
99 my_json JSON(format = "structured"),
100 ts TIMESTAMP TIME INDEX,
101)"#;
102 let options = parse(sql).unwrap();
103 assert_eq!(options.len(), 1);
104 assert_eq!(
105 options.value(JSON_OPT_FORMAT).and_then(|x| x.as_string()),
106 Some(JSON_FORMAT_FULL_STRUCTURED)
107 );
108
109 let sql = r#"
110CREATE TABLE json_data (
111 my_json JSON(format = "raw"),
112 ts TIMESTAMP TIME INDEX,
113)"#;
114 let options = parse(sql).unwrap();
115 assert_eq!(options.len(), 1);
116 assert_eq!(
117 options.value(JSON_OPT_FORMAT).and_then(|x| x.as_string()),
118 Some(JSON_FORMAT_RAW)
119 );
120
121 let sql = r#"
122CREATE TABLE json_data (
123 my_json JSON(),
124 ts TIMESTAMP TIME INDEX,
125)"#;
126 let options = parse(sql).unwrap();
127 assert!(options.is_empty());
128
129 let sql = r#"
130CREATE TABLE json_data (
131 my_json JSON,
132 ts TIMESTAMP TIME INDEX,
133)"#;
134 let options = parse(sql);
135 assert!(options.is_none());
136 }
137}