Skip to content

Commit 9ba24fd

Browse files
committed
Merge branch 'master' of git://git.postgresql.org/git/postgresql into ci2
2 parents 7446b78 + cef5dbb commit 9ba24fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+3949
-796
lines changed

configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10600,7 +10600,7 @@ fi
1060010600
## Header files
1060110601
##
1060210602

10603-
for ac_header in atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h
10603+
for ac_header in atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h
1060410604
do :
1060510605
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
1060610606
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"

configure.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ AC_SUBST(UUID_LIBS)
11791179
## Header files
11801180
##
11811181

1182-
AC_CHECK_HEADERS([atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h])
1182+
AC_CHECK_HEADERS([atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h])
11831183

11841184
# On BSD, test for net/if.h will fail unless sys/socket.h
11851185
# is included first.

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,35 @@ SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1
16201620
| 21
16211621
(10 rows)
16221622

1623+
-- full outer join + WHERE clause with shippable extensions set
1624+
EXPLAIN (VERBOSE, COSTS OFF)
1625+
SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1626+
QUERY PLAN
1627+
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1628+
Limit
1629+
Output: t1.c1, t2.c2, t1.c3
1630+
-> Foreign Scan
1631+
Output: t1.c1, t2.c2, t1.c3
1632+
Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1633+
Remote SQL: SELECT r1."C 1", r1.c3, r2.c2 FROM ("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) WHERE ((public.postgres_fdw_abs(r1."C 1") > 0))
1634+
(6 rows)
1635+
1636+
ALTER SERVER loopback OPTIONS (DROP extensions);
1637+
-- full outer join + WHERE clause with shippable extensions not set
1638+
EXPLAIN (VERBOSE, COSTS OFF)
1639+
SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1640+
QUERY PLAN
1641+
-------------------------------------------------------------------------------------------------------------------------------
1642+
Limit
1643+
Output: t1.c1, t2.c2, t1.c3
1644+
-> Foreign Scan
1645+
Output: t1.c1, t2.c2, t1.c3
1646+
Filter: (postgres_fdw_abs(t1.c1) > 0)
1647+
Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1648+
Remote SQL: SELECT r1."C 1", r1.c3, r2.c2 FROM ("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
1649+
(7 rows)
1650+
1651+
ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
16231652
-- join two tables with FOR UPDATE clause
16241653
-- tests whole-row reference for row marks
16251654
EXPLAIN (VERBOSE, COSTS OFF)

contrib/postgres_fdw/postgres_fdw.c

Lines changed: 123 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,11 @@ static void add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
414414
static void add_foreign_grouping_paths(PlannerInfo *root,
415415
RelOptInfo *input_rel,
416416
RelOptInfo *grouped_rel);
417+
static void apply_server_options(PgFdwRelationInfo *fpinfo);
418+
static void apply_table_options(PgFdwRelationInfo *fpinfo);
419+
static void merge_fdw_options(PgFdwRelationInfo *fpinfo,
420+
const PgFdwRelationInfo *fpinfo_o,
421+
const PgFdwRelationInfo *fpinfo_i);
417422

418423

419424
/*
@@ -513,31 +518,8 @@ postgresGetForeignRelSize(PlannerInfo *root,
513518
fpinfo->shippable_extensions = NIL;
514519
fpinfo->fetch_size = 100;
515520

516-
foreach(lc, fpinfo->server->options)
517-
{
518-
DefElem *def = (DefElem *) lfirst(lc);
519-
520-
if (strcmp(def->defname, "use_remote_estimate") == 0)
521-
fpinfo->use_remote_estimate = defGetBoolean(def);
522-
else if (strcmp(def->defname, "fdw_startup_cost") == 0)
523-
fpinfo->fdw_startup_cost = strtod(defGetString(def), NULL);
524-
else if (strcmp(def->defname, "fdw_tuple_cost") == 0)
525-
fpinfo->fdw_tuple_cost = strtod(defGetString(def), NULL);
526-
else if (strcmp(def->defname, "extensions") == 0)
527-
fpinfo->shippable_extensions =
528-
ExtractExtensionList(defGetString(def), false);
529-
else if (strcmp(def->defname, "fetch_size") == 0)
530-
fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
531-
}
532-
foreach(lc, fpinfo->table->options)
533-
{
534-
DefElem *def = (DefElem *) lfirst(lc);
535-
536-
if (strcmp(def->defname, "use_remote_estimate") == 0)
537-
fpinfo->use_remote_estimate = defGetBoolean(def);
538-
else if (strcmp(def->defname, "fetch_size") == 0)
539-
fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
540-
}
521+
apply_server_options(fpinfo);
522+
apply_table_options(fpinfo);
541523

542524
/*
543525
* If the table or the server is configured to use remote estimates,
@@ -4114,6 +4096,15 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
41144096
if (fpinfo_o->local_conds || fpinfo_i->local_conds)
41154097
return false;
41164098

4099+
/*
4100+
* Merge FDW options. We might be tempted to do this after we have deemed
4101+
* the foreign join to be OK. But we must do this beforehand so that we
4102+
* know which quals can be evaluated on the foreign server, which might
4103+
* depend on shippable_extensions.
4104+
*/
4105+
fpinfo->server = fpinfo_o->server;
4106+
merge_fdw_options(fpinfo, fpinfo_o, fpinfo_i);
4107+
41174108
/*
41184109
* Separate restrict list into join quals and pushed-down (other) quals.
41194110
*
@@ -4279,15 +4270,6 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
42794270
/* Mark that this join can be pushed down safely */
42804271
fpinfo->pushdown_safe = true;
42814272

4282-
/*
4283-
* If user is willing to estimate cost for a scan of either of the joining
4284-
* relations using EXPLAIN, he intends to estimate scans on that relation
4285-
* more accurately. Then, it makes sense to estimate the cost of the join
4286-
* with that relation more accurately using EXPLAIN.
4287-
*/
4288-
fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate ||
4289-
fpinfo_i->use_remote_estimate;
4290-
42914273
/* Get user mapping */
42924274
if (fpinfo->use_remote_estimate)
42934275
{
@@ -4299,17 +4281,6 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
42994281
else
43004282
fpinfo->user = NULL;
43014283

4302-
/* Get foreign server */
4303-
fpinfo->server = fpinfo_o->server;
4304-
4305-
/*
4306-
* Since both the joining relations come from the same server, the server
4307-
* level options should have same value for both the relations. Pick from
4308-
* any side.
4309-
*/
4310-
fpinfo->fdw_startup_cost = fpinfo_o->fdw_startup_cost;
4311-
fpinfo->fdw_tuple_cost = fpinfo_o->fdw_tuple_cost;
4312-
43134284
/*
43144285
* Set cached relation costs to some negative value, so that we can detect
43154286
* when they are set to some sensible costs, during one (usually the
@@ -4318,15 +4289,6 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
43184289
fpinfo->rel_startup_cost = -1;
43194290
fpinfo->rel_total_cost = -1;
43204291

4321-
/*
4322-
* Set fetch size to maximum of the joining sides, since we are expecting
4323-
* the rows returned by the join to be proportional to the relation sizes.
4324-
*/
4325-
if (fpinfo_o->fetch_size > fpinfo_i->fetch_size)
4326-
fpinfo->fetch_size = fpinfo_o->fetch_size;
4327-
else
4328-
fpinfo->fetch_size = fpinfo_i->fetch_size;
4329-
43304292
/*
43314293
* Set the string describing this join relation to be used in EXPLAIN
43324294
* output of corresponding ForeignScan.
@@ -4384,6 +4346,110 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
43844346
}
43854347
}
43864348

4349+
/*
4350+
* Parse options from foreign server and apply them to fpinfo.
4351+
*
4352+
* New options might also require tweaking merge_fdw_options().
4353+
*/
4354+
static void
4355+
apply_server_options(PgFdwRelationInfo *fpinfo)
4356+
{
4357+
ListCell *lc;
4358+
4359+
foreach(lc, fpinfo->server->options)
4360+
{
4361+
DefElem *def = (DefElem *) lfirst(lc);
4362+
4363+
if (strcmp(def->defname, "use_remote_estimate") == 0)
4364+
fpinfo->use_remote_estimate = defGetBoolean(def);
4365+
else if (strcmp(def->defname, "fdw_startup_cost") == 0)
4366+
fpinfo->fdw_startup_cost = strtod(defGetString(def), NULL);
4367+
else if (strcmp(def->defname, "fdw_tuple_cost") == 0)
4368+
fpinfo->fdw_tuple_cost = strtod(defGetString(def), NULL);
4369+
else if (strcmp(def->defname, "extensions") == 0)
4370+
fpinfo->shippable_extensions =
4371+
ExtractExtensionList(defGetString(def), false);
4372+
else if (strcmp(def->defname, "fetch_size") == 0)
4373+
fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
4374+
}
4375+
}
4376+
4377+
/*
4378+
* Parse options from foreign table and apply them to fpinfo.
4379+
*
4380+
* New options might also require tweaking merge_fdw_options().
4381+
*/
4382+
static void
4383+
apply_table_options(PgFdwRelationInfo *fpinfo)
4384+
{
4385+
ListCell *lc;
4386+
4387+
foreach(lc, fpinfo->table->options)
4388+
{
4389+
DefElem *def = (DefElem *) lfirst(lc);
4390+
4391+
if (strcmp(def->defname, "use_remote_estimate") == 0)
4392+
fpinfo->use_remote_estimate = defGetBoolean(def);
4393+
else if (strcmp(def->defname, "fetch_size") == 0)
4394+
fpinfo->fetch_size = strtol(defGetString(def), NULL, 10);
4395+
}
4396+
}
4397+
4398+
/*
4399+
* Merge FDW options from input relations into a new set of options for a join
4400+
* or an upper rel.
4401+
*
4402+
* For a join relation, FDW-specific information about the inner and outer
4403+
* relations is provided using fpinfo_i and fpinfo_o. For an upper relation,
4404+
* fpinfo_o provides the information for the input relation; fpinfo_i is
4405+
* expected to NULL.
4406+
*/
4407+
static void
4408+
merge_fdw_options(PgFdwRelationInfo *fpinfo,
4409+
const PgFdwRelationInfo *fpinfo_o,
4410+
const PgFdwRelationInfo *fpinfo_i)
4411+
{
4412+
/* We must always have fpinfo_o. */
4413+
Assert(fpinfo_o);
4414+
4415+
/* fpinfo_i may be NULL, but if present the servers must both match. */
4416+
Assert(!fpinfo_i ||
4417+
fpinfo_i->server->serverid == fpinfo_o->server->serverid);
4418+
4419+
/*
4420+
* Copy the server specific FDW options. (For a join, both relations come
4421+
* from the same server, so the server options should have the same value
4422+
* for both relations.)
4423+
*/
4424+
fpinfo->fdw_startup_cost = fpinfo_o->fdw_startup_cost;
4425+
fpinfo->fdw_tuple_cost = fpinfo_o->fdw_tuple_cost;
4426+
fpinfo->shippable_extensions = fpinfo_o->shippable_extensions;
4427+
fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate;
4428+
fpinfo->fetch_size = fpinfo_o->fetch_size;
4429+
4430+
/* Merge the table level options from either side of the join. */
4431+
if (fpinfo_i)
4432+
{
4433+
/*
4434+
* We'll prefer to use remote estimates for this join if any table
4435+
* from either side of the join is using remote estimates. This is
4436+
* most likely going to be preferred since they're already willing to
4437+
* pay the price of a round trip to get the remote EXPLAIN. In any
4438+
* case it's not entirely clear how we might otherwise handle this
4439+
* best.
4440+
*/
4441+
fpinfo->use_remote_estimate = fpinfo_o->use_remote_estimate ||
4442+
fpinfo_i->use_remote_estimate;
4443+
4444+
/*
4445+
* Set fetch size to maximum of the joining sides, since we are
4446+
* expecting the rows returned by the join to be proportional to the
4447+
* relation sizes.
4448+
*/
4449+
fpinfo->fetch_size = Max(fpinfo_o->fetch_size, fpinfo_i->fetch_size);
4450+
}
4451+
}
4452+
43874453
/*
43884454
* postgresGetForeignJoinPaths
43894455
* Add possible ForeignPath to joinrel, if join is safe to push down.
@@ -4714,18 +4780,6 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
47144780
/* Safe to pushdown */
47154781
fpinfo->pushdown_safe = true;
47164782

4717-
/*
4718-
* If user is willing to estimate cost for a scan using EXPLAIN, he
4719-
* intends to estimate scans on that relation more accurately. Then, it
4720-
* makes sense to estimate the cost of the grouping on that relation more
4721-
* accurately using EXPLAIN.
4722-
*/
4723-
fpinfo->use_remote_estimate = ofpinfo->use_remote_estimate;
4724-
4725-
/* Copy startup and tuple cost as is from underneath input rel's fpinfo */
4726-
fpinfo->fdw_startup_cost = ofpinfo->fdw_startup_cost;
4727-
fpinfo->fdw_tuple_cost = ofpinfo->fdw_tuple_cost;
4728-
47294783
/*
47304784
* Set cached relation costs to some negative value, so that we can detect
47314785
* when they are set to some sensible costs, during one (usually the
@@ -4734,9 +4788,6 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
47344788
fpinfo->rel_startup_cost = -1;
47354789
fpinfo->rel_total_cost = -1;
47364790

4737-
/* Set fetch size same as that of underneath input rel's fpinfo */
4738-
fpinfo->fetch_size = ofpinfo->fetch_size;
4739-
47404791
/*
47414792
* Set the string describing this grouped relation to be used in EXPLAIN
47424793
* output of corresponding ForeignScan.
@@ -4812,13 +4863,13 @@ add_foreign_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
48124863
fpinfo->outerrel = input_rel;
48134864

48144865
/*
4815-
* Copy foreign table, foreign server, user mapping, shippable extensions
4816-
* etc. details from the input relation's fpinfo.
4866+
* Copy foreign table, foreign server, user mapping, FDW options etc.
4867+
* details from the input relation's fpinfo.
48174868
*/
48184869
fpinfo->table = ifpinfo->table;
48194870
fpinfo->server = ifpinfo->server;
48204871
fpinfo->user = ifpinfo->user;
4821-
fpinfo->shippable_extensions = ifpinfo->shippable_extensions;
4872+
merge_fdw_options(fpinfo, ifpinfo , NULL);
48224873

48234874
/* Assess if it is safe to push down aggregation and grouping. */
48244875
if (!foreign_grouping_ok(root, grouped_rel))

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,14 @@ SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT
447447
EXPLAIN (VERBOSE, COSTS OFF)
448448
SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
449449
SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
450+
-- full outer join + WHERE clause with shippable extensions set
451+
EXPLAIN (VERBOSE, COSTS OFF)
452+
SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
453+
ALTER SERVER loopback OPTIONS (DROP extensions);
454+
-- full outer join + WHERE clause with shippable extensions not set
455+
EXPLAIN (VERBOSE, COSTS OFF)
456+
SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
457+
ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
450458
-- join two tables with FOR UPDATE clause
451459
-- tests whole-row reference for row marks
452460
EXPLAIN (VERBOSE, COSTS OFF)

0 commit comments

Comments
 (0)