@@ -78,6 +78,29 @@ static CustomScanMethodscrossmatch_plan_methods;
7878static CustomExecMethods crossmatch_exec_methods ;
7979
8080
81+ #define IsVarSpointDist (arg ,dist_func_oid ) \
82+ (\
83+ IsA(arg, FuncExpr) &&\
84+ ((FuncExpr *) (arg))->funcid == (dist_func_oid) &&\
85+ IsA(linitial(((FuncExpr *) (arg))->args), Var) &&\
86+ IsA(lsecond(((FuncExpr *) (arg))->args), Var)\
87+ )
88+
89+
90+ static float8
91+ cstring_to_float8 (char * str )
92+ {
93+ return DatumGetFloat8 (DirectFunctionCall1 (float8in ,
94+ CStringGetDatum (str )));
95+ }
96+
97+ static char *
98+ float8_to_cstring (float8 val )
99+ {
100+ return DatumGetCString (DirectFunctionCall1 (float8out ,
101+ Float8GetDatum (val )));
102+ }
103+
81104static float8
82105get_const_val (Const * node )
83106{
@@ -174,6 +197,26 @@ pick_suitable_index(Oid relation, AttrNumber column)
174197return found_index ;
175198}
176199
200+ static void
201+ get_spoint_attnums (FuncExpr * fexpr ,RelOptInfo * outer ,RelOptInfo * inner ,
202+ AttrNumber * outer_spoint ,AttrNumber * inner_spoint )
203+ {
204+ ListCell * dist_arg ;
205+
206+ Assert (outer -> relid != 0 && inner -> relid != 0 );
207+
208+ foreach (dist_arg ,fexpr -> args )
209+ {
210+ Var * arg = (Var * )lfirst (dist_arg );
211+
212+ if (arg -> varno == outer -> relid )
213+ * outer_spoint = arg -> varoattno ;
214+
215+ if (arg -> varno == inner -> relid )
216+ * inner_spoint = arg -> varoattno ;
217+ }
218+ }
219+
177220static Path *
178221crossmatch_find_cheapest_path (PlannerInfo * root ,
179222RelOptInfo * joinrel ,
@@ -211,7 +254,9 @@ create_crossmatch_path(PlannerInfo *root,
211254ParamPathInfo * param_info ,
212255List * restrict_clauses ,
213256Relids required_outer ,
214- float8 threshold )
257+ float8 threshold ,
258+ AttrNumber outer_spoint ,
259+ AttrNumber inner_spoint )
215260{
216261CrossmatchJoinPath * result ;
217262
@@ -221,8 +266,8 @@ create_crossmatch_path(PlannerInfo *root,
221266Oid inner_idx ;
222267
223268/* TODO: use actual column numbers */
224- if ((outer_idx = pick_suitable_index (outer_rel ,1 ))== InvalidOid ||
225- (inner_idx = pick_suitable_index (inner_rel ,1 ))== InvalidOid )
269+ if ((outer_idx = pick_suitable_index (outer_rel ,outer_spoint ))== InvalidOid ||
270+ (inner_idx = pick_suitable_index (inner_rel ,inner_spoint ))== InvalidOid )
226271{
227272return ;
228273}
@@ -280,7 +325,7 @@ join_pathlist_hook(PlannerInfo *root,
280325PointerGetDatum (dist_func_name )));
281326
282327if (dist_func == InvalidOid )
283- elog ( ERROR , "function dist not found!" ) ;
328+ return ;
284329
285330if (set_join_pathlist_next )
286331set_join_pathlist_next (root ,
@@ -312,10 +357,11 @@ join_pathlist_hook(PlannerInfo *root,
312357arg2 = lsecond (opExpr -> args );
313358
314359if (opExpr -> opno == Float8LessOperator &&
315- IsA (arg1 ,FuncExpr )&&
316- ((FuncExpr * )arg1 )-> funcid == dist_func &&
317- IsA (arg2 ,Const ))
360+ IsVarSpointDist (arg1 ,dist_func )&& IsA (arg2 ,Const ))
318361{
362+ AttrNumber outer_spoint ,
363+ inner_spoint ;
364+
319365Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
320366Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
321367
@@ -329,17 +375,22 @@ join_pathlist_hook(PlannerInfo *root,
329375required_outer ,
330376& restrict_clauses );
331377
378+ get_spoint_attnums ((FuncExpr * )arg1 ,outerrel ,innerrel ,
379+ & outer_spoint ,& inner_spoint );
380+
332381create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
333382param_info ,restrict_clauses ,required_outer ,
334- get_const_val ((Const * )arg2 ));
383+ get_const_val ((Const * )arg2 ),
384+ outer_spoint ,inner_spoint );
335385
336386break ;
337387}
338388else if (opExpr -> opno == get_commutator (Float8LessOperator )&&
339- IsA (arg1 ,Const )&&
340- IsA (arg2 ,FuncExpr )&&
341- ((FuncExpr * )arg2 )-> funcid == dist_func )
389+ IsA (arg1 ,Const )&& IsVarSpointDist (arg2 ,dist_func ))
342390{
391+ AttrNumber outer_spoint ,
392+ inner_spoint ;
393+
343394/* TODO: merge duplicate code */
344395Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
345396Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
@@ -354,9 +405,13 @@ join_pathlist_hook(PlannerInfo *root,
354405required_outer ,
355406& restrict_clauses );
356407
408+ get_spoint_attnums ((FuncExpr * )arg2 ,outerrel ,innerrel ,
409+ & outer_spoint ,& inner_spoint );
410+
357411create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
358412param_info ,restrict_clauses ,required_outer ,
359- get_const_val ((Const * )arg1 ));
413+ get_const_val ((Const * )arg1 ),
414+ outer_spoint ,inner_spoint );
360415}
361416}
362417}
@@ -372,46 +427,35 @@ create_crossmatch_plan(PlannerInfo *root,
372427{
373428CrossmatchJoinPath * gpath = (CrossmatchJoinPath * )best_path ;
374429List * joinrestrictclauses = gpath -> joinrestrictinfo ;
375- List * joinclauses ;/* NOTE: do we really need it? */
376- List * otherclauses ;
430+ List * joinclauses ;
377431CustomScan * cscan ;
378- float8 * threshold = palloc (sizeof (float8 ));
379432
380- if (IS_OUTER_JOIN (gpath -> jointype ))
381- {
382- extract_actual_join_clauses (joinrestrictclauses ,
383- & joinclauses ,& otherclauses );
384- }
385- else
386- {
387- joinclauses = extract_actual_clauses (joinrestrictclauses ,
388- false);
389- otherclauses = NIL ;
390- }
433+ Assert (!IS_OUTER_JOIN (gpath -> jointype ));
434+ joinclauses = extract_actual_clauses (joinrestrictclauses , false);
391435
392436cscan = makeNode (CustomScan );
393437cscan -> scan .plan .targetlist = tlist ;
394- cscan -> custom_scan_tlist = tlist ;/* output of this node */
395438cscan -> scan .plan .qual = NIL ;
396439cscan -> scan .scanrelid = 0 ;
440+ cscan -> custom_scan_tlist = tlist ;/* output of this node */
397441
398442cscan -> flags = best_path -> flags ;
399443cscan -> methods = & crossmatch_plan_methods ;
400444
401- cscan -> custom_private = list_make2 (list_make4_oid (gpath -> outer_idx ,
445+ cscan -> custom_private = list_make1 (list_make4_oid (gpath -> outer_idx ,
402446gpath -> outer_rel ,
403447gpath -> inner_idx ,
404- gpath -> inner_rel ),
405- list_make1 ( threshold ));
406- * threshold = gpath -> threshold ;
448+ gpath -> inner_rel ));
449+ cscan -> custom_private = lappend ( cscan -> custom_private ,
450+ makeString ( float8_to_cstring ( gpath -> threshold ))) ;
407451
408452return & cscan -> scan .plan ;
409453}
410454
411455static Node *
412456crossmatch_create_scan_state (CustomScan * node )
413457{
414- CrossmatchScanState * scan_state = palloc0 (sizeof (CrossmatchScanState ));
458+ CrossmatchScanState * scan_state = palloc0 (sizeof (CrossmatchScanState ));
415459
416460NodeSetTag (scan_state ,T_CustomScanState );
417461scan_state -> css .flags = node -> flags ;
@@ -426,7 +470,7 @@ crossmatch_create_scan_state(CustomScan *node)
426470scan_state -> outer_rel = lsecond_oid (linitial (node -> custom_private ));
427471scan_state -> inner_idx = lthird_oid (linitial (node -> custom_private ));
428472scan_state -> inner_rel = lfourth_oid (linitial (node -> custom_private ));
429- scan_state -> threshold = * ( float8 * ) linitial (lsecond (node -> custom_private ));
473+ scan_state -> threshold = cstring_to_float8 ( strVal (lsecond (node -> custom_private ) ));
430474
431475return (Node * )scan_state ;
432476}
@@ -533,8 +577,14 @@ crossmatch_exec(CustomScanState *node)
533577node -> ss .ps .ps_TupFromTlist = false;
534578}
535579else
536- return ExecStoreTuple (htup ,node -> ss .ps .ps_ResultTupleSlot ,
537- InvalidBuffer , false);
580+ {
581+ TupleTableSlot * result ;
582+
583+ result = ExecStoreTuple (htup ,node -> ss .ps .ps_ResultTupleSlot ,
584+ InvalidBuffer , false);
585+
586+ return result ;
587+ }
538588}
539589}
540590
@@ -572,6 +622,12 @@ crossmatch_explain(CustomScanState *node, List *ancestors, ExplainState *es)
572622appendStringInfo (& str ,"%s" ,
573623get_rel_name (scan_state -> inner_idx ));
574624ExplainPropertyText ("Inner index" ,str .data ,es );
625+
626+ resetStringInfo (& str );
627+
628+ appendStringInfo (& str ,"%s" ,
629+ float8_to_cstring (scan_state -> threshold ));
630+ ExplainPropertyText ("Threshold" ,str .data ,es );
575631}
576632
577633void