OTL学习笔记--OTLHelper的实现

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块可能含有输入和(或)输出参数,这些参数可能是标量也可能是向量。

clip_image002

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文件的导入,不过灵活性差了一点,要根据表结构来使用不同的结构体,这个应该还能进一步抽象。。

OTLHelper

主程序调用代码:

[cpp]  view plain copy
  1. #include "cppstd.h"  
  2. #include "OTLHelper.h"  
  3. // The following #define is required with MyODBC 3.51.11 and higher  
  4. #define OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE  
  5. int main()  
  6. {  
  7.     //连接字符串,用户名/密码@数据源名  
  8.     string strConn="root/****@mysql35";  
  9.       
  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. }  

示例工程代码可以在此下载 。OTL还有很多内容,例如:SQL的变量绑定和常量SQL的使用、OTL流中的读迭代器、与STL兼容的迭代器、连接缓冲池、操作大型对象、使用UNICODE字符串或使用UTF8字符串。

OTL小巧功能却十分强大,整个库仅有一个400k大小的头文件,这种有点另类的封装方法,有利有弊吧,不过OTL提供的不依赖第三方的数据库连接解决方法,这点令人十分佩服。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值