@@ -263,7 +263,6 @@ create_crossmatch_path(PlannerInfo *root,
263263Oid outer_idx ;
264264Oid inner_idx ;
265265
266- /* TODO: use actual column numbers */
267266if ((outer_idx = pick_suitable_index (outer_rel ,outer_spoint ))== InvalidOid ||
268267(inner_idx = pick_suitable_index (inner_rel ,inner_spoint ))== InvalidOid )
269268{
@@ -297,6 +296,49 @@ create_crossmatch_path(PlannerInfo *root,
297296add_path (joinrel ,& result -> cpath .path );
298297}
299298
299+ static void
300+ try_crossmatch_path (RestrictInfo * restrInfo ,
301+ FuncExpr * distFuncExpr ,
302+ Const * thresholdConst ,
303+ PlannerInfo * root ,
304+ RelOptInfo * joinrel ,
305+ RelOptInfo * outerrel ,
306+ RelOptInfo * innerrel ,
307+ JoinPathExtraData * extra )
308+ {
309+ AttrNumber outer_spoint ,
310+ inner_spoint ;
311+ List * restrict_clauses ;
312+ Path * outer_path ,
313+ * inner_path ;
314+ Relids required_outer ;
315+ ParamPathInfo * param_info ;
316+
317+ /* Remove current RestrictInfo from restrict clauses */
318+ restrict_clauses = list_delete_ptr (list_copy (extra -> restrictlist ),restrInfo );
319+
320+ outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
321+ inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
322+
323+ required_outer = calc_nestloop_required_outer (outer_path ,inner_path );
324+
325+ param_info = get_joinrel_parampathinfo (root ,
326+ joinrel ,
327+ outer_path ,
328+ inner_path ,
329+ extra -> sjinfo ,
330+ required_outer ,
331+ & restrict_clauses );
332+
333+ get_spoint_attnums (distFuncExpr ,outerrel ,innerrel ,
334+ & outer_spoint ,& inner_spoint );
335+
336+ create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
337+ param_info ,restrict_clauses ,required_outer ,
338+ get_const_val (thresholdConst ),
339+ outer_spoint ,inner_spoint );
340+ }
341+
300342static void
301343join_pathlist_hook (PlannerInfo * root ,
302344RelOptInfo * joinrel ,
@@ -308,7 +350,6 @@ join_pathlist_hook(PlannerInfo *root,
308350ListCell * restr ;
309351text * dist_func_name = cstring_to_text ("dist(spoint,spoint)" );
310352Oid dist_func ;
311- List * restrict_clauses = extra -> restrictlist ;
312353Relids required_relids = NULL ;
313354
314355if (outerrel -> reloptkind == RELOPT_BASEREL &&
@@ -357,59 +398,16 @@ join_pathlist_hook(PlannerInfo *root,
357398if (opExpr -> opno == Float8LessOperator &&
358399IsVarSpointDist (arg1 ,dist_func )&& IsA (arg2 ,Const ))
359400{
360- AttrNumber outer_spoint ,
361- inner_spoint ;
362-
363- Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
364- Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
365-
366- Relids required_outer = calc_nestloop_required_outer (outer_path ,inner_path );
367-
368- ParamPathInfo * param_info = get_joinrel_parampathinfo (root ,
369- joinrel ,
370- outer_path ,
371- inner_path ,
372- extra -> sjinfo ,
373- required_outer ,
374- & restrict_clauses );
375-
376- get_spoint_attnums ((FuncExpr * )arg1 ,outerrel ,innerrel ,
377- & outer_spoint ,& inner_spoint );
378-
379- create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
380- param_info ,restrict_clauses ,required_outer ,
381- get_const_val ((Const * )arg2 ),
382- outer_spoint ,inner_spoint );
383-
401+ try_crossmatch_path (restrInfo , (FuncExpr * )arg1 , (Const * )arg2 ,
402+ root ,joinrel ,outerrel ,innerrel ,extra );
384403break ;
385404}
386405else if (opExpr -> opno == get_commutator (Float8LessOperator )&&
387406IsA (arg1 ,Const )&& IsVarSpointDist (arg2 ,dist_func ))
388407{
389- AttrNumber outer_spoint ,
390- inner_spoint ;
391-
392- /* TODO: merge duplicate code */
393- Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
394- Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
395-
396- Relids required_outer = calc_nestloop_required_outer (outer_path ,inner_path );
397-
398- ParamPathInfo * param_info = get_joinrel_parampathinfo (root ,
399- joinrel ,
400- outer_path ,
401- inner_path ,
402- extra -> sjinfo ,
403- required_outer ,
404- & restrict_clauses );
405-
406- get_spoint_attnums ((FuncExpr * )arg2 ,outerrel ,innerrel ,
407- & outer_spoint ,& inner_spoint );
408-
409- create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
410- param_info ,restrict_clauses ,required_outer ,
411- get_const_val ((Const * )arg1 ),
412- outer_spoint ,inner_spoint );
408+ try_crossmatch_path (restrInfo , (FuncExpr * )arg2 , (Const * )arg1 ,
409+ root ,joinrel ,outerrel ,innerrel ,extra );
410+ break ;
413411}
414412}
415413}
@@ -433,7 +431,7 @@ create_crossmatch_plan(PlannerInfo *root,
433431
434432cscan = makeNode (CustomScan );
435433cscan -> scan .plan .targetlist = tlist ;
436- cscan -> scan .plan .qual = NIL ;
434+ cscan -> scan .plan .qual = joinclauses ;
437435cscan -> scan .scanrelid = 0 ;
438436cscan -> custom_scan_tlist = tlist ;/* output of this node */
439437
@@ -516,7 +514,7 @@ static TupleTableSlot *
516514crossmatch_exec (CustomScanState * node )
517515{
518516CrossmatchScanState * scan_state = (CrossmatchScanState * )node ;
519- TupleTableSlot * slot = node -> ss .ss_ScanTupleSlot ;
517+ TupleTableSlot * scanSlot = node -> ss .ss_ScanTupleSlot ;
520518HeapTuple htup = scan_state -> stored_tuple ;
521519
522520for (;;)
@@ -594,37 +592,43 @@ crossmatch_exec(CustomScanState *node)
594592
595593htup = heap_form_tuple (tupdesc ,values ,nulls );
596594scan_state -> stored_tuple = htup ;
595+
596+ /* Fill scanSlot with a new tuple */
597+ ExecStoreTuple (htup ,scanSlot ,InvalidBuffer , false);
597598}
598599}
599600
600601if (node -> ss .ps .ps_ProjInfo )
601602{
602603ExprDoneCond isDone ;
603- TupleTableSlot * result ;
604+ TupleTableSlot * resultSlot ;
604605
605606ResetExprContext (node -> ss .ps .ps_ProjInfo -> pi_exprContext );
606607
607- /* TODO: find a better way to fill 'ecxt_scantuple' */
608- node -> ss .ps .ps_ProjInfo -> pi_exprContext -> ecxt_scantuple = ExecStoreTuple (htup ,slot ,InvalidBuffer , false);
608+ /* Check join conditions */
609+ node -> ss .ps .ps_ExprContext -> ecxt_scantuple = scanSlot ;
610+ if (!ExecQual (node -> ss .ps .qual ,node -> ss .ps .ps_ExprContext , false))
611+ continue ;
609612
610- result = ExecProject (node -> ss .ps .ps_ProjInfo ,& isDone );
613+ node -> ss .ps .ps_ProjInfo -> pi_exprContext -> ecxt_scantuple = scanSlot ;
614+ resultSlot = ExecProject (node -> ss .ps .ps_ProjInfo ,& isDone );
611615
612616if (isDone != ExprEndResult )
613617{
614618node -> ss .ps .ps_TupFromTlist = (isDone == ExprMultipleResult );
615- return result ;
619+ return resultSlot ;
616620}
617621else
618622node -> ss .ps .ps_TupFromTlist = false;
619623}
620624else
621625{
622- TupleTableSlot * result ;
623-
624- result = ExecStoreTuple (htup ,node -> ss .ps .ps_ResultTupleSlot ,
625- InvalidBuffer , false);
626+ ExecStoreTuple (htup ,scanSlot ,InvalidBuffer , false);
626627
627- return result ;
628+ /* Check join conditions */
629+ node -> ss .ps .ps_ExprContext -> ecxt_scantuple = scanSlot ;
630+ if (ExecQual (node -> ss .ps .qual ,node -> ss .ps .ps_ExprContext , false))
631+ return scanSlot ;
628632}
629633}
630634}