11#include "postgres.h"
22#include "optimizer/paths.h"
3+ #include "optimizer/pathnode.h"
34#include "optimizer/restrictinfo.h"
45#include "utils/builtins.h"
56#include "utils/elog.h"
1011#include "commands/explain.h"
1112#include "funcapi.h"
1213
14+ #include "access/htup_details.h"
15+ #include "point.h"
16+
1317extern void _PG_init (void );
1418
1519static set_join_pathlist_hook_type set_join_pathlist_next ;
@@ -26,20 +30,93 @@ typedef struct
2630List * joinrestrictinfo ;
2731}CrossmatchJoinPath ;
2832
33+ typedef struct
34+ {
35+ CustomScanState css ;
36+
37+ HeapTupleData scan_tuple ;/* buffer to fetch tuple */
38+ List * dev_tlist ;/* tlist to be returned from the device */
39+ List * dev_quals ;/* quals to be run on the device */
40+ }CrossmatchScanState ;
41+
2942static CustomPathMethods crossmatch_path_methods ;
3043static CustomScanMethods crossmatch_plan_methods ;
3144static CustomExecMethods crossmatch_exec_methods ;
3245
33- void join_pathlist_hook (PlannerInfo * root ,
34- RelOptInfo * joinrel ,
35- RelOptInfo * outerrel ,
36- RelOptInfo * innerrel ,
37- JoinType jointype ,
38- JoinPathExtraData * extra )
46+
47+ static Path *
48+ crossmatch_find_cheapest_path (PlannerInfo * root ,
49+ RelOptInfo * joinrel ,
50+ RelOptInfo * inputrel )
51+ {
52+ Path * input_path = inputrel -> cheapest_total_path ;
53+ Relids other_relids ;
54+ ListCell * lc ;
55+
56+ other_relids = bms_difference (joinrel -> relids ,inputrel -> relids );
57+ if (bms_overlap (PATH_REQ_OUTER (input_path ),other_relids ))
58+ {
59+ input_path = NULL ;
60+ foreach (lc ,inputrel -> pathlist )
61+ {
62+ Path * curr_path = lfirst (lc );
63+
64+ if (bms_overlap (PATH_REQ_OUTER (curr_path ),other_relids ))
65+ continue ;
66+ if (input_path == NULL ||
67+ input_path -> total_cost > curr_path -> total_cost )
68+ input_path = curr_path ;
69+ }
70+ }
71+ bms_free (other_relids );
72+
73+ return input_path ;
74+ }
75+
76+ static void
77+ create_crossmatch_path (PlannerInfo * root ,
78+ RelOptInfo * joinrel ,
79+ Path * outer_path ,
80+ Path * inner_path ,
81+ ParamPathInfo * param_info ,
82+ List * restrict_clauses ,
83+ Relids required_outer )
84+ {
85+ CrossmatchJoinPath * result ;
86+
87+ result = palloc0 (sizeof (CrossmatchJoinPath ));
88+ NodeSetTag (result ,T_CustomPath );
89+
90+ result -> cpath .path .pathtype = T_CustomScan ;
91+ result -> cpath .path .parent = joinrel ;
92+ result -> cpath .path .param_info = param_info ;
93+ result -> cpath .path .pathkeys = NIL ;
94+ result -> cpath .path .rows = joinrel -> rows ;
95+ result -> cpath .flags = 0 ;
96+ result -> cpath .methods = & crossmatch_path_methods ;
97+ result -> outer_path = outer_path ;
98+ result -> inner_path = inner_path ;
99+ result -> joinrestrictinfo = restrict_clauses ;
100+
101+ /* TODO: real costs */
102+ result -> cpath .path .startup_cost = 1 ;
103+ result -> cpath .path .total_cost = 1 ;
104+
105+ add_path (joinrel ,& result -> cpath .path );
106+ }
107+
108+ static void
109+ join_pathlist_hook (PlannerInfo * root ,
110+ RelOptInfo * joinrel ,
111+ RelOptInfo * outerrel ,
112+ RelOptInfo * innerrel ,
113+ JoinType jointype ,
114+ JoinPathExtraData * extra )
39115{
40116ListCell * restr ;
41117text * dist_func_name = cstring_to_text ("dist(spoint,spoint)" );
42118Oid dist_func ;
119+ List * restrict_clauses = extra -> restrictlist ;
43120
44121dist_func = DatumGetObjectId (DirectFunctionCall1 (to_regprocedure ,
45122PointerGetDatum (dist_func_name )));
@@ -59,6 +136,15 @@ void join_pathlist_hook (PlannerInfo *root,
59136{
60137RestrictInfo * restrInfo = (RestrictInfo * )lfirst (restr );
61138
139+ if (outerrel -> reloptkind == RELOPT_BASEREL &&
140+ innerrel -> reloptkind == RELOPT_BASEREL &&
141+ bms_is_member (outerrel -> relid ,restrInfo -> clause_relids )&&
142+ bms_is_member (innerrel -> relid ,restrInfo -> clause_relids ))
143+ {
144+ /* This is our case */
145+ }
146+ else continue ;
147+
62148if (IsA (restrInfo -> clause ,OpExpr ))
63149{
64150OpExpr * opExpr = (OpExpr * )restrInfo -> clause ;
@@ -77,53 +163,53 @@ void join_pathlist_hook (PlannerInfo *root,
77163((FuncExpr * )arg1 )-> funcid == dist_func &&
78164IsA (arg2 ,Const ))
79165{
80- elog (LOG ,"found <" );
166+ Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
167+ Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
168+
169+ Relids required_outer = calc_nestloop_required_outer (outer_path ,inner_path );
170+
171+ ParamPathInfo * param_info = get_joinrel_parampathinfo (root ,
172+ joinrel ,
173+ outer_path ,
174+ inner_path ,
175+ extra -> sjinfo ,
176+ required_outer ,
177+ & restrict_clauses );
178+
179+ /* DEBUG */
180+ create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
181+ param_info ,restrict_clauses ,required_outer );
182+
183+ break ;
81184}
82185else if (opExpr -> opno == get_commutator (Float8LessOperator )&&
83186IsA (arg1 ,Const )&&
84187IsA (arg2 ,FuncExpr )&&
85188 ((FuncExpr * )arg2 )-> funcid == dist_func )
86189{
87- elog (LOG ,"found >" );
190+ Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
191+ Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
192+
193+ Relids required_outer = calc_nestloop_required_outer (outer_path ,inner_path );
194+
195+ ParamPathInfo * param_info = get_joinrel_parampathinfo (root ,
196+ joinrel ,
197+ outer_path ,
198+ inner_path ,
199+ extra -> sjinfo ,
200+ required_outer ,
201+ & restrict_clauses );
202+
203+ /* DEBUG */
204+ create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
205+ param_info ,restrict_clauses ,required_outer );
88206}
89207}
90208}
91209
92210pprint (root -> parse -> rtable );
93211}
94212
95- static CrossmatchJoinPath *
96- create_crossmatch_path (PlannerInfo * root ,
97- RelOptInfo * joinrel ,
98- Path * outer_path ,
99- Path * inner_path ,
100- ParamPathInfo * param_info ,
101- List * restrict_clauses ,
102- Relids required_outer )
103- {
104- CrossmatchJoinPath * result ;
105-
106- result = palloc0 (sizeof (CrossmatchJoinPath ));
107- NodeSetTag (result ,T_CustomPath );
108-
109- result -> cpath .path .pathtype = T_CustomScan ;
110- result -> cpath .path .parent = joinrel ;
111- result -> cpath .path .param_info = param_info ;
112- result -> cpath .path .pathkeys = NIL ;
113- result -> cpath .path .rows = joinrel -> rows ;
114- result -> cpath .flags = 0 ;
115- result -> cpath .methods = & crossmatch_path_methods ;
116- result -> outer_path = outer_path ;
117- result -> inner_path = inner_path ;
118- result -> joinrestrictinfo = restrict_clauses ;
119-
120- /* DEBUG costs */
121- result -> cpath .path .startup_cost = 1 ;
122- result -> cpath .path .total_cost = 1 ;
123-
124- return result ;
125- }
126-
127213static Plan *
128214create_crossmatch_plan (PlannerInfo * root ,
129215RelOptInfo * rel ,
@@ -153,30 +239,67 @@ create_crossmatch_plan(PlannerInfo *root,
153239cscan = makeNode (CustomScan );
154240cscan -> scan .plan .targetlist = tlist ;
155241cscan -> scan .plan .qual = NIL ;
242+ cscan -> scan .scanrelid = 0 ;
243+
244+ cscan -> custom_scan_tlist = tlist ;
245+
246+ elog (LOG ,"tlist:" );
247+ pprint (tlist );
156248
157249cscan -> flags = best_path -> flags ;
158250cscan -> methods = & crossmatch_plan_methods ;
159251cscan -> custom_plans = list_copy_tail (custom_plans ,1 );
160252
161-
253+ return & cscan -> scan . plan ;
162254}
163255
164256static Node *
165257crossmatch_create_scan_state (CustomScan * node )
166258{
167- return NULL ;
259+ CrossmatchScanState * scan_state = palloc0 (sizeof (CrossmatchScanState ));
260+
261+ NodeSetTag (scan_state ,T_CustomScanState );
262+ scan_state -> css .flags = node -> flags ;
263+ if (node -> methods == & crossmatch_plan_methods )
264+ scan_state -> css .methods = & crossmatch_exec_methods ;
265+ else
266+ elog (ERROR ,"Bug? unexpected CustomPlanMethods" );
267+
268+ return (Node * )scan_state ;
168269}
169270
271+ static int i = 0 ;
272+
170273static void
171274crossmatch_begin (CustomScanState * node ,EState * estate ,int eflags )
172275{
173-
276+ i = 0 ;
174277}
175278
176279static TupleTableSlot *
177280crossmatch_exec (CustomScanState * node )
178281{
179- return NULL ;
282+ TupleTableSlot * slot = node -> ss .ss_ScanTupleSlot ;
283+ TupleDesc tupdesc = node -> ss .ss_ScanTupleSlot -> tts_tupleDescriptor ;
284+ HeapTuple htup ;
285+
286+ /* TODO: fill with real data from joined tables */
287+ Datum values [2 ]= {DirectFunctionCall1 (spherepoint_in ,CStringGetDatum ("(0d, 0d)" )),
288+ DirectFunctionCall1 (spherepoint_in ,CStringGetDatum ("(0d, 0d)" )) };
289+ bool nulls [2 ]= {0 ,0 };
290+
291+ htup = heap_form_tuple (tupdesc ,values ,nulls );
292+
293+ elog (LOG ,"natts: %d" ,tupdesc -> natts );
294+
295+ i ++ ;
296+
297+ if (i > 10 )
298+ ExecClearTuple (slot );
299+ else
300+ ExecStoreTuple (htup ,slot ,InvalidBuffer , false);
301+
302+ return slot ;
180303}
181304
182305static void
@@ -206,17 +329,17 @@ _PG_init(void)
206329set_join_pathlist_hook = join_pathlist_hook ;
207330
208331crossmatch_path_methods .CustomName = "CrossmatchJoin" ;
209- crossmatch_path_methods .PlanCustomPath = & create_crossmatch_plan ;
332+ crossmatch_path_methods .PlanCustomPath = create_crossmatch_plan ;
210333
211334crossmatch_plan_methods .CustomName = "CrossmatchJoin" ;
212- crossmatch_plan_methods .CreateCustomScanState = & crossmatch_create_scan_state ;
335+ crossmatch_plan_methods .CreateCustomScanState = crossmatch_create_scan_state ;
213336
214337crossmatch_exec_methods .CustomName = "CrossmatchJoin" ;
215- crossmatch_exec_methods .BeginCustomScan = & crossmatch_begin ;
216- crossmatch_exec_methods .ExecCustomScan = & crossmatch_exec ;
217- crossmatch_exec_methods .EndCustomScan = & crossmatch_end ;
218- crossmatch_exec_methods .ReScanCustomScan = & crossmatch_rescan ;
338+ crossmatch_exec_methods .BeginCustomScan = crossmatch_begin ;
339+ crossmatch_exec_methods .ExecCustomScan = crossmatch_exec ;
340+ crossmatch_exec_methods .EndCustomScan = crossmatch_end ;
341+ crossmatch_exec_methods .ReScanCustomScan = crossmatch_rescan ;
219342crossmatch_exec_methods .MarkPosCustomScan = NULL ;
220343crossmatch_exec_methods .RestrPosCustomScan = NULL ;
221- crossmatch_exec_methods .ExplainCustomScan = & crossmatch_explain ;
344+ crossmatch_exec_methods .ExplainCustomScan = crossmatch_explain ;
222345}