1
1
#include "partition_filter.h"
2
2
#include "utils/guc.h"
3
+ #include "nodes/nodeFuncs.h"
3
4
4
5
5
6
bool pg_pathman_enable_partition_filter = true;
@@ -8,6 +9,7 @@ CustomScanMethodspartition_filter_plan_methods;
8
9
CustomExecMethods partition_filter_exec_methods ;
9
10
10
11
12
+ static List * pfilter_build_tlist (List * tlist );
11
13
12
14
void
13
15
init_partition_filter_static_data (void )
@@ -37,7 +39,7 @@ init_partition_filter_static_data(void)
37
39
}
38
40
39
41
Plan *
40
- create_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
42
+ make_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
41
43
{
42
44
CustomScan * cscan = makeNode (CustomScan );
43
45
@@ -46,54 +48,64 @@ create_partition_filter_plan(Plan *subplan, PartRelationInfo *prel)
46
48
cscan -> scan .plan .plan_rows = subplan -> plan_rows ;
47
49
cscan -> scan .plan .plan_width = subplan -> plan_width ;
48
50
49
- cscan -> scan .plan .qual = NIL ;
50
-
51
+ cscan -> methods = & partition_filter_plan_methods ;
51
52
cscan -> custom_plans = list_make1 (subplan );
52
53
53
- cscan -> scan .plan .targetlist = subplan -> targetlist ;
54
+ cscan -> scan .plan .targetlist = pfilter_build_tlist ( subplan -> targetlist ) ;
54
55
55
56
/* No relation will be scanned */
56
57
cscan -> scan .scanrelid = 0 ;
57
58
cscan -> custom_scan_tlist = subplan -> targetlist ;
58
59
59
- cscan -> methods = & partition_filter_plan_methods ;
60
+ /* Save partitioned table's Oid */
61
+ cscan -> custom_private = list_make1_int (prel -> key .relid );
60
62
61
63
return & cscan -> scan .plan ;
62
64
}
63
65
64
66
Node *
65
67
partition_filter_create_scan_state (CustomScan * node )
66
68
{
67
- PartitionFilterState * state = palloc0 (sizeof (PartitionFilterState ));
69
+ PartitionFilterState * state = palloc0 (sizeof (PartitionFilterState ));
68
70
69
71
NodeSetTag (state ,T_CustomScanState );
70
72
71
73
state -> css .flags = node -> flags ;
72
74
state -> css .methods = & partition_filter_exec_methods ;
73
75
76
+ /* Extract necessary variables */
74
77
state -> subplan = (Plan * )linitial (node -> custom_plans );
78
+ state -> partitioned_table = linitial_int (node -> custom_private );
79
+
80
+ /* Prepare dummy Const node */
81
+ NodeSetTag (& state -> temp_const ,T_Const );
82
+ state -> temp_const .location = -1 ;
75
83
76
84
return (Node * )state ;
77
85
}
78
86
79
87
void
80
88
partition_filter_begin (CustomScanState * node ,EState * estate ,int eflags )
81
89
{
82
- PartitionFilterState * state = (PartitionFilterState * )node ;
90
+ PartitionFilterState * state = (PartitionFilterState * )node ;
83
91
84
92
node -> custom_ps = list_make1 (ExecInitNode (state -> subplan ,estate ,eflags ));
85
-
93
+ state -> prel = get_pathman_relation_info ( state -> partitioned_table , NULL );
86
94
state -> firstStart = true;
87
95
}
88
96
89
97
TupleTableSlot *
90
98
partition_filter_exec (CustomScanState * node )
91
99
{
92
- PartitionFilterState * state = (PartitionFilterState * )node ;
100
+ #define CopyToTempConst (const_field ,attr_field ) \
101
+ ( state->temp_const.const_field = \
102
+ slot->tts_tupleDescriptor->attrs[attnum - 1]->attr_field )
93
103
94
- EState * estate = node -> ss .ps .state ;
95
- PlanState * child_ps = (PlanState * )linitial (node -> custom_ps );
96
- TupleTableSlot * slot ;
104
+ PartitionFilterState * state = (PartitionFilterState * )node ;
105
+
106
+ EState * estate = node -> ss .ps .state ;
107
+ PlanState * child_ps = (PlanState * )linitial (node -> custom_ps );
108
+ TupleTableSlot * slot ;
97
109
98
110
if (state -> firstStart )
99
111
state -> savedRelInfo = estate -> es_result_relation_info ;
@@ -102,6 +114,27 @@ partition_filter_exec(CustomScanState *node)
102
114
103
115
if (!TupIsNull (slot ))
104
116
{
117
+ WalkerContext wcxt ;
118
+ bool isnull ;
119
+ AttrNumber attnum = state -> prel -> attnum ;
120
+ Datum value = slot_getattr (slot ,attnum ,& isnull );
121
+
122
+ state -> temp_const .constvalue = value ;
123
+ state -> temp_const .constisnull = isnull ;
124
+
125
+ CopyToTempConst (consttype ,atttypid );
126
+ CopyToTempConst (consttypmod ,atttypmod );
127
+ CopyToTempConst (constcollid ,attcollation );
128
+ CopyToTempConst (constlen ,attlen );
129
+ CopyToTempConst (constbyval ,attbyval );
130
+
131
+ wcxt .prel = state -> prel ;
132
+ wcxt .econtext = NULL ;
133
+ wcxt .hasLeast = false;
134
+ wcxt .hasGreatest = false;
135
+
136
+ walk_expr_tree ((Expr * )& state -> temp_const ,& wcxt );
137
+
105
138
/* estate->es_result_relation_info = NULL; */
106
139
107
140
return slot ;
@@ -132,6 +165,38 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
132
165
/* Nothing to do here now */
133
166
}
134
167
168
+ /*
169
+ * Build partition filter's target list pointing to subplan tuple's elements
170
+ */
171
+ static List *
172
+ pfilter_build_tlist (List * tlist )
173
+ {
174
+ List * result_tlist = NIL ;
175
+ ListCell * lc ;
176
+ int i = 1 ;
177
+
178
+ foreach (lc ,tlist )
179
+ {
180
+ TargetEntry * tle = (TargetEntry * )lfirst (lc );
181
+
182
+ Var * var = makeVar (INDEX_VAR ,/* point to subplan's elements */
183
+ i ,/* direct attribute mapping */
184
+ exprType ((Node * )tle -> expr ),
185
+ exprTypmod ((Node * )tle -> expr ),
186
+ exprCollation ((Node * )tle -> expr ),
187
+ 0 );
188
+
189
+ result_tlist = lappend (result_tlist ,
190
+ makeTargetEntry ((Expr * )var ,
191
+ i ,
192
+ NULL ,
193
+ tle -> resjunk ));
194
+ i ++ ;/* next resno */
195
+ }
196
+
197
+ return result_tlist ;
198
+ }
199
+
135
200
/* Add proxy PartitionFilter nodes to subplans of ModifyTable node */
136
201
void
137
202
add_partition_filters (List * rtable ,ModifyTable * modify_table )
@@ -150,6 +215,6 @@ add_partition_filters(List *rtable, ModifyTable *modify_table)
150
215
PartRelationInfo * prel = get_pathman_relation_info (getrelid (rindex ,rtable ),
151
216
NULL );
152
217
if (prel )
153
- lfirst (lc1 )= create_partition_filter_plan ((Plan * )lfirst (lc1 ),prel );
218
+ lfirst (lc1 )= make_partition_filter_plan ((Plan * )lfirst (lc1 ),prel );
154
219
}
155
220
}