@@ -23,7 +23,7 @@ use super::utils;
2323// Fdw private state for modify
2424struct FdwModifyState < E : Into < ErrorReport > , W : ForeignDataWrapper < E > > {
2525 // foreign data wrapper instance
26- instance : W ,
26+ instance : Option < W > ,
2727
2828 // row id attribute number and type id
2929 rowid_name : String ,
@@ -45,7 +45,7 @@ struct FdwModifyState<E: Into<ErrorReport>, W: ForeignDataWrapper<E>> {
4545impl < E : Into < ErrorReport > , W : ForeignDataWrapper < E > > FdwModifyState < E , W > {
4646 unsafe fn new ( foreigntableid : Oid , tmp_ctx : MemoryContext ) -> Self {
4747 Self {
48- instance : instance:: create_fdw_instance_from_table_id ( foreigntableid) ,
48+ instance : Some ( instance:: create_fdw_instance_from_table_id ( foreigntableid) ) ,
4949 rowid_name : String :: default ( ) ,
5050 rowid_attno : 0 ,
5151 rowid_typid : Oid :: INVALID ,
@@ -58,28 +58,69 @@ impl<E: Into<ErrorReport>, W: ForeignDataWrapper<E>> FdwModifyState<E, W> {
5858 }
5959
6060 fn begin_modify ( & mut self ) -> Result < ( ) , E > {
61- self . instance . begin_modify ( & self . opts )
61+ if let Some ( ref mut instance) = self . instance {
62+ instance. begin_modify ( & self . opts )
63+ } else {
64+ Ok ( ( ) )
65+ }
6266 }
6367
6468 fn insert ( & mut self , row : & Row ) -> Result < ( ) , E > {
65- self . instance . insert ( row)
69+ if let Some ( ref mut instance) = self . instance {
70+ instance. insert ( row)
71+ } else {
72+ Ok ( ( ) )
73+ }
6674 }
6775
6876 fn update ( & mut self , rowid : & Cell , new_row : & Row ) -> Result < ( ) , E > {
69- self . instance . update ( rowid, new_row)
77+ if let Some ( ref mut instance) = self . instance {
78+ instance. update ( rowid, new_row)
79+ } else {
80+ Ok ( ( ) )
81+ }
7082 }
7183
7284 fn delete ( & mut self , rowid : & Cell ) -> Result < ( ) , E > {
73- self . instance . delete ( rowid)
85+ if let Some ( ref mut instance) = self . instance {
86+ instance. delete ( rowid)
87+ } else {
88+ Ok ( ( ) )
89+ }
7490 }
7591
7692 fn end_modify ( & mut self ) -> Result < ( ) , E > {
77- self . instance . end_modify ( )
93+ if let Some ( ref mut instance) = self . instance {
94+ instance. end_modify ( )
95+ } else {
96+ Ok ( ( ) )
97+ }
7898 }
7999}
80100
81101impl < E : Into < ErrorReport > , W : ForeignDataWrapper < E > > utils:: SerdeList for FdwModifyState < E , W > { }
82102
103+ impl < E : Into < ErrorReport > , W : ForeignDataWrapper < E > > Drop for FdwModifyState < E , W > {
104+ fn drop ( & mut self ) {
105+ // drop foreign data wrapper instance
106+ self . instance . take ( ) ;
107+
108+ // remove the allocated memory context
109+ unsafe {
110+ memctx:: delete_wrappers_memctx ( self . tmp_ctx ) ;
111+ self . tmp_ctx = ptr:: null :: < MemoryContextData > ( ) as _ ;
112+ }
113+ }
114+ }
115+
116+ // drop the modify state, so the inner fdw instance can be dropped too
117+ unsafe fn drop_fdw_modify_state < E : Into < ErrorReport > , W : ForeignDataWrapper < E > > (
118+ fdw_state : * mut FdwModifyState < E , W > ,
119+ ) {
120+ let boxed_fdw_state = Box :: from_raw ( fdw_state) ;
121+ drop ( boxed_fdw_state) ;
122+ }
123+
83124// find rowid column in relation description
84125unsafe fn find_rowid_column (
85126 target_relation : pg_sys:: Relation ,
@@ -291,7 +332,11 @@ pub(super) extern "C-unwind" fn begin_foreign_modify<
291332 state. rowid_attno =
292333 pg_sys:: ExecFindJunkAttributeInTlist ( ( * subplan) . targetlist , rowid_name_c) ;
293334
294- state. begin_modify ( ) . report_unwrap ( ) ;
335+ let result = state. begin_modify ( ) ;
336+ if result. is_err ( ) {
337+ drop_fdw_modify_state ( state. as_ptr ( ) ) ;
338+ result. report_unwrap ( ) ;
339+ }
295340
296341 ( * rinfo) . ri_FdwState = state. into_pg ( ) as _ ;
297342 }
@@ -315,7 +360,12 @@ pub(super) extern "C-unwind" fn exec_foreign_insert<
315360
316361 PgMemoryContexts :: For ( state. tmp_ctx ) . switch_to ( |_| {
317362 let row = utils:: tuple_table_slot_to_row ( slot) ;
318- state. insert ( & row) . report_unwrap ( ) ;
363+ let result = state. insert ( & row) ;
364+ if result. is_err ( ) {
365+ drop_fdw_modify_state ( state. as_ptr ( ) ) ;
366+ ( * rinfo) . ri_FdwState = ptr:: null :: < FdwModifyState < E , W > > ( ) as _ ;
367+ result. report_unwrap ( ) ;
368+ }
319369 } ) ;
320370 }
321371
@@ -350,7 +400,12 @@ pub(super) extern "C-unwind" fn exec_foreign_delete<
350400 PgMemoryContexts :: For ( state. tmp_ctx ) . switch_to ( |_| {
351401 let cell = get_rowid_cell ( & state, plan_slot) ;
352402 if let Some ( rowid) = cell {
353- state. delete ( & rowid) . report_unwrap ( ) ;
403+ let result = state. delete ( & rowid) ;
404+ if result. is_err ( ) {
405+ drop_fdw_modify_state ( state. as_ptr ( ) ) ;
406+ ( * rinfo) . ri_FdwState = ptr:: null :: < FdwModifyState < E , W > > ( ) as _ ;
407+ result. report_unwrap ( ) ;
408+ }
354409 }
355410 } ) ;
356411 }
@@ -399,7 +454,12 @@ pub(super) extern "C-unwind" fn exec_foreign_update<
399454 }
400455 } ) ;
401456
402- state. update ( & rowid, & new_row) . report_unwrap ( ) ;
457+ let result = state. update ( & rowid, & new_row) ;
458+ if result. is_err ( ) {
459+ drop_fdw_modify_state ( state. as_ptr ( ) ) ;
460+ ( * rinfo) . ri_FdwState = ptr:: null :: < FdwModifyState < E , W > > ( ) as _ ;
461+ result. report_unwrap ( ) ;
462+ }
403463 }
404464 } ) ;
405465 }
@@ -426,16 +486,10 @@ pub(super) extern "C-unwind" fn end_foreign_modify<
426486 // here just to tell PgBox don't free the state, instead we will handle
427487 // drop the state by ourselves
428488 let mut state = PgBox :: < FdwModifyState < E , W > > :: from_pg ( fdw_state) ;
429- state. end_modify ( ) . report_unwrap ( ) ;
430-
431- // remove the allocated memory context
432- memctx:: delete_wrappers_memctx ( state. tmp_ctx ) ;
433- state. tmp_ctx = ptr:: null :: < MemoryContextData > ( ) as _ ;
434-
489+ let result = state. end_modify ( ) ;
490+ drop_fdw_modify_state ( state. as_ptr ( ) ) ;
435491 ( * rinfo) . ri_FdwState = ptr:: null :: < FdwModifyState < E , W > > ( ) as _ ;
436492
437- // drop the scan state, so the fdw instance can be dropped too
438- let boxed_fdw_state = Box :: from_raw ( fdw_state) ;
439- drop ( boxed_fdw_state) ;
493+ result. report_unwrap ( ) ;
440494 }
441495}
0 commit comments