@@ -12857,3 +12857,160 @@ fn display_alter_materialized_view_propagates_write_errors() {
1285712857 ) ;
1285812858 }
1285912859}
12860+
12861+ #[ test]
12862+ fn parse_create_foreign_table_partition_of ( ) {
12863+ let sql = "CREATE FOREIGN TABLE part PARTITION OF root FOR VALUES FROM (0) TO (10) SERVER s" ;
12864+ let Statement :: CreateForeignTable ( stmt) = pg_and_generic ( ) . verified_stmt ( sql) else {
12865+ unreachable ! ( )
12866+ } ;
12867+ assert_eq ! (
12868+ stmt. partition_of,
12869+ Some ( ObjectName :: from( vec![ Ident :: new( "root" ) ] ) )
12870+ ) ;
12871+ assert_eq ! (
12872+ stmt. for_values,
12873+ Some ( ForValues :: From {
12874+ from: vec![ PartitionBoundValue :: Expr ( Expr :: value( number( "0" ) ) ) ] ,
12875+ to: vec![ PartitionBoundValue :: Expr ( Expr :: value( number( "10" ) ) ) ] ,
12876+ } )
12877+ ) ;
12878+ assert ! ( stmt. columns. is_empty( ) ) ;
12879+
12880+ let sql = "CREATE FOREIGN TABLE part PARTITION OF public.root (id NOT NULL, CONSTRAINT positive CHECK (id > 0)) FOR VALUES FROM (MINVALUE) TO (MAXVALUE) SERVER s" ;
12881+ let Statement :: CreateForeignTable ( stmt) = pg_and_generic ( ) . verified_stmt ( sql) else {
12882+ unreachable ! ( )
12883+ } ;
12884+ assert_eq ! (
12885+ stmt. columns,
12886+ vec![ ColumnDef {
12887+ name: Ident :: new( "id" ) ,
12888+ data_type: DataType :: Unspecified ,
12889+ options: vec![ ColumnOptionDef {
12890+ name: None ,
12891+ option: ColumnOption :: NotNull ,
12892+ } ] ,
12893+ } ]
12894+ ) ;
12895+ assert_eq ! ( stmt. constraints. len( ) , 1 ) ;
12896+ assert_eq ! (
12897+ stmt. for_values,
12898+ Some ( ForValues :: From {
12899+ from: vec![ PartitionBoundValue :: MinValue ] ,
12900+ to: vec![ PartitionBoundValue :: MaxValue ] ,
12901+ } )
12902+ ) ;
12903+
12904+ for sql in [
12905+ "CREATE FOREIGN TABLE IF NOT EXISTS part PARTITION OF root DEFAULT SERVER s OPTIONS (table_name 'remote')" ,
12906+ "CREATE FOREIGN TABLE part PARTITION OF root (CONSTRAINT positive CHECK (id > 0)) FOR VALUES IN (1, 2) SERVER s" ,
12907+ "CREATE FOREIGN TABLE part PARTITION OF root FOR VALUES WITH (MODULUS 4, REMAINDER 0) SERVER s" ,
12908+ "CREATE FOREIGN TABLE part PARTITION OF root (id NOT NULL) FOR VALUES IN (3) SERVER s" ,
12909+ ] {
12910+ pg_and_generic ( ) . verified_stmt ( sql) ;
12911+ }
12912+
12913+ pg_and_generic ( ) . one_statement_parses_to (
12914+ "CREATE FOREIGN TABLE part PARTITION OF root (id WITH OPTIONS NOT NULL) DEFAULT SERVER s" ,
12915+ "CREATE FOREIGN TABLE part PARTITION OF root (id NOT NULL) DEFAULT SERVER s" ,
12916+ ) ;
12917+
12918+ for ( sql, expected) in [
12919+ (
12920+ "CREATE FOREIGN TABLE part PARTITION OF root SERVER s" ,
12921+ "Expected: FOR VALUES or DEFAULT after PARTITION OF, found: SERVER" ,
12922+ ) ,
12923+ (
12924+ "CREATE FOREIGN TABLE part PARTITION OF root DEFAULT INHERITS (other) SERVER s" ,
12925+ "Expected: SERVER, found: INHERITS" ,
12926+ ) ,
12927+ (
12928+ "CREATE FOREIGN TABLE part PARTITION OF root INHERITS (other) FOR VALUES IN (1) SERVER s" ,
12929+ "Expected: FOR VALUES or DEFAULT after PARTITION OF, found: INHERITS" ,
12930+ ) ,
12931+ (
12932+ "CREATE FOREIGN TABLE part PARTITION OF root FOR VALUES IN (1)" ,
12933+ "Expected: SERVER, found: EOF" ,
12934+ ) ,
12935+ (
12936+ "CREATE FOREIGN TABLE part PARTITION OF" ,
12937+ "Expected: identifier, found: EOF" ,
12938+ ) ,
12939+ (
12940+ "CREATE FOREIGN TABLE part PARTITION OF root FOR VALUES IN () SERVER s" ,
12941+ "Expected: at least one value, found: )" ,
12942+ ) ,
12943+ (
12944+ "CREATE FOREIGN TABLE part PARTITION OF root FOR VALUES SERVER s" ,
12945+ "Expected: IN, FROM, or WITH after FOR VALUES, found: SERVER" ,
12946+ ) ,
12947+ (
12948+ "CREATE FOREIGN TABLE part (id INT) PARTITION OF root DEFAULT SERVER s" ,
12949+ "Expected: SERVER, found: PARTITION" ,
12950+ ) ,
12951+ (
12952+ "CREATE FOREIGN TABLE part PARTITION OF root (id INT) DEFAULT SERVER s" ,
12953+ "Expected: ',' or ')' after column definition, found: INT" ,
12954+ ) ,
12955+ (
12956+ "CREATE FOREIGN TABLE part (id) SERVER s" ,
12957+ "Expected: a data type name, found: )" ,
12958+ ) ,
12959+ ] {
12960+ assert_eq ! (
12961+ pg_and_generic( )
12962+ . parse_sql_statements( sql)
12963+ . unwrap_err( )
12964+ . to_string( ) ,
12965+ format!( "sql parser error: {expected}" ) ,
12966+ "{sql}"
12967+ ) ;
12968+ }
12969+ }
12970+
12971+ #[ test]
12972+ #[ cfg( feature = "visitor" ) ]
12973+ fn visit_relations_create_foreign_table_partition_of ( ) {
12974+ let stmts = pg ( )
12975+ . parse_sql_statements ( "CREATE FOREIGN TABLE part PARTITION OF public.root DEFAULT SERVER s" )
12976+ . unwrap ( ) ;
12977+ let mut relations = vec ! [ ] ;
12978+ let _ = sqlparser:: ast:: visit_relations ( & stmts, |relation| {
12979+ relations. push ( relation. to_string ( ) ) ;
12980+ core:: ops:: ControlFlow :: < ( ) > :: Continue ( ( ) )
12981+ } ) ;
12982+ assert_eq ! ( relations, [ "part" , "public.root" ] ) ;
12983+ }
12984+
12985+ #[ test]
12986+ fn display_create_foreign_table_partition_of_propagates_formatter_errors ( ) {
12987+ use core:: fmt:: { self , Write } ;
12988+
12989+ struct RejectingWriter ( & ' static str ) ;
12990+
12991+ impl Write for RejectingWriter {
12992+ fn write_str ( & mut self , value : & str ) -> fmt:: Result {
12993+ if value == self . 0 {
12994+ Err ( fmt:: Error )
12995+ } else {
12996+ Ok ( ( ) )
12997+ }
12998+ }
12999+ }
13000+
13001+ let stmt = pg_and_generic ( ) . verified_stmt (
13002+ "CREATE FOREIGN TABLE part PARTITION OF root (id NOT NULL, CONSTRAINT positive CHECK (id > 0)) FOR VALUES IN (1) SERVER s" ,
13003+ ) ;
13004+ for rejected in [
13005+ "CREATE FOREIGN TABLE " ,
13006+ " PARTITION OF " ,
13007+ " (" ,
13008+ ", " ,
13009+ ")" ,
13010+ "FOR VALUES IN (" ,
13011+ " SERVER " ,
13012+ ] {
13013+ let mut writer = RejectingWriter ( rejected) ;
13014+ assert_eq ! ( write!( writer, "{stmt}" ) , Err ( fmt:: Error ) , "{rejected:?}" ) ;
13015+ }
13016+ }
0 commit comments