ECPG 是 Postgres 提供的 C 的開發輔助函式庫,提供所謂 Embedded SQL in C 的功能,類似 Oracle Pro*C 一樣的功能。兩者在使用上提供的 API 差異並不大,比較顯著的差別就在所使用的 SQL 指令,Postgres ECPG 和 Oracle Pro*C 步太能直接通用。
EnterpriseDB 則基於 Postgres ECPG 進一步提供移轉 Oracle Pro*C 到 Postgres 的額外功能,叫做 ECPGPlus。ECPGPlus 針對 EnterpriseDB 提供的企業版資料庫所具備的 Oracle 相容特性,提供相對應的 Embedded SQL in C 轉換,以便以最大幅度直接相容 Oracle Pro*C 的程式碼,達到系統移轉時降低改動幅度的目的。
以下自 EDB 的 PostgreSQL 企業版編譯一個 Oracle 的 Pro*C 程式碼,示範 ECPGPlus 的使用。
以下編譯過程,大致如下:
ECPG 程式碼 →ECPGPlus⇒ C 程式碼 →GCC⇒ Object File →GCC⇒ 執行檔
環境:64 位元 CentOS 7.2
bash-$ cat /etc/*release CentOS Linux release 7.2.1511 (Core) NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7" CentOS Linux release 7.2.1511 (Core) CentOS Linux release 7.2.1511 (Core)
一. 範例程式
以下為網路找來的 Pro*C 範例,目標是直接用 ECPGPlus 編譯,並且成功的執行它。
在這裡,我變動程式碼的幾個部份,以紅色標記:
- 將 Oracle Pro*C 要用到的 oraca.h 這個 Header 拿掉(在這裡直接註解掉)
- 原本文章提供的範例中,資料庫的連線是連到帳號為 hello,密碼也為 hello 的帳號。在 EDB 中,則需要進一步提供連線資訊,以紅字增添。
pro_c_test.pc
|
#include <stdio.h> #include <sqlca.h> #include <sqlcpr.h> //#include <oraca.h> #include <sqlda.h> /* Declare error handling function. */ //void sql_error(); int main(int argc, char** argv) { char user[]="hello"; char pwd[]="hello"; char dbstr[]="edb@10.146.0.2:5444"; char msg_buf[51]=""; /* Register sql_error() as the error handler. */ //EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error\n"); EXEC SQL WHENEVER SQLERROR sqlprint; EXEC SQL CONNECT :user IDENTIFIED BY :pwd AT :dbstr; EXEC SQL INSERT INTO hello_world VALUES ('Hello world!'); EXEC SQL COMMIT; EXEC SQL SELECT msg INTO :msg_buf FROM hello_world WHERE rownum <= 1; printf("%s\n", msg_buf); return(0); } /* void sql_error(char *msg) { char err_msg[128]; int buf_len, msg_len; EXEC SQL WHENEVER SQLERROR CONTINUE; printf("%s\n", msg); buf_len = sizeof (err_msg); sqlglm(err_msg, &buf_len, &msg_len); if (msg_len > buf_len) msg_len = buf_len; printf("%.*s\n", msg_len, err_msg); EXEC SQL ROLLBACK RELEASE; exit(1); } */
此外,在 EDB 底下產生需要的表格、帳號:
bash-$ edb-psql -d edb Password: psql.bin (9.5.5.10) Type "help" for help. edb=# CREATE USER hello PASSWORD 'hello'; CREATE ROLE edb=# \c edb hello Password for user hello: You are now connected to database "edb" as user "hello". edb=> CREATE TABLE hello_world(msg VARCHAR2(50)); CREATE TABLE edb=# \q
然後記得到 $PGDATA/pg_hba.conf 設定,以允許有關的資料庫連線:在此允許子網域用密碼進行連線。
bash-$ source /opt/PostgresPlus/9.5AS/pgplus_env.sh bash-$ echo "host edb hello 10.146.0.0/24 md5" >> $PGDATA/pg_hba.conf bash-$ pg_ctl reload server signaled
二. 編譯環境準備
到 EDB 9.5 企業版為止,編譯 ECPGPlus 需要的套件,除了編譯需要的工具之外,還需要有 32 位元的 Cross-Compiling 工具
bash-$ sudo yum group install "Development Tools" bash-$ sudo yum install glibc-devel.i686 kernel-headers
接著,把 EDB 的函式庫路徑加到系統路徑下,以便編譯完畢後,本地程式的執行
bash-$ sudo echo $(pg_config --libdir) >> /etc/ld.so.conf.d/edb.conf bash-$ sudo ldconfig
三. 將 Embedded SQL 轉成 C 的程式碼
此步驟把 Pro*C 程式碼,使用企業版 Postgres 提供的 ecpg 程式轉換成可以編譯的 C 程式碼。原生 PostgreSQL 的 ECPG 程式碼也是相同處理流程,與此處企業版處理 Pro*C 的差異,僅僅在指定的參數選項 -C PROC 而已(參考手冊)。
bash-$ source /opt/PostgresPlus/9.5AS/pgplus_env.sh bash-$ ecpg -C PROC -c -I $(pg_config --includedir) ./pro_c_test.pc
四.編譯出 Object File
bash-$ # 編譯出 Object File
bash-$ gcc -I$(pg_config --includedir) -L$(pg_config --libdir) ./pro_c_test.c -c
bash-$ # 把 Object Files 和函式庫一起作 link,產生執行檔(方法一)
bash-$ gcc -L$(pg_config --libdir) $(pg_config --libdir)/{libssl.so.1.0.0,libcrypto.so.1.0.0,libpq.so,libecpg.so,libpgtypes.so} pro_c_test.o -o pro_c_test.bin
bash-$ # 把 Object Files 和函式庫一起作 link,產生執行檔(方法二)
bash-$ gcc -L$(pg_config --libdir) $(pg_config --libdir)/{libpq.so,libecpg.so,libpgtypes.so} -Wl,-rpath,$(pg_config --libdir) pro_c_test.o -o pro_c_test.bin
五. 執行;並登入資料庫查看表格
bash-$ ./pro_c_test.bin Hello world! bash-$ psql -U hello Password for user hello: psql.bin (9.5.5.10) Type "help" for help. edb=> select * from hello_world ; msg -------------- Hello world! (1 row)
以上便將範例 Pro*C 程式移轉成功。
參考資料:
沒有留言:
張貼留言