19
19
#include "utils/lsyscache.h"
20
20
21
21
22
+ #define ALLOC_EXP 2
23
+
24
+
22
25
bool pg_pathman_enable_partition_filter = true;
23
26
24
27
CustomScanMethods partition_filter_plan_methods ;
@@ -27,6 +30,7 @@ CustomExecMethodspartition_filter_exec_methods;
27
30
28
31
static void partition_filter_visitor (Plan * plan ,void * context );
29
32
static List * pfilter_build_tlist (List * tlist );
33
+ static int append_rri_to_estate (EState * estate ,ResultRelInfo * rri ,int cur_allocated );
30
34
31
35
32
36
void
@@ -86,7 +90,7 @@ check_acl_for_partition(EState *estate,
86
90
rte -> relkind = part_rel -> rd_rel -> relkind ;
87
91
rte -> requiredPerms = ACL_INSERT ;
88
92
89
- /* Check permissions for current partition */
93
+ /*FIXME: Check permissions for partition */
90
94
ExecCheckRTPerms (list_make1 (rte ), true);
91
95
92
96
/* TODO: append RTE to estate->es_range_table */
@@ -125,40 +129,51 @@ init_result_parts_storage(ResultPartsStorage *parts_storage,
125
129
126
130
parts_storage -> on_new_rri_holder_callback = on_new_rri_holder_cb ;
127
131
parts_storage -> callback_arg = on_new_rri_holder_cb_arg ;
132
+
133
+ /* Partitions must remain locked till transaction's end */
134
+ parts_storage -> head_open_lock_mode = RowExclusiveLock ;
135
+ parts_storage -> heap_close_lock_mode = NoLock ;
128
136
}
129
137
130
138
/*
131
139
* Free ResultPartsStorage (close relations etc).
132
140
*/
133
141
void
134
- fini_result_parts_storage (ResultPartsStorage * parts_storage )
142
+ fini_result_parts_storage (ResultPartsStorage * parts_storage , bool close_rels )
135
143
{
136
- HASH_SEQ_STATUS stat ;
137
- ResultRelInfoHolder * rri_holder ;/* ResultRelInfo holder */
138
-
139
- hash_seq_init (& stat ,parts_storage -> result_rels_table );
140
- while ((rri_holder = (ResultRelInfoHolder * )hash_seq_search (& stat ))!= NULL )
144
+ /* Close partitions and their indices if asked to */
145
+ if (close_rels )
141
146
{
142
- ExecCloseIndices (rri_holder -> result_rel_info );
143
- heap_close (rri_holder -> result_rel_info -> ri_RelationDesc ,
144
- RowExclusiveLock );
147
+ HASH_SEQ_STATUS stat ;
148
+ ResultRelInfoHolder * rri_holder ;/* ResultRelInfo holder */
149
+
150
+ hash_seq_init (& stat ,parts_storage -> result_rels_table );
151
+ while ((rri_holder = (ResultRelInfoHolder * )hash_seq_search (& stat ))!= NULL )
152
+ {
153
+ ExecCloseIndices (rri_holder -> result_rel_info );
154
+
155
+ heap_close (rri_holder -> result_rel_info -> ri_RelationDesc ,
156
+ parts_storage -> heap_close_lock_mode );
157
+ }
145
158
}
159
+
160
+ /* Finally destroy hash table */
146
161
hash_destroy (parts_storage -> result_rels_table );
147
162
}
148
163
149
164
/*
150
165
* Find a ResultRelInfo for the partition using ResultPartsStorage.
151
166
*/
152
167
ResultRelInfoHolder *
153
- scan_result_parts_storage (Oid partid ,ResultPartsStorage * storage )
168
+ scan_result_parts_storage (Oid partid ,ResultPartsStorage * parts_storage )
154
169
{
155
170
#define CopyToResultRelInfo (field_name ) \
156
- ( part_result_rel_info->field_name =storage ->saved_rel_info->field_name )
171
+ ( part_result_rel_info->field_name =parts_storage ->saved_rel_info->field_name )
157
172
158
173
ResultRelInfoHolder * rri_holder ;
159
174
bool found ;
160
175
161
- rri_holder = hash_search (storage -> result_rels_table ,
176
+ rri_holder = hash_search (parts_storage -> result_rels_table ,
162
177
(const void * )& partid ,
163
178
HASH_ENTER ,& found );
164
179
@@ -167,16 +182,16 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *storage)
167
182
{
168
183
ResultRelInfo * part_result_rel_info = makeNode (ResultRelInfo );
169
184
185
+ /* Check that 'saved_rel_info' is set */
186
+ if (!parts_storage -> saved_rel_info )
187
+ elog (ERROR ,"ResultPartsStorage contains no saved_rel_info" );
188
+
170
189
InitResultRelInfo (part_result_rel_info ,
171
- heap_open (partid ,RowExclusiveLock ),
172
- 0 ,
190
+ heap_open (partid ,parts_storage -> head_open_lock_mode ),
191
+ parts_storage -> saved_rel_info -> ri_RangeTableIndex ,
173
192
0 );/* TODO: select suitable options */
174
193
175
- ExecOpenIndices (part_result_rel_info ,storage -> speculative_inserts );
176
-
177
- /* Check that 'saved_rel_info' is set */
178
- if (!storage -> saved_rel_info )
179
- elog (ERROR ,"ResultPartsStorage contains no saved_rel_info" );
194
+ ExecOpenIndices (part_result_rel_info ,parts_storage -> speculative_inserts );
180
195
181
196
/* Copy necessary fields from saved ResultRelInfo */
182
197
CopyToResultRelInfo (ri_WithCheckOptions );
@@ -189,18 +204,21 @@ scan_result_parts_storage(Oid partid, ResultPartsStorage *storage)
189
204
/* ri_ConstraintExprs will be initialized by ExecRelCheck() */
190
205
part_result_rel_info -> ri_ConstraintExprs = NULL ;
191
206
192
- /* Make 'range table index' point to the parent relation */
193
- part_result_rel_info -> ri_RangeTableIndex =
194
- storage -> saved_rel_info -> ri_RangeTableIndex ;
195
-
196
207
/* Now fill the ResultRelInfo holder */
197
208
rri_holder -> partid = partid ;
198
209
rri_holder -> result_rel_info = part_result_rel_info ;
199
210
211
+ /* Add ResultRelInfo to storage->es_alloc_result_rels */
212
+ parts_storage -> es_alloc_result_rels =
213
+ append_rri_to_estate (parts_storage -> estate ,
214
+ part_result_rel_info ,
215
+ parts_storage -> es_alloc_result_rels );
216
+
200
217
/* Call on_new_rri_holder_callback() if needed */
201
- if (storage -> on_new_rri_holder_callback )
202
- storage -> on_new_rri_holder_callback (storage -> estate ,rri_holder ,
203
- storage -> callback_arg );
218
+ if (parts_storage -> on_new_rri_holder_callback )
219
+ parts_storage -> on_new_rri_holder_callback (parts_storage -> estate ,
220
+ rri_holder ,
221
+ parts_storage -> callback_arg );
204
222
}
205
223
206
224
return rri_holder ;
@@ -412,8 +430,8 @@ partition_filter_end(CustomScanState *node)
412
430
{
413
431
PartitionFilterState * state = (PartitionFilterState * )node ;
414
432
415
- /*Close cached relations */
416
- fini_result_parts_storage (& state -> result_parts );
433
+ /*Executor will close rels via estate->es_result_relations */
434
+ fini_result_parts_storage (& state -> result_parts , false );
417
435
418
436
Assert (list_length (node -> custom_ps )== 1 );
419
437
ExecEndNode ((PlanState * )linitial (node -> custom_ps ));
@@ -432,6 +450,29 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
432
450
/* Nothing to do here now */
433
451
}
434
452
453
+ static int
454
+ append_rri_to_estate (EState * estate ,ResultRelInfo * rri ,int cur_allocated )
455
+ {
456
+ int result_rels_allocated = cur_allocated ;
457
+
458
+ if (result_rels_allocated <=estate -> es_num_result_relations )
459
+ {
460
+ ResultRelInfo * rri_array = estate -> es_result_relations ;
461
+
462
+ result_rels_allocated = result_rels_allocated * ALLOC_EXP + 1 ;
463
+ estate -> es_result_relations = palloc (result_rels_allocated *
464
+ sizeof (ResultRelInfo ));
465
+ memcpy (estate -> es_result_relations ,
466
+ rri_array ,
467
+ estate -> es_num_result_relations * sizeof (ResultRelInfo ));
468
+ }
469
+
470
+ /* Append ResultRelInfo to 'es_result_relations' array */
471
+ estate -> es_result_relations [estate -> es_num_result_relations ++ ]= * rri ;
472
+
473
+ return result_rels_allocated ;
474
+ }
475
+
435
476
/*
436
477
* Build partition filter's target list pointing to subplan tuple's elements
437
478
*/
@@ -465,9 +506,9 @@ pfilter_build_tlist(List *tlist)
465
506
}
466
507
467
508
/*
468
- * Add partition filters to ModifyTable node's children
509
+ * Add partition filters to ModifyTable node's children.
469
510
*
470
- * 'context' should point to the PlannedStmt->rtable
511
+ * 'context' should point to the PlannedStmt->rtable.
471
512
*/
472
513
static void
473
514
partition_filter_visitor (Plan * plan ,void * context )