@@ -263,7 +263,6 @@ create_crossmatch_path(PlannerInfo *root,
263
263
Oid outer_idx ;
264
264
Oid inner_idx ;
265
265
266
- /* TODO: use actual column numbers */
267
266
if ((outer_idx = pick_suitable_index (outer_rel , outer_spoint )) == InvalidOid ||
268
267
(inner_idx = pick_suitable_index (inner_rel , inner_spoint )) == InvalidOid )
269
268
{
@@ -297,6 +296,49 @@ create_crossmatch_path(PlannerInfo *root,
297
296
add_path (joinrel , & result -> cpath .path );
298
297
}
299
298
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
+
300
342
static void
301
343
join_pathlist_hook (PlannerInfo * root ,
302
344
RelOptInfo * joinrel ,
@@ -308,7 +350,6 @@ join_pathlist_hook(PlannerInfo *root,
308
350
ListCell * restr ;
309
351
text * dist_func_name = cstring_to_text ("dist(spoint,spoint)" );
310
352
Oid dist_func ;
311
- List * restrict_clauses = extra -> restrictlist ;
312
353
Relids required_relids = NULL ;
313
354
314
355
if (outerrel -> reloptkind == RELOPT_BASEREL &&
@@ -357,59 +398,16 @@ join_pathlist_hook(PlannerInfo *root,
357
398
if (opExpr -> opno == Float8LessOperator &&
358
399
IsVarSpointDist (arg1 , dist_func ) && IsA (arg2 , Const ))
359
400
{
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 );
384
403
break ;
385
404
}
386
405
else if (opExpr -> opno == get_commutator (Float8LessOperator ) &&
387
406
IsA (arg1 , Const ) && IsVarSpointDist (arg2 , dist_func ))
388
407
{
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 ;
413
411
}
414
412
}
415
413
}
@@ -433,7 +431,7 @@ create_crossmatch_plan(PlannerInfo *root,
433
431
434
432
cscan = makeNode (CustomScan );
435
433
cscan -> scan .plan .targetlist = tlist ;
436
- cscan -> scan .plan .qual = NIL ;
434
+ cscan -> scan .plan .qual = joinclauses ;
437
435
cscan -> scan .scanrelid = 0 ;
438
436
cscan -> custom_scan_tlist = tlist ; /* output of this node */
439
437
@@ -516,7 +514,7 @@ static TupleTableSlot *
516
514
crossmatch_exec (CustomScanState * node )
517
515
{
518
516
CrossmatchScanState * scan_state = (CrossmatchScanState * ) node ;
519
- TupleTableSlot * slot = node -> ss .ss_ScanTupleSlot ;
517
+ TupleTableSlot * scanSlot = node -> ss .ss_ScanTupleSlot ;
520
518
HeapTuple htup = scan_state -> stored_tuple ;
521
519
522
520
for (;;)
@@ -594,37 +592,43 @@ crossmatch_exec(CustomScanState *node)
594
592
595
593
htup = heap_form_tuple (tupdesc , values , nulls );
596
594
scan_state -> stored_tuple = htup ;
595
+
596
+ /* Fill scanSlot with a new tuple */
597
+ ExecStoreTuple (htup , scanSlot , InvalidBuffer , false);
597
598
}
598
599
}
599
600
600
601
if (node -> ss .ps .ps_ProjInfo )
601
602
{
602
603
ExprDoneCond isDone ;
603
- TupleTableSlot * result ;
604
+ TupleTableSlot * resultSlot ;
604
605
605
606
ResetExprContext (node -> ss .ps .ps_ProjInfo -> pi_exprContext );
606
607
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 ;
609
612
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 );
611
615
612
616
if (isDone != ExprEndResult )
613
617
{
614
618
node -> ss .ps .ps_TupFromTlist = (isDone == ExprMultipleResult );
615
- return result ;
619
+ return resultSlot ;
616
620
}
617
621
else
618
622
node -> ss .ps .ps_TupFromTlist = false;
619
623
}
620
624
else
621
625
{
622
- TupleTableSlot * result ;
623
-
624
- result = ExecStoreTuple (htup , node -> ss .ps .ps_ResultTupleSlot ,
625
- InvalidBuffer , false);
626
+ ExecStoreTuple (htup , scanSlot , InvalidBuffer , false);
626
627
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 ;
628
632
}
629
633
}
630
634
}
0 commit comments