Data di dunia nyata sering tersebar: data master karyawan tinggal di database pusat, transaksi harian di database cabang, arsip lama di server terpisah. PostgreSQL menuntut satu koneksi memilih satu database dan tidak menyediakan sintaks nama_database.public.nama_tabel untuk melompat antar database — pembatasan yang mengejutkan pendatang baru dari MySQL. Extension postgres_fdw menjembatani celah itu: extension ini membuat tabel milik database PostgreSQL mana pun — di server yang sama maupun di seberang jaringan — tampak sebagai tabel lokal biasa yang bisa di-SELECT, di-join, bahkan di-UPDATE. Chapter ini membangun demo dua database lengkap di satu server: memasang extension, mendefinisikan objek koneksinya, membaca dan menulis data lintas database, lalu membedah rencana eksekusinya di balik layar.
Menyiapkan Dua Database #
Demo kita membutuhkan dua database di satu server: database kerja chapter ini berperan sebagai kantor cabang, dan database kedua sebagai kantor pusat pemilik data master. Perintah CREATE DATABASE tidak bisa dijalankan dari dalam database yang sedang tersambung, sehingga file pertama dijalankan dari database maintenance postgres, lalu berpindah ke database baru itu lewat meta-command \connect untuk membangun tabel masternya:
-- Demo postgres_fdw butuh DUA database: database kerja chapter ini berperan
-- sebagai "kantor cabang", database kedua sebagai "kantor pusat" pemilik
-- data master. CREATE DATABASE harus dijalankan dari database lain
-- (postgres), karena PostgreSQL tidak mengizinkan pembuatan database
-- dari dalam database yang sedang dipakai.
DROP DATABASE IF EXISTS kantor_pusat_fdw;
CREATE DATABASE kantor_pusat_fdw;
-- Pindah ke database pusat, lalu bangun tabel master-nya.
\connect kantor_pusat_fdw
CREATE TABLE karyawan (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text NOT NULL,
gaji integer NOT NULL
);
INSERT INTO karyawan VALUES
(1, 'Budi Santoso', 'Jakarta', 12500000),
(2, 'Siti Rahayu', 'Bandung', 9800000),
(3, 'Agus Wibowo', 'Surabaya', 10200000),
(4, 'Dewi Lestari', 'Jakarta', 8700000),
(5, 'Rina Marlina', 'Medan', 7600000),
(6, 'Tono Sutrisno', 'Bandung', 6900000);
CREATE TABLE cabang (
kode text PRIMARY KEY,
kota text NOT NULL,
manager text NOT NULL
);
INSERT INTO cabang VALUES
('JKT', 'Jakarta', 'Budi Santoso'),
('BDG', 'Bandung', 'Siti Rahayu'),
('SBY', 'Surabaya', 'Agus Wibowo');Output yang Dihasilkan:
DROP DATABASE
CREATE DATABASE
You are now connected to database "kantor_pusat_fdw" as user "postgres".
CREATE TABLE
INSERT 0 6
CREATE TABLE
INSERT 0 3Baris You are now connected to database "kantor_pusat_fdw" membuktikan psql berpindah database di tengah file; seluruh CREATE TABLE dan INSERT setelahnya dieksekusi di database pusat, bukan di postgres. Database pusat kini memegang dua tabel master — karyawan dengan enam baris dan cabang dengan tiga baris — yang selama sisa chapter akan kita baca dan tulis dari database cabang tanpa pernah keluar dari sesi SQL kita.
Server, User Mapping, dan Foreign Table #
postgres_fdw mengimplementasikan konsep foreign data wrapper dari standar SQL/MED. Konsepnya membagi koneksi menjadi tiga objek terpisah, masing-masing menjawab satu pertanyaan:
| Objek | Menjawab pertanyaan | Isi utamanya |
|---|---|---|
CREATE SERVER | Ke mana menyambung? | host, port, dbname |
CREATE USER MAPPING | Sebagai siapa menyambung? | user, password — per role lokal |
CREATE FOREIGN TABLE | Tabel mana yang dipetakan? | Kolom plus schema_name, table_name remote |
Alur ketiganya berjalan berlapis: query menyentuh foreign table, foreign table menunjuk server, server membaca user mapping milik role yang menjalankan query, lalu postgres_fdw membuka koneksi libpq ke database tujuan:
File berikut memasang extension dan mendefinisikan ketiga objek itu di database cabang:
-- postgres_fdw dipasang di database cabang (database kerja chapter ini).
-- Pemasangannya menuntut superuser karena extension ini membuka koneksi
-- keluar dari server.
CREATE EXTENSION postgres_fdw;
-- SERVER menjawab "ke mana menyambung": socket, port, dan database tujuan.
CREATE SERVER kantor_server FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '/home/z/my-project/pgrun', port '54329', dbname 'kantor_pusat_fdw');
-- USER MAPPING menjawab "sebagai siapa": kredensial untuk koneksi keluar.
CREATE USER MAPPING FOR postgres SERVER kantor_server
OPTIONS (user 'postgres');
-- FOREIGN TABLE memetakan tabel pusat menjadi tabel yang tampak lokal.
-- OPTIONS schema_name dan table_name menunjuk tabel aslinya di pusat.
CREATE FOREIGN TABLE karyawan_pusat (
id integer NOT NULL,
nama text NOT NULL,
kota text NOT NULL,
gaji integer NOT NULL
) SERVER kantor_server
OPTIONS (schema_name 'public', table_name 'karyawan');
-- Katalog mencatat ketiga objek koneksi tersebut.
SELECT s.srvname AS server, w.fdwname AS wrapper, s.srvoptions AS opsi_server
FROM pg_foreign_server s
JOIN pg_foreign_data_wrapper w ON w.oid = s.srvfdw
ORDER BY s.srvname;
SELECT srvname AS server, umoptions AS opsi_user
FROM pg_user_mappings
ORDER BY srvname;Output yang Dihasilkan:
CREATE EXTENSION
CREATE SERVER
CREATE USER MAPPING
CREATE FOREIGN TABLE
server | wrapper | opsi_server
---------------+--------------+--------------------------------------------------------------------
kantor_server | postgres_fdw | {host=/home/z/my-project/pgrun,port=54329,dbname=kantor_pusat_fdw}
(1 row)
server | opsi_user
---------------+-----------------
kantor_server | {user=postgres}
(1 row)Mari kita bedah objek-objeknya satu per satu:
CREATE EXTENSION postgres_fdwmemasang wrapper-nya. Extension ini menuntut superuser untuk dipasang — berbeda denganpgcryptoataupg_trgmyang trusted — karena objek yang dibuatnya dapat membuka koneksi keluar atas nama server.CREATE SERVER kantor_servermencatat alamat tujuan. Opsihostdi server kursus berupa direktori socket/home/z/my-project/pgrun; di produksi nilainya biasanya hostname atau IP server lain, dandbnameboleh berbeda dari database lokal.CREATE USER MAPPING FOR postgresmengikat kredensial ke role lokal. Server kursus memakai autentikasitrustsehingga cukupuser 'postgres'tanpa password.CREATE FOREIGN TABLE karyawan_pusatmemetakanpublic.karyawandi pusat. Definisi kolomnya ditulis tangan dan tidak divalidasi terhadap tabel aslinya — tipe data yang tidak cocok baru terasa saat query gagal mem-parse hasil, bukan saat foreign table dibuat.- Dua query katalog menutup file:
pg_foreign_servermenyimpan opsi server persis seperti output{host=/home/z/my-project/pgrun,port=54329,dbname=kantor_pusat_fdw}, dan viewpg_user_mappingsmenyimpan opsi user mapping{user=postgres}.
Membaca Data Pusat dan Join dengan Tabel Lokal #
Setelah pemetaan berdiri, foreign table dipakai persis seperti tabel biasa — filter, urutan, dan join bekerja tanpa sintaks khusus. Contoh berikut sekaligus memperlihatkan federasi: tabel bonus dibuat lokal di database cabang, lalu di-join dengan karyawan_pusat yang datanya tinggal di database pusat:
-- Data pusat dibaca persis seperti tabel lokal biasa.
SELECT id, nama, kota, gaji
FROM karyawan_pusat
WHERE kota = 'Jakarta'
ORDER BY id;
-- Federasi sesungguhnya: tabel LOKAL (bonus cabang) di-join dengan tabel
-- REMOTE (karyawan pusat) dalam satu query. PostgreSQL menggabungkan
-- keduanya secara transparan.
CREATE TABLE bonus (
karyawan_id integer PRIMARY KEY,
bonus integer NOT NULL
);
INSERT INTO bonus VALUES
(1, 1500000),
(2, 900000),
(4, 750000);
SELECT k.nama, k.kota, b.bonus
FROM karyawan_pusat k
JOIN bonus b ON b.karyawan_id = k.id
ORDER BY k.id;Output yang Dihasilkan:
id | nama | kota | gaji
----+--------------+---------+----------
1 | Budi Santoso | Jakarta | 12500000
4 | Dewi Lestari | Jakarta | 8700000
(2 rows)
CREATE TABLE
INSERT 0 3
nama | kota | bonus
--------------+---------+---------
Budi Santoso | Jakarta | 1500000
Siti Rahayu | Bandung | 900000
Dewi Lestari | Jakarta | 750000
(3 rows)Query pertama mengembalikan dua karyawan Jakarta tanpa satu baris pun disalin manual — postgres_fdw membuka koneksi, mengirim query ke pusat, dan menukar hasilnya menjadi baris lokal. Query join kemudian menggabungkan dua sumber sekaligus: tiga baris hasil memuat nama dan kota dari database pusat berdampingan dengan bonus dari database cabang. Inilah federasi yang oleh PostgreSQL native mustahil dilakukan, karena satu koneksi memang tidak boleh membaca dua database sekaligus.
Menulis ke Database Pusat #
postgres_fdw tidak berhenti di membaca: foreign table-nya writable. Statement INSERT, UPDATE, dan DELETE pada foreign table diteruskan ke database pusat sebagai statement remote, dan klausa RETURNING tetap bekerja karena baris hasilnya dikirim balik ke sesi lokal:
-- Foreign table postgres_fdw bersifat writable: INSERT diteruskan ke
-- database pusat. RETURNING bekerja seperti pada tabel biasa.
INSERT INTO karyawan_pusat VALUES (7, 'Farhan Gunawan', 'Jakarta', 9300000)
RETURNING id, nama;
-- UPDATE juga diteruskan; hanya baris yang cocok filter yang berubah di pusat.
UPDATE karyawan_pusat SET gaji = 8100000 WHERE id = 4
RETURNING id, gaji;
-- Baca ulang seluruh tabel: baris 7 yang baru dan gaji baris 4 yang
-- diubah kini terlihat dari sisi cabang.
SELECT id, nama, gaji
FROM karyawan_pusat
ORDER BY id;Output yang Dihasilkan:
id | nama
----+----------------
7 | Farhan Gunawan
(1 row)
INSERT 0 1
id | gaji
----+---------
4 | 8100000
(1 row)
UPDATE 1
id | nama | gaji
----+----------------+----------
1 | Budi Santoso | 12500000
2 | Siti Rahayu | 9800000
3 | Agus Wibowo | 10200000
4 | Dewi Lestari | 8100000
5 | Rina Marlina | 7600000
6 | Tono Sutrisno | 6900000
7 | Farhan Gunawan | 9300000
(7 rows)Tanda INSERT 0 1 dan UPDATE 1 pada output adalah tag dari eksekusi di sisi pusat yang dilaporkan kembali. SELECT penutup memperlihatkan hasil akhirnya dari mata cabang: baris 7 (Farhan Gunawan) hadir dan gaji Dewi Lestari turun menjadi 8100000 — dua perubahan yang menyimpan diri di database pusat, bukan di database tempat query dijalankan. Kejujuran data ini kita buktikan kembali di bagian pembersihan dengan menyambung langsung ke database pusat.
IMPORT FOREIGN SCHEMA #
Menulis CREATE FOREIGN TABLE satu per satu wajar untuk satu-dua tabel, tetapi melelahkan untuk schema berisi belasan tabel. Perintah IMPORT FOREIGN SCHEMA membalik kerjanya: server pusat ditanya daftar tabelnya, lalu foreign table dibuatkan otomatis — lengkap dengan kolom dan tipenya — ke schema tujuan yang kita pilih:
-- CREATE FOREIGN TABLE manual cocok untuk satu-dua tabel. Untuk memetakan
-- seluruh schema sekaligus, IMPORT FOREIGN SCHEMA membaca daftar tabel di
-- sisi pusat dan membuat foreign table-nya otomatis -- di sini ke schema pusat.
CREATE SCHEMA pusat;
IMPORT FOREIGN SCHEMA public
FROM SERVER kantor_server
INTO pusat;
-- Meta-command psql \det *.* mendaftar seluruh foreign table di semua schema
-- beserta server yang memilikinya.
\det *.*
-- Tabel hasil import langsung bisa dikueri tanpa definisi manual.
SELECT kode, kota, manager
FROM pusat.cabang
ORDER BY kode;Output yang Dihasilkan:
CREATE SCHEMA
IMPORT FOREIGN SCHEMA
List of foreign tables
Schema | Table | Server
--------+----------------+---------------
public | karyawan_pusat | kantor_server
pusat | cabang | kantor_server
pusat | karyawan | kantor_server
(3 rows)
kode | kota | manager
------+----------+--------------
BDG | Bandung | Siti Rahayu
JKT | Jakarta | Budi Santoso
SBY | Surabaya | Agus Wibowo
(3 rows)Daftar \det *.* memperlihatkan hasil akhir pemetaan: karyawan_pusat di schema public yang kita definisikan manual, plus cabang dan karyawan di schema pusat yang lahir dari import. Perhatikan bahwa import membuat foreign table baru bernama sama dengan tabel aslinya — pusat.karyawan — sehingga penempatan ke schema terpisah mencegah bentrok nama dengan pemetaan manual kita. Klausa LIMIT TO (...) atau EXCEPT (...) dapat memfilter tabel mana saja yang ikut diimpor saat schema pusat berisi lebih banyak tabel.
EXPLAIN: Foreign Scan dan Remote SQL #
Bagaimana executor membaca foreign table? EXPLAIN (VERBOSE, COSTS) menjawabnya: node Foreign Scan menggantikan Seq Scan, dan baris Remote SQL memperlihatkan query yang benar-benar dikirim ke server pusat — termasuk predikat WHERE yang diteruskan ke sana (pushdown), sehingga penyaringan terjadi di pusat dan hanya baris Jakarta yang melintasi koneksi:
-- EXPLAIN memperlihatkan Foreign Scan: baris tidak dibaca dari storage lokal,
-- melainkan ditarik dari database pusat. VERBOSE menampilkan Remote SQL --
-- query yang benar-benar dikirim ke server pusat, lengkap dengan predikat
-- WHERE yang diteruskan (pushdown).
EXPLAIN (VERBOSE, COSTS)
SELECT id, nama
FROM karyawan_pusat
WHERE kota = 'Jakarta'
ORDER BY id;Output yang Dihasilkan:
QUERY PLAN
-------------------------------------------------------------------------------------
Sort (cost=128.63..128.65 rows=7 width=36)
Output: id, nama
Sort Key: karyawan_pusat.id
-> Foreign Scan on public.karyawan_pusat (cost=100.00..128.53 rows=7 width=36)
Output: id, nama
Remote SQL: SELECT id, nama FROM public.karyawan WHERE ((kota = 'Jakarta'))
Query Identifier: 7252216033711214534
(7 rows)Pembacaan rencananya baris demi baris:
Foreign Scan on public.karyawan_pusat— tidak ada pembacaan storage lokal; node ini memanggil postgres_fdw untuk menarik baris darikantor_server.Remote SQL: SELECT id, nama FROM public.karyawan WHERE ((kota = 'Jakarta'))— query yang dikirim ke pusat. Predikatkota = 'Jakarta'berada di sana, bukan difilter lokal, sehingga jaringan hanya mengangkut baris yang relevan.Sortdi atas Foreign Scan — pengurutanORDER BY iduntuk kasus ini dilakukan lokal setelah baris tiba; postgres_fdw meneruskan lebih banyak klausa (join, agregasi,LIMIT) ke remote bila rencananya menguntungkan.cost=100.00..— biaya dasar yang tinggi itu sengaja: planner menaruh penalti tetap pada foreign scan karena koneksi jaringan dianggap mahal. Opsi serveruse_remote_estimate = truememinta planner memakai estimasiEXPLAINdari server pusat agar biaya dihitung lebih akurat.
Pola Pemakaian di Produksi #
Kapan postgres_fdw layak dipasang? Empat pola berikut mencakup mayoritas kasus nyata:
| Pola | Skenario | Catatan |
|---|---|---|
| Query lintas database (satu server) | Aplikasi butuh data dari database lain di server yang sama | Satu-satunya jalur resmi — PostgreSQL memang tidak punya sintaks db.schema.tabel |
| Federasi lintas server | Dashboard menyatukan data cabang dari beberapa region | Join dan agregasi bisa diteruskan ke sisi data bila menguntungkan |
| Batu loncatan migrasi | Pindah server bertahap: baca dari server lama, tulis ke server baru | Foreign table menjembatani dua sisi selama masa transisi |
| Integrasi tanpa ETL | Tabel referensi vendor cukup dibaca langsung | Hemat pipeline; ingat kinerja bergantung pada pushdown filter |
Satu batas kinerja perlu ditanam sejak awal: setiap query foreign table adalah perjalanan jaringan. Join antara tabel lokal dan remote dengan jutaan baris akan menarik data lintas koneksi bila penyaringannya tidak bisa diteruskan — pakai EXPLAIN (VERBOSE) seperti di atas untuk memastikan predikat penting benar-benar sampai ke Remote SQL, dan biarkan tabel remote difilter selektif mungkin.
Membersihkan Seluruh Objek #
Pembersihan postgres_fdw berjalan berurutan dari objek teratas. DROP SERVER ... CASCADE menjatuhkan user mapping dan seluruh foreign table yang bergantung pada kantor_server — termasuk dua foreign table hasil import di schema pusat:
-- Satu CASCADE menjatuhkan user mapping dan seluruh foreign table yang
-- bergantung pada server ini, termasuk yang berada di schema pusat.
DROP SERVER kantor_server CASCADE;
-- Schema pusat kini kosong karena foreign table di dalamnya ikut dijatuhkan.
DROP SCHEMA pusat;
-- Extension dilepas terakhir setelah tidak ada objek yang memakainya.
DROP EXTENSION postgres_fdw;Output yang Dihasilkan:
DROP SERVER
DROP SCHEMA
DROP EXTENSIONFile terakhir menutup siklus dengan membuktikan klaim “data tinggal di pusat” secara langsung, lalu menjatuhkan database kedua:
-- Bukti data benar-benar tersimpan di database pusat: sambungan langsung ke
-- kantor_pusat_fdw tanpa perantara foreign table.
\connect kantor_pusat_fdw
SELECT id, nama, gaji
FROM karyawan
WHERE id IN (4, 7)
ORDER BY id;
-- Kembali ke database maintenance, lalu jatuhkan database pusat demo.
\connect postgres
DROP DATABASE kantor_pusat_fdw;Output yang Dihasilkan:
You are now connected to database "kantor_pusat_fdw" as user "postgres".
id | nama | gaji
----+----------------+---------
4 | Dewi Lestari | 8100000
7 | Farhan Gunawan | 9300000
(2 rows)
You are now connected to database "postgres" as user "postgres".
DROP DATABASEBaris 7 (Farhan Gunawan) dan gaji 8100000 milik Dewi Lestari muncul dari public.karyawan yang dibaca langsung di database pusat — bukti final bahwa INSERT dan UPDATE lewat foreign table memang mendarat di sana. Kedua database demo kini bersih, dan seluruh objek koneksi sudah tidak tersisa.
postgres_fdw menuntut persiapan: server, user mapping, dan foreign table dideklarasikan dulu agar bisa dipakai ribuan kali. Namun kebutuhan lintas database kadang hanya sesaat — menarik satu angka dari database tetangga tanpa meninggalkan jejak objek permanen. Untuk kebutuhan itulah extension dblink menyediakan API koneksi ad-hoc yang lebih tua dan lebih mentah; chapter berikutnya membedahnya lalu membandingkan keduanya dengan jujur.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
bersih-bersih.sql
Unduh berkas-- Satu CASCADE menjatuhkan user mapping dan seluruh foreign table yang
-- bergantung pada server ini, termasuk yang berada di schema pusat.
DROP SERVER kantor_server CASCADE;
-- Schema pusat kini kosong karena foreign table di dalamnya ikut dijatuhkan.
DROP SCHEMA pusat;
-- Extension dilepas terakhir setelah tidak ada objek yang memakainya.
DROP EXTENSION postgres_fdw;
buat-database-pusat.sql
Unduh berkas-- Demo postgres_fdw butuh DUA database: database kerja chapter ini berperan
-- sebagai "kantor cabang", database kedua sebagai "kantor pusat" pemilik
-- data master. CREATE DATABASE harus dijalankan dari database lain
-- (postgres), karena PostgreSQL tidak mengizinkan pembuatan database
-- dari dalam database yang sedang dipakai.
DROP DATABASE IF EXISTS kantor_pusat_fdw;
CREATE DATABASE kantor_pusat_fdw;
-- Pindah ke database pusat, lalu bangun tabel master-nya.
\connect kantor_pusat_fdw
CREATE TABLE karyawan (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text NOT NULL,
gaji integer NOT NULL
);
INSERT INTO karyawan VALUES
(1, 'Budi Santoso', 'Jakarta', 12500000),
(2, 'Siti Rahayu', 'Bandung', 9800000),
(3, 'Agus Wibowo', 'Surabaya', 10200000),
(4, 'Dewi Lestari', 'Jakarta', 8700000),
(5, 'Rina Marlina', 'Medan', 7600000),
(6, 'Tono Sutrisno', 'Bandung', 6900000);
CREATE TABLE cabang (
kode text PRIMARY KEY,
kota text NOT NULL,
manager text NOT NULL
);
INSERT INTO cabang VALUES
('JKT', 'Jakarta', 'Budi Santoso'),
('BDG', 'Bandung', 'Siti Rahayu'),
('SBY', 'Surabaya', 'Agus Wibowo');
explain-foreign-scan.sql
Unduh berkas-- EXPLAIN memperlihatkan Foreign Scan: baris tidak dibaca dari storage lokal,
-- melainkan ditarik dari database pusat. VERBOSE menampilkan Remote SQL --
-- query yang benar-benar dikirim ke server pusat, lengkap dengan predikat
-- WHERE yang diteruskan (pushdown).
EXPLAIN (VERBOSE, COSTS)
SELECT id, nama
FROM karyawan_pusat
WHERE kota = 'Jakarta'
ORDER BY id;
hapus-database-pusat.sql
Unduh berkas-- Bukti data benar-benar tersimpan di database pusat: sambungan langsung ke
-- kantor_pusat_fdw tanpa perantara foreign table.
\connect kantor_pusat_fdw
SELECT id, nama, gaji
FROM karyawan
WHERE id IN (4, 7)
ORDER BY id;
-- Kembali ke database maintenance, lalu jatuhkan database pusat demo.
\connect postgres
DROP DATABASE kantor_pusat_fdw;
import-foreign-schema.sql
Unduh berkas-- CREATE FOREIGN TABLE manual cocok untuk satu-dua tabel. Untuk memetakan
-- seluruh schema sekaligus, IMPORT FOREIGN SCHEMA membaca daftar tabel di
-- sisi pusat dan membuat foreign table-nya otomatis -- di sini ke schema pusat.
CREATE SCHEMA pusat;
IMPORT FOREIGN SCHEMA public
FROM SERVER kantor_server
INTO pusat;
-- Meta-command psql \det *.* mendaftar seluruh foreign table di semua schema
-- beserta server yang memilikinya.
\det *.*
-- Tabel hasil import langsung bisa dikueri tanpa definisi manual.
SELECT kode, kota, manager
FROM pusat.cabang
ORDER BY kode;
kueri-join-lokal.sql
Unduh berkas-- Data pusat dibaca persis seperti tabel lokal biasa.
SELECT id, nama, kota, gaji
FROM karyawan_pusat
WHERE kota = 'Jakarta'
ORDER BY id;
-- Federasi sesungguhnya: tabel LOKAL (bonus cabang) di-join dengan tabel
-- REMOTE (karyawan pusat) dalam satu query. PostgreSQL menggabungkan
-- keduanya secara transparan.
CREATE TABLE bonus (
karyawan_id integer PRIMARY KEY,
bonus integer NOT NULL
);
INSERT INTO bonus VALUES
(1, 1500000),
(2, 900000),
(4, 750000);
SELECT k.nama, k.kota, b.bonus
FROM karyawan_pusat k
JOIN bonus b ON b.karyawan_id = k.id
ORDER BY k.id;
pasang-dan-server.sql
Unduh berkas-- postgres_fdw dipasang di database cabang (database kerja chapter ini).
-- Pemasangannya menuntut superuser karena extension ini membuka koneksi
-- keluar dari server.
CREATE EXTENSION postgres_fdw;
-- SERVER menjawab "ke mana menyambung": socket, port, dan database tujuan.
CREATE SERVER kantor_server FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host '/home/z/my-project/pgrun', port '54329', dbname 'kantor_pusat_fdw');
-- USER MAPPING menjawab "sebagai siapa": kredensial untuk koneksi keluar.
CREATE USER MAPPING FOR postgres SERVER kantor_server
OPTIONS (user 'postgres');
-- FOREIGN TABLE memetakan tabel pusat menjadi tabel yang tampak lokal.
-- OPTIONS schema_name dan table_name menunjuk tabel aslinya di pusat.
CREATE FOREIGN TABLE karyawan_pusat (
id integer NOT NULL,
nama text NOT NULL,
kota text NOT NULL,
gaji integer NOT NULL
) SERVER kantor_server
OPTIONS (schema_name 'public', table_name 'karyawan');
-- Katalog mencatat ketiga objek koneksi tersebut.
SELECT s.srvname AS server, w.fdwname AS wrapper, s.srvoptions AS opsi_server
FROM pg_foreign_server s
JOIN pg_foreign_data_wrapper w ON w.oid = s.srvfdw
ORDER BY s.srvname;
SELECT srvname AS server, umoptions AS opsi_user
FROM pg_user_mappings
ORDER BY srvname;
tulis-ke-remote.sql
Unduh berkas-- Foreign table postgres_fdw bersifat writable: INSERT diteruskan ke
-- database pusat. RETURNING bekerja seperti pada tabel biasa.
INSERT INTO karyawan_pusat VALUES (7, 'Farhan Gunawan', 'Jakarta', 9300000)
RETURNING id, nama;
-- UPDATE juga diteruskan; hanya baris yang cocok filter yang berubah di pusat.
UPDATE karyawan_pusat SET gaji = 8100000 WHERE id = 4
RETURNING id, gaji;
-- Baca ulang seluruh tabel: baris 7 yang baru dan gaji baris 4 yang
-- diubah kini terlihat dari sisi cabang.
SELECT id, nama, gaji
FROM karyawan_pusat
ORDER BY id;