OTL簡介
OTL是Oracle, ODBC and DB2-CLI Template Library的縮寫,目前版本是4.0,是基於C++模板機制的C++庫。
OTL 4.0 由一個C++模板框架(C++ template framework)和許多OTL適配器(OTL-adapters)組成。框架是OTL streams的泛型實現,OTL適配器是底層數據庫API的包裝類,作爲對象的類型參數傳遞給模板框架。
OTL 4.0 通過由模板框架和OTL適配器(OTL-adapters)生成少數的幾個類:
--otl_stream
--otl_connect
--otl_exception
--otl_long_string
--幾個PL/SQL (Oracle)的模板容器類
就能完成全功能的C++數據庫訪問功能.。
OTL的代碼展開即是對數據庫API函數的直接調用,所以能夠提供很高的性能(與數據庫提供的API相比,只增加了10-15%的開銷),並且在多核環境下和傳統批處理程序下都擁有很高的可靠性。OTL 4.0 是一個簡潔而且不依賴其他環境的模板庫,具有高度可移植性.。
OTL 4.0 符合ANSI C++標準(ANSI C++的類型轉換,乾淨模板化代碼等等),可以通過兼容STL的流迭代器來使用STL,OTL在otl_stream中還原生支持STL std::string。在OTL還能使用ACE(#define OTL_ACE //定義這個宏),支持ACE_TStrings。
OTL4.0支持以下數據庫:
--從Oracle7.3以來的所有版本(通過相應版本的原生OCI接口)
--支持DB2 UDB LUW / zOS (通過原生DB2 CLI接口),
--支持MS SQL Server 2005/2008 (通過原生SNAC接口),
--支持Informix 11 (通過I原生nformix CLI接口),
--支持TimesTen 7或更高版本 (通過原生TimesTen CLI接口),
--支持SAP-MAX/DB (通過原生SAP/DB CLI接口),
--支持符合MS Windows ODBC 3.x和ODBC 2.5 (老版本程序需要)標準的數據源,
--支持Linux/Unix/Mac OS X (通過unixodbc和iODBC驅動管理器): Sybase, MySQL, PostgreSQL, EnterpriseDB, SQLite, MS ACCESS, Firebird等等.
--這份數據庫支持列表還在不斷的增長。
最近的幾年裏,軟件平臺發生了從32位平臺到64位平臺的轉變:OTL的源代碼是可移植的,支持32位和64位的C++編譯器,支持在Oracle中使用UTF-8和UTF-16;OTL還支持在其他數據庫中使用UTF-16,這需要底層數據庫API或ODBC驅動的支持。
以上簡介翻譯至 http://otl.sourceforge.net/otl3_intro.htm ,OTL下載地址 http://otl.sourceforge.net/otlv4_h.zip
OTL中流的概念
OTL設計者認爲,任何SQL語句、PL/SQL塊或存儲過程調用都可以被輸入和輸出變量特徵化。例如:
-- 一個SELECT語句在其WHERE子句中擁有標量的輸入變量,而在其SELECT子句則定義了輸出的列,如果SELECT語句返回的是多行記錄則輸出列是個向量參數。
-- 一個INSERT和UPDATE語句需要將數據寫入表中,它們擁有輸入參數。另外,一個DELETE語句由於需要指明刪除記錄的類型,同樣擁有輸入。工業強度的數據庫服務器通常也支持批量操作,例如批量的查詢、更新、刪除和插入,因此INSERT/UPDATE/DELETE語句的參數在批量操作的情況下也可能是向量。
-- 一個存儲過程可能含有輸入和(或)輸出參數。通常存儲過程的參數是標量,但是也有特例,例如返回的是引用遊標(Oracle)或者記錄集(MS SQL SERVER或者Sybase)。
-- 一個PL/SQL塊可能含有輸入和(或)輸出參數,這些參數可能是標量也可能是向量。
OTL的流
因此,任何的SQL或者其程序上的擴展在交互過程中都可以如圖4-1所示看作擁有輸入和輸出的黑盒。OTL通過將數據流和SQL的概念聯合起來,用otl_stream類表達這種抽象。
由於SQL語句可能以批量的方式執行,otl_stream是一個緩衝流。它擁有兩個獨立的緩衝區:輸入和輸出。輸入緩衝區由所有集中到一起的輸入參數組成,輸出緩衝區則由所有集中到一起的輸出變量組成。
OTL流和C++的緩衝流很相似。一個SQL語句或存儲過程調用被當作一個普通的緩衝流被打開。OTL流的操作邏輯和C++流操作邏輯基本相同,但是OTL流的輸出和輸出緩衝區可能重疊。
OTL流擁有flush()方法在輸入緩衝區寫滿的時候將其自動刷新,也含有一系列的<<和>>運算符來讀和寫不同數據類型的對象。它最重要的優點是爲任何類型的SQL語句和存儲過程調用提供了統一的接口。應用開發者能夠通過熟悉少量的語法和函數名稱像使用C++流一樣來使用OTL流。
在OTL流的內部擁有一個小型的解析器來解析所聲明的綁定變量以及綁定變量的數據類型。因此,免去了使用特殊的綁定函數來綁定已聲明的C/C++主機變量(host variables)。由於所有必須的緩衝區在OTL流中會自動創建,因此OTL僅僅需要被打開來進行讀和寫相應的數值。
OTL流接口要求使用OTL異常。OTL流操作都能可能拋擲otl_exception異常。因此爲了攔截異常並阻止程序異常終止,必須使用try/catch塊來包裹OTL流的使用代碼。
OTL流的實現otl_stream具有較高的自動化功能,當OTL流的所有的輸入變量被定義好(也就是輸入緩衝區被填滿),它會觸發OTL流中的黑盒來執行。在黑盒執行的過程中輸出緩衝區被填充。在執行完成後,輸出緩衝區中的值能夠從OTL流中被讀取。如果執行的是一個SELECT語句並且返回多於輸出緩衝區大小的行,那麼在輸出緩衝區的內容被讀取後,OTL會自動讀取下一批行記錄到輸出緩衝區。
以上摘抄至《OTL使用指南》,廣東從興電子有限公司的文檔
OTL的一般使用步驟
-- 使用宏指明底層數據庫API類型和控制編譯器對OTL的編譯(啓用OTL支持的特性,而且定義的宏應該在頭文件包含之前)。例如:
#define OTL_ORA11G
#define OTL_ODBC_MSSQL_2008
#define OTL_DB2_CLI
#define OTL_ODBC_POSTGRESQL
#define OTL_ODBC_MYSQL
#define OTL_ODBC
#define OTL_ODBC_UNIX
#define OTL_STL
#define OTL_ANSI_CPP
#define OTL_UNICODE
-- 創建otl_connect對象,該對象一般爲全局共享的。
-- 調用otl_connect的靜態方法otl_initialize()初始化OTL環境。
-- 調用otl_connect的rlogon()方法連接數據庫。
-- 創建otl_stream()對象,該對象一般爲局部的。
-- 調用otl_stream的open()方法打開SQL進行解析。
-- 使用otl_stream的<<操作符綁定SQL中的變量。
-- 使用otl_stream的>>操作符讀取返回結果。
-- 調用otl_connect的logoff()方法從數據庫斷開。
爲了便於自己使用,我編寫了簡易的OTLHelper類,封裝了一些常用操作,接口如下圖所示,其中import()方法實現了csv文件的導入,不過靈活性差了一點,要根據表結構來使用不同的結構體,這個應該還能進一步抽象。。
主程序調用代碼:
view plaincopy to clipboardprint?
01.#include "cppstd.h"
02.#include "OTLHelper.h"
03.// The following #define is required with MyODBC 3.51.11 and higher
04.#define OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE
05.int main()
06.{
07. //連接字符串,用戶名/密碼@數據源名
08. string strConn="root/****@mysql35";
09.
10. //sql語句
11. string sql_delete="drop table test_withoutIndex";
12. string sql_create="create table test_withoutIndex(timestamp char(9),millisecond int,value double,quality_code int)";
13. string sql_select="select * from test_withoutIndex where value>500";
14.
15. //導入文件路徑
16. string file_import="test_data.csv";
17.
18. //數據庫表名
19. string non_index_table="test_withoutIndex";
20. string index_table="test_withIndex";
21.
22. //連接對象
23. OTLHelper otl_hp;
24. try
25. {
26. start_time=clock();
27.
28. otl_hp.connect(strConn);
29. //otl_hp.direct_exec(sql_delete,otl_exception::disabled);
30. //otl_hp.direct_exec(sql_create);
31. //otl_hp.import(file_import,non_index_table);
32. //otl_hp.import(file_import,index_table);
33. otl_hp.select(sql_select);
34. //otl_hp.update(8);
35. otl_hp.disconnect();
36.
37. end_time=clock();
38. }
39.
40. //異常處理
41. catch(otl_exception& p)
42. {
43. cerr<<p.msg<<endl; // print out error message
44. cerr<<p.stm_text<<endl; // print out SQL that caused the error
45. cerr<<p.sqlstate<<endl; // print out SQLSTATE message
46. cerr<<p.var_info<<endl; // print out the variable that caused the error
47. }
48. return 0;
49.}
#include "cppstd.h"
#include "OTLHelper.h"
// The following #define is required with MyODBC 3.51.11 and higher
#define OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE
int main()
{
//連接字符串,用戶名/密碼@數據源名
string strConn="root/****@mysql35";
//sql語句
string sql_delete="drop table test_withoutIndex";
string sql_create="create table test_withoutIndex(timestamp char(9),millisecond int,value double,quality_code int)";
string sql_select="select * from test_withoutIndex where value>500";
//導入文件路徑
string file_import="test_data.csv";
//數據庫表名
string non_index_table="test_withoutIndex";
string index_table="test_withIndex";
//連接對象
OTLHelper otl_hp;
try
{
start_time=clock();
otl_hp.connect(strConn);
//otl_hp.direct_exec(sql_delete,otl_exception::disabled);
//otl_hp.direct_exec(sql_create);
//otl_hp.import(file_import,non_index_table);
//otl_hp.import(file_import,index_table);
otl_hp.select(sql_select);
//otl_hp.update(8);
otl_hp.disconnect();
end_time=clock();
}
//異常處理
catch(otl_exception& p)
{
cerr<<p.msg<<endl; // print out error message
cerr<<p.stm_text<<endl; // print out SQL that caused the error
cerr<<p.sqlstate<<endl; // print out SQLSTATE message
cerr<<p.var_info<<endl; // print out the variable that caused the error
}
return 0;
}
示例工程代碼可以在此下載 。OTL還有很多內容,例如:SQL的變量綁定和常量SQL的使用、OTL流中的讀迭代器、與STL兼容的迭代器、連接緩衝池、操作大型對象、使用UNICODE字符串或使用UTF8字符串。
OTL小巧功能卻十分強大,整個庫僅有一個400k大小的頭文件,這種有點另類的封裝方法,有利有弊吧,不過OTL提供的不依賴第三方的數據庫連接解決方法,這點令人十分佩服。