@@ -10,6 +10,7 @@ CustomExecMethodspartition_filter_exec_methods;
10
10
11
11
12
12
static List * pfilter_build_tlist (List * tlist );
13
+ static ResultRelInfo * getResultRelInfo (Oid partid ,PartitionFilterState * state );
13
14
14
15
void
15
16
init_partition_filter_static_data (void )
@@ -39,7 +40,8 @@ init_partition_filter_static_data(void)
39
40
}
40
41
41
42
Plan *
42
- make_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
43
+ make_partition_filter_plan (Plan * subplan ,Oid partitioned_table ,
44
+ OnConflictAction conflict_action )
43
45
{
44
46
CustomScan * cscan = makeNode (CustomScan );
45
47
@@ -57,8 +59,9 @@ make_partition_filter_plan(Plan *subplan, PartRelationInfo *prel)
57
59
cscan -> scan .scanrelid = 0 ;
58
60
cscan -> custom_scan_tlist = subplan -> targetlist ;
59
61
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 );
62
65
63
66
return & cscan -> scan .plan ;
64
67
}
@@ -76,6 +79,11 @@ partition_filter_create_scan_state(CustomScan *node)
76
79
/* Extract necessary variables */
77
80
state -> subplan = (Plan * )linitial (node -> custom_plans );
78
81
state -> 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 );
79
87
80
88
/* Prepare dummy Const node */
81
89
NodeSetTag (& state -> temp_const ,T_Const );
@@ -89,9 +97,21 @@ partition_filter_begin(CustomScanState *node, EState *estate, int eflags)
89
97
{
90
98
PartitionFilterState * state = (PartitionFilterState * )node ;
91
99
100
+ HTAB * result_rels_table ;
101
+ HASHCTL * result_rels_table_config = & state -> result_rels_table_config ;
102
+
92
103
node -> custom_ps = list_make1 (ExecInitNode (state -> subplan ,estate ,eflags ));
93
104
state -> 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 ;
95
115
}
96
116
97
117
TupleTableSlot *
@@ -107,14 +127,15 @@ partition_filter_exec(CustomScanState *node)
107
127
PlanState * child_ps = (PlanState * )linitial (node -> custom_ps );
108
128
TupleTableSlot * slot ;
109
129
110
- if (state -> firstStart )
111
- state -> savedRelInfo = estate -> es_result_relation_info ;
112
-
113
130
slot = ExecProcNode (child_ps );
114
131
115
132
if (!TupIsNull (slot ))
116
133
{
117
134
WalkerContext wcxt ;
135
+ List * ranges ;
136
+ int nparts ;
137
+ Oid * parts ;
138
+
118
139
bool isnull ;
119
140
AttrNumber attnum = state -> prel -> attnum ;
120
141
Datum value = slot_getattr (slot ,attnum ,& isnull );
@@ -133,9 +154,11 @@ partition_filter_exec(CustomScanState *node)
133
154
wcxt .hasLeast = false;
134
155
wcxt .hasGreatest = false;
135
156
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 */
137
160
138
- /* estate->es_result_relation_info =NULL; */
161
+ estate -> es_result_relation_info = getResultRelInfo ( parts [ 0 ], state );
139
162
140
163
return slot ;
141
164
}
@@ -146,8 +169,22 @@ partition_filter_exec(CustomScanState *node)
146
169
void
147
170
partition_filter_end (CustomScanState * node )
148
171
{
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 );
150
186
187
+ Assert (list_length (node -> custom_ps )== 1 );
151
188
ExecEndNode ((PlanState * )linitial (node -> custom_ps ));
152
189
}
153
190
@@ -165,6 +202,34 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
165
202
/* Nothing to do here now */
166
203
}
167
204
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
+
168
233
/*
169
234
* Build partition filter's target list pointing to subplan tuple's elements
170
235
*/
@@ -212,9 +277,12 @@ add_partition_filters(List *rtable, ModifyTable *modify_table)
212
277
forboth (lc1 ,modify_table -> plans ,lc2 ,modify_table -> resultRelations )
213
278
{
214
279
Index 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
+
217
283
if (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 );
219
287
}
220
288
}