@@ -10,6 +10,7 @@ CustomExecMethodspartition_filter_exec_methods;
1010
1111
1212static List * pfilter_build_tlist (List * tlist );
13+ static ResultRelInfo * getResultRelInfo (Oid partid ,PartitionFilterState * state );
1314
1415void
1516init_partition_filter_static_data (void )
@@ -39,7 +40,8 @@ init_partition_filter_static_data(void)
3940}
4041
4142Plan *
42- make_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
43+ make_partition_filter_plan (Plan * subplan ,Oid partitioned_table ,
44+ OnConflictAction conflict_action )
4345{
4446CustomScan * cscan = makeNode (CustomScan );
4547
@@ -57,8 +59,9 @@ make_partition_filter_plan(Plan *subplan, PartRelationInfo *prel)
5759cscan -> scan .scanrelid = 0 ;
5860cscan -> custom_scan_tlist = subplan -> targetlist ;
5961
60- /* Save partitioned table's Oid */
61- cscan -> custom_private = list_make1_int (prel -> key .relid );
62+ /* Pack partitioned table's Oid and conflict_action */
63+ cscan -> custom_private = list_make2_int (partitioned_table ,
64+ conflict_action );
6265
6366return & cscan -> scan .plan ;
6467}
@@ -76,6 +79,11 @@ partition_filter_create_scan_state(CustomScan *node)
7679/* Extract necessary variables */
7780state -> subplan = (Plan * )linitial (node -> custom_plans );
7881state -> partitioned_table = linitial_int (node -> custom_private );
82+ state -> onConflictAction = lsecond_int (node -> custom_private );
83+
84+ /* Check boundaries */
85+ Assert (state -> onConflictAction >=ONCONFLICT_NONE ||
86+ state -> onConflictAction <=ONCONFLICT_UPDATE );
7987
8088/* Prepare dummy Const node */
8189NodeSetTag (& state -> temp_const ,T_Const );
@@ -89,9 +97,21 @@ partition_filter_begin(CustomScanState *node, EState *estate, int eflags)
8997{
9098PartitionFilterState * state = (PartitionFilterState * )node ;
9199
100+ HTAB * result_rels_table ;
101+ HASHCTL * result_rels_table_config = & state -> result_rels_table_config ;
102+
92103node -> custom_ps = list_make1 (ExecInitNode (state -> subplan ,estate ,eflags ));
93104state -> prel = get_pathman_relation_info (state -> partitioned_table ,NULL );
94- state -> firstStart = true;
105+
106+ memset (result_rels_table_config ,0 ,sizeof (HASHCTL ));
107+ result_rels_table_config -> keysize = sizeof (Oid );
108+ result_rels_table_config -> entrysize = sizeof (ResultRelInfoHandle );
109+
110+ result_rels_table = hash_create ("ResultRelInfo storage" ,10 ,
111+ result_rels_table_config ,
112+ HASH_ELEM |HASH_BLOBS );
113+
114+ state -> result_rels_table = result_rels_table ;
95115}
96116
97117TupleTableSlot *
@@ -107,14 +127,15 @@ partition_filter_exec(CustomScanState *node)
107127PlanState * child_ps = (PlanState * )linitial (node -> custom_ps );
108128TupleTableSlot * slot ;
109129
110- if (state -> firstStart )
111- state -> savedRelInfo = estate -> es_result_relation_info ;
112-
113130slot = ExecProcNode (child_ps );
114131
115132if (!TupIsNull (slot ))
116133{
117134WalkerContext wcxt ;
135+ List * ranges ;
136+ int nparts ;
137+ Oid * parts ;
138+
118139bool isnull ;
119140AttrNumber attnum = state -> prel -> attnum ;
120141Datum value = slot_getattr (slot ,attnum ,& isnull );
@@ -133,9 +154,11 @@ partition_filter_exec(CustomScanState *node)
133154wcxt .hasLeast = false;
134155wcxt .hasGreatest = false;
135156
136- walk_expr_tree ((Expr * )& state -> temp_const ,& wcxt );
157+ ranges = walk_expr_tree ((Expr * )& state -> temp_const ,& wcxt )-> rangeset ;
158+ parts = get_partition_oids (ranges ,& nparts ,state -> prel );
159+ Assert (nparts == 1 );/* there has to be only 1 partition */
137160
138- /* estate->es_result_relation_info =NULL; */
161+ estate -> es_result_relation_info = getResultRelInfo ( parts [ 0 ], state );
139162
140163return slot ;
141164}
@@ -146,8 +169,22 @@ partition_filter_exec(CustomScanState *node)
146169void
147170partition_filter_end (CustomScanState * node )
148171{
149- Assert (list_length (node -> custom_ps )== 1 );
172+ PartitionFilterState * state = (PartitionFilterState * )node ;
173+
174+ HASH_SEQ_STATUS stat ;
175+ ResultRelInfoHandle * rri_handle ;
176+
177+ hash_seq_init (& stat ,state -> result_rels_table );
178+ while ((rri_handle = (ResultRelInfoHandle * )hash_seq_search (& stat ))!= NULL )
179+ {
180+ ExecCloseIndices (rri_handle -> resultRelInfo );
181+ heap_close (rri_handle -> resultRelInfo -> ri_RelationDesc ,
182+ RowExclusiveLock );
183+ }
184+
185+ hash_destroy (state -> result_rels_table );
150186
187+ Assert (list_length (node -> custom_ps )== 1 );
151188ExecEndNode ((PlanState * )linitial (node -> custom_ps ));
152189}
153190
@@ -165,6 +202,34 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
165202/* Nothing to do here now */
166203}
167204
205+
206+ static ResultRelInfo *
207+ getResultRelInfo (Oid partid ,PartitionFilterState * state )
208+ {
209+ ResultRelInfoHandle * resultRelInfoHandle ;
210+ bool found ;
211+
212+ resultRelInfoHandle = hash_search (state -> result_rels_table ,
213+ (const void * )& partid ,
214+ HASH_ENTER ,& found );
215+
216+ if (!found )
217+ {
218+ ResultRelInfo * resultRelInfo = (ResultRelInfo * )palloc (sizeof (ResultRelInfo ));
219+ InitResultRelInfo (resultRelInfo ,
220+ heap_open (partid ,RowExclusiveLock ),
221+ 0 ,
222+ state -> css .ss .ps .state -> es_instrument );
223+
224+ ExecOpenIndices (resultRelInfo ,state -> onConflictAction != ONCONFLICT_NONE );
225+
226+ resultRelInfoHandle -> partid = partid ;
227+ resultRelInfoHandle -> resultRelInfo = resultRelInfo ;
228+ }
229+
230+ return resultRelInfoHandle -> resultRelInfo ;
231+ }
232+
168233/*
169234 * Build partition filter's target list pointing to subplan tuple's elements
170235 */
@@ -212,9 +277,12 @@ add_partition_filters(List *rtable, ModifyTable *modify_table)
212277forboth (lc1 ,modify_table -> plans ,lc2 ,modify_table -> resultRelations )
213278{
214279Index rindex = lfirst_int (lc2 );
215- PartRelationInfo * prel = get_pathman_relation_info (getrelid (rindex ,rtable ),
216- NULL );
280+ Oid relid = getrelid (rindex ,rtable );
281+ PartRelationInfo * prel = get_pathman_relation_info (relid ,NULL );
282+
217283if (prel )
218- lfirst (lc1 )= make_partition_filter_plan ((Plan * )lfirst (lc1 ),prel );
284+ lfirst (lc1 )= make_partition_filter_plan ((Plan * )lfirst (lc1 ),
285+ relid ,
286+ modify_table -> onConflictAction );
219287}
220288}