설문조사
PostgreSQL/PPAS 관련 듣고 싶은 교육은


총 게시물 13건, 최근 0 건
   

C 모듈을 이용한 함수 생성

글쓴이 : PostgresDBA 날짜 : 2014-03-25 (화) 09:46 조회 : 10431
오라클에서는 호스트명을 아래 명령으로 쉽게  알아낼수 있습니다.

SQL> select host_name from v$instance
HOST_NAME
-----------
ORASERVER

하지만 PostgreSQL 에서는 기본적으로 카달로그에 해당정보가 존재하지 않습니다.

그래서 c 모듈을 직접 작성해서 구현해보도록 하겠습니다.
(아래는 http://wiki.postgresql.org/wiki/Pg_gethostname 를 참조하여 작성된 글입니다.)

select pg_gethostname(); 이렇게 sql 을 이용하여 호스트네임을 조회할수 있도록 해보겠습니다.

호스트네임을 구해내는 C 모듈 소스는 다음과 같습니다.
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$cat pg_gethostname.c 
/*
        A PostgreSQL function for getting the hostname.
 
        File: `pg_config --libdir`/pg_gethostname.c
 
        To compile...  (make sure pg_config is in your PATH)
        gcc  -I$(pg_config --includedir-server) -fpic -c pg_gethostname.c -L$(pg_config --libdir)
        gcc --shared -o pg_gethostname.so pg_gethostname.o
 
        To create the funciton in PostgreSQL...
        CREATE OR REPLACE FUNCTION pg_gethostname() RETURNS text
                AS 'pg_gethostname'
                LANGUAGE C IMMUTABLE STRICT;
 
*/
#include "postgres.h"
#include <limits.h>
#include <unistd.h>
#include <string.h>
#include "fmgr.h"
 
#include "utils/palloc.h"
#include "utils/elog.h"
#include "storage/bufpage.h"
 
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
 
 
PG_FUNCTION_INFO_V1( pg_gethostname );
 
Datum pg_gethostname( PG_FUNCTION_ARGS );
 
Datum pg_gethostname( PG_FUNCTION_ARGS )
{
        text *t;
        char server_hostname[HOST_NAME_MAX];
        size_t length;
 
        if ( gethostname( server_hostname, HOST_NAME_MAX ) != 0 )
        {
                // returning an empty string for the hostname if it fails makes
                // sense because if it succeeded, we would have a name
                server_hostname[0] = '\0';
        }
 
        length = strnlen( server_hostname, HOST_NAME_MAX );
        t = (text *) palloc(VARHDRSZ + length );
        SET_VARSIZE( t, VARHDRSZ + length );
        memcpy( VARDATA(t), server_hostname, length );
 
        PG_RETURN_TEXT_P( t );
}
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

C 소스를 메이크하는 화일은 다음과 같습니다.

[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$cat makefile 
# makefile
MODULES = pg_gethostname

PG_ConFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

디렉토리를 조회해볼까요?
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$ls -l
total 8
-rw-r--r-- 1 postgres postgres  112 Mar  7 08:31 makefile
-rw-r--r-- 1 postgres postgres 1320 Mar  7 08:31 pg_gethostname.c
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

make 명령으로 c 오브젝트화일을 생성하도록 하겠습니다.

[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$make
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -I. -I. -I/opt/PostgreSQL/9.3/include/postgresql/server -I/opt/PostgreSQL/9.3/include/postgresql/internal -D_GNU_SOURCE -I/opt/local/20140108/fc7f8f12-7861-11e3-aaff-000c29d23b02/include/libxml2  -I/usr/local/include/libxml2 -I/usr/local/include  -c -o pg_gethostname.o pg_gethostname.c
gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fpic -L/opt/PostgreSQL/9.3/lib -L/opt/local/20140108/fc7f8f12-7861-11e3-aaff-000c29d23b02/lib  -L/usr/local/lib -Wl,--as-needed -Wl,-rpath,'/opt/PostgreSQL/9.3/lib',--enable-new-dtags  -shared -o pg_gethostname.so pg_gethostname.o
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

다시 한번 디렉토리를 조회해보도록 하겠습니다.
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$ls -l
total 20
-rw-r--r-- 1 postgres postgres  112 Mar  7 08:31 makefile
-rw-r--r-- 1 postgres postgres 1320 Mar  7 08:31 pg_gethostname.c
-rw-r--r-- 1 postgres postgres 2184 Mar  7 08:39 pg_gethostname.o
-rwxr-xr-x 1 postgres postgres 6765 Mar  7 08:39 pg_gethostname.so*
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

생성된 *.so 화일을 PostgreSQL 에서  인지할수 있도록 설치해도록 하겠습니다.
아래를 보면 pg_gethostname.so 화일을 /opt/PostgreSQL/9.3/lib/postgresql/ 디렉토리로 복사를 하는군요. 그런데 권한 에러 때문에 복사가 안되서 root 로 스위치한후에 설치를 진행했습니다

[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$make install
/bin/mkdir -p '/opt/PostgreSQL/9.3/lib/postgresql'
/usr/bin/install -c -m 755  pg_gethostname.so '/opt/PostgreSQL/9.3/lib/postgresql/'
/usr/bin/install: cannot create regular file `/opt/PostgreSQL/9.3/lib/postgresql/pg_gethostname.so': Permission denied
make: *** [install] Error 1
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$su 
Password: 
[root@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]#make install
/bin/mkdir -p '/opt/PostgreSQL/9.3/lib/postgresql'
/usr/bin/install -c -m 755  pg_gethostname.so '/opt/PostgreSQL/9.3/lib/postgresql/'
[root@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]#exit
exit
[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$

이제 위에서 설치된 C 모듈을 PostgreSQL 에서 함수 형태로 불러다 쓸수 있도록 인식작업을 하도록 하겠습니다.

[postgres@pgdbserver:/opt/PostgreSQL/9.3/oradba/test]$psql -U postgres -d postgres
psql.bin (9.3.2)
Type "help" for help.

No entry for terminal type "vt100";
using dumb terminal settings.
postgres=# CREATE OR REPLACE FUNCTION pg_gethostname() RETURNS text AS 'pg_gethostname' LANGUAGE C IMMUTABLE STRICT;                              
CREATE FUNCTION
postgres=# select pg_gethostname();
 pg_gethostname 
----------------
 pgdbserver
(1 row)

postgres=# 

보시는 바와 같이 우리가 원하는 결과가 산출되었습니다.
클라이언트틀로 살펴보니 pg_gethostname() 이란 함수가 정상적으로 등록되었음을 알수 있네요.

hostname.png


사실은 이 과정을 이해하기 위해서는 
http://www.postgresql.org/docs/9.3/static/xfunc-c.html
이 부분을 열심히 공부하셔야 합니다.

   

postgresdba.com