diff options
-rw-r--r-- | contrib/postgres_fdw/deparse.c | 72 | ||||
-rw-r--r-- | contrib/postgres_fdw/expected/postgres_fdw.out | 25 | ||||
-rw-r--r-- | contrib/postgres_fdw/sql/postgres_fdw.sql | 12 |
3 files changed, 107 insertions, 2 deletions
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 8f4d8a50226..a9766f97346 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -37,11 +37,14 @@ #include "access/sysattr.h" #include "access/table.h" #include "catalog/pg_aggregate.h" +#include "catalog/pg_authid.h" #include "catalog/pg_collation.h" #include "catalog/pg_namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_opfamily.h" #include "catalog/pg_proc.h" +#include "catalog/pg_ts_config.h" +#include "catalog/pg_ts_dict.h" #include "catalog/pg_type.h" #include "commands/defrem.h" #include "nodes/makefuncs.h" @@ -385,6 +388,75 @@ foreign_expr_walker(Node *node, Const *c = (Const *) node; /* + * Constants of regproc and related types can't be shipped + * unless the referenced object is shippable. But NULL's ok. + * (See also the related code in dependency.c.) + */ + if (!c->constisnull) + { + switch (c->consttype) + { + case REGPROCOID: + case REGPROCEDUREOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + ProcedureRelationId, fpinfo)) + return false; + break; + case REGOPEROID: + case REGOPERATOROID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + OperatorRelationId, fpinfo)) + return false; + break; + case REGCLASSOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + RelationRelationId, fpinfo)) + return false; + break; + case REGTYPEOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + TypeRelationId, fpinfo)) + return false; + break; + case REGCOLLATIONOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + CollationRelationId, fpinfo)) + return false; + break; + case REGCONFIGOID: + + /* + * For text search objects only, we weaken the + * normal shippability criterion to allow all OIDs + * below FirstNormalObjectId. Without this, none + * of the initdb-installed TS configurations would + * be shippable, which would be quite annoying. + */ + if (DatumGetObjectId(c->constvalue) >= FirstNormalObjectId && + !is_shippable(DatumGetObjectId(c->constvalue), + TSConfigRelationId, fpinfo)) + return false; + break; + case REGDICTIONARYOID: + if (DatumGetObjectId(c->constvalue) >= FirstNormalObjectId && + !is_shippable(DatumGetObjectId(c->constvalue), + TSDictionaryRelationId, fpinfo)) + return false; + break; + case REGNAMESPACEOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + NamespaceRelationId, fpinfo)) + return false; + break; + case REGROLEOID: + if (!is_shippable(DatumGetObjectId(c->constvalue), + AuthIdRelationId, fpinfo)) + return false; + break; + } + } + + /* * If the constant has nondefault collation, either it's of a * non-builtin type, or it reflects folding of a CollateExpr. * It's unsafe to send to the remote unless it's used in a diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index a6c1b162758..ebf9ea35988 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -1163,12 +1163,35 @@ SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' EN Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" (4 rows) --- check schema-qualification of regconfig constant +-- a regconfig constant referring to this text search configuration +-- is initially unshippable CREATE TEXT SEARCH CONFIGURATION public.custom_search (COPY = pg_catalog.english); EXPLAIN (VERBOSE, COSTS OFF) SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + QUERY PLAN +------------------------------------------------------------------------- + Foreign Scan on public.ft1 + Output: c1, to_tsvector('custom_search'::regconfig, c3) + Filter: (length(to_tsvector('custom_search'::regconfig, ft1.c3)) > 0) + Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1" WHERE (("C 1" = 642)) +(4 rows) + +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; + c1 | to_tsvector +-----+------------- + 642 | '00642':1 +(1 row) + +-- but if it's in a shippable extension, it can be shipped +ALTER EXTENSION postgres_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search; +-- however, that doesn't flush the shippability cache, so do a quick reconnect +\c - +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index a4f988fdb82..b7817c5a415 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -442,7 +442,8 @@ SELECT * FROM ft1 WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END; --- check schema-qualification of regconfig constant +-- a regconfig constant referring to this text search configuration +-- is initially unshippable CREATE TEXT SEARCH CONFIGURATION public.custom_search (COPY = pg_catalog.english); EXPLAIN (VERBOSE, COSTS OFF) @@ -450,6 +451,15 @@ SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; +-- but if it's in a shippable extension, it can be shipped +ALTER EXTENSION postgres_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search; +-- however, that doesn't flush the shippability cache, so do a quick reconnect +\c - +EXPLAIN (VERBOSE, COSTS OFF) +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; +SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1 +WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0; -- =================================================================== -- JOIN queries |