diff --git a/crates/codegen/src/get_node_properties.rs b/crates/codegen/src/get_node_properties.rs index 0adf77fa..7291dab1 100644 --- a/crates/codegen/src/get_node_properties.rs +++ b/crates/codegen/src/get_node_properties.rs @@ -812,6 +812,30 @@ fn custom_handlers(node: &Node) -> TokenStream { panic!("Encountered multiple defined func_name elements in CreateConversionStmt"); } }, + "CreateTransformStmt" => quote! { + tokens.push(TokenProperty::from(Token::Create)); + if n.replace { + tokens.push(TokenProperty::from(Token::Or)); + tokens.push(TokenProperty::from(Token::Replace)); + } + tokens.push(TokenProperty::from(Token::Transform)); + if n.type_name.is_some() { + tokens.push(TokenProperty::from(Token::For)); + } + tokens.push(TokenProperty::from(Token::Language)); + if n.fromsql.is_some() { + tokens.push(TokenProperty::from(Token::From)); + tokens.push(TokenProperty::from(Token::SqlP)); + tokens.push(TokenProperty::from(Token::With)); + tokens.push(TokenProperty::from(Token::Function)); + } + if n.tosql.is_some() { + tokens.push(TokenProperty::from(Token::To)); + tokens.push(TokenProperty::from(Token::SqlP)); + tokens.push(TokenProperty::from(Token::With)); + tokens.push(TokenProperty::from(Token::Function)); + } + }, _ => quote! {}, } } diff --git a/crates/parser/src/codegen.rs b/crates/parser/src/codegen.rs index b6c1a661..d52ffee9 100644 --- a/crates/parser/src/codegen.rs +++ b/crates/parser/src/codegen.rs @@ -317,4 +317,32 @@ mod tests { ], ) } + + #[test] + fn test_create_transform() { + test_get_node_properties( + "CREATE OR REPLACE TRANSFORM FOR hstore LANGUAGE plpython3u ( + FROM SQL WITH FUNCTION hstore_to_plpython(internal), + TO SQL WITH FUNCTION plpython_to_hstore(internal) + );", + SyntaxKind::CreateTransformStmt, + vec![ + TokenProperty::from(SyntaxKind::Create), + TokenProperty::from(SyntaxKind::Or), + TokenProperty::from(SyntaxKind::Replace), + TokenProperty::from(SyntaxKind::Transform), + TokenProperty::from(SyntaxKind::For), + TokenProperty::from(SyntaxKind::Language), + TokenProperty::from(SyntaxKind::From), + TokenProperty::from(SyntaxKind::SqlP), + TokenProperty::from(SyntaxKind::With), + TokenProperty::from(SyntaxKind::Function), + TokenProperty::from(SyntaxKind::To), + TokenProperty::from(SyntaxKind::SqlP), + TokenProperty::from(SyntaxKind::With), + TokenProperty::from(SyntaxKind::Function), + TokenProperty::from("plpython3u".to_string()), + ], + ) + } } diff --git a/crates/parser/tests/data/statements/valid/0056.sql b/crates/parser/tests/data/statements/valid/0056.sql new file mode 100644 index 00000000..5149bc20 --- /dev/null +++ b/crates/parser/tests/data/statements/valid/0056.sql @@ -0,0 +1,9 @@ +CREATE TRANSFORM FOR hstore LANGUAGE plpython3u ( + FROM SQL WITH FUNCTION hstore_to_plpython(internal), + TO SQL WITH FUNCTION plpython_to_hstore(internal) +); + +CREATE OR REPLACE TRANSFORM FOR hstore LANGUAGE plpython3u ( + FROM SQL WITH FUNCTION hstore_to_plpython(internal), + TO SQL WITH FUNCTION plpython_to_hstore(internal) +); diff --git a/crates/parser/tests/snapshots/statements/valid/0056@1.snap b/crates/parser/tests/snapshots/statements/valid/0056@1.snap new file mode 100644 index 00000000..c378ba0f --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0056@1.snap @@ -0,0 +1,251 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE TRANSFORM FOR hstore LANGUAGE plpython3u (\n FROM SQL WITH FUNCTION hstore_to_plpython(internal),\n TO SQL WITH FUNCTION plpython_to_hstore(internal)\n);" +--- +Parse { + cst: SourceFile@0..163 + CreateTransformStmt@0..163 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Transform@7..16 "TRANSFORM" + Whitespace@16..17 " " + For@17..20 "FOR" + Whitespace@20..21 " " + TypeName@21..27 + Ident@21..27 "hstore" + Whitespace@27..28 " " + Language@28..36 "LANGUAGE" + Whitespace@36..37 " " + Ident@37..47 "plpython3u" + Whitespace@47..48 " " + Ascii40@48..49 "(" + Newline@49..50 "\n" + Whitespace@50..54 " " + From@54..58 "FROM" + Whitespace@58..59 " " + SqlP@59..62 "SQL" + Whitespace@62..63 " " + With@63..67 "WITH" + Whitespace@67..68 " " + Function@68..76 "FUNCTION" + Whitespace@76..77 " " + ObjectWithArgs@77..107 + Ident@77..95 "hstore_to_plpython" + Ascii40@95..96 "(" + TypeName@96..104 + Ident@96..104 "internal" + Ascii41@104..105 ")" + Ascii44@105..106 "," + Newline@106..107 "\n" + Whitespace@107..111 " " + To@111..113 "TO" + Whitespace@113..114 " " + SqlP@114..117 "SQL" + Whitespace@117..118 " " + With@118..122 "WITH" + Whitespace@122..123 " " + Function@123..131 "FUNCTION" + Whitespace@131..132 " " + ObjectWithArgs@132..163 + Ident@132..150 "plpython_to_hstore" + Ascii40@150..151 "(" + TypeName@151..159 + Ident@151..159 "internal" + Ascii41@159..160 ")" + Newline@160..161 "\n" + Ascii41@161..162 ")" + Ascii59@162..163 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreateTransformStmt( + CreateTransformStmt { + replace: false, + type_name: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "hstore", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 21, + }, + ), + lang: "plpython3u", + fromsql: Some( + ObjectWithArgs { + objname: [ + Node { + node: Some( + String( + String { + sval: "hstore_to_plpython", + }, + ), + ), + }, + ], + objargs: [ + Node { + node: Some( + TypeName( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 96, + }, + ), + ), + }, + ], + objfuncargs: [ + Node { + node: Some( + FunctionParameter( + FunctionParameter { + name: "", + arg_type: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 96, + }, + ), + mode: FuncParamDefault, + defexpr: None, + }, + ), + ), + }, + ], + args_unspecified: false, + }, + ), + tosql: Some( + ObjectWithArgs { + objname: [ + Node { + node: Some( + String( + String { + sval: "plpython_to_hstore", + }, + ), + ), + }, + ], + objargs: [ + Node { + node: Some( + TypeName( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 151, + }, + ), + ), + }, + ], + objfuncargs: [ + Node { + node: Some( + FunctionParameter( + FunctionParameter { + name: "", + arg_type: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 151, + }, + ), + mode: FuncParamDefault, + defexpr: None, + }, + ), + ), + }, + ], + args_unspecified: false, + }, + ), + }, + ), + range: 0..162, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0056@2.snap b/crates/parser/tests/snapshots/statements/valid/0056@2.snap new file mode 100644 index 00000000..d9ee6d34 --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0056@2.snap @@ -0,0 +1,255 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE OR REPLACE TRANSFORM FOR hstore LANGUAGE plpython3u (\n FROM SQL WITH FUNCTION hstore_to_plpython(internal),\n TO SQL WITH FUNCTION plpython_to_hstore(internal)\n);" +--- +Parse { + cst: SourceFile@0..174 + CreateTransformStmt@0..174 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Or@7..9 "OR" + Whitespace@9..10 " " + Replace@10..17 "REPLACE" + Whitespace@17..18 " " + Transform@18..27 "TRANSFORM" + Whitespace@27..28 " " + For@28..31 "FOR" + Whitespace@31..32 " " + TypeName@32..38 + Ident@32..38 "hstore" + Whitespace@38..39 " " + Language@39..47 "LANGUAGE" + Whitespace@47..48 " " + Ident@48..58 "plpython3u" + Whitespace@58..59 " " + Ascii40@59..60 "(" + Newline@60..61 "\n" + Whitespace@61..65 " " + From@65..69 "FROM" + Whitespace@69..70 " " + SqlP@70..73 "SQL" + Whitespace@73..74 " " + With@74..78 "WITH" + Whitespace@78..79 " " + Function@79..87 "FUNCTION" + Whitespace@87..88 " " + ObjectWithArgs@88..118 + Ident@88..106 "hstore_to_plpython" + Ascii40@106..107 "(" + TypeName@107..115 + Ident@107..115 "internal" + Ascii41@115..116 ")" + Ascii44@116..117 "," + Newline@117..118 "\n" + Whitespace@118..122 " " + To@122..124 "TO" + Whitespace@124..125 " " + SqlP@125..128 "SQL" + Whitespace@128..129 " " + With@129..133 "WITH" + Whitespace@133..134 " " + Function@134..142 "FUNCTION" + Whitespace@142..143 " " + ObjectWithArgs@143..174 + Ident@143..161 "plpython_to_hstore" + Ascii40@161..162 "(" + TypeName@162..170 + Ident@162..170 "internal" + Ascii41@170..171 ")" + Newline@171..172 "\n" + Ascii41@172..173 ")" + Ascii59@173..174 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreateTransformStmt( + CreateTransformStmt { + replace: true, + type_name: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "hstore", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 32, + }, + ), + lang: "plpython3u", + fromsql: Some( + ObjectWithArgs { + objname: [ + Node { + node: Some( + String( + String { + sval: "hstore_to_plpython", + }, + ), + ), + }, + ], + objargs: [ + Node { + node: Some( + TypeName( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 107, + }, + ), + ), + }, + ], + objfuncargs: [ + Node { + node: Some( + FunctionParameter( + FunctionParameter { + name: "", + arg_type: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 107, + }, + ), + mode: FuncParamDefault, + defexpr: None, + }, + ), + ), + }, + ], + args_unspecified: false, + }, + ), + tosql: Some( + ObjectWithArgs { + objname: [ + Node { + node: Some( + String( + String { + sval: "plpython_to_hstore", + }, + ), + ), + }, + ], + objargs: [ + Node { + node: Some( + TypeName( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 162, + }, + ), + ), + }, + ], + objfuncargs: [ + Node { + node: Some( + FunctionParameter( + FunctionParameter { + name: "", + arg_type: Some( + TypeName { + names: [ + Node { + node: Some( + String( + String { + sval: "internal", + }, + ), + ), + }, + ], + type_oid: 0, + setof: false, + pct_type: false, + typmods: [], + typemod: -1, + array_bounds: [], + location: 162, + }, + ), + mode: FuncParamDefault, + defexpr: None, + }, + ), + ), + }, + ], + args_unspecified: false, + }, + ), + }, + ), + range: 0..173, + }, + ], +}