@@ -49,6 +49,9 @@ static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
49
49
static List * subbuild_joinrel_joinlist (RelOptInfo * joinrel ,
50
50
List * joininfo_list ,
51
51
List * new_joininfo );
52
+ static void set_foreign_rel_properties (RelOptInfo * joinrel ,
53
+ RelOptInfo * outer_rel , RelOptInfo * inner_rel );
54
+ static void add_join_rel (PlannerInfo * root , RelOptInfo * joinrel );
52
55
53
56
54
57
/*
@@ -327,6 +330,82 @@ find_join_rel(PlannerInfo *root, Relids relids)
327
330
return NULL ;
328
331
}
329
332
333
+ /*
334
+ * set_foreign_rel_properties
335
+ * Set up foreign-join fields if outer and inner relation are foreign
336
+ * tables (or joins) belonging to the same server and assigned to the same
337
+ * user to check access permissions as.
338
+ *
339
+ * In addition to an exact match of userid, we allow the case where one side
340
+ * has zero userid (implying current user) and the other side has explicit
341
+ * userid that happens to equal the current user; but in that case, pushdown of
342
+ * the join is only valid for the current user. The useridiscurrent field
343
+ * records whether we had to make such an assumption for this join or any
344
+ * sub-join.
345
+ *
346
+ * Otherwise these fields are left invalid, so GetForeignJoinPaths will not be
347
+ * called for the join relation.
348
+ *
349
+ */
350
+ static void
351
+ set_foreign_rel_properties (RelOptInfo * joinrel , RelOptInfo * outer_rel ,
352
+ RelOptInfo * inner_rel )
353
+ {
354
+ if (OidIsValid (outer_rel -> serverid ) &&
355
+ inner_rel -> serverid == outer_rel -> serverid )
356
+ {
357
+ if (inner_rel -> userid == outer_rel -> userid )
358
+ {
359
+ joinrel -> serverid = outer_rel -> serverid ;
360
+ joinrel -> userid = outer_rel -> userid ;
361
+ joinrel -> useridiscurrent = outer_rel -> useridiscurrent || inner_rel -> useridiscurrent ;
362
+ joinrel -> fdwroutine = outer_rel -> fdwroutine ;
363
+ }
364
+ else if (!OidIsValid (inner_rel -> userid ) &&
365
+ outer_rel -> userid == GetUserId ())
366
+ {
367
+ joinrel -> serverid = outer_rel -> serverid ;
368
+ joinrel -> userid = outer_rel -> userid ;
369
+ joinrel -> useridiscurrent = true;
370
+ joinrel -> fdwroutine = outer_rel -> fdwroutine ;
371
+ }
372
+ else if (!OidIsValid (outer_rel -> userid ) &&
373
+ inner_rel -> userid == GetUserId ())
374
+ {
375
+ joinrel -> serverid = outer_rel -> serverid ;
376
+ joinrel -> userid = inner_rel -> userid ;
377
+ joinrel -> useridiscurrent = true;
378
+ joinrel -> fdwroutine = outer_rel -> fdwroutine ;
379
+ }
380
+ }
381
+ }
382
+
383
+ /*
384
+ * add_join_rel
385
+ * Add given join relation to the list of join relations in the given
386
+ * PlannerInfo. Also add it to the auxiliary hashtable if there is one.
387
+ */
388
+ static void
389
+ add_join_rel (PlannerInfo * root , RelOptInfo * joinrel )
390
+ {
391
+ /* GEQO requires us to append the new joinrel to the end of the list! */
392
+ root -> join_rel_list = lappend (root -> join_rel_list , joinrel );
393
+
394
+ /* store it into the auxiliary hashtable if there is one. */
395
+ if (root -> join_rel_hash )
396
+ {
397
+ JoinHashEntry * hentry ;
398
+ bool found ;
399
+
400
+ hentry = (JoinHashEntry * ) hash_search (root -> join_rel_hash ,
401
+ & (joinrel -> relids ),
402
+ HASH_ENTER ,
403
+ & found );
404
+ Assert (!found );
405
+ hentry -> join_rel = joinrel ;
406
+ }
407
+ }
408
+
330
409
/*
331
410
* build_join_rel
332
411
* Returns relation entry corresponding to the union of two given rels,
@@ -425,46 +504,8 @@ build_join_rel(PlannerInfo *root,
425
504
joinrel -> joininfo = NIL ;
426
505
joinrel -> has_eclass_joins = false;
427
506
428
- /*
429
- * Set up foreign-join fields if outer and inner relation are foreign
430
- * tables (or joins) belonging to the same server and assigned to the same
431
- * user to check access permissions as. In addition to an exact match of
432
- * userid, we allow the case where one side has zero userid (implying
433
- * current user) and the other side has explicit userid that happens to
434
- * equal the current user; but in that case, pushdown of the join is only
435
- * valid for the current user. The useridiscurrent field records whether
436
- * we had to make such an assumption for this join or any sub-join.
437
- *
438
- * Otherwise these fields are left invalid, so GetForeignJoinPaths will
439
- * not be called for the join relation.
440
- */
441
- if (OidIsValid (outer_rel -> serverid ) &&
442
- inner_rel -> serverid == outer_rel -> serverid )
443
- {
444
- if (inner_rel -> userid == outer_rel -> userid )
445
- {
446
- joinrel -> serverid = outer_rel -> serverid ;
447
- joinrel -> userid = outer_rel -> userid ;
448
- joinrel -> useridiscurrent = outer_rel -> useridiscurrent || inner_rel -> useridiscurrent ;
449
- joinrel -> fdwroutine = outer_rel -> fdwroutine ;
450
- }
451
- else if (!OidIsValid (inner_rel -> userid ) &&
452
- outer_rel -> userid == GetUserId ())
453
- {
454
- joinrel -> serverid = outer_rel -> serverid ;
455
- joinrel -> userid = outer_rel -> userid ;
456
- joinrel -> useridiscurrent = true;
457
- joinrel -> fdwroutine = outer_rel -> fdwroutine ;
458
- }
459
- else if (!OidIsValid (outer_rel -> userid ) &&
460
- inner_rel -> userid == GetUserId ())
461
- {
462
- joinrel -> serverid = outer_rel -> serverid ;
463
- joinrel -> userid = inner_rel -> userid ;
464
- joinrel -> useridiscurrent = true;
465
- joinrel -> fdwroutine = outer_rel -> fdwroutine ;
466
- }
467
- }
507
+ /* Compute information relevant to the foreign relations. */
508
+ set_foreign_rel_properties (joinrel , outer_rel , inner_rel );
468
509
469
510
/*
470
511
* Create a new tlist containing just the vars that need to be output from
@@ -532,25 +573,8 @@ build_join_rel(PlannerInfo *root,
532
573
is_parallel_safe (root , (Node * ) joinrel -> reltarget -> exprs ))
533
574
joinrel -> consider_parallel = true;
534
575
535
- /*
536
- * Add the joinrel to the query's joinrel list, and store it into the
537
- * auxiliary hashtable if there is one. NB: GEQO requires us to append
538
- * the new joinrel to the end of the list!
539
- */
540
- root -> join_rel_list = lappend (root -> join_rel_list , joinrel );
541
-
542
- if (root -> join_rel_hash )
543
- {
544
- JoinHashEntry * hentry ;
545
- bool found ;
546
-
547
- hentry = (JoinHashEntry * ) hash_search (root -> join_rel_hash ,
548
- & (joinrel -> relids ),
549
- HASH_ENTER ,
550
- & found );
551
- Assert (!found );
552
- hentry -> join_rel = joinrel ;
553
- }
576
+ /* Add the joinrel to the PlannerInfo. */
577
+ add_join_rel (root , joinrel );
554
578
555
579
/*
556
580
* Also, if dynamic-programming join search is active, add the new joinrel
0 commit comments