本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
將舊版應用程式從 Oracle Pro*C 遷移至 ECPG
由 Sai Parthasaradhi (AWS) 和 Mahesh Balumuri (AWS) 建立
環境:PoC 或試行 | 來源:Oracle | 目標:PostgreSQL |
R 類型:重新架構 | 工作負載:Oracle | 技術:遷移;資料庫 |
Summary
大多數具有內嵌SQL程式碼的舊版應用程式會使用 Oracle Pro*C 前置編譯器來存取資料庫。當您將這些 Oracle 資料庫遷移至 PostgreSQL 的 Amazon Relational Database Service (Amazon RDS) 或 Amazon Aurora Postgre SQL-Compatible Edition 時,您必須將應用程式程式碼轉換為與 Postgre 中 前置編譯器相容的格式SQL,稱為 ECPG。此模式說明如何在 PostgreSQL 中將 Oracle Pro*C 程式碼轉換為同等程式碼ECPG。
如需 Pro*C 的詳細資訊,請參閱 Oracle 文件 。如需 的簡介ECPG,請參閱其他資訊一節。
先決條件和限制
先決條件
史詩
任務 | 描述 | 所需的技能 |
---|
安裝 PostgreSQL 套件。 | 使用以下命令安裝所需的 PostgreSQL 套件。 yum update -y
yum install -y yum-utils
rpm -ivh https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
dnf -qy module disable postgresql
| 應用程式開發人員、 DevOps 工程師 |
安裝標頭檔案和程式庫。 | 使用以下命令安裝包含標頭檔案和程式庫的postgresql12-devel 套件。在開發和執行期環境中安裝套件,以避免執行期環境中的錯誤。 dnf -y install postgresql12-devel
yum install ncompress zip ghostscript jq unzip wget git -y
僅針對開發環境,也請執行下列命令。 yum install zlib-devel make -y
ln -s /usr/pgsql-12/bin/ecpg /usr/bin/
| 應用程式開發人員、 DevOps 工程師 |
設定環境路徑變數。 | 設定 PostgreSQL 用戶端程式庫的環境路徑。 export PATH=$PATH:/usr/pgsql-12/bin
| 應用程式開發人員、 DevOps 工程師 |
視需要安裝其他軟體。 | 如果需要,請在 Oracle 中安裝 pgLoader作為 SQL*Loader 的替代。 wget -O /etc/yum.repos.d/pgloader-ccl.repo https://dl.packager.io/srv/opf/pgloader-ccl/master/installer/el/7.repo
yum install pgloader-ccl -y
ln -s /opt/pgloader-ccl/bin/pgloader /usr/bin/
如果您從 Pro*C 模組呼叫任何 Java 應用程式,請安裝 Java。 yum install java -y
安裝 ant 以編譯 Java 程式碼。 yum install ant -y
| 應用程式開發人員、 DevOps 工程師 |
安裝 AWS CLI。 | 安裝 AWSCLI來執行命令,以從您的應用程式與 AWS Secrets Manager 和 Amazon Simple Storage Service (Amazon S3) 等AWS服務互動。 cd /tmp/
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install -i /usr/local/aws-cli -b /usr/local/bin --update
| 應用程式開發人員、 DevOps 工程師 |
識別要轉換的程式。 | 識別您要從 Pro*C 轉換為 的應用程式ECPG。 | 應用程式開發人員、應用程式擁有者 |
任務 | 描述 | 所需的技能 |
---|
移除不需要的標頭。 | 移除 Postgre 中不需要的include 標頭SQL,例如 oci.h 、 oratypes 和 sqlda 。 | 應用程式擁有者、應用程式開發人員 |
更新變數宣告。 | 為用作主機變數的所有變數宣告新增EXEC SQL 陳述式。 從您的應用程式中移除EXEC SQL VAR 宣告,例如下列項目。 EXEC SQL VAR query IS STRING(2048);
| 應用程式開發人員、應用程式擁有者 |
更新ROWNUM功能。 | Postgre 中無法使用該ROWNUM 函數SQL。將此取代為SQL查詢中的ROW_NUMBER 視窗函數。 Pro*C 程式碼: SELECT SUBSTR(RTRIM(FILE_NAME,'.txt'),12) INTO :gcpclFileseq
FROM (SELECT FILE_NAME
FROM DEMO_FILES_TABLE
WHERE FILE_NAME LIKE '%POC%'
ORDER BY FILE_NAME DESC) FL2
WHERE ROWNUM <=1 ORDER BY ROWNUM;
ECPG 程式碼: SELECT SUBSTR(RTRIM(FILE_NAME,'.txt'),12) INTO :gcpclFileseq
FROM (SELECT FILE_NAME , ROW_NUMBER() OVER (ORDER BY FILE_NAME DESC) AS ROWNUM
FROM demo_schema.DEMO_FILES_TABLE
WHERE FILE_NAME LIKE '%POC%'
ORDER BY FILE_NAME DESC) FL2
WHERE ROWNUM <=1 ORDER BY ROWNUM;
| 應用程式開發人員、應用程式擁有者 |
更新函數參數以使用別名變數。 | 在 Postgre 中SQL,函數參數無法用作主機變數。使用別名變數覆寫它們。 Pro*C 程式碼: int processData(int referenceId){
EXEC SQL char col_val[100];
EXEC SQL select column_name INTO :col_val from table_name where col=:referenceId;
}
ECPG 程式碼: int processData(int referenceIdParam){
EXEC SQL int referenceId = referenceIdParam;
EXEC SQL char col_val[100];
EXEC SQL select column_name INTO :col_val from table_name where col=:referenceId;
}
| 應用程式開發人員、應用程式擁有者 |
更新結構類型。 | 如果struct 類型變數用作主機變數typedef ,則定義 EXEC SQL BEGIN 和 END 區塊中的struct 類型。如果在標頭 (.h ) 檔案中定義struct 了類型,請包含EXEC SQL 包含陳述式的檔案。 Pro*C 程式碼: 標頭檔案 (demo.h ) struct s_partition_ranges
{
char sc_table_group[31];
char sc_table_name[31];
char sc_range_value[10];
};
struct s_partition_ranges_ind
{
short ss_table_group;
short ss_table_name;
short ss_range_value;
};
ECPG 程式碼: 標頭檔案 (demo.h ) EXEC SQL BEGIN DECLARE SECTION;
typedef struct
{
char sc_table_group[31];
char sc_table_name[31];
char sc_range_value[10];
} s_partition_ranges;
typedef struct
{
short ss_table_group;
short ss_table_name;
short ss_range_value;
} s_partition_ranges_ind;
EXEC SQL END DECLARE SECTION;
Pro*C 檔案 (demo.pc ) #include "demo.h"
struct s_partition_ranges gc_partition_data[MAX_PART_TABLE] ;
struct s_partition_ranges_ind gc_partition_data_ind[MAX_PART_TABLE] ;
ECPG 檔案 (demo.pc ) exec sql include "demo.h"
EXEC SQL BEGIN DECLARE SECTION;
s_partition_ranges gc_partition_data[MAX_PART_TABLE] ;
s_partition_ranges_ind gc_partition_data_ind[MAX_PART_TABLE] ;
EXEC SQL END DECLARE SECTION;
| 應用程式開發人員、應用程式擁有者 |
修改邏輯以從游標擷取。 | 若要使用陣列變數從游標擷取多列,請將程式碼變更為使用 FETCH FORWARD 。 Pro*C 程式碼: EXEC SQL char aPoeFiles[MAX_FILES][FILENAME_LENGTH];
EXEC SQL FETCH filename_cursor into :aPoeFiles;
ECPG 程式碼: EXEC SQL char aPoeFiles[MAX_FILES][FILENAME_LENGTH];
EXEC SQL int fetchSize = MAX_FILES;
EXEC SQL FETCH FORWARD :fetchSize filename_cursor into :aPoeFiles;
| 應用程式開發人員、應用程式擁有者 |
修改沒有傳回值的套件呼叫。 | 沒有傳回值的 Oracle 套件函數應該使用指標變數呼叫。如果您的應用程式包含多個具有相同名稱的函數,或如果未知類型函數產生執行期錯誤,請將值輸入至資料類型。 Pro*C 程式碼: void ProcessData (char *data , int id)
{
EXEC SQL EXECUTE
BEGIN
pkg_demo.process_data (:data, :id);
END;
END-EXEC;
}
ECPG 程式碼: void ProcessData (char *dataParam, int idParam )
{
EXEC SQL char *data = dataParam;
EXEC SQL int id = idParam;
EXEC SQL short rowInd;
EXEC SQL short rowInd = 0;
EXEC SQL SELECT pkg_demo.process_data (
inp_data => :data::text,
inp_id => :id
) INTO :rowInd;
}
| 應用程式開發人員、應用程式擁有者 |
重寫 SQL_CURSOR 變數。 | 重寫SQL_CURSOR 變數及其實作。 Pro*C 程式碼: /* SQL Cursor */
SQL_CURSOR demo_cursor;
EXEC SQL ALLOCATE :demo_cursor;
EXEC SQL EXECUTE
BEGIN
pkg_demo.get_cursor(
demo_cur=>:demo_cursor
);
END;
END-EXEC;
ECPG 程式碼: EXEC SQL DECLARE demo_cursor CURSOR FOR SELECT
* from
pkg_demo.open_filename_rc(
demo_cur=>refcursor
) ;
EXEC SQL char open_filename_rcInd[100];
# As the below function returns cursor_name as
# return we need to use char[] type as indicator.
EXEC SQL SELECT pkg_demo.get_cursor (
demo_cur=>'demo_cursor'
) INTO :open_filename_rcInd;
| 應用程式開發人員、應用程式擁有者 |
套用常見的遷移模式。 | 變更SQL查詢,使其與 Postgre 相容SQL。 當 不支援匿名區塊時ECPG,將其移至資料庫。 移除 Postgre dbms_application_info 不支援的邏輯SQL。 游標關閉後移動EXEC SQL COMMIT 陳述式。如果您在迴圈中提交查詢,以從游標擷取記錄,則游標會關閉,而且游標不存在錯誤。 如需處理 ECPG和 錯誤碼中的例外狀況的資訊,請參閱 PostgreSQL 文件中的錯誤處理。
| 應用程式開發人員、應用程式擁有者 |
視需要啟用偵錯。 | 若要在偵錯模式下執行ECPG程式,請在主函數區塊中新增下列命令。 ECPGdebug(1, stderr);
| 應用程式開發人員、應用程式擁有者 |
任務 | 描述 | 所需的技能 |
---|
為 建立可執行檔ECPG。 | 如果您有名為 的內嵌 SQL C 來源檔案prog1.pgc ,您可以使用下列命令序列來建立可執行程式。 ecpg prog1.pgc
cc -I/usr/local/pgsql/include -c prog1.c
cc -o prog1 prog1.o -L/usr/local/pgsql/lib -lecpg
| 應用程式開發人員、應用程式擁有者 |
建立要編譯的 make 檔案。 | 建立 make 檔案以編譯ECPG程式,如下列範例檔案所示。 CFLAGS ::= $(CFLAGS) -I/usr/pgsql-12/include -g -Wall
LDFLAGS ::= $(LDFLAGS) -L/usr/pgsql-12/lib -Wl,-rpath,/usr/pgsql-12/lib
LDLIBS ::= $(LDLIBS) -lecpg
PROGRAMS = test
.PHONY: all clean
%.c: %.pgc
ecpg $<
all: $(PROGRAMS)
clean:
rm -f $(PROGRAMS) $(PROGRAMS:%=%.c) $(PROGRAMS:%=%.o)
| 應用程式開發人員、應用程式擁有者 |
任務 | 描述 | 所需的技能 |
---|
測試代碼。 | 測試轉換的應用程式程式碼,以確保其正常運作。 | 應用程式開發人員、應用程式擁有者、測試工程師 |
相關資源
其他資訊
PostgreSQL 具有內嵌SQL的前置編譯器 ECPG,相當於 Oracle Pro*C 前置編譯器。ECPG 透過將SQL呼叫取代為特殊函數呼叫,將具有內嵌SQL陳述式的 C 程式轉換為標準 C 程式碼。然後,可以使用任何 C 編譯器工具鏈處理輸出檔案。
輸入和輸出檔案
ECPG 會將您在命令列上指定的每個輸入檔案轉換為對應的 C 輸出檔案。如果輸入檔案名稱沒有副檔名,則假設為 .pgc。檔案的副檔名由 取代.c
,以建構輸出檔案名稱。不過,您可以使用 -o
選項覆寫預設輸出檔案名稱。
如果您使用破折號 (-
) 作為輸入檔案名稱, 會從標準輸入ECPG讀取程式,並寫入標準輸出,除非您使用 -o
選項覆寫該項目。
標頭檔案
PostgreSQL 編譯器編譯預先處理的 C 程式碼檔案時,會在 PostgreSQL include
目錄中尋找ECPG標頭檔案。因此,您可能必須使用 -I
選項,將編譯器指向正確的目錄 (例如 -I/usr/local/pgsql/include
)。
Libraries (程式庫)
使用 C 程式碼搭配內嵌的程式SQL必須與libecpg
程式庫連結。例如,您可以使用連結器選項 -L/usr/local/pgsql/lib -lecpg
。
已轉換ECPG的應用程式透過內嵌SQL程式庫 (ecpglib
) 呼叫libpq
程式庫中的函數,並使用標準前端/後端通訊協定與 PostgreSQL 伺服器通訊。