PostgreSQL'de file_fdw Kullanımı

Merhaba,

FDW ile ilgili nasıl kullanılması gerektiği ve temel olarak ne işe yaradığıyla ilgili detaylıca buradaki yazımda bahsetmiştim. Postgres'de iki adet in-core FDW bulunmaktadır; file_fdw ve postgres_fdw.

Bu yazımda file_fdw'nun nasıl kullanıldığından bahsetmek istiyorum.

file_fdw, file system foreign data wrapper olarak geçiyor. Yani Postgres veritabanından postgres kullanıcısının erişim yetkisi olan dizinler üzerinde bulunan dosyaları okumayı sağlıyor. Bu, elinizde bir metin dosyası varsa eğer içeriğini uygun tablo yapısıyla birlikte veritabanı üzerinden okuyabileceğiniz anlamına gelir. Dosya içine bir satır daha eklediniz diyelim, verilerin akışı siz SELECT attığınız anda anlık olur ve siz yeni eklenen satırı tablonuzda görebilirsiniz.


file_fdw ile sunucu üzerinde çalıştıracağınız komutların sonucunu PostgreSQL 10 ile gelen ve file_fdw için yeni eklenen bir seçenek olan program seçeneğini kullanarak da çalışan programın sonucunu bir tablo yapısıyla görüntüleyebilirsiniz. file_fdw ile birlikte program komutunun kullanım örneğini yazının sonunda paylaştım sizlerle.  

file_fdw, metin dosyalarını sistem sunucusundan (postgres kullanıcısının yetkisinin olduğu) yerlerdeki dosyaları okur ve bir SQL ifadesi ile Postgres veritabanından dosya içindeki verileri çekmemizi sağlar.Diyelim ki postgres kullanıcısının yetkisinin olmadığı bir dizin içindeki dosyaya erişmek istediniz. "Permission Denied" hatası alacaksınız.

file_fdw kullanmak için SERVER ve FOREIGN TABLE oluşturmanız yeterli. USER MAPPING oluşturulmasına ihtiyaç duymaz.

Öncelikle SERVER oluşturuyorum. SERVER'a ait options ile hangi dosyaya erişmek istediğim bilgisini veriyorum. Burada herhangib ir kontrol yapmıyor Sadece file_fdw kullanarak bir SERVER oluşturacağımızı belirtmiş oluyoruz.
 

artemis=# CREATE SERVER csv 
          FOREIGN DATA WRAPPER file_fdw;
CREATE SERVER


Sonrasında foreign tablomu uygun parametrelerle oluşturuyorum. Tam da burada önemli bir konu var. Options alanında delimiter kullanılması oldukça önemli, diğer türlü tüm satırı tek bir metin olarak görmemize sebep oluyor.

Foreign tablosunu oluştururken kullanacağım parametrelerim aşağıdaki gibi:

artemis=#
CREATE FOREIGN TABLE users(id integer, name text)
          SERVER csv OPTIONS(filename '/var/lib/pgsql/users_.csv', format 'csv', delimiter ';' ,null '');
CREATE FOREIGN TABLE


SERVER ve FOREIGN TABLE oluşturduğuma göre, test etmek için bir CSV dosyasına ihtiyacım var bu noktada. Foreign tablo oluştururken kullandığım filename seçeneğine ait dosya adı ve uzantısıyla birebir uyan ve foreign tablonun tablo yapısına uygun bir CSV dosyasına ihtiyacım var. 


Kullanmak istediğim foreign tablo yapısına uygun bir CSV dosyasını yine SQL ve COPY TO yardımıyla oluşturuyorum manuel eklememek için. Istediğim yapı tam da 100 satırlık, biri integer diğeri text olmak üzere iki sütunluk bir veri dosyası yaratıyorum CSV uzantılı.

Çalıştıracağım script tam a şöyle; 

artemis=# COPY(SELECT i AS id, 
               '"' || md5(i::text)|| '"' AS name 
               FROM GENERATE_SERIES(1,100) AS i) 
          TO '/var/lib/pgsql/users_.csv' 
          DELIMITER ';' CSV;
COPY 100 

 
/var/lib/pgsql altında users_.csv adında bir dosyam mevcut artık tam da foreign tablomda belirttiğim gibi. 

Foreign tabloma LIMIT 1 ile SELECT attığımda CSV dosyasının içindeki bir satırı getiriyor.

artemis=# SELECT * FROM users LIMIT 1;
id  | name
----+------------------------------------
1   | "c4ca4238a0b923820dcc509a6f75849b"
(1 row)

 


file_fdw ve program seçeneği

Postgres10 ile birlikte gelen yeni bir seçenek olan "program" i da kullanarak file_fdw extension'una ait foreign tablolar oluşturabilirsiniz.

Çalışmasını istediğimiz komut /bin/date olsun. Sunucu üzerinde çalışacak olan /bin/date komut sonucunun, foreign table ile gelmesini sağlamak için options içinde program'ın yanına tek tırnak içinde çalıştırmak istediğim komutu yazdım.

artemis=# CREATE FOREIGN TABLE now_(date text) 
          SERVER program_file_fdw 
          OPTIONS (program '/bin/date', format 'csv');
CREATE FOREIGN TABLE
 

artemis=# select * from now_ ;
             date            
------------------------------
 Wed Oct  3 00:45:11 +03 2018
(1 row)


Paylaştığım örnekler oldukça basit ama umuyorum ki yol gösterici olacaktır okuyanlar için :)
 
Sevgiler,

Comments

Popular posts from this blog

PostgreSQL High Availability - Patroni 2

PostgreSQL Foreign Data Wrappers

PostgreSQL High Availability - Patroni 1