@@ -233,6 +233,10 @@ fini_result_parts_storage(ResultPartsStorage *parts_storage)
233233
234234 free_conversion_map (rri_holder -> tuple_map );
235235 }
236+
237+ /* Don't forget to close 'prel'! */
238+ if (rri_holder -> prel )
239+ close_pathman_relation_info (rri_holder -> prel );
236240 }
237241
238242 /* Finally destroy hash table */
@@ -352,9 +356,18 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
352356 /* Generate tuple transformation map and some other stuff */
353357 rri_holder -> tuple_map = build_part_tuple_map (base_rel , child_rel );
354358
355- /* Are there subpartitions? */
356- rri_holder -> has_children = child_rel -> rd_rel -> relhassubclass ;
357- rri_holder -> expr_state = NULL ;
359+ /* Default values */
360+ rri_holder -> prel = NULL ;
361+ rri_holder -> prel_expr_state = NULL ;
362+
363+ if ((rri_holder -> prel = get_pathman_relation_info (partid )) != NULL )
364+ {
365+ rri_holder -> prel_expr_state =
366+ prepare_expr_state (rri_holder -> prel , /* NOTE: this prel! */
367+ parts_storage -> base_rri -> ri_RelationDesc ,
368+ parts_storage -> estate ,
369+ parts_storage -> command_type == CMD_UPDATE );
370+ }
358371
359372 /* Call initialization callback if needed */
360373 if (parts_storage -> init_rri_holder_cb )
@@ -452,29 +465,41 @@ ResultRelInfoHolder *
452465select_partition_for_insert (ResultPartsStorage * parts_storage ,
453466 TupleTableSlot * slot )
454467{
455- bool close_prel = false;
456468 PartRelationInfo * prel = parts_storage -> prel ;
457469 ExprState * expr_state = parts_storage -> prel_expr_state ;
458470 ExprContext * expr_context = parts_storage -> prel_econtext ;
471+
459472 Oid parent_relid = PrelParentRelid (prel ),
460473 partition_relid = InvalidOid ;
474+
475+ Datum value ;
476+ bool isnull ;
477+ bool compute_value = true;
478+
461479 Oid * parts ;
462480 int nparts ;
463- bool isnull ;
464- Datum value ;
465481 ResultRelInfoHolder * result ;
466482
467- parts_storage -> prel_econtext -> ecxt_scantuple = slot ;
483+ do
484+ {
485+ if (compute_value )
486+ {
487+ /* Prepare expression context */
488+ ResetExprContext (expr_context );
468489
469- /* Execute expression */
470- value = ExecEvalExprCompat (expr_state , expr_context ,
471- & isnull , mult_result_handler );
490+ /* Execute expression */
491+ expr_context -> ecxt_scantuple = slot ;
472492
473- if (isnull )
474- elog (ERROR , ERR_PART_ATTR_NULL );
493+ value = ExecEvalExprCompat (expr_state , expr_context ,
494+ & isnull , mult_result_handler );
495+
496+ if (isnull )
497+ elog (ERROR , ERR_PART_ATTR_NULL );
498+
499+ /* Ok, we have a value */
500+ compute_value = false;
501+ }
475502
476- do
477- {
478503 /* Search for matching partitions */
479504 parts = find_partitions_for_value (value , prel -> ev_type , prel , & nparts );
480505
@@ -492,28 +517,37 @@ select_partition_for_insert(ResultPartsStorage *parts_storage,
492517 /* Get ResultRelationInfo holder for the selected partition */
493518 result = scan_result_parts_storage (partition_relid , parts_storage );
494519
495- /* Should we close 'prel'? */
496- if (close_prel )
497- close_pathman_relation_info (prel );
498-
499- if (result == NULL || nparts == 0 )
520+ /* Somebody has dropped or created partitions */
521+ if (!PrelIsFresh (prel ) && (nparts == 0 || result == NULL ))
500522 {
501- /* This partition has been dropped | we have a new one */
523+ /* Compare original and current Oids */
524+ Oid relid1 = PrelParentRelid (parts_storage -> prel ),
525+ relid2 = PrelParentRelid (prel );
526+
527+ /* Reopen 'prel' to make it fresh again */
528+ close_pathman_relation_info (prel );
502529 prel = get_pathman_relation_info (parent_relid );
503- shout_if_prel_is_invalid (parent_relid , prel , PT_ANY );
504530
505- /* Store new 'prel' in 'parts_storage' */
506- close_pathman_relation_info (parts_storage -> prel );
507- parts_storage -> prel = prel ;
531+ /* Store new 'prel' */
532+ if (relid1 == relid2 )
533+ {
534+ shout_if_prel_is_invalid (parent_relid , prel , PT_ANY );
535+ parts_storage -> prel = prel ;
536+ }
537+ else if (result && result -> prel )
538+ /* TODO: WTF? this is a new RRI, not the one we used before */
539+ result -> prel = prel ;
508540 }
509- else if (result -> has_children )
541+
542+ /* This partition is a parent itself */
543+ if (result && result -> prel )
510544 {
511- /* This partition is a parent itself, repeat */
512- prel = get_pathman_relation_info ( partition_relid ) ;
513- shout_if_prel_is_invalid ( partition_relid , prel , PT_ANY );
514- close_prel = true;
545+ prel = result -> prel ;
546+ expr_state = result -> prel_expr_state ;
547+ parent_relid = PrelParentRelid ( prel );
548+ compute_value = true;
515549
516- /* We're not done yet */
550+ /* Repeat with a new dispatch */
517551 result = NULL ;
518552 }
519553 }
0 commit comments