-- ============================================================================= -- FDW 反向映射配置(测试环境)— 在 test_etl_feiqiu 数据库中执行 -- 用途:通过 postgres_fdw 将 test_zqyy_app.member_birthday_manual 只读映射到 -- test_etl_feiqiu,使 ETL DWS 任务在测试环境下可读取手动补录的会员生日数据。 -- 方向:test_etl_feiqiu → test_zqyy_app(与 setup_fdw_test.sql 方向相反) -- 前提:test_zqyy_app 数据库已部署 member_birthday_manual 表(见 C2 迁移脚本) -- 基于 setup_fdw_reverse.sql,仅将目标库替换为测试库 -- Requirements: 5.3 -- ============================================================================= -- ----------------------------------------------------------------------------- -- 1. 安装 postgres_fdw 扩展(如已安装则跳过) -- ----------------------------------------------------------------------------- CREATE EXTENSION IF NOT EXISTS postgres_fdw; -- ----------------------------------------------------------------------------- -- 2. 创建外部服务器(指向 test_zqyy_app 测试业务库) -- 部署时按实际环境替换 host / port -- ----------------------------------------------------------------------------- CREATE SERVER IF NOT EXISTS test_zqyy_app_server FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'localhost', dbname 'test_zqyy_app', port '5432'); -- ----------------------------------------------------------------------------- -- 3. 创建用户映射(只读角色) -- etl_user = test_etl_feiqiu 侧的 ETL 连接角色 -- app_reader = test_zqyy_app 侧的只读角色 -- 密码占位符 '***',部署时替换为真实凭据 -- ----------------------------------------------------------------------------- CREATE USER MAPPING IF NOT EXISTS FOR etl_user SERVER test_zqyy_app_server OPTIONS (user 'app_reader', password '***'); -- ----------------------------------------------------------------------------- -- 4. 创建目标 schema(存放来自业务库的外部表) -- ----------------------------------------------------------------------------- CREATE SCHEMA IF NOT EXISTS fdw_app; -- ----------------------------------------------------------------------------- -- 5. 创建外部表:member_birthday_manual -- 映射 test_zqyy_app.public.member_birthday_manual,ETL 侧只读 -- 列定义须与源表结构保持一致(见 C2 迁移脚本) -- ----------------------------------------------------------------------------- CREATE FOREIGN TABLE IF NOT EXISTS fdw_app.member_birthday_manual ( id BIGINT, member_id BIGINT, birthday_value DATE, recorded_by_assistant_id BIGINT, recorded_by_name VARCHAR(50), recorded_at TIMESTAMPTZ, source VARCHAR(20), site_id BIGINT ) SERVER test_zqyy_app_server OPTIONS (schema_name 'public', table_name 'member_birthday_manual'); -- ----------------------------------------------------------------------------- -- 6. 授权:允许 etl_user 访问 fdw_app schema 及其外部表 -- ----------------------------------------------------------------------------- GRANT USAGE ON SCHEMA fdw_app TO etl_user; GRANT SELECT ON ALL TABLES IN SCHEMA fdw_app TO etl_user; -- 未来新增的外部表自动授权 ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_app GRANT SELECT ON TABLES TO etl_user; -- ============================================================================= -- 回滚脚本(按逆序执行) -- ============================================================================= -- ALTER DEFAULT PRIVILEGES IN SCHEMA fdw_app REVOKE SELECT ON TABLES FROM etl_user; -- REVOKE SELECT ON ALL TABLES IN SCHEMA fdw_app FROM etl_user; -- REVOKE USAGE ON SCHEMA fdw_app FROM etl_user; -- DROP FOREIGN TABLE IF EXISTS fdw_app.member_birthday_manual; -- DROP SCHEMA IF EXISTS fdw_app CASCADE; -- DROP USER MAPPING IF EXISTS FOR etl_user SERVER test_zqyy_app_server; -- DROP SERVER IF EXISTS test_zqyy_app_server CASCADE; -- ============================================================================= -- 验证 SQL -- ============================================================================= -- 1. 确认外部服务器 test_zqyy_app_server 存在 -- SELECT srvname, srvowner::regrole, srvoptions -- FROM pg_foreign_server -- WHERE srvname = 'test_zqyy_app_server'; -- 预期:1 行,srvoptions 包含 dbname=test_zqyy_app -- 2. 确认用户映射存在 -- SELECT um.umid, s.srvname, um.umoptions -- FROM pg_user_mapping um -- JOIN pg_foreign_server s ON um.umserver = s.oid -- WHERE s.srvname = 'test_zqyy_app_server'; -- 预期:1 行 -- 3. 确认 fdw_app schema 存在 -- SELECT schema_name -- FROM information_schema.schemata -- WHERE schema_name = 'fdw_app'; -- 预期:1 行 -- 4. 确认外部表 fdw_app.member_birthday_manual 存在且列完整 -- SELECT column_name, data_type -- FROM information_schema.columns -- WHERE table_schema = 'fdw_app' -- AND table_name = 'member_birthday_manual' -- ORDER BY ordinal_position; -- 预期:8 列(id, member_id, birthday_value, recorded_by_assistant_id, -- recorded_by_name, recorded_at, source, site_id) -- 5. 确认外部表可读取(需 test_zqyy_app 侧表已存在且有网络连通性) -- SELECT COUNT(*) FROM fdw_app.member_birthday_manual; -- 预期:返回行数(可能为 0)