@@ -319,6 +319,11 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
319
319
/* Generate tuple transformation map and some other stuff */
320
320
rri_holder -> tuple_map = build_part_tuple_map (parent_rel , child_rel );
321
321
322
+ /* Are there subpartitions? */
323
+ rri_holder -> has_subpartitions =
324
+ (get_pathman_relation_info (partid ) != NULL );
325
+ rri_holder -> expr_state = NULL ;
326
+
322
327
/* Call on_new_rri_holder_callback() if needed */
323
328
if (parts_storage -> on_new_rri_holder_callback )
324
329
parts_storage -> on_new_rri_holder_callback (parts_storage -> estate ,
@@ -412,7 +417,7 @@ find_partitions_for_value(Datum value, Oid value_type,
412
417
* Smart wrapper for scan_result_parts_storage().
413
418
*/
414
419
ResultRelInfoHolder *
415
- select_partition_for_insert (Datum value , Oid value_type ,
420
+ select_partition_for_insert (ExprContext * econtext , ExprState * expr_state ,
416
421
const PartRelationInfo * prel ,
417
422
ResultPartsStorage * parts_storage ,
418
423
EState * estate )
@@ -422,9 +427,23 @@ select_partition_for_insert(Datum value, Oid value_type,
422
427
Oid selected_partid = InvalidOid ;
423
428
Oid * parts ;
424
429
int nparts ;
430
+ TupleTableSlot * tmp_slot ;
431
+ // const PartRelationInfo *subprel;
432
+ bool isnull ;
433
+ ExprDoneCond itemIsDone ;
434
+ Datum value ;
435
+
436
+ /* Execute expression */
437
+ value = ExecEvalExpr (expr_state , econtext , & isnull , & itemIsDone );
438
+
439
+ if (isnull )
440
+ elog (ERROR , ERR_PART_ATTR_NULL );
441
+
442
+ if (itemIsDone != ExprSingleResult )
443
+ elog (ERROR , ERR_PART_ATTR_MULTIPLE_RESULTS );
425
444
426
445
/* Search for matching partitions */
427
- parts = find_partitions_for_value (value , value_type , prel , & nparts );
446
+ parts = find_partitions_for_value (value , prel -> atttype , prel , & nparts );
428
447
429
448
if (nparts > 1 )
430
449
elog (ERROR , ERR_PART_ATTR_MULTIPLE );
@@ -438,9 +457,57 @@ select_partition_for_insert(Datum value, Oid value_type,
438
457
}
439
458
else selected_partid = parts [0 ];
440
459
460
+ // subprel = get_pathman_relation_info(state->partitioned_table))
441
461
/* Replace parent table with a suitable partition */
442
462
old_mcxt = MemoryContextSwitchTo (estate -> es_query_cxt );
443
463
rri_holder = scan_result_parts_storage (selected_partid , parts_storage );
464
+
465
+ /* If partition has subpartitions */
466
+ if (rri_holder -> has_subpartitions )
467
+ {
468
+ const PartRelationInfo * subprel ;
469
+
470
+ /* Fetch PartRelationInfo for this partitioned relation */
471
+ subprel = get_pathman_relation_info (selected_partid );
472
+ Assert (subprel != NULL );
473
+
474
+ /* Build an expression state if not yet */
475
+ if (!rri_holder -> expr_state )
476
+ {
477
+ MemoryContext tmp_mcxt ;
478
+ Node * expr ;
479
+ Index varno = 1 ;
480
+ ListCell * lc ;
481
+
482
+ /* Change varno in Vars according to range table */
483
+ expr = copyObject (subprel -> expr );
484
+ foreach (lc , estate -> es_range_table )
485
+ {
486
+ RangeTblEntry * entry = lfirst (lc );
487
+ if (entry -> relid == selected_partid )
488
+ {
489
+ if (varno > 1 )
490
+ ChangeVarNodes (expr , 1 , varno , 0 );
491
+ break ;
492
+ }
493
+ varno += 1 ;
494
+ }
495
+
496
+ /* Prepare state for expression execution */
497
+ tmp_mcxt = MemoryContextSwitchTo (estate -> es_query_cxt );
498
+ rri_holder -> expr_state = ExecInitExpr ((Expr * ) expr , NULL );
499
+ MemoryContextSwitchTo (tmp_mcxt );
500
+ }
501
+
502
+ Assert (rri_holder -> expr_state != NULL );
503
+
504
+ /* Dive in */
505
+ rri_holder = select_partition_for_insert (econtext , rri_holder -> expr_state ,
506
+ subprel ,
507
+ parts_storage ,
508
+ estate );
509
+ }
510
+
444
511
MemoryContextSwitchTo (old_mcxt );
445
512
446
513
/* Could not find suitable partition */
@@ -598,9 +665,9 @@ partition_filter_exec(CustomScanState *node)
598
665
MemoryContext old_mcxt ;
599
666
const PartRelationInfo * prel ;
600
667
ResultRelInfoHolder * rri_holder ;
601
- bool isnull ;
602
- Datum value ;
603
- ExprDoneCond itemIsDone ;
668
+ // bool isnull;
669
+ // Datum value;
670
+ // ExprDoneCond itemIsDone;
604
671
TupleTableSlot * tmp_slot ;
605
672
606
673
/* Fetch PartRelationInfo for this partitioned relation */
@@ -618,22 +685,15 @@ partition_filter_exec(CustomScanState *node)
618
685
/* Switch to per-tuple context */
619
686
old_mcxt = MemoryContextSwitchTo (GetPerTupleMemoryContext (estate ));
620
687
621
- /* Execute expression */
622
688
tmp_slot = econtext -> ecxt_scantuple ;
623
689
econtext -> ecxt_scantuple = slot ;
624
- value = ExecEvalExpr (state -> expr_state , econtext , & isnull , & itemIsDone );
625
- econtext -> ecxt_scantuple = tmp_slot ;
626
-
627
- if (isnull )
628
- elog (ERROR , ERR_PART_ATTR_NULL );
629
-
630
- if (itemIsDone != ExprSingleResult )
631
- elog (ERROR , ERR_PART_ATTR_MULTIPLE_RESULTS );
632
690
633
691
/* Search for a matching partition */
634
- rri_holder = select_partition_for_insert (value , prel -> atttype , prel ,
692
+ rri_holder = select_partition_for_insert (econtext , state -> expr_state , prel ,
635
693
& state -> result_parts , estate );
636
694
695
+ econtext -> ecxt_scantuple = tmp_slot ;
696
+
637
697
/* Switch back and clean up per-tuple context */
638
698
MemoryContextSwitchTo (old_mcxt );
639
699
ResetExprContext (econtext );
0 commit comments