@@ -319,6 +319,11 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *parts_storage)
319319 /* Generate tuple transformation map and some other stuff */
320320 rri_holder -> tuple_map = build_part_tuple_map (parent_rel , child_rel );
321321
322+ /* Are there subpartitions? */
323+ rri_holder -> has_subpartitions =
324+ (get_pathman_relation_info (partid ) != NULL );
325+ rri_holder -> expr_state = NULL ;
326+
322327 /* Call on_new_rri_holder_callback() if needed */
323328 if (parts_storage -> on_new_rri_holder_callback )
324329 parts_storage -> on_new_rri_holder_callback (parts_storage -> estate ,
@@ -412,7 +417,7 @@ find_partitions_for_value(Datum value, Oid value_type,
412417 * Smart wrapper for scan_result_parts_storage().
413418 */
414419ResultRelInfoHolder *
415- select_partition_for_insert (Datum value , Oid value_type ,
420+ select_partition_for_insert (ExprContext * econtext , ExprState * expr_state ,
416421 const PartRelationInfo * prel ,
417422 ResultPartsStorage * parts_storage ,
418423 EState * estate )
@@ -422,9 +427,23 @@ select_partition_for_insert(Datum value, Oid value_type,
422427 Oid selected_partid = InvalidOid ;
423428 Oid * parts ;
424429 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 );
425444
426445 /* 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 );
428447
429448 if (nparts > 1 )
430449 elog (ERROR , ERR_PART_ATTR_MULTIPLE );
@@ -438,9 +457,57 @@ select_partition_for_insert(Datum value, Oid value_type,
438457 }
439458 else selected_partid = parts [0 ];
440459
460+ // subprel = get_pathman_relation_info(state->partitioned_table))
441461 /* Replace parent table with a suitable partition */
442462 old_mcxt = MemoryContextSwitchTo (estate -> es_query_cxt );
443463 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+
444511 MemoryContextSwitchTo (old_mcxt );
445512
446513 /* Could not find suitable partition */
@@ -598,9 +665,9 @@ partition_filter_exec(CustomScanState *node)
598665 MemoryContext old_mcxt ;
599666 const PartRelationInfo * prel ;
600667 ResultRelInfoHolder * rri_holder ;
601- bool isnull ;
602- Datum value ;
603- ExprDoneCond itemIsDone ;
668+ // bool isnull;
669+ // Datum value;
670+ // ExprDoneCond itemIsDone;
604671 TupleTableSlot * tmp_slot ;
605672
606673 /* Fetch PartRelationInfo for this partitioned relation */
@@ -618,22 +685,15 @@ partition_filter_exec(CustomScanState *node)
618685 /* Switch to per-tuple context */
619686 old_mcxt = MemoryContextSwitchTo (GetPerTupleMemoryContext (estate ));
620687
621- /* Execute expression */
622688 tmp_slot = econtext -> ecxt_scantuple ;
623689 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 );
632690
633691 /* 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 ,
635693 & state -> result_parts , estate );
636694
695+ econtext -> ecxt_scantuple = tmp_slot ;
696+
637697 /* Switch back and clean up per-tuple context */
638698 MemoryContextSwitchTo (old_mcxt );
639699 ResetExprContext (econtext );
0 commit comments