@@ -253,6 +253,11 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
253253 LockRelationOid (partid , parts_storage -> head_open_lock_mode );
254254 if (!SearchSysCacheExists1 (RELOID , ObjectIdGetDatum (partid )))
255255 {
256+ /* Don't forget to drop invalid hash table entry */
257+ hash_search (parts_storage -> result_rels_table ,
258+ (const void * ) & partid ,
259+ HASH_REMOVE , NULL );
260+
256261 UnlockRelationOid (partid , parts_storage -> head_open_lock_mode );
257262 return NULL ;
258263 }
@@ -419,34 +424,50 @@ select_partition_for_insert(Datum value, Oid value_type,
419424{
420425 MemoryContext old_mcxt ;
421426 ResultRelInfoHolder * rri_holder ;
427+ Oid parent_relid = PrelParentRelid (prel );
422428 Oid selected_partid = InvalidOid ;
423429 Oid * parts ;
424430 int nparts ;
425431
426- /* Search for matching partitions */
427- parts = find_partitions_for_value (value , value_type , prel , & nparts );
428-
429- if (nparts > 1 )
430- elog (ERROR , ERR_PART_ATTR_MULTIPLE );
431- else if (nparts == 0 )
432+ do
432433 {
433- selected_partid = create_partitions_for_value ( PrelParentRelid ( prel ),
434- value , prel -> ev_type );
434+ /* Search for matching partitions */
435+ parts = find_partitions_for_value ( value , value_type , prel , & nparts );
435436
436- /* get_pathman_relation_info() will refresh this entry */
437- invalidate_pathman_relation_info (PrelParentRelid (prel ), NULL );
438- }
439- else selected_partid = parts [0 ];
437+ if (nparts > 1 )
438+ elog (ERROR , ERR_PART_ATTR_MULTIPLE );
439+ else if (nparts == 0 )
440+ {
441+ selected_partid = create_partitions_for_value (parent_relid ,
442+ value , prel -> ev_type );
440443
441- /* Replace parent table with a suitable partition */
442- old_mcxt = MemoryContextSwitchTo ( estate -> es_query_cxt );
443- rri_holder = scan_result_parts_storage ( selected_partid , parts_storage );
444- MemoryContextSwitchTo ( old_mcxt ) ;
444+ /* get_pathman_relation_info() will refresh this entry */
445+ invalidate_pathman_relation_info ( parent_relid , NULL );
446+ }
447+ else selected_partid = parts [ 0 ] ;
445448
446- /* Could not find suitable partition */
447- if (rri_holder == NULL )
448- elog (ERROR , ERR_PART_ATTR_NO_PART ,
449- datum_to_cstring (value , prel -> ev_type ));
449+ /* Replace parent table with a suitable partition */
450+ old_mcxt = MemoryContextSwitchTo (estate -> es_query_cxt );
451+ rri_holder = scan_result_parts_storage (selected_partid , parts_storage );
452+ MemoryContextSwitchTo (old_mcxt );
453+
454+ /* This partition has been dropped, repeat with a new 'prel' */
455+ if (rri_holder == NULL )
456+ {
457+ /* get_pathman_relation_info() will refresh this entry */
458+ invalidate_pathman_relation_info (parent_relid , NULL );
459+
460+ /* Get a fresh PartRelationInfo */
461+ prel = get_pathman_relation_info (parent_relid );
462+
463+ /* Paranoid check (all partitions have vanished) */
464+ if (!prel )
465+ elog (ERROR , "table \"%s\" is not partitioned" ,
466+ get_rel_name_or_relid (parent_relid ));
467+ }
468+ }
469+ /* Loop until we get some result */
470+ while (rri_holder == NULL );
450471
451472 return rri_holder ;
452473}
@@ -629,7 +650,10 @@ partition_filter_exec(CustomScanState *node)
629650 if (itemIsDone != ExprSingleResult )
630651 elog (ERROR , ERR_PART_ATTR_MULTIPLE_RESULTS );
631652
632- /* Search for a matching partition */
653+ /*
654+ * Search for a matching partition.
655+ * WARNING: 'prel' might change after this call!
656+ */
633657 rri_holder = select_partition_for_insert (value , prel -> ev_type , prel ,
634658 & state -> result_parts , estate );
635659
0 commit comments