From 10adca556391a8f169ca3645d32839540c8847ed Mon Sep 17 00:00:00 2001 From: psteinroe Date: Thu, 21 Dec 2023 17:12:20 +0100 Subject: [PATCH] fix: location and add support for create publication --- crates/codegen/src/get_location.rs | 18 +++ crates/codegen/src/get_node_properties.rs | 68 ++++++++++ .../tests/data/statements/valid/0053.sql | 7 + .../snapshots/statements/valid/0049@2.snap | 59 +++++---- .../snapshots/statements/valid/0053@1.snap | 101 ++++++++++++++ .../snapshots/statements/valid/0053@2.snap | 113 ++++++++++++++++ .../snapshots/statements/valid/0053@3.snap | 35 +++++ .../snapshots/statements/valid/0053@4.snap | 102 +++++++++++++++ .../snapshots/statements/valid/0053@5.snap | 123 ++++++++++++++++++ .../snapshots/statements/valid/0053@6.snap | 69 ++++++++++ .../snapshots/statements/valid/0053@7.snap | 93 +++++++++++++ 11 files changed, 758 insertions(+), 30 deletions(-) create mode 100644 crates/parser/tests/data/statements/valid/0053.sql create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@1.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@2.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@3.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@4.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@5.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@6.snap create mode 100644 crates/parser/tests/snapshots/statements/valid/0053@7.snap diff --git a/crates/codegen/src/get_location.rs b/crates/codegen/src/get_location.rs index 53903aba..2d018a99 100644 --- a/crates/codegen/src/get_location.rs +++ b/crates/codegen/src/get_location.rs @@ -55,6 +55,22 @@ pub fn get_location_mod(proto_file: &ProtoFile) -> proc_macro2::TokenStream { } else { Some(n.location) }, + NodeEnum::PublicationObjSpec(n) => { + match &n.pubtable { + Some(pubtable) => match &pubtable.relation { + Some(range_var) => Some(range_var.location), + None => Some(n.location), + }, + None => Some(n.location), + } + }, + NodeEnum::BooleanTest(n) => { + if n.arg.is_some() { + get_location_internal(&n.arg.as_ref().unwrap().node.as_ref().unwrap()) + } else { + Some(n.location) + } + }, #(NodeEnum::#node_identifiers(n) => #location_idents),* }; if location.is_some() && location.unwrap() < 0 { @@ -74,6 +90,8 @@ fn manual_node_names() -> Vec<&'static str> { "CollateClause", "TypeCast", "ColumnDef", + "NullTest", + "PublicationObjSpec", ] } diff --git a/crates/codegen/src/get_node_properties.rs b/crates/codegen/src/get_node_properties.rs index ecd2ec29..b21dd3cf 100644 --- a/crates/codegen/src/get_node_properties.rs +++ b/crates/codegen/src/get_node_properties.rs @@ -692,6 +692,74 @@ fn custom_handlers(node: &Node) -> TokenStream { tokens.push(TokenProperty::from(Token::With)); } }, + "CreatePublicationStmt" => quote! { + tokens.push(TokenProperty::from(Token::Create)); + tokens.push(TokenProperty::from(Token::Publication)); + if n.for_all_tables { + tokens.push(TokenProperty::from(Token::For)); + tokens.push(TokenProperty::from(Token::All)); + tokens.push(TokenProperty::from(Token::Tables)); + } + if let Some(n) = n.options.first() { + tokens.push(TokenProperty::from(Token::With)); + } + if let Some(n) = n.pubobjects.first() { + tokens.push(TokenProperty::from(Token::For)); + if let Some(NodeEnum::PublicationObjSpec(n)) = &n.node { + match n.pubobjtype() { + protobuf::PublicationObjSpecType::PublicationobjTable => { + tokens.push(TokenProperty::from(Token::Table)); + }, + protobuf::PublicationObjSpecType::PublicationobjTablesInSchema => { + tokens.push(TokenProperty::from(Token::Tables)); + tokens.push(TokenProperty::from(Token::InP)); + tokens.push(TokenProperty::from(Token::Schema)); + }, + _ => panic!("Unknown CreatePublicationStmt {:#?}", n.pubobjtype()) + } + } + } + if let Some(n) = n.pubobjects.last() { + if let Some(NodeEnum::PublicationObjSpec(n)) = &n.node { + match n.pubobjtype() { + protobuf::PublicationObjSpecType::PublicationobjTablesInSchema => { + tokens.push(TokenProperty::from(Token::Tables)); + tokens.push(TokenProperty::from(Token::InP)); + tokens.push(TokenProperty::from(Token::Schema)); + }, + _ => {} + } + } + } + }, + "PublicationTable" => quote! { + if n.where_clause.is_some() { + tokens.push(TokenProperty::from(Token::Where)); + } + }, + "BooleanTest" => quote! { + match n.booltesttype() { + protobuf::BoolTestType::IsTrue => { + tokens.push(TokenProperty::from(Token::Is)); + tokens.push(TokenProperty::from(Token::TrueP)); + }, + protobuf::BoolTestType::IsNotTrue => { + tokens.push(TokenProperty::from(Token::Is)); + tokens.push(TokenProperty::from(Token::Not)); + tokens.push(TokenProperty::from(Token::TrueP)); + }, + protobuf::BoolTestType::IsFalse => { + tokens.push(TokenProperty::from(Token::Is)); + tokens.push(TokenProperty::from(Token::FalseP)); + }, + protobuf::BoolTestType::IsNotFalse => { + tokens.push(TokenProperty::from(Token::Is)); + tokens.push(TokenProperty::from(Token::Not)); + tokens.push(TokenProperty::from(Token::FalseP)); + }, + _ => panic!("Unknown BooleanTest {:#?}", n.booltesttype()), + } + }, "CompositeTypeStmt" => quote! { tokens.push(TokenProperty::from(Token::Create)); tokens.push(TokenProperty::from(Token::TypeP)); diff --git a/crates/parser/tests/data/statements/valid/0053.sql b/crates/parser/tests/data/statements/valid/0053.sql new file mode 100644 index 00000000..52be0e41 --- /dev/null +++ b/crates/parser/tests/data/statements/valid/0053.sql @@ -0,0 +1,7 @@ +CREATE PUBLICATION mypublication FOR TABLE users, departments; +CREATE PUBLICATION active_departments FOR TABLE departments WHERE (active IS TRUE); +CREATE PUBLICATION alltables FOR ALL TABLES; +CREATE PUBLICATION insert_only FOR TABLE mydata WITH (publish = 'insert'); +CREATE PUBLICATION production_publication FOR TABLE users, departments, TABLES IN SCHEMA production; +CREATE PUBLICATION sales_publication FOR TABLES IN SCHEMA marketing, sales; +CREATE PUBLICATION users_filtered FOR TABLE users (user_id, firstname); diff --git a/crates/parser/tests/snapshots/statements/valid/0049@2.snap b/crates/parser/tests/snapshots/statements/valid/0049@2.snap index fbe1867e..d4b59350 100644 --- a/crates/parser/tests/snapshots/statements/valid/0049@2.snap +++ b/crates/parser/tests/snapshots/statements/valid/0049@2.snap @@ -1,36 +1,35 @@ --- source: crates/parser/tests/statement_parser_test.rs -description: "\nCREATE EXTENSION IF NOT EXISTS x CASCADE VERSION \"1.2\" SCHEMA a;" +description: "CREATE EXTENSION IF NOT EXISTS x CASCADE VERSION \"1.2\" SCHEMA a;" --- Parse { - cst: SourceFile@0..65 - Newline@0..1 "\n" - CreateExtensionStmt@1..65 - Create@1..7 "CREATE" - Whitespace@7..8 " " - Extension@8..17 "EXTENSION" - Whitespace@17..18 " " - IfP@18..20 "IF" - Whitespace@20..21 " " - Not@21..24 "NOT" - Whitespace@24..25 " " - Exists@25..31 "EXISTS" - Whitespace@31..32 " " - Ident@32..33 "x" - Whitespace@33..34 " " - DefElem@34..41 - Cascade@34..41 "CASCADE" - Whitespace@41..42 " " - DefElem@42..55 - VersionP@42..49 "VERSION" - Whitespace@49..50 " " - Ident@50..55 "\"1.2\"" - Whitespace@55..56 " " - DefElem@56..64 - Schema@56..62 "SCHEMA" - Whitespace@62..63 " " - Ident@63..64 "a" - Ascii59@64..65 ";" + cst: SourceFile@0..64 + CreateExtensionStmt@0..64 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Extension@7..16 "EXTENSION" + Whitespace@16..17 " " + IfP@17..19 "IF" + Whitespace@19..20 " " + Not@20..23 "NOT" + Whitespace@23..24 " " + Exists@24..30 "EXISTS" + Whitespace@30..31 " " + Ident@31..32 "x" + Whitespace@32..33 " " + DefElem@33..40 + Cascade@33..40 "CASCADE" + Whitespace@40..41 " " + DefElem@41..54 + VersionP@41..48 "VERSION" + Whitespace@48..49 " " + Ident@49..54 "\"1.2\"" + Whitespace@54..55 " " + DefElem@55..63 + Schema@55..61 "SCHEMA" + Whitespace@61..62 " " + Ident@62..63 "a" + Ascii59@63..64 ";" , errors: [], stmts: [ @@ -112,7 +111,7 @@ Parse { ], }, ), - range: 0..64, + range: 0..63, }, ], } diff --git a/crates/parser/tests/snapshots/statements/valid/0053@1.snap b/crates/parser/tests/snapshots/statements/valid/0053@1.snap new file mode 100644 index 00000000..93bc15fd --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@1.snap @@ -0,0 +1,101 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE PUBLICATION mypublication FOR TABLE users, departments;" +--- +Parse { + cst: SourceFile@0..62 + CreatePublicationStmt@0..62 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..32 "mypublication" + Whitespace@32..33 " " + For@33..36 "FOR" + Whitespace@36..37 " " + Table@37..42 "TABLE" + Whitespace@42..43 " " + PublicationObjSpec@43..48 + PublicationTable@43..48 + RangeVar@43..48 + Ident@43..48 "users" + Ascii44@48..49 "," + Whitespace@49..50 " " + PublicationObjSpec@50..61 + PublicationTable@50..61 + RangeVar@50..61 + Ident@50..61 "departments" + Ascii59@61..62 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "mypublication", + options: [], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "users", + inh: true, + relpersistence: "p", + alias: None, + location: 43, + }, + ), + where_clause: None, + columns: [], + }, + ), + location: 0, + }, + ), + ), + }, + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "departments", + inh: true, + relpersistence: "p", + alias: None, + location: 50, + }, + ), + where_clause: None, + columns: [], + }, + ), + location: 50, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..61, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@2.snap b/crates/parser/tests/snapshots/statements/valid/0053@2.snap new file mode 100644 index 00000000..9cba1ecd --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@2.snap @@ -0,0 +1,113 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: CREATE PUBLICATION active_departments FOR TABLE departments WHERE (active IS TRUE); +--- +Parse { + cst: SourceFile@0..83 + CreatePublicationStmt@0..83 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..37 "active_departments" + Whitespace@37..38 " " + For@38..41 "FOR" + Whitespace@41..42 " " + Table@42..47 "TABLE" + Whitespace@47..48 " " + PublicationObjSpec@48..81 + PublicationTable@48..81 + RangeVar@48..59 + Ident@48..59 "departments" + Whitespace@59..60 " " + Where@60..65 "WHERE" + Whitespace@65..66 " " + Ascii40@66..67 "(" + BooleanTest@67..81 + ColumnRef@67..73 + Ident@67..73 "active" + Whitespace@73..74 " " + Is@74..76 "IS" + Whitespace@76..77 " " + TrueP@77..81 "TRUE" + Ascii41@81..82 ")" + Ascii59@82..83 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "active_departments", + options: [], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "departments", + inh: true, + relpersistence: "p", + alias: None, + location: 48, + }, + ), + where_clause: Some( + Node { + node: Some( + BooleanTest( + BooleanTest { + xpr: None, + arg: Some( + Node { + node: Some( + ColumnRef( + ColumnRef { + fields: [ + Node { + node: Some( + String( + String { + sval: "active", + }, + ), + ), + }, + ], + location: 67, + }, + ), + ), + }, + ), + booltesttype: IsTrue, + location: 74, + }, + ), + ), + }, + ), + columns: [], + }, + ), + location: 0, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..82, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@3.snap b/crates/parser/tests/snapshots/statements/valid/0053@3.snap new file mode 100644 index 00000000..988c4acb --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@3.snap @@ -0,0 +1,35 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: CREATE PUBLICATION alltables FOR ALL TABLES; +--- +Parse { + cst: SourceFile@0..44 + CreatePublicationStmt@0..44 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..28 "alltables" + Whitespace@28..29 " " + For@29..32 "FOR" + Whitespace@32..33 " " + All@33..36 "ALL" + Whitespace@36..37 " " + Tables@37..43 "TABLES" + Ascii59@43..44 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "alltables", + options: [], + pubobjects: [], + for_all_tables: true, + }, + ), + range: 0..43, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@4.snap b/crates/parser/tests/snapshots/statements/valid/0053@4.snap new file mode 100644 index 00000000..73d2ab6b --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@4.snap @@ -0,0 +1,102 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE PUBLICATION insert_only FOR TABLE mydata WITH (publish = 'insert');" +--- +Parse { + cst: SourceFile@0..74 + CreatePublicationStmt@0..74 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..30 "insert_only" + Whitespace@30..31 " " + For@31..34 "FOR" + Whitespace@34..35 " " + Table@35..40 "TABLE" + Whitespace@40..41 " " + PublicationObjSpec@41..47 + PublicationTable@41..47 + RangeVar@41..47 + Ident@41..47 "mydata" + Whitespace@47..48 " " + With@48..52 "WITH" + Whitespace@52..53 " " + Ascii40@53..54 "(" + DefElem@54..72 + Ident@54..61 "publish" + Whitespace@61..62 " " + Ascii61@62..63 "=" + Whitespace@63..64 " " + Sconst@64..72 "'insert'" + Ascii41@72..73 ")" + Ascii59@73..74 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "insert_only", + options: [ + Node { + node: Some( + DefElem( + DefElem { + defnamespace: "", + defname: "publish", + arg: Some( + Node { + node: Some( + String( + String { + sval: "insert", + }, + ), + ), + }, + ), + defaction: DefelemUnspec, + location: 54, + }, + ), + ), + }, + ], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "mydata", + inh: true, + relpersistence: "p", + alias: None, + location: 41, + }, + ), + where_clause: None, + columns: [], + }, + ), + location: 0, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..73, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@5.snap b/crates/parser/tests/snapshots/statements/valid/0053@5.snap new file mode 100644 index 00000000..30366130 --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@5.snap @@ -0,0 +1,123 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE PUBLICATION production_publication FOR TABLE users, departments, TABLES IN SCHEMA production;" +--- +Parse { + cst: SourceFile@0..100 + CreatePublicationStmt@0..100 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..41 "production_publication" + Whitespace@41..42 " " + For@42..45 "FOR" + Whitespace@45..46 " " + Table@46..51 "TABLE" + Whitespace@51..52 " " + PublicationObjSpec@52..57 + PublicationTable@52..57 + RangeVar@52..57 + Ident@52..57 "users" + Ascii44@57..58 "," + Whitespace@58..59 " " + PublicationObjSpec@59..70 + PublicationTable@59..70 + RangeVar@59..70 + Ident@59..70 "departments" + Ascii44@70..71 "," + Whitespace@71..72 " " + Tables@72..78 "TABLES" + Whitespace@78..79 " " + InP@79..81 "IN" + Whitespace@81..82 " " + Schema@82..88 "SCHEMA" + Whitespace@88..89 " " + PublicationObjSpec@89..99 + Ident@89..99 "production" + Ascii59@99..100 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "production_publication", + options: [], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "users", + inh: true, + relpersistence: "p", + alias: None, + location: 52, + }, + ), + where_clause: None, + columns: [], + }, + ), + location: 0, + }, + ), + ), + }, + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "departments", + inh: true, + relpersistence: "p", + alias: None, + location: 59, + }, + ), + where_clause: None, + columns: [], + }, + ), + location: 59, + }, + ), + ), + }, + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTablesInSchema, + name: "production", + pubtable: None, + location: 89, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..99, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@6.snap b/crates/parser/tests/snapshots/statements/valid/0053@6.snap new file mode 100644 index 00000000..cf552bd2 --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@6.snap @@ -0,0 +1,69 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE PUBLICATION sales_publication FOR TABLES IN SCHEMA marketing, sales;" +--- +Parse { + cst: SourceFile@0..75 + CreatePublicationStmt@0..75 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..36 "sales_publication" + Whitespace@36..37 " " + For@37..40 "FOR" + Whitespace@40..41 " " + Tables@41..47 "TABLES" + Whitespace@47..48 " " + InP@48..50 "IN" + Whitespace@50..51 " " + Schema@51..57 "SCHEMA" + Whitespace@57..58 " " + PublicationObjSpec@58..67 + Ident@58..67 "marketing" + Ascii44@67..68 "," + Whitespace@68..69 " " + PublicationObjSpec@69..74 + Ident@69..74 "sales" + Ascii59@74..75 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "sales_publication", + options: [], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTablesInSchema, + name: "marketing", + pubtable: None, + location: 58, + }, + ), + ), + }, + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTablesInSchema, + name: "sales", + pubtable: None, + location: 69, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..74, + }, + ], +} diff --git a/crates/parser/tests/snapshots/statements/valid/0053@7.snap b/crates/parser/tests/snapshots/statements/valid/0053@7.snap new file mode 100644 index 00000000..a23e6d48 --- /dev/null +++ b/crates/parser/tests/snapshots/statements/valid/0053@7.snap @@ -0,0 +1,93 @@ +--- +source: crates/parser/tests/statement_parser_test.rs +description: "CREATE PUBLICATION users_filtered FOR TABLE users (user_id, firstname);" +--- +Parse { + cst: SourceFile@0..71 + CreatePublicationStmt@0..71 + Create@0..6 "CREATE" + Whitespace@6..7 " " + Publication@7..18 "PUBLICATION" + Whitespace@18..19 " " + Ident@19..33 "users_filtered" + Whitespace@33..34 " " + For@34..37 "FOR" + Whitespace@37..38 " " + Table@38..43 "TABLE" + Whitespace@43..44 " " + PublicationObjSpec@44..69 + PublicationTable@44..69 + RangeVar@44..49 + Ident@44..49 "users" + Whitespace@49..50 " " + Ascii40@50..51 "(" + Ident@51..58 "user_id" + Ascii44@58..59 "," + Whitespace@59..60 " " + Ident@60..69 "firstname" + Ascii41@69..70 ")" + Ascii59@70..71 ";" + , + errors: [], + stmts: [ + RawStmt { + stmt: CreatePublicationStmt( + CreatePublicationStmt { + pubname: "users_filtered", + options: [], + pubobjects: [ + Node { + node: Some( + PublicationObjSpec( + PublicationObjSpec { + pubobjtype: PublicationobjTable, + name: "", + pubtable: Some( + PublicationTable { + relation: Some( + RangeVar { + catalogname: "", + schemaname: "", + relname: "users", + inh: true, + relpersistence: "p", + alias: None, + location: 44, + }, + ), + where_clause: None, + columns: [ + Node { + node: Some( + String( + String { + sval: "user_id", + }, + ), + ), + }, + Node { + node: Some( + String( + String { + sval: "firstname", + }, + ), + ), + }, + ], + }, + ), + location: 0, + }, + ), + ), + }, + ], + for_all_tables: false, + }, + ), + range: 0..70, + }, + ], +}