|
19 | 19 | #include"catalog/pg_type.h" |
20 | 20 | #include"foreign/fdwapi.h" |
21 | 21 | #include"foreign/foreign.h" |
| 22 | +#include"miscadmin.h" |
22 | 23 | #include"nodes/nodeFuncs.h" |
23 | 24 | #include"rewrite/rewriteManip.h" |
24 | 25 | #include"utils/guc.h" |
@@ -239,6 +240,9 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage) |
239 | 240 | (constvoid*)&partid, |
240 | 241 | HASH_ENTER,&found); |
241 | 242 |
|
| 243 | +/* Don't execute recheck_partition_for_value() every time */ |
| 244 | +rri_holder->first_time= !found; |
| 245 | + |
242 | 246 | /* If not found, create & cache new ResultRelInfo */ |
243 | 247 | if (!found) |
244 | 248 | { |
@@ -432,43 +436,52 @@ select_partition_for_insert(Datum value, Oid value_type, |
432 | 436 |
|
433 | 437 | do |
434 | 438 | { |
| 439 | +boolrefresh_prel; |
| 440 | + |
435 | 441 | /* Search for matching partitions */ |
436 | 442 | parts=find_partitions_for_value(value,value_type,prel,&nparts); |
437 | 443 |
|
438 | 444 | if (nparts>1) |
439 | 445 | elog(ERROR,ERR_PART_ATTR_MULTIPLE); |
440 | 446 | elseif (nparts==0) |
441 | 447 | { |
442 | | -selected_partid=create_partitions_for_value(parent_relid, |
443 | | -value,value_type); |
| 448 | +selected_partid=create_partitions_for_value(parent_relid, |
| 449 | +value,value_type); |
444 | 450 |
|
445 | | -/* get_pathman_relation_info() will refresh this entry */ |
446 | | -invalidate_pathman_relation_info(parent_relid,NULL); |
| 451 | +/* get_pathman_relation_info() will refresh this entry */ |
| 452 | +invalidate_pathman_relation_info(parent_relid,NULL); |
447 | 453 | } |
448 | 454 | elseselected_partid=parts[0]; |
449 | 455 |
|
450 | | -/* Replace parent table with a suitable partition */ |
| 456 | +pfree(parts); |
| 457 | + |
| 458 | +/* Get ResultRelationInfo of a suitable partition (may invalidate 'prel') */ |
451 | 459 | old_mcxt=MemoryContextSwitchTo(estate->es_query_cxt); |
452 | 460 | rri_holder=scan_result_parts_storage(selected_partid,parts_storage); |
453 | 461 | MemoryContextSwitchTo(old_mcxt); |
454 | 462 |
|
455 | | -/* This partition has been dropped, repeat with a new 'prel' */ |
456 | | -if (rri_holder==NULL) |
| 463 | +/* |
| 464 | + * We'd like to refresh PartRelationInfo if: |
| 465 | + *1) Partition we've just chosen had been removed; |
| 466 | + *2) It changed and we've chosen a visible partition for the 1st time. |
| 467 | + */ |
| 468 | +refresh_prel= !PointerIsValid(rri_holder)|| |
| 469 | + (!PrelIsValid(prel)&&rri_holder->first_time&&nparts>0); |
| 470 | + |
| 471 | +if (refresh_prel) |
457 | 472 | { |
458 | | -/* get_pathman_relation_info() will refresh this entry */ |
459 | 473 | invalidate_pathman_relation_info(parent_relid,NULL); |
460 | 474 |
|
461 | 475 | /* Get a fresh PartRelationInfo */ |
462 | 476 | prel=get_pathman_relation_info(parent_relid); |
| 477 | +shout_if_prel_is_invalid(parent_relid,prel,PT_ANY); |
463 | 478 |
|
464 | | -/* Paranoid check (all partitions have vanished) */ |
465 | | -if (!prel) |
466 | | -elog(ERROR,"table \"%s\" is not partitioned", |
467 | | -get_rel_name_or_relid(parent_relid)); |
| 479 | +/* Reset selected partition */ |
| 480 | +rri_holder=NULL; |
468 | 481 | } |
469 | 482 | } |
470 | 483 | /* Loop until we get some result */ |
471 | | -while (rri_holder==NULL); |
| 484 | +while (!PointerIsValid(rri_holder)); |
472 | 485 |
|
473 | 486 | returnrri_holder; |
474 | 487 | } |
|