11#include "partition_filter.h"
22#include "utils/guc.h"
3+ #include "nodes/nodeFuncs.h"
34
45
56bool pg_pathman_enable_partition_filter = true;
@@ -8,6 +9,7 @@ CustomScanMethodspartition_filter_plan_methods;
89CustomExecMethods partition_filter_exec_methods ;
910
1011
12+ static List * pfilter_build_tlist (List * tlist );
1113
1214void
1315init_partition_filter_static_data (void )
@@ -37,7 +39,7 @@ init_partition_filter_static_data(void)
3739}
3840
3941Plan *
40- create_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
42+ make_partition_filter_plan (Plan * subplan ,PartRelationInfo * prel )
4143{
4244CustomScan * cscan = makeNode (CustomScan );
4345
@@ -46,54 +48,64 @@ create_partition_filter_plan(Plan *subplan, PartRelationInfo *prel)
4648cscan -> scan .plan .plan_rows = subplan -> plan_rows ;
4749cscan -> scan .plan .plan_width = subplan -> plan_width ;
4850
49- cscan -> scan .plan .qual = NIL ;
50-
51+ cscan -> methods = & partition_filter_plan_methods ;
5152cscan -> custom_plans = list_make1 (subplan );
5253
53- cscan -> scan .plan .targetlist = subplan -> targetlist ;
54+ cscan -> scan .plan .targetlist = pfilter_build_tlist ( subplan -> targetlist ) ;
5455
5556/* No relation will be scanned */
5657cscan -> scan .scanrelid = 0 ;
5758cscan -> custom_scan_tlist = subplan -> targetlist ;
5859
59- cscan -> methods = & partition_filter_plan_methods ;
60+ /* Save partitioned table's Oid */
61+ cscan -> custom_private = list_make1_int (prel -> key .relid );
6062
6163return & cscan -> scan .plan ;
6264}
6365
6466Node *
6567partition_filter_create_scan_state (CustomScan * node )
6668{
67- PartitionFilterState * state = palloc0 (sizeof (PartitionFilterState ));
69+ PartitionFilterState * state = palloc0 (sizeof (PartitionFilterState ));
6870
6971NodeSetTag (state ,T_CustomScanState );
7072
7173state -> css .flags = node -> flags ;
7274state -> css .methods = & partition_filter_exec_methods ;
7375
76+ /* Extract necessary variables */
7477state -> 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 ;
7583
7684return (Node * )state ;
7785}
7886
7987void
8088partition_filter_begin (CustomScanState * node ,EState * estate ,int eflags )
8189{
82- PartitionFilterState * state = (PartitionFilterState * )node ;
90+ PartitionFilterState * state = (PartitionFilterState * )node ;
8391
8492node -> custom_ps = list_make1 (ExecInitNode (state -> subplan ,estate ,eflags ));
85-
93+ state -> prel = get_pathman_relation_info ( state -> partitioned_table , NULL );
8694state -> firstStart = true;
8795}
8896
8997TupleTableSlot *
9098partition_filter_exec (CustomScanState * node )
9199{
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 )
93103
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 ;
97109
98110if (state -> firstStart )
99111state -> savedRelInfo = estate -> es_result_relation_info ;
@@ -102,6 +114,27 @@ partition_filter_exec(CustomScanState *node)
102114
103115if (!TupIsNull (slot ))
104116{
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+
105138/* estate->es_result_relation_info = NULL; */
106139
107140return slot ;
@@ -132,6 +165,38 @@ partition_filter_explain(CustomScanState *node, List *ancestors, ExplainState *e
132165/* Nothing to do here now */
133166}
134167
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+
135200/* Add proxy PartitionFilter nodes to subplans of ModifyTable node */
136201void
137202add_partition_filters (List * rtable ,ModifyTable * modify_table )
@@ -150,6 +215,6 @@ add_partition_filters(List *rtable, ModifyTable *modify_table)
150215PartRelationInfo * prel = get_pathman_relation_info (getrelid (rindex ,rtable ),
151216NULL );
152217if (prel )
153- lfirst (lc1 )= create_partition_filter_plan ((Plan * )lfirst (lc1 ),prel );
218+ lfirst (lc1 )= make_partition_filter_plan ((Plan * )lfirst (lc1 ),prel );
154219}
155220}