@@ -78,6 +78,29 @@ static CustomScanMethodscrossmatch_plan_methods;
78
78
static CustomExecMethods crossmatch_exec_methods ;
79
79
80
80
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
+
81
104
static float8
82
105
get_const_val (Const * node )
83
106
{
@@ -174,6 +197,26 @@ pick_suitable_index(Oid relation, AttrNumber column)
174
197
return found_index ;
175
198
}
176
199
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
+
177
220
static Path *
178
221
crossmatch_find_cheapest_path (PlannerInfo * root ,
179
222
RelOptInfo * joinrel ,
@@ -211,7 +254,9 @@ create_crossmatch_path(PlannerInfo *root,
211
254
ParamPathInfo * param_info ,
212
255
List * restrict_clauses ,
213
256
Relids required_outer ,
214
- float8 threshold )
257
+ float8 threshold ,
258
+ AttrNumber outer_spoint ,
259
+ AttrNumber inner_spoint )
215
260
{
216
261
CrossmatchJoinPath * result ;
217
262
@@ -221,8 +266,8 @@ create_crossmatch_path(PlannerInfo *root,
221
266
Oid inner_idx ;
222
267
223
268
/* 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 )
226
271
{
227
272
return ;
228
273
}
@@ -280,7 +325,7 @@ join_pathlist_hook(PlannerInfo *root,
280
325
PointerGetDatum (dist_func_name )));
281
326
282
327
if (dist_func == InvalidOid )
283
- elog ( ERROR , "function dist not found!" ) ;
328
+ return ;
284
329
285
330
if (set_join_pathlist_next )
286
331
set_join_pathlist_next (root ,
@@ -312,10 +357,11 @@ join_pathlist_hook(PlannerInfo *root,
312
357
arg2 = lsecond (opExpr -> args );
313
358
314
359
if (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 ))
318
361
{
362
+ AttrNumber outer_spoint ,
363
+ inner_spoint ;
364
+
319
365
Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
320
366
Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
321
367
@@ -329,17 +375,22 @@ join_pathlist_hook(PlannerInfo *root,
329
375
required_outer ,
330
376
& restrict_clauses );
331
377
378
+ get_spoint_attnums ((FuncExpr * )arg1 ,outerrel ,innerrel ,
379
+ & outer_spoint ,& inner_spoint );
380
+
332
381
create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
333
382
param_info ,restrict_clauses ,required_outer ,
334
- get_const_val ((Const * )arg2 ));
383
+ get_const_val ((Const * )arg2 ),
384
+ outer_spoint ,inner_spoint );
335
385
336
386
break ;
337
387
}
338
388
else 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 ))
342
390
{
391
+ AttrNumber outer_spoint ,
392
+ inner_spoint ;
393
+
343
394
/* TODO: merge duplicate code */
344
395
Path * outer_path = crossmatch_find_cheapest_path (root ,joinrel ,outerrel );
345
396
Path * inner_path = crossmatch_find_cheapest_path (root ,joinrel ,innerrel );
@@ -354,9 +405,13 @@ join_pathlist_hook(PlannerInfo *root,
354
405
required_outer ,
355
406
& restrict_clauses );
356
407
408
+ get_spoint_attnums ((FuncExpr * )arg2 ,outerrel ,innerrel ,
409
+ & outer_spoint ,& inner_spoint );
410
+
357
411
create_crossmatch_path (root ,joinrel ,outer_path ,inner_path ,
358
412
param_info ,restrict_clauses ,required_outer ,
359
- get_const_val ((Const * )arg1 ));
413
+ get_const_val ((Const * )arg1 ),
414
+ outer_spoint ,inner_spoint );
360
415
}
361
416
}
362
417
}
@@ -372,46 +427,35 @@ create_crossmatch_plan(PlannerInfo *root,
372
427
{
373
428
CrossmatchJoinPath * gpath = (CrossmatchJoinPath * )best_path ;
374
429
List * joinrestrictclauses = gpath -> joinrestrictinfo ;
375
- List * joinclauses ;/* NOTE: do we really need it? */
376
- List * otherclauses ;
430
+ List * joinclauses ;
377
431
CustomScan * cscan ;
378
- float8 * threshold = palloc (sizeof (float8 ));
379
432
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);
391
435
392
436
cscan = makeNode (CustomScan );
393
437
cscan -> scan .plan .targetlist = tlist ;
394
- cscan -> custom_scan_tlist = tlist ;/* output of this node */
395
438
cscan -> scan .plan .qual = NIL ;
396
439
cscan -> scan .scanrelid = 0 ;
440
+ cscan -> custom_scan_tlist = tlist ;/* output of this node */
397
441
398
442
cscan -> flags = best_path -> flags ;
399
443
cscan -> methods = & crossmatch_plan_methods ;
400
444
401
- cscan -> custom_private = list_make2 (list_make4_oid (gpath -> outer_idx ,
445
+ cscan -> custom_private = list_make1 (list_make4_oid (gpath -> outer_idx ,
402
446
gpath -> outer_rel ,
403
447
gpath -> 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 ))) ;
407
451
408
452
return & cscan -> scan .plan ;
409
453
}
410
454
411
455
static Node *
412
456
crossmatch_create_scan_state (CustomScan * node )
413
457
{
414
- CrossmatchScanState * scan_state = palloc0 (sizeof (CrossmatchScanState ));
458
+ CrossmatchScanState * scan_state = palloc0 (sizeof (CrossmatchScanState ));
415
459
416
460
NodeSetTag (scan_state ,T_CustomScanState );
417
461
scan_state -> css .flags = node -> flags ;
@@ -426,7 +470,7 @@ crossmatch_create_scan_state(CustomScan *node)
426
470
scan_state -> outer_rel = lsecond_oid (linitial (node -> custom_private ));
427
471
scan_state -> inner_idx = lthird_oid (linitial (node -> custom_private ));
428
472
scan_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 ) ));
430
474
431
475
return (Node * )scan_state ;
432
476
}
@@ -533,8 +577,14 @@ crossmatch_exec(CustomScanState *node)
533
577
node -> ss .ps .ps_TupFromTlist = false;
534
578
}
535
579
else
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
+ }
538
588
}
539
589
}
540
590
@@ -572,6 +622,12 @@ crossmatch_explain(CustomScanState *node, List *ancestors, ExplainState *es)
572
622
appendStringInfo (& str ,"%s" ,
573
623
get_rel_name (scan_state -> inner_idx ));
574
624
ExplainPropertyText ("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 );
575
631
}
576
632
577
633
void