|
28 | 28 | // limitations under the License. |
29 | 29 | use log::debug; |
30 | 30 |
|
| 31 | +use crate::ast::Statement; |
31 | 32 | use crate::dialect::{Dialect, Precedence}; |
32 | 33 | use crate::keywords::Keyword; |
33 | 34 | use crate::parser::{Parser, ParserError}; |
@@ -258,4 +259,81 @@ impl Dialect for PostgreSqlDialect { |
258 | 259 | fn supports_set_names(&self) -> bool { |
259 | 260 | true |
260 | 261 | } |
| 262 | + |
| 263 | + fn parse_statement( |
| 264 | + &self, |
| 265 | + parser: &mut Parser, |
| 266 | + ) -> Option<Result<crate::ast::Statement, ParserError>> { |
| 267 | + if parser.parse_keywords(&[Keyword::CREATE, Keyword::PROCEDURE]) { |
| 268 | + Some(parse_create_procedure(parser)) |
| 269 | + } else { |
| 270 | + None |
| 271 | + } |
| 272 | + } |
| 273 | +} |
| 274 | + |
| 275 | +/// CREATE PROCEDURE |
| 276 | +/// <https://www.postgresql.org/docs/17/sql-createprocedure.html> |
| 277 | +fn parse_create_procedure(parser: &mut Parser) -> Result<Statement, ParserError> { |
| 278 | + let name = parser.parse_object_name(false)?; |
| 279 | + |
| 280 | + // TODO: This doesn't support PostgreSQL's VARIADIC argmode, nor is there support in crate::ast::ArgMode |
| 281 | + let params = parser.parse_optional_procedure_parameters()?; |
| 282 | + |
| 283 | + let mut language = None; |
| 284 | + |
| 285 | + // TODO: Make room for this in the AST |
| 286 | + let mut _transforms = vec![]; |
| 287 | + |
| 288 | + enum Security { |
| 289 | + Invoker, |
| 290 | + Definer, |
| 291 | + } |
| 292 | + |
| 293 | + let mut security = None; |
| 294 | + |
| 295 | + loop { |
| 296 | + if parser.parse_keyword(Keyword::LANGUAGE) { |
| 297 | + if language.is_some() { |
| 298 | + todo!("Return error for two LANGUAGE definitions") |
| 299 | + } |
| 300 | + language = Some(parser.parse_identifier()?); |
| 301 | + } else if parser.parse_keyword(Keyword::TRANSFORM) { |
| 302 | + loop { |
| 303 | + parser.expect_keywords(&[Keyword::FOR, Keyword::TYPE])?; |
| 304 | + _transforms.push(parser.parse_object_name(false)?); |
| 305 | + if !parser.consume_token(&Token::Comma) { |
| 306 | + break |
| 307 | + } |
| 308 | + } |
| 309 | + } else if parser.parse_keywords(&[Keyword::EXTERNAL, Keyword::SECURITY]) |
| 310 | + || parser.parse_keyword(Keyword::SECURITY) |
| 311 | + { |
| 312 | + if security.is_some() { |
| 313 | + todo!("Return error for two SECURITY definitions") |
| 314 | + } |
| 315 | + if parser.parse_keyword(Keyword::INVOKER) { |
| 316 | + security = Some(Security::Invoker) |
| 317 | + } else if parser.parse_keyword(Keyword::DEFINER) { |
| 318 | + security = Some(Security::Definer) |
| 319 | + } else { |
| 320 | + todo!("Return error for unknown SECURITY type") |
| 321 | + } |
| 322 | + } else if parser.parse_keyword(Keyword::SET) { |
| 323 | + } else { |
| 324 | + break; |
| 325 | + } |
| 326 | + } |
| 327 | + |
| 328 | + parser.expect_keyword_is(Keyword::AS)?; |
| 329 | + |
| 330 | + let body = parser.parse_conditional_statements(&[Keyword::END])?; |
| 331 | + |
| 332 | + Ok(Statement::CreateProcedure { |
| 333 | + name, |
| 334 | + or_alter: false, |
| 335 | + params, |
| 336 | + language, |
| 337 | + body, |
| 338 | + }) |
261 | 339 | } |
0 commit comments