使用自定义 postgres 扩展时外部数据库请求失败
Foreign database request fails when custom postgres extensions are used
假设我们在 2 个不同的服务器上有 2 个数据库:
- A 在 https://A.com/db
- B 在 https://B.com/db
在数据库 A 上,创建了一个 "city" table,此 table 使用 "earthdistance" 扩展名:
CREATE EXTENSION "uuid-ossp";
CREATE EXTENSION "cube"; -- required by earthdistance
CREATE EXTENSION "earthdistance";
CREATE TABLE "city" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v1mc(),
"name" VARCHAR(254) DEFAULT '',
"lat" DOUBLE PRECISION NOT NULL,
"lon" DOUBLE PRECISION NOT NULL
);
CREATE INDEX "city_geo_idx" ON "city" USING gist(ll_to_earth(lat, lon));
INSERT INTO "city" VALUES(DEFAULT, 'Hong Kong', 22.313031, 114.170623);
在数据库 B 上,创建了从 A 到 table "city" table 的外部引用:
CREATE EXTENSION "uuid-ossp";
CREATE EXTENSION "postgres_fdw";
CREATE SERVER "foreign_a"
FOREIGN DATA WRAPPER "postgres_fdw"
OPTIONS (host 'https://A.com/db', port '5432', dbname 'a');
CREATE USER MAPPING FOR "postgres"
SERVER "foreign_a"
OPTIONS (user 'postgres', password 'postgres');
CREATE FOREIGN TABLE "city" (
"id" UUID,
"name" VARCHAR(254) DEFAULT ''
)
SERVER "foreign_a"
OPTIONS (schema_name 'public', table_name 'city');
现阶段,运行出现SELECT * FROM "city"
returns以下错误:
[2018-06-25 19:05:17] [42704] ERROR: type "earth" does not exist
[2018-06-25 19:05:17] Where: Remote SQL command: SELECT id, name FROM public.city
[2018-06-25 19:05:17] SQL function "ll_to_earth" during inlining
在数据库 B 上添加缺少的扩展并不能解决问题:
CREATE EXTENSION "cube" SCHEMA "public";
CREATE EXTENSION "earthdistance" SCHEMA "public";
SELECT * FROM "city";
再次:
[2018-06-25 19:05:58] [42704] ERROR: type "earth" does not exist
[2018-06-25 19:05:58] Where: Remote SQL command: SELECT id, name FROM public.city
[2018-06-25 19:05:58] SQL function "ll_to_earth" during inlining
非常感谢任何帮助!
In the remote sessions opened by postgres_fdw, the search_path
parameter is set to just pg_catalog,
so that only built-in objects are visible without schema qualification. (...) this can pose a hazard for functions that are executed on the remote server via triggers or rules on remote tables.
这适用于引用类型 earth
的函数 ll_to_earth()
,该类型无法在当前搜索路径中找到。不幸的是,postgres_fdw
不给你改变远程 search_path
的机会(这似乎是扩展的一个弱点)。您可以通过在 pg_catalog
.
中安装扩展 cube
和 earthdistance
来解决此问题
-- on database A:
DROP EXTENSION cube CASCADE;
CREATE EXTENSION cube SCHEMA pg_catalog;
CREATE EXTENSION earthdistance SCHEMA pg_catalog;
警告。 Many Postgres experts 不建议在 pg_catalog.
中安装扩展 我个人也认为你不应该尝试 pg_catalog.
另一方面,在系统目录中安装一个经过验证的正式与 Postgres 一起发布的扩展是不犯罪,特别是因为我在这里看不到替代解决方案。
假设我们在 2 个不同的服务器上有 2 个数据库:
- A 在 https://A.com/db
- B 在 https://B.com/db
在数据库 A 上,创建了一个 "city" table,此 table 使用 "earthdistance" 扩展名:
CREATE EXTENSION "uuid-ossp";
CREATE EXTENSION "cube"; -- required by earthdistance
CREATE EXTENSION "earthdistance";
CREATE TABLE "city" (
"id" UUID PRIMARY KEY DEFAULT uuid_generate_v1mc(),
"name" VARCHAR(254) DEFAULT '',
"lat" DOUBLE PRECISION NOT NULL,
"lon" DOUBLE PRECISION NOT NULL
);
CREATE INDEX "city_geo_idx" ON "city" USING gist(ll_to_earth(lat, lon));
INSERT INTO "city" VALUES(DEFAULT, 'Hong Kong', 22.313031, 114.170623);
在数据库 B 上,创建了从 A 到 table "city" table 的外部引用:
CREATE EXTENSION "uuid-ossp";
CREATE EXTENSION "postgres_fdw";
CREATE SERVER "foreign_a"
FOREIGN DATA WRAPPER "postgres_fdw"
OPTIONS (host 'https://A.com/db', port '5432', dbname 'a');
CREATE USER MAPPING FOR "postgres"
SERVER "foreign_a"
OPTIONS (user 'postgres', password 'postgres');
CREATE FOREIGN TABLE "city" (
"id" UUID,
"name" VARCHAR(254) DEFAULT ''
)
SERVER "foreign_a"
OPTIONS (schema_name 'public', table_name 'city');
现阶段,运行出现SELECT * FROM "city"
returns以下错误:
[2018-06-25 19:05:17] [42704] ERROR: type "earth" does not exist
[2018-06-25 19:05:17] Where: Remote SQL command: SELECT id, name FROM public.city
[2018-06-25 19:05:17] SQL function "ll_to_earth" during inlining
在数据库 B 上添加缺少的扩展并不能解决问题:
CREATE EXTENSION "cube" SCHEMA "public";
CREATE EXTENSION "earthdistance" SCHEMA "public";
SELECT * FROM "city";
再次:
[2018-06-25 19:05:58] [42704] ERROR: type "earth" does not exist
[2018-06-25 19:05:58] Where: Remote SQL command: SELECT id, name FROM public.city
[2018-06-25 19:05:58] SQL function "ll_to_earth" during inlining
非常感谢任何帮助!
In the remote sessions opened by postgres_fdw, the
search_path
parameter is set to justpg_catalog,
so that only built-in objects are visible without schema qualification. (...) this can pose a hazard for functions that are executed on the remote server via triggers or rules on remote tables.
这适用于引用类型 earth
的函数 ll_to_earth()
,该类型无法在当前搜索路径中找到。不幸的是,postgres_fdw
不给你改变远程 search_path
的机会(这似乎是扩展的一个弱点)。您可以通过在 pg_catalog
.
cube
和 earthdistance
来解决此问题
-- on database A:
DROP EXTENSION cube CASCADE;
CREATE EXTENSION cube SCHEMA pg_catalog;
CREATE EXTENSION earthdistance SCHEMA pg_catalog;
警告。 Many Postgres experts 不建议在 pg_catalog.
中安装扩展 我个人也认为你不应该尝试 pg_catalog.
另一方面,在系统目录中安装一个经过验证的正式与 Postgres 一起发布的扩展是不犯罪,特别是因为我在这里看不到替代解决方案。