Skip to content

Commit f80b257

Browse files
committed
Begin improving support for CREATE PROCEDURE options
1 parent 21c6d42 commit f80b257

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

src/ast/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3914,6 +3914,7 @@ pub enum Statement {
39143914
or_alter: bool,
39153915
name: ObjectName,
39163916
params: Option<Vec<ProcedureParam>>,
3917+
language: Option<Ident>,
39173918
body: ConditionalStatements,
39183919
},
39193920
/// ```sql
@@ -4817,6 +4818,7 @@ impl fmt::Display for Statement {
48174818
name,
48184819
or_alter,
48194820
params,
4821+
language,
48204822
body,
48214823
} => {
48224824
write!(
@@ -4832,6 +4834,10 @@ impl fmt::Display for Statement {
48324834
}
48334835
}
48344836

4837+
if let Some(language) = language {
4838+
write!(f, " LANGUAGE {language}")?;
4839+
}
4840+
48354841
write!(f, " AS {body}")
48364842
}
48374843
Statement::CreateMacro {

src/dialect/postgresql.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// limitations under the License.
2929
use log::debug;
3030

31+
use crate::ast::Statement;
3132
use crate::dialect::{Dialect, Precedence};
3233
use crate::keywords::Keyword;
3334
use crate::parser::{Parser, ParserError};
@@ -258,4 +259,81 @@ impl Dialect for PostgreSqlDialect {
258259
fn supports_set_names(&self) -> bool {
259260
true
260261
}
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+
})
261339
}

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,7 @@ define_keywords!(
922922
TRACE,
923923
TRAILING,
924924
TRANSACTION,
925+
TRANSFORM,
925926
TRANSIENT,
926927
TRANSLATE,
927928
TRANSLATE_REGEX,

src/parser/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15780,6 +15780,13 @@ impl<'a> Parser<'a> {
1578015780
pub fn parse_create_procedure(&mut self, or_alter: bool) -> Result<Statement, ParserError> {
1578115781
let name = self.parse_object_name(false)?;
1578215782
let params = self.parse_optional_procedure_parameters()?;
15783+
15784+
let language = if self.parse_keyword(Keyword::LANGUAGE) {
15785+
Some(self.parse_identifier()?)
15786+
} else {
15787+
None
15788+
};
15789+
1578315790
self.expect_keyword_is(Keyword::AS)?;
1578415791

1578515792
let body = self.parse_conditional_statements(&[Keyword::END])?;
@@ -15788,6 +15795,7 @@ impl<'a> Parser<'a> {
1578815795
name,
1578915796
or_alter,
1579015797
params,
15798+
language,
1579115799
body,
1579215800
})
1579315801
}

0 commit comments

Comments
 (0)