vibesql_parser/parser/
table_options.rs1use super::{ParseError, Parser};
2use crate::{keywords::Keyword, token::Token};
3
4impl Parser {
5 pub fn parse_table_options(&mut self) -> Result<Vec<vibesql_ast::TableOption>, ParseError> {
7 let mut options = Vec::new();
8
9 loop {
10 let option = if self.try_consume_keyword(Keyword::KeyBlockSize) {
12 self.parse_key_block_size_option()?
13 } else if self.try_consume_keyword(Keyword::Connection) {
14 self.parse_connection_option()?
15 } else if self.try_consume_keyword(Keyword::InsertMethod) {
16 self.parse_insert_method_option()?
17 } else if self.try_consume_keyword(Keyword::Union) {
18 self.parse_union_option()?
19 } else if self.try_consume_keyword(Keyword::RowFormat) {
20 self.parse_row_format_option()?
21 } else if self.try_consume_keyword(Keyword::DelayKeyWrite) {
22 self.parse_delay_key_write_option()?
23 } else if self.try_consume_keyword(Keyword::TableChecksum)
24 || self.try_consume_keyword(Keyword::Checksum)
25 {
26 self.parse_table_checksum_option()?
27 } else if self.try_consume_keyword(Keyword::StatsSamplePages) {
28 self.parse_stats_sample_pages_option()?
29 } else if self.try_consume_keyword(Keyword::Password) {
30 self.parse_password_option()?
31 } else if self.try_consume_keyword(Keyword::AvgRowLength) {
32 self.parse_avg_row_length_option()?
33 } else if self.try_consume_keyword(Keyword::MinRows) {
34 self.parse_min_rows_option()?
35 } else if self.try_consume_keyword(Keyword::MaxRows) {
36 self.parse_max_rows_option()?
37 } else if self.try_consume_keyword(Keyword::SecondaryEngine) {
38 self.parse_secondary_engine_option()?
39 } else if self.try_consume_keyword(Keyword::Collate) {
40 self.parse_collate_option()?
41 } else if self.try_consume_keyword(Keyword::Comment) {
42 self.parse_comment_option()?
43 } else if self.try_consume_keyword(Keyword::Storage) {
44 self.parse_storage_option()?
45 } else {
46 break;
48 };
49
50 options.push(option);
51
52 self.try_consume(&Token::Comma);
54 }
55
56 Ok(options)
57 }
58
59 fn parse_key_block_size_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
60 self.try_consume(&Token::Symbol('='));
62 let value = self.parse_numeric_value()?;
64 Ok(vibesql_ast::TableOption::KeyBlockSize(value))
65 }
66
67 fn parse_connection_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
68 self.try_consume(&Token::Symbol('='));
70 match self.peek() {
72 Token::String(s) => {
73 let val = s.clone();
74 self.advance();
75 Ok(vibesql_ast::TableOption::Connection(Some(val)))
76 }
77 _ => Err(ParseError { message: "Expected string value for CONNECTION".to_string() }),
78 }
79 }
80
81 fn parse_insert_method_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
82 self.try_consume(&Token::Symbol('='));
84 let method = if self.try_consume_keyword(Keyword::First) {
85 vibesql_ast::InsertMethod::First
86 } else if self.try_consume_keyword(Keyword::Last) {
87 vibesql_ast::InsertMethod::Last
88 } else if self.try_consume_keyword(Keyword::No) {
89 vibesql_ast::InsertMethod::No
90 } else {
91 return Err(ParseError {
92 message: "Expected FIRST, LAST, or NO for INSERT_METHOD".to_string(),
93 });
94 };
95 Ok(vibesql_ast::TableOption::InsertMethod(method))
96 }
97
98 fn parse_union_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
99 self.try_consume(&Token::Symbol('='));
101 self.try_consume(&Token::LParen);
103 let mut tables = Vec::new();
104 if !self.try_consume(&Token::RParen) {
105 loop {
106 match self.peek() {
107 Token::Identifier(id) | Token::DelimitedIdentifier(id) => {
108 tables.push(id.clone());
109 self.advance();
110 }
111 _ => {
112 return Err(ParseError {
113 message: "Expected table name in UNION".to_string(),
114 })
115 }
116 }
117 if self.try_consume(&Token::Comma) {
118 continue;
119 } else {
120 break;
121 }
122 }
123 self.expect_token(Token::RParen)?;
124 }
125 Ok(vibesql_ast::TableOption::Union(Some(tables)))
126 }
127
128 fn parse_row_format_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
129 self.try_consume(&Token::Symbol('='));
131 let format = if self.try_consume_keyword(Keyword::Default) {
132 vibesql_ast::RowFormat::Default
133 } else if self.try_consume_keyword(Keyword::Dynamic) {
134 vibesql_ast::RowFormat::Dynamic
135 } else if self.try_consume_keyword(Keyword::Fixed) {
136 vibesql_ast::RowFormat::Fixed
137 } else if self.try_consume_keyword(Keyword::Compressed) {
138 vibesql_ast::RowFormat::Compressed
139 } else if self.try_consume_keyword(Keyword::Redundant) {
140 vibesql_ast::RowFormat::Redundant
141 } else if self.try_consume_keyword(Keyword::Compact) {
142 vibesql_ast::RowFormat::Compact
143 } else {
144 return Err(ParseError { message: "Expected row format value".to_string() });
145 };
146 Ok(vibesql_ast::TableOption::RowFormat(Some(format)))
147 }
148
149 fn parse_delay_key_write_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
150 self.try_consume(&Token::Symbol('='));
152 let value = self.parse_numeric_value()?;
154 Ok(vibesql_ast::TableOption::DelayKeyWrite(value))
155 }
156
157 fn parse_table_checksum_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
158 self.try_consume(&Token::Symbol('='));
160 let value = self.parse_numeric_value()?;
162 Ok(vibesql_ast::TableOption::TableChecksum(value))
163 }
164
165 fn parse_stats_sample_pages_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
166 self.try_consume(&Token::Symbol('='));
168 let value = self.parse_numeric_value()?;
170 Ok(vibesql_ast::TableOption::StatsSamplePages(value))
171 }
172
173 fn parse_password_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
174 self.try_consume(&Token::Symbol('='));
176 match self.peek() {
178 Token::String(s) => {
179 let val = s.clone();
180 self.advance();
181 Ok(vibesql_ast::TableOption::Password(Some(val)))
182 }
183 _ => Err(ParseError { message: "Expected string value for PASSWORD".to_string() }),
184 }
185 }
186
187 fn parse_avg_row_length_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
188 self.try_consume(&Token::Symbol('='));
190 let value = self.parse_numeric_value()?;
192 Ok(vibesql_ast::TableOption::AvgRowLength(value))
193 }
194
195 fn parse_min_rows_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
196 self.try_consume(&Token::Symbol('='));
198 let value = self.parse_numeric_value()?;
200 Ok(vibesql_ast::TableOption::MinRows(value))
201 }
202
203 fn parse_max_rows_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
204 self.try_consume(&Token::Symbol('='));
206 let value = self.parse_numeric_value()?;
208 Ok(vibesql_ast::TableOption::MaxRows(value))
209 }
210
211 fn parse_secondary_engine_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
212 self.try_consume(&Token::Symbol('='));
214 let value = if self.try_consume_keyword(Keyword::Null) {
216 Some("NULL".to_string())
217 } else if let Token::Identifier(id) = self.peek() {
218 let val = id.clone();
219 self.advance();
220 Some(val)
221 } else {
222 None
223 };
224 Ok(vibesql_ast::TableOption::SecondaryEngine(value))
225 }
226
227 fn parse_collate_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
228 self.try_consume(&Token::Symbol('='));
230 match self.peek() {
232 Token::Identifier(id) => {
233 let val = id.clone();
234 self.advance();
235 Ok(vibesql_ast::TableOption::Collate(Some(val)))
236 }
237 _ => Err(ParseError { message: "Expected collation name".to_string() }),
238 }
239 }
240
241 fn parse_comment_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
242 self.try_consume(&Token::Symbol('='));
244 match self.peek() {
246 Token::String(s) => {
247 let val = s.clone();
248 self.advance();
249 Ok(vibesql_ast::TableOption::Comment(Some(val)))
250 }
251 _ => Err(ParseError { message: "Expected string value for COMMENT".to_string() }),
252 }
253 }
254
255 fn parse_storage_option(&mut self) -> Result<vibesql_ast::TableOption, ParseError> {
257 self.try_consume(&Token::Symbol('='));
259 let format = if self.try_consume_keyword(Keyword::Row) {
261 vibesql_ast::StorageFormat::Row
262 } else if self.try_consume_keyword(Keyword::Columnar) {
263 vibesql_ast::StorageFormat::Columnar
264 } else {
265 return Err(ParseError { message: "Expected ROW or COLUMNAR for STORAGE".to_string() });
266 };
267 Ok(vibesql_ast::TableOption::Storage(format))
268 }
269
270 pub(super) fn parse_numeric_value(&mut self) -> Result<Option<i64>, ParseError> {
272 if let Token::Number(n) = self.peek() {
273 let val = if let Ok(int_val) = n.parse::<i64>() {
275 int_val
276 } else if let Ok(float_val) = n.parse::<f64>() {
277 float_val as i64
278 } else {
279 return Err(ParseError { message: "Invalid numeric value".to_string() });
280 };
281 self.advance();
282 Ok(Some(val))
283 } else {
284 Ok(None)
285 }
286 }
287}