OTL中文文档

说明

该文档说明的是4.0版本的ORACLE/ODBC和DB2-CLI模板库(OTL)。OTL4.0(后面简称OTL)模板库是基于C++的模板的。

OTL4.0是组合了C++的模板框架和OTL适配器。框架是一个简单的OTL_stream的概念,OTL适配器则是一个基于数据库API的经量级的类库,并且作为参数传给OTL的框架参数。

OTL4.0仅通过otl_stream、otl_connect、otl_exception、olt_long_string和几个简单的ORACLE数据库的从模板框架和OTL适配器派生的的table_container类便包含了所有其他的C++数据库访问类库的所有优点。

因为OTL的代码里面是直接调用数据库的API操作的,所以相比于原生的数据库API操作,OTL的性能上仅低10-15%左右,并且还能良好的支持多进程。OTL4.0因为专业与精简的类库,具有非常高的通用性。

OTL是ANSI编码的,与STL具有非常紧密的联系。并且支持STL的string在otl_stream里面;还整合了ACE通过支持ACE_TString。

OTL支持的数据库有,ORACLE7.3以上的版本、DB2 UDB LUW / Zos、MS SQL SERVER 2005/2008、Informix 11、TimesTen 7以上版本、SAP-MAX/DB、ODBC 2.5和3.0(通过unixodbc或iODBC)、Sybase、MySql、PostgreSQL、EnterpriseDB、SQLite、MS ACCESS、Firebird等等,后续还会添加更多支持。

在过去的一段时间里面,OTL在字符集方面作了一些修改。添加了64位平台的支持,现在OTL已经开始同时支持32和64位平台。并且在数据库的API或ODBC支持的情况下对ORACLE来讲还支持UTF-8和UTF16字符集,对其他的数据库则支持UTF-16字符集。

 

OTL流的概念

任何的SQL语句、SQL语句块或存储过程,都是通过输入与输出变量进行处理参数与结果的。如:

例1:一个SELECT语句把标量的输入变量作为WHERE子句部分的条件;同时SELECT部分则定义了输出的字段,并且在结果集为多行的情况下还是一个VECTOR结构。

例2:一个INSERT语句把数据写入数据库中,同样需要输入数据。UPDATE也是同样的道理。

例3:一个DELETE语句从表中删除数据,删除的条件同样需要通过参数输入。

例4:一个存储过程可能同时具有输入与输出参数。通过存储过程的参数都是标量,但某些特殊情况下ORACLE的存储过程还可以返回一个游标、MS SQL SERVER还可以返回一个结果集。

例5:一个多功能的SQL语句块则有可能具有标量或矢量的输入与输出参数。

专业的程序里面往往有大量的SQL操作,如大量的INSERT/UPDATE/SELECT/DELETE等。所以参数对于SQL语句来讲,都可以理解为VECTOR的类型。

下面的图示表示的非常清楚。对于任何的SQL语句或语句块存储过程等,这些SQL都可以作为一个黑盒子一样。它们的输入与输出总是具有VECTOR类型。

OTL翻译(2) <wbr>-- <wbr>OTL流的概念

为什么不把SQL语句与数据(输入或输出参数)整合在一起?而是通过多个不同的结构来包装SQL语句与数据呢?OTL通过otl_stream来回答这个问题。

SQL语句在执行的时候,通过otl_strea对数据进行操作,otl_stream是一个缓冲流,它包括输入与输出两个缓冲区。输入缓冲区用来存放输入参数,输出缓冲区用来存放输出参数。

C++流总是通过重载 >> 和 << 两个操作符来处理输入与输出数据,otl_stream同样也重载了这两个符号用来处理输入与输出数据。

OTL的流与C++的流类似。一个SQL语句或存储过程打开的时候通过一个普通的缓冲流,OTL的逻辑SQL语句部分还是保留。OTL的流把输入与输出缓冲区分开处理。

OTL流里面有个刷新的函数,当缓冲区满的时候或是重新读取或写入数据的时候,就通过该刷新操作把重新刷新缓冲区的数据。更重要的是OTL的流具有相当简单的接口,对于熟悉C++流的你来说,只要记住简单的几个操作即可。

在OTL流内部有一个简单的变量解析器。所以不需要绑定变量的时候指定变量类型与占位符,所有这些都在OTL流内部动态的处理。OTL流仅需要打开进行读和写。

OTL流可能会抛出otl_exceptionr的异常,所以为了避免程序core down需要在处理OTL流的时候,用try…catch…块把相关代码包含起来。

OTL流的数据处理是自动的。当所有的输入变量全部定义后,它就自动的触发SQL去执行,并把输出填到输出缓冲区里面。此时输出就可以去缓冲区里面读取数据。如果缓冲区里面的数据满了后,还有数据未读出,则等等读取缓冲区数据后,再去取其他部分的数据(如缓冲区只能容1000行数据,但某次SELECT取出了2000条数据,则先取出1000条后,如果缓冲区数据被程序取出后,OTL再自动的去取另外的1000条数据填进缓冲区里面)。

 

OTL的类

相比于传统的C++类库而言,OTL更像是一个代码容器,里面复杂,但对外的接口简单。OTL在处理程序方面受到了STL的影响。

OTL有一个模板框架,它实现了otl_stream的概念。该框架由模板类和内联函数组成。模板类把普通的类型作为参数,这些参数的类型提供了对数据库API的详细操作。

对于已有的数据库API,OTL提供如下的数据库API支持:

  • Oracle Call Interface for Oracle 7/8/8i /9i/10g/10gR2/11g (OCI7/8/8i/9i/10g/10gR2/11g)
  • Open Data Base Connectivity (ODBC)
  • MS SQL Server 2005/2008's SQL Native Client (SNAC)
  • DB2 Call Level Interface (CLI)
  • Informix CLI
  • TimesTen CLI
  • SAP DB CLI

OTL适配器通过经量级的封装数据库API,并且由于OTL适配器是直接的与模板框架进行通信,所以OTL能够提供近乎直接调用数据库API的性能。

OTL的模板框架提供了如下的OTL类:

  • otl_stream
  • otl_connect
  • otl_exception
  • otl_long_string

 

otl_stream

otl_stream是具体实现otl_stream_concept的类。任何的SQL语句、SQL语句块和存储过程都能通过otl_stream进行处理。

传统的数据库API处理SQL语句的时候,需要绑定变量与占位符,因此,程序员需要定义变量、解析SQL语句、调用绑定占位符的函数、把变量绑定到占位符上、执行SQL、读取输出的变量等等。如此循环。以上所有的这些操作在OTL里面的otl_stream类里面都是自动处理的,otl_stream类提供了与数据库交互自动化最大性能。该性能仅取决于一个参数-缓冲区大小。缓冲区是用于存放SQL执行过程中的逻辑行数。

注:在timesten7.0.2或以上版本的数据库中,定义了OTL_TIMESTEN_UNIX或OTL_TIMESTEN_WINDOWS宏的时候,缓冲区大小可以设置为0。此时表示默认使用数据库的最佳缓冲区大小。一般情况下是一个元素大小。具体更多信息请参考数据库的手册。

一个SQL语句在otl_stream里面至少需要一个输入或输出占位符,对于没有占位符的SQL语句,它将被作为常量的SQL语句作为另一种方式执行。

从OTL4.0.115版本开始后,缓冲区大小的类型为整形,以前的版本全是短整形。如果需要支持旧版本的代码,请在编译代码前添加定义OTL_STREAM_LEGACY_BUFFER_SIZE_TYPE宏。

otl_stream类有如下的公共方法:

 

序号

函数名

说明

1

otl_stream(…)

序号

参数

说明

1

const int arr_size

缓冲区大小

2

const char * sqlstm

SQL语句或SQL语句块

3

otl_connect & db

otl_connect对象

4

const char *

ref_cur_placeholder

= 0

如果otl_stream返回一个游标,则该参数指定游标的占位符

5

const char * sqlstm_label = 0

sql语句标识,如果指定了该参数,则会用sqlstm_label填充otl_exception::stm_text,并且原来的SQL语句将不可见。

 

仅ORACLE 7/8/9/10/11版本

构造函数。

该构造函数创建一个otl_steram对象,并且调用open()函数。

2

otl_stream(…)

序号

参数

说明

1

const int arr_size

缓冲区大小

2

const char * sqlstm

SQL语句或SQL语句块

3

otl_connect & db

otl_connect对象

4

const int

implicit_select

= otl_explicit_select

如果otl_stream返回一个存储过程的结果集,该参数必须指定为otl_implicit_select

5

const char *

sqlstm_label = 0

sql语句标识,如果指定了该参数,则会用sqlstm_label填充otl_exception::stm_text,并且原来的SQL语句将不可见。

 

仅ODBC/DB2 CLI

构造函数,该构造函数创建一个otl_stream对象,并且调用open()函数。

在ODBC和DB2 CLI下面对该对象还定义了如下两个常量:

otl_explicit_select:指定该流为一个简单的SELECT语句流;

otl_implicit_select:指定该流为一个返回结果集的流;

3

void open(…)

序号

参数

说明

1

const int arr_size

缓冲区大小

2

const char * sqlstm

SQL语句或SQL语句块

3

otl_connect & db

otl_connect对象

4

const char *

ref_cur_placeholder

= 0

如果otl_stream返回一个游标,则该参数指定游标的占位符

5

const char * sqlstm_label = 0

sql语句标识,如果指定了该参数,则会用sqlstm_label填充otl_exception::stm_text,并且原来的SQL语句将不可见。

 

仅ORACLE 7/8/9/10/11版本

该函数打开(执行)SQL语句,总共分为如下:解析SQL语句、在流内部为输入输出变量分配内存空间、自动绑定变量到对应的占位符。

4

void open(…)

序号

参数

说明

1

const int arr_size

缓冲区大小

2

const char * sqlstm

SQL语句或SQL语句块

3

otl_connect & db

otl_connect对象

4

const int

implicit_select

= otl_explicit_select

如果otl_stream返回一个存储过程的结果集,该参数必须指定为otl_implicit_select

5

const char *

sqlstm_label = 0

sql语句标识,如果指定了该参数,则会用sqlstm_label填充otl_exception::stm_text,并且原来的SQL语句将不可见。

 

仅ODBC/DB2 CLI

该函数打开(执行)SQL语句,总共分为如下:解析SQL语句、在流内部为输入输出变量分配内存空间、自动绑定变量到对应的占位符。

5

int eof()

测试流里面是否所有的数据全被读取出来,该函数与C++的IO流里面的eof()函数同理。

6

int setBufSize(const int buf_size)

设置缓冲区大小。

该函数仅是对后续的otl_connect::operator>>(otl_stream&)操作保存(新建)一个新的缓冲区。

7

void flush()

刷新输出流缓冲区。

它实际上的操作是通过执行流里面的SQL语句来填充输出缓冲区。流在缓冲区满的情况下自动的进行刷新操作。

该函数与C++的IO流的flush()同理。

如果在设置了auto-commit标识的情况下,在刷新了输出缓冲区后,也就会自动的进行一次事务提交。更详细的解释请见set_commit()

8

void flush(…)

序号

参数

说明

1

const int row_offset = 0

指定刷新缓冲区的行数

2

const bool force_flush = false

忽略以前的错误强制刷新

 

在OCI 8/8i/9i/10g/11g的版本里面还带有一个带两个参数的flush()版本的函数。该函数有两方面的作用:

1、 对大数据量的操作更高效

2、 能够识别(发现)出重复的数据,并抛出异常

9

int get_auto_commit_flag()

取得自动提交标识。

1:表示自动提交标识已设置

0:表示自动提交标识未设置

10

int get_stream_type()

仅ORACLE 7/8/9/10/11版本

取得流的类型。

返回的类型由如下的整形常量:

otl_no_stream_type—流还未通过SQL进行实例化

otl_select_stream_type—流是一个简单的SELECT语句的流

otl_inout_stream_type—流是通过一个带有输入输出参数的匿名的SQL块进行实例化的,还有可能是一个存储过程。

otl_refcur_stream_type—流是通过一个SQL语句块进行实例化的,该SQL块返回的是一个游标。在这种流的情况下,只能有输入参数,输出参数一定是一个游标。

otl_constant_sql_type—该类型本只能在使用create_stored_proc_call()里面使用,然而它代表了一种流类型。

在create_stord_proc_call()里面它本义也是指不带有参数的,而且它必须通过otl_cursor::direct_exec()执行。

otl_mixed_refcur_stream_type—只由create_stoerd_proc_call()实例的类型。它能够带有输入或输出参数,并且一定有返回一个游标。

如果create_stored_proc_call()的sql_stm参数设定了的情况下,流的缓冲区大小必须设置为1,并且必须通过otl_refcur_stream去读取游标的数据。更详细的请见例:153

11

static void create_stored_proc_call(…)

序号

参数

说明

1

otl_connect& db

otl_connect对象

2

otl_stream &

args_strm

otl_stream的外部实例。

意思是函数外部的一个变量。

为了保证函数能从数据字典表里面取得数据库的信息,该变量必须通过“SELECT … FROM ALL_ARGUMENTS …”来实例化。

该变量实例化一次就可以以后续的函数里多次使用。

3

chat * sql_stm

输出参数。

带有参数的存储过程名,或兼容otl_stream的SQL语句块。

4

int & stm_type

输出参数,otl_stream的类型

5

char *

refcur_placeholder

输出参数。

如果存储过程返回一个游标,则该参数保存游标的名字。

后面可以被otl_stream::otl_stream()/otl_stream::open()使用。

6

const char * proc_name

存储过程名

7

const char *

package_name

存储过程所在的包的名字

8

const char *

schema_name = 0

存储过程和包所在的模式名(用户名)

9

const bool

schema_name_include

= false

指定调用的存储过程名里面是否带有模式(用户)名。

10

const int

varchar_size = 2001

存储过程里面的VARCHAR类型的参数是没有大小的。

该参数指定VARCHAR参数的大小。

11

const int

all_num2type

= otl_var_double

该参数定义了NUMBER类型参数如何对应绑定变量

12

const int

refcur_buf_size = 1

在存储过程返回游标的情况下,该参数指定游标缓冲区大小。

该参数此时对性能影响较大。

 

仅ORACLE 7/8/9/10/11版本

不能定义在OTL_UNICODE宏下面实现。

通过存储过程名去实现一个兼容的otl_stream流。

这是个静态的函数,意图去实现调用oracle的存储过程。

为了能够获取到存储过程的参数和类型,该函数使用ORACLE的系统数据字典。可能会抛出32014、32015、32016的OTL异常。

该函数能够调用下列的函数或存储过程:

1:当前或指定用户名下面的SQL包的存储过程或函数;当前或指定用户名下面的全局的存储过程或函数。

2:公共或私有同义词下面的SQL包的存储过程或函数;公共或私有同义词下面的全局的存储过程或函数。

3:没有重载(同名)的存储过程或函数。

4:带有标量的输入或输出参数,或带有输出游标的存储过程或函数。

12

void clean(const int clean_up_error_flag = 0)

在不刷新缓冲区的情况下,清理掉缓冲区里面的内容。

如果clean_up_error_flag参数设置为1,那么除了清掉缓冲区内容的同时,还清理掉流里面抛出的异常信息。

详细请见例:65、66、67.该参数的意义在于提供一个不需要关闭流的情况下可以重新返回数据库的相关错误信息。

在4.0.6及以后的版本中,该函数还能中断一个正在执行中的SQL语句,并且清空错误信息。

13

void rewind()

重新处理一个流(恢复一个流到初始状态)。

如果该流没有参数,则强制该流的执行。

14

operator int()

把流转换为int类型的重载操作符。

它返回!eof()的结果状态。它能够被用在一直循环里面,如下:

 while(s>>f1>>f2){ 
    cout<<"f1="<<f1
        <<", f2="
        <<f2<<endl; 
  }

15

void cancal()

仅ODBC / DB2 CLI。

中止一个正在处理中的SELECT语句或是存储过程。

而且对于一个线程中正在运行的,另一个线程能异步的中止该正在执行中的流。

具体的中止操作取决于数据库层的API函数。

并且错误信息也是由数据库层抛出。

OCI8/8i/9i/10g也有一个相类似的函数otl_connect:cancel(),但是与DB2 CLI确是不同的。

16

bool get_next_diag_rec(…)

序号

参数

说明

1

short int & rec_ndx

动态记录的索引

2

SQLCHAR *sqlstate_buf

SQL状态缓冲区,在unicode情况下,该参数类型为SQLWCHAR

3

SQLCHAR * msgbuf

消息缓冲区,在unicode情况下,参数类型为SQLWCHAR

4

short int msg_buf_size

消息缓冲区大小

5

int & native_error

本机错误

 

仅支持ODBC。

必须定义OTL_ODBC_SQL_STATEMENT_WITH_DIAG_REC_OUTPUT宏。

该函数是用来通过MS SQL SERVER的BACKUP/DBCC命令获取动态的记录。函数内部实际是调用SQLGetDiagRec()函数。

记录的索引从1开始计数。

函数能自动的增加索引。

更详细资料请见例:688、689

17

SQLHSTMT get_stm_handle()

仅ODBC适用

必须定义OTL_ODBC_SQL_STATEMENT_WITH_DIAG_REC_OUTPUT宏。

该函数用来返回底层的ODBC句柄。

18

int is_null()

测试是否stream返回一个空值

19

void set_lob_stream_mode(const bool mode = false)

设置log_stream_mode标识。

该标识通知流使用otl_lob_stream操作。

在OCI8上面该函数不是必须的,不过在ODBC/DB2 CLI或是otl_stream_read_iterator一起使用的时候,必须设置该值。

或是在代码里面添加多数据库支持的时候,必须调用该函数。

20

long get_rpc()

返回数据库本次操作返回的记录行数。

返回的数据由INSERT/UPDATE/DELETE语句返回的操作行数;

对于INSERT操作,它返回的是小于或等于缓冲区大小。对于UPDATE或DELETE语句,它取决于实际更新或删除的行数。

在4.0.6及以后的版本中,该函数对于SELECT语句返回的是累计操作的行数。

对于ORACLE和DB2 CLI或ODBC,该函数返回值有些不同。如对于出错状态的情况下,ORACLE返回的是实际成功的行数,而对于DB2或ODBC它返回的总是0.

结论:对于想兼容所有的数据库来说,该函数并不适用于所有的数据库。但对于ORACLE的不同版本的数据库来说,它还是通用的。

21

void set_commit(int auto_commit = 0)

设置流的auto-commit标识。

当流的输出缓冲区刷新的时候,就会自动进行事务提交操作。

如果想避免自动提交,请设置自动提交标识为false。

该自动提交标识与数据库的自动提交是两码事,该自动提交标识只是OTL自己的自动事务提交标识。

实际上设置为非自动提交还是非常方便的,在这种情况下,就可以使用otl_nocommit_stream类。

otl_nocommit_stream类是一个直接继承otl_stream类的子类,仅是关闭了自动提交标识。

22

void set_flush(const bool auto_flush = true)

设置流的自动刷新标识。

默认值为真。

实际上,流的析构函数试图进行刷新操作。

自动刷新标识可以通过该函数进行关闭。

如果自动刷新标识被关闭后,流就必须通过otl_stream::close()或otl_stream::flush()操作来强制刷新流,因为就算流的脏标志为真的情况下流的析构函数也不会去刷新缓冲区。

该函数仅是禁止析构函数里面的自动刷新功能。

对于一般的缓冲区提交不能禁止。

例如缓冲区满的情况下还是会自动进行刷新操作。

23

otl_var_desc * describe_out_vars(int & desc_len)

一组用来分析流的输入或输出绑定变量的函数。函数返回一个otl_var_desc结构体的指针。

otl_var_desc类类型如下:

序号

类型

说明

1

int param_type

0:输入变量

1:输出变量

2输入输出变量

2

int ftype

otl的数据类型,详细见OTL类型与数据库类型对比表

3

int elem_size

元素大小

4

int array_size

数组大小。

对于标量来说,总是1

5

int pos

在SELECT语句里面,表示一个相对的输出变量的位置,如1、2、3

6

int name_pos

在定义了语句占位符的情况下,它表示占位符的相对的位置。

如0,1,2

7

char name[128]

在变量定义为占位符的情况下,它表里前127个字节

8

int pl_tab_flag

在OCI里面,如果变量定义为表名,则值为1,否则为0

 

该函数用来取得输出变量的属性,参数desc_len返回的是otl_var_desc结构体大小。

如果流里面没有输出参数,则返回0。

如果有参数同时为输入和输出参数,它返回输出参数部分。

流的输出参数指的是取出流的部分。

24

otl_var_desc * describe_in_vars(int & desc_len)

该函数用来取得输入变量的属性,参数desc_len返回的是otl_var_desc结构体大小。如果流里面没有输入参数,则返回0。

如果有参数同时为输入和输出参数,它返回输入参数部分。

流的输入参数指的是输入流的部分。

25

otl_var_desc * describe_next_out_var()

取得下一步输出变量。“下一个”指的是从流中读取了以后,下一个读出来的输出变量。比如调用了otl_stream::operator<<()后,有时候我们想要知道下一步输出变量的类型。如果没有下一个变量的时候,函数返回0.

26

otl_var_desc * describe_next_in_var()

取得下一步输入变量。“下一个”指的是从往流中写入了以后,下一个写入的输入变量。比如调用了otl_stream::operator<<()后,有时候我们想要知道下一步输入变量的类型。如果没有下一个变量的时候,函数返回0.

27

(1) void close()

关闭流。

该函数与C++里面的流具有相同的概念。

该函数有两个版本,一个是普通的版本,另一个是在定义了OTL_STREAM_POOLING_ON宏下的另一个版本。

28

(2) void close(const bool save_in_stream_pool = true)

定义了OTL_STREAM_POOLING_ON宏情况下使用。

save_in_stream_pool标志是一个初始化标志。

当它设置为真的时候,在定义了OTL_STREAM_POOLING_ON宏的情况下,关闭一个流,并非真正的把流关闭了,而是把该流放到一个流缓冲池下面。

如果后续还要接着使用该流,那直接调用缓冲池里面的流就可以,而不用重新再新建一个流。

如果标志设置为假,那么关闭流的时候就是真正关闭了流。

在对于某些流需要消耗大量系统资源的情况下,该参数非常有用。

因为可以减少分配、删除流资源的时间而提高性能。

更详细的请见例:113、114、115

29

int good()

测试流是否是打开的。

与C++里面的流打开具有相同的功能。

30

otl_column_desc * describe_select(int & desc_len)

取得流的输出变量的字段列表。

仅对下列有效:

  • straight SELECT statement (OCIx, ODBC, and DB2-CLI)
  • Referenced cursor (OCIx)
  • Result set returned via a stored procedure call (ODBC for MS SQL Server and Sybase, DB2-CLI for DB2)

函数返回otl_column_desc结构体的指针。

otl_column_desc类型如下:

序号

成员变量

说明

1

char * name

字段名

2

int dbtype

该值依赖于特定的数据库。

对于OCI或ODBC有不同的值,详细请参见数据库。

3

int otl_var_dbtype

OTL定义的字段类型编码

4

int dbsize

字段长度

5

int scale

数值类型的精度

6

int prec

数值类型的小数位

7

int nullok

指定字段是否为空

8

int charset_form

仅在定义了OTL_UNICODE和OTL_ORA9I/OTL_ORA10G宏时候有效。

1:单字节

2:双字节

3:其他

9

int char_size

仅在定义了OTL_UNICODE和OTL_ORA9I/OTL_ORA10G宏时候有效。

字段长度(按字母),在OTL_ORA8I情况下该值为0,因为相应的属性不被支持。

 

OTL定义了如下的类型与相应的数据库类型相对应:

序号

OTL类型常量

OTL类型编码

对应的数据库类型

1

otl_var_bigint

20

MS SQL SERVER/DB2/MYSQL/POSTGRESQL里面的bigint类型(singed 64 bit integer)

2

otl_var_blob

12

oracle8/9/10/11里面的blob类型

3

otl_var_char

1

NULL结尾的字符类型

4

otl_var_clob

11

oracle8/9/10/11里面的clob类型

5

otl_var_db2date

17

db2 date类型

6

otl_var_db2time

16

db2 time类型

7

otl_var_double

2

8字节长度的浮点型

8

otl_var_float

3

4字节长度的浮点型

9

otl_var_int

4

有符号的32位整形

10

otl_var_long_int

7

对于LLP64的C++编译器是32位有符号整形;

对于LP-64编译器,则是64位有符号整形

11

otl_var_ltz_timestamp

19

对于ORACLE 9I/10G/11G,带有TIME ZONE的TIMESTAMP类型

12

otl_var_raw

23

RAW, BINARY, VARBINARY, BYTEA, VARCHAR BYTE, CHAR BYTE类型

13

otl_var_raw_long

10

ORACLE里面的LONG RAW;

MS SQL SERVER/SYBASE里面的IMAGE;

DB2里面的BLOB类型

14

otl_var_short

6

16位有符号整型

15

otl_var_timestamp

8

ORACLE的TIMESTAMP;

DB2的TIMESTAMP;

MS SQL的DATETIME/DATETIME2/TIME/DATE;

SYBASE的TIMESTAMP类型

16

otl_var_tz_timestamp

18

ORACLE下的带timezone的timestamp

17

otl_var_unsigned_int

5

无符号32位整型

18

otl_var_varchar_long

9

ORACLE里面的LONG;

MS SQL里面的TEXT;

DB2的CLOB类型

除了返回结构体的指针外,该函数还返回一个desc_len的参数。

该参数表示返回的字段列表的长度。

该函数返回的结构的指针不用用户删除,流里面在析构的时候会处理删除任务。

31

void reset_to_last_valid_row()

当OTL抛出“incompatible data type in stream operation”异常的时候,该异常为OTL内部的异常,它在流里面的SQL执行之前抛出,此时reset_to_last_valid_row()函数就能把输出缓冲区恢复到最后一个正确的位置。这个时候就能正确的调用flush()操作。如下:

otl_stream str
(
 100,
 "INSERT INTO test_tab VALUES(:f1<int>,:f2<char[31]>)",
 db
);

 ...  
try
{
    // writing rows into the stream
}
catch(const otl_exception& ex)
{
    if(ex.code==32000)
    {
        str.reset_to_last_valid_row();
        str.flush();
    }
}

32

otl_stream & operator>>(unsigned char * s)

从流里面读取数据

当定义了OTL_UNICODE的时候,它返回的是以NULL结尾的双字节的字符串。否则返回的是单字节的字符串。

33

otl_stream &

operator>>(otl_long_unicode_string & s)

在定义了OTL_UNICODE或OTL_UNICODE_CHAR_TYPE宏情况下,返回UNICODE的LOB类型

34

otl_stream &

operator>>(OTL_UNICODE_CHAR_TYPE&c)

在定义了OTL_UNICODE或OTL_UNICODE_CHAR_TYPE宏情况下,返回UNICODE的字符类型

35

otl_stream

operator>>

(OTL_UNICODE_CHAR_TYPE * s)

在定义了OTL_UNICODE或OTL_UNICODE_CHAR_TYPE宏情况下,返回UNICODE的字符串

36

otl_stream &

operator>>

(OTL_UNICODE_STRING_TYPE & s)

在定义了OTL_UNICODE或OTL_UNICODE_CHAR_TYPE/OTL_UNICODE_STRING_TYPE宏情况下,返回UNICODE的string类型,能够很好的读取大数据字段类型,如TEXT类型等。

37

otl_stream &

operator>>(char & c)

返回单字节的字符

38

otl_stream &

operator>>(undigned char & c)

返回单字节的无符号字符

39

otl_stream &

operator>>(char * s)

返回单字节的字符串类型

40

otl_stream&

operator>>(unsigned char* s);

返回无符号的单字节字符串类型

41

otl_stream&

operator>>(otl_long_string& s);

返回LOB类型

42

otl_stream&

operator>>(std::string& s);

必须定义OTL_STL宏。

读取流中的string类型

43

otl_stream& operator>>(ACE_TString& s);  

必须定义OTL_ACE。

读取流中的ACE_TString类型。

44

otl_stream&

operator>>(USER_DEFINED_STRING_CLASS & s); 

必须定义USER_DEFINE_STRING_CLASS和OTL_USER_DEFINED_CLASS_ON宏。

读取用户自定义的与string类型兼容的类型。

45

otl_stream&

operator>>(int& n); 

读取32位有符号整型

46

otl_stream&

operator>>(unsigned& u);

读取32位无符号整武师

47

otl_stream&

operator>>(short& sh);  

读取16位短整型

48

otl_stream&

operator>>(long int& l);

读取长整型(具体长度由编译器决定)

49

otl_stream&

operator>>(float& f);   

读取4字节长度的浮点型

50

otl_stream&

operator>>(double& d);  

读取8字节长度的浮点型

51

otl_stream&

operator>>(OTL_BIGINT& d);   

在定义了OTL_BIGINT的情况下。

对于不支持bigint的ODBC来说,该操作能将一个数字串转换为64位的有符号整型。

必须定义OTL_STRING_TO_BIGINT/OTL_BIGINT_TO_STRING。

52

otl_stream&

operator>>(otl_datetime& dt);

读取流中的时间信息

53

otl_stream&

operator>>(otl_XXX_tab<…>& tab); 

通过OCI来读取SQL语句中的表信息

54

otl_stream&

operator>>(otl_lob_stream& lob);

把CLOB/BLOB/TEXT/IMAGE类型读取到otl_lob_stream类型里面

55

otl_stream&

operator>>(otl_refcur_stream& refcur);

把游标的信息读取到otl_refcur_stream类型里面。

56

otl_stream&

operator<<(const unsigned char* s);

往流中写入信息。

往流中写入一个以NULL结尾的字符串。

如果定义了OTL_UNICODE,则是双字节字符串。

57

otl_stream& operator<<(otl_long_unicode_string& s);

往流中写入UNICODE LOB类型

58

otl_stream&

operator<<(const OTL_UNICODE_CHAR_TYPE& c);

在定义了OTL_UNICODE_CHAR_TYPE宏的情况下,往流中写入一个UNICODE字符

59

otl_stream&

operator<<(const OTL_UNICODE_CHAR_TYPE* s);

往流中写入一个UNICODE字符串

60

otl_stream&

operator>>(const OTL_UNICODE_STRING_TYPE& s);

在定义了OTL_UNICODE/OTL_UNICODE_CHAR_TYPE/OTL_UNICODE_STRING_TYPE宏的情况下,把一个字符串写入到流中。

(可以是大对象)

61

otl_stream&

operator<<(const char c);

往流中写入一个字符

62

otl_stream&

operator<<(const unsigned char c);

往流中写入一个无符号的字符

63

otl_stream&

operator<<(const char* s);   

往流中写入一个以NULL结尾的字符串

64

otl_stream&

operator<<(const unsigned char* s);

往流中写入一个以NULL结尾的无符号的字符串

65

otl_stream& operator<<

(const otl_long_string& d);

往流中写入LOB类型对象

66

otl_stream&

operator<<(const std::string& s);

在定义了OTL_STL宏的情况下,往流里面写入一个STL的string类型。

67

otl_stream&

operator<<(const ACE_TString &s);

在这、定义了OTL_ACE宏的情况下,往流中写入一个ACE_TString类型。

68

otl_stream&

operator<<

(const USER_DEFINED_STRING_CLASS &s);

在定义了USER_DEFINED_STRING_CLASS和OTL_USER_DEFINED_CLASS_ON宏的情况下,往流中写入一个用户自定义的字符串类型

69

otl_stream&

operator<<(const int n);

往流中写入一个有符号的整型

70

otl_stream&

operator<<(const unsigned u);

往流中写入一个无符号的整型

71

otl_stream&

operator<<(const short sh);  

往流中写入一个短整型

72

otl_stream&

operator<<(const long int l);

往流中写入一个长整型

73

otl_stream&

operator<<(const float f);   

往流中写入4字节长度的浮点型

74

otl_stream&

operator<<(const double d);  

往流中写入8字节长度的浮点型

75

otl_stream&

operator<<(const OTL_BIGINT d);

在定义了OTL_BIGINT的情况下。

对于不支持bigint的ODBC来说,该操作能将一个数字串转换为64位的有符号整型。

必须定义OTL_STRING_TO_BIGINT/OTL_BIGINT_TO_STRING。

76

otl_stream&

operator<<(const otl_null &n);    

往流中写入NULL值。

OTL定义了一个匿名的NULL类,如下:

class otl_null

{

public:

otl_null();

~otl_null();

};

77

otl_stream&

operator<<(const otl_datetime& dt);

往流中写入日期/时间类型。

OTL定义了自已的一个otl_datetime类,如下:

序号

成员变量

说明

1

int

year

2

int

month

3

int

day

4

int

hour

小时

5

int

minute

分钟

6

int

second

7

unsigned long

fraction

微秒部分,默认为0

8

int

frac_precision

秒的精度部分,默认为0

9

short int

tz_hour

定义了OTL_ORA_TIMESTAMP或OTL_ODBC_TIME_ZONE宏情况下的时区小时

10

short int

tz_minute

定义了OTL_ORA_TIMESTAMP或OTL_ODBC_TIME_ZONE宏情况下的时区分钟

fraction/frac_precision两个成员是由数据库决定的。

具体数据库支持的精度不一样,该两个成员变量值也不一样。

78

otl_stream&

operator<<(const otl_XXX_tab<…>& tab);

往流中写入SQL的表信息

79

otl_stream&

operator<<(otl_lob_stream& lob);

往流中写入otl_lob_stream对象

80

void

set_all_column_types

(const unsigned int amask=0);

设置一组输出字段的类型。

可以有如下设置:

otl_all_num2str

otl_all_date2str

otl_all_num2str | otl_all_date2str

81

void

set_column_type

(const int column_ndx,

 const int col_type,

 const int col_size=0);

设置输出字段的类型。

column_ndx索引为输出字段的相对位置,如1、2、3.

col_type是由OTL定义的一组类型。

col_size是指用来存放新的类型的长度,该长度只对otl_var_char类型有效,对于数值类型能自动计算得出。

该函数能被简单的SELECT语句、带游标的SELECT语句和返回结果集的SELECT语句调用。

该函数里面的类型组合如下:

序号

数据库数据类型

OTL默认对应类型

OTL兼容的类型

1

NUMBER(ORACLE)

otl_var_double

otl_var_char, otl_var_int, otl_var_float, otl_var_short, otl_var_unsigned_int

2

NUMBER,

FLOAT,

REAL,

MONEY,

DECIMAL(MS SQL SERVER/SYBASE/DB2)

otl_var_double

otl_var_char, otl_var_int, otl_var_float, otl_var_short, otl_var_unsigned_int, otl_var_long_int

3

INT(MS SQL SERVER/SYBASE/DB2)

otl_var_int

otl_var_char, otl_var_double, otl_var_float, otl_var_short, otl_var_unsigned_int, otl_var_long_int

4

SMALLINT,

TINYINT(MS SQL SERVER/SYBASE/DB2)

otl_var_short

otl_var_char, otl_var_int, otl_var_float, otl_var_double, otl_var_unsigned_int, otl_var_long_int

5

DATE(ORACLE),

DATETIME(MS SQL SERVER/SYBASE)

otl_timestamp

otl_var_char

6

LONG ( ORACLE)

otl_var_varchar_long

otl_var_char (<=32000 bytes)

7

TEXT(MS SQL SERVER/SYBASE)

otl_var_varchar_long

otl_var_char(<= max. size of varchar, e.g. <=8000 in MS SQL)       

该函数强烈要求限制使用,只有在那些确实因为数值容纳不下的情况下,才允许使用otl_var_char进行转换

82

int

get_dirty_buf_len();   

返回流的缓冲区里面脏数据的行数。

所谓的脏数据,指的是对于缓冲区大于1的时候,当执行SQL语句的时候,缓冲区未被填满的情况下,已经使用了的缓冲区条数。

如缓冲区为100条记录,在执行某SELECT语句后,取出30条数据,那么缓冲区此时不会被刷新,缓冲区里面有30条数据,执行此函数后就返回30。

如果缓冲区长度被设置为1后,该函数总是返回0.因为如果缓冲区为1后,每次取出记录都会填满缓冲区,此时缓冲区被填满后就会自动刷新,所以缓冲区里面未被刷新的数据总是0条,所以总是返回0。

该函数同样可以返回SELECT语句的游标或结果集缓冲区里面的脏数据。

对于其它的(非SELECT/UPDATE/DELETE/UPDATE)SQL语句块或存储过程,该函数未定义。

83

int

get_prefetched_row_count(); 

返回SELEC语句、有结果集的存储过程或ORACLE的游标的累计的结果行数。

而对于其他的存储过程则总是返回0.

如:对于某SELECT语句,第一次执行返回50,第二次执行返回50,第三次执行结果返回23,那么执行该函数时候,依次返回的的结果是50、100、123。

84

void

skip_to_end_of_row(); 

把读取流的指针定位到当前行的末尾。

以便下次读取流的时候,又从逻辑行的第一列开始读取。

85

void

check_end_of_row();

检测是否到达行的末尾。

如果没有到达行的末尾,该函数抛出END_OF_ROW check failed异常。

86

otl_stream& 

operator>>

(otl_stream& (*pf) (otl_stream&));

该函数调用(*pf)流函数(check_end_of_row())。

常用法如下:

s>>f1>>f2>>endr;

87

otl_stream&

operator<<

(otl_stream& (*pf) (otl_stream&));

同上,把输出定义为输入。

 

声明绑定变量

本章节将详细的说明如何在otl_stream流里面声明绑定变量。

SQL语句、SQL语句块或存储过程在程序里面使用的时候总是带有占位符。OTL里面带有一个小的解析器用来解析这些占位符,并且在内部进行变量的内存分配操作。

在ORACLE里面占位符的表示方法与其他数据库不同,在ORACLE里面的占位符是通过带有冒号的前缀来表示的,如::f1/:supervisor_name/:employee_id等,并且同一个占位符可能在同一个SQL语句里面使用多次。

在ODBC或DB2 CLI里面,占位符则是通过问号来表示的。如:

INSERT INTO TABLE_NAEM VALUES(?,?,?,?).

在OTL 2.0/ODBC版本里面仍然采用了位置名的占位符。如:

INSERT INTO TABLE_NAME(:1<INT>,:2<INT>,:3<INT>,:4<INT>);

在这里,数字被转换为问号。

在OTL4.0里面仍然支持上面的数字占位符。但是4.0版本里面还有名字占位符,因此推荐两种都可以使用。但是有一点不同的是,在4.0的名字占位符使用的时候,对于同一个SQL语句,里面的占位符不能同名使用。

ORACLE传统的名字占位符,后面都会扩展带有字段的类型信息,如:

INSERT INTO TABLE_NAME VALUES(:EMP_ID<INT>);

这样一次性把占位符信息定义完全,程序里面就不用再去声明宿主变量和单独调用绑定函数。对于标量的变量来说,容纳一行足够了。但是在OTL里面,它把占位符进行了扩展。下面的类型就是对扩展的占位符相对应的表:

序号

类型

OTL扩展类型

1

bigint

64有符号整型。

它被用在MS SQL SERVER/DB2/MYSQL/POSTGERSQL等数据库上,表示这些数据库上原BIGING类型。ODBC和DB2 CLI是在原生API基础上已经支持了64位的BIGINT类型,所以OTL也是如此。

但对于32位的OCIx来讲,它们并不支持64位长整型,像这种情况下,OTL提供了OTL_BIGINT,OTL_BIGINT_TO_STRING,OTL_STRING_TO_BIGINT宏来帮助在BIGINT与STRING类型之间作转换。

它把BIGINT转换为VHAR[]类型来存储。

64位的OCI在64位的编译平台下面,是支持BIGINT的,但它需要定义OTL_ORA_MAP_BIGINT_TO_LONG宏来支持。

OCI11.2版本里面开始支持BIGINT,所以只需要定义OTL_BIGINT和OTL_ORA11G_R2就可以啦。

2

blob

针对ORACLE的8、9、10、11版本里面的BLOB类型。

3

char[length]

otl 4.0.118及以上版本

char(length)

以NULL结尾的字符串类型。

最大长度取决于数据库。

对ORACLE来说是332545,对ODBC来说它取决于数据库与ODBC驱动,对DB2 CLI来说大于2.在定义了OTL_UNICODE宏的情况下,它是双字节的以NULL结尾的字符串。实际上使用的时候会把最后一个字符写为结尾。

如想存储数据库里面VARCHAR(10)长度的字符串的时候,必须定义为11位(或12位UNICODE)。

对于未定义长度的CHAR类型,OTL会抛出一个异常信息。如下:

     "INSERT INTO test_tab VALUES(:f1<int>,:f2<char>)"
     Error code: 32013
     Error message: Invalid bind variable declaration
     var info: f2 char

4

charz

在ORACLE7、8、8I、9I、10G的时候等同于CHAR[]。

仅被用于数据库里类型为CHAR[]的时候。

charz实际上是用来解决“PLS-00418:array bind type must match PL/SQL table row type”错误的。

在OCI内部对VARCHAR2/CHAR都能匹配的很好,只是对CHAR[]必须通过CHARZ来支持。

5

clob

对ORACLE8、9里面的CLOB/NCLOB

6

db2date

对应DB2的DATE类型。

它仅用于DB2数据库的DATE类型占位符。

7

db2time

对应DB2的TIME类型。

它仅用于DB2 CLI或DB2 ODBC时候TIME的占位符。

同时它需要otl_datetime类的支持。

详细见例:91.

8

double

8字节长度的浮点数

9

float

4字节长度的浮点数

10

int

32位有符号整型

11

long

对OCIx:

在32位平台或LLP64位的WINDOWS平台上为32位有符号的整型。

在LP64位的64位编译器平台上(XNUX)平台上为64位有符号整型。

对ODBC:

32位平台上为32位有符号整型。

对某些ODBC驱动下是64位有符号整型。

对于标准的ODBC驱动来说,SQL_C_LONG是32位的,但某些驱动把它定义为64位。

如果你想把它关联为64位,你需要定义OTL_MAP_LONG_TO_SQL_C_SBIGINT宏。

对DB2 CLI:

所有平台都为32位有符号整型。

如果你想把它关联到64位,你需要定义OTL_MAP_LONG_TO_SQL_C_SBIGIN宏。

LONG类型在不同的平台(WIN或LINUX)平台上,或是不同的数据库之间并不是通用的。

但是如果你的代码只是在同一个平台或同一个数据库下面,LONG还是可用的。

12

ltz_timestamp

对ORACLE 9i里面的带有本地时区的TIMESTAMP类型。

必须定义OTL_ORA_TIMESTAMP宏,使用otl_datetime类。

13

nchar[length]

仅在oracle 8/9/10g,在定义了OTL_UNICODE或OTL_ORA_UTF8宏的情况下,在设置了otl_connect::set_character_set(SQLCS_NCHAR)的时候等同于char[]。

仅用于在同一个SQL语句里面同时使用了VARCHAR2/CHAR和NVARCHAR2/NCHAR的时候使用。

14

nclob

仅在oracle 8/9/10g,在定义了OTL_UNICODE或OTL_ORA_UTF8宏的情况下,在设置了otl_connect::set_character_set(SQLCS_NCHAR)的时候等同于clob。

仅用于在同一个SQL语句里面同时使用了CLOB和NCLOB的时候使用。

15

raw[length]

ORACLE7/8/9/10里的raw/long raw;

ODBC里的SQL_BINARY(BINARY 在MS SQL/SYBASE 15/MYSQL;CHAR(XXX)BYTE在SAP/MAX DB);SQL_VARBINARY(VARBINARY在MS SQL/SYBASE 15/MYSQL;

BYTEA在POSTGRESQL,VARCHAR(XXX)BYTE在SAP/MAX DB)。

对于这种类型的字段还可以通过otl_long_string来读取。

具体的长度取决于具体的数据库。

其他可以见宏

OTL_MAP_SQL_VARBINARY_TO_RAW_LONG

OTL_MAP_SQL_GUID_TO_CHAR

OTL_MAP_SQL_BINARY_TO_CHAR

16

raw_long

ORACLE 7、8、9、10、11:RAW LONGRAW;

ODBC:SQL_LONGVARBINARY,SQL_VARBINARY

DB2 CLI:BLOB

17

refcur

对ORACLE的8、9、10、11来说,当一个存储过程返回一个游标的时候,一个游标的占位符必须定义在SQL块中。

示例如下:

"begin "
" my_pkg.my_proc(:f1<int,in>,:f2<int,in>, "
"         :str1<char[100],out>, "
// :str1 is an output string parameter
"         :cur1<refcur,out[50]>, "
"         :cur2<refcur,out[50]>); "
// :cur1, :cur2 are a bind variable names, refcur -- their types, 
// out -- output parameter, 50 -- the buffer size when this
// reference cursor will be attached to otl_refcur_stream
"end;"

18

short

16位有符号整型

19

timestamp

序号

数据库

类型

1

MS SQL SERVER/SYBASE

DATETIME

2

DB2

TIMESTAMP

3

ORACLE

DATE

4

ORACLE 9I

TIMESTAMP(OTL_ORA_TIMESTAMP)

它需要otl_datetime类协助处理。

20

tz_timestamp

对ORACLE 9i里面的带有时区的TIMESTAMP类型。

必须定义OTL_ORA_TIMESTAMP宏,使用otl_datetime类。

21

unsigned

32位无符号整型

22

varchar_long

ORACLE 7/8/9里的LONG;

ODBC里的SQL_LONGVARCHAR;

DB2里的CLOB

varchar_long,raw_long clob和blob需要otl_long_string类作为数据容器。otl_connect类里的set_max_long_size()函数能设置最大长度。详细请见otl_connect类。

下面三个词用来说明对SQL语句或SQL语句块或存储过程里面表明变量的输入与输出属性。

in – input variable

out – output variable

inout – in/out variable

例1 (ORACLE)

 BEGIN
   :rc<int,out> := my_func(:salary<float,in>,  
                           :ID<int,inout>, 
                           :name<char[32],out>
                          );
 END;

例 2(ODBC 或DB2 CLI)
New (OTL 4.0/ODBC, OTL 4.0/DB2-CLI) style

{
    call :rc<int,out> := my_func(:salary<float,in>,  
                                 :ID<int,inout>, 
                                 :name<char[32],out>
                                )
}

Old (OTL 2.0/ODBC) style:

{
    call :1<int,out> := my_func(:2<float,in>,  
                                :3<int,inout>, 
                                :4<char[32],out>
                               )
}

在绑定变量的时候,括号与类型之间是不能有空格的。如果有空格会报错。例如以下两个例子会报错:

例1:

insert into tab1 values(:salary< double >, :name< char [ 32 ] > , :emp_id< int>);

例2:

:rc< int, out > := ...;

 

在SQL语句中嵌入冒号

infomix的CLI能够组合OTL/ODBC实现。informix的SQL语句里面能够把冒号当作SQL语句的一部分,因此为了增加对冒号当作SQL语句的一部分的支持,OTL里面使用“\\:”来转义冒号。

 

 在SELECT输出中明确绑定变量

OTL在解析了SELECT语句以后,就动态的识别字段的名字、类型和长度。OTL把这些数据类型与C++的数据类型关联的时候采用的是默认的关联方式。我们可以通过调用otl_stream::set_column_type()和otl_stream::set_all_column_type()函数来更改这种默认的类型关联。不过相比在SQL语句中明确绑定变量的类型来说,它并不是很准确。在SELECT语句中明确绑定变量格式如::#N<datatype>。这里的N指的是SELECT的时候字段的相对位置。因为数据库并不能解析这种格式的绑定变量,所以在SQL语句传给数据库API前,必须把这种格式的绑定变量处理掉。如:

SELECT F1:#1<SHORT>,F2 FROM TABLE;

处理后的结果如下:

SELECT F1,F2 FROM TABLE;

这种情况下的数据类型仅支持如下:

char<xxx>/double/float/int/bigint/unsigned/short/long/raw<xxx>/raw_long/timestamp/varchar_long

当然实际代码中对以上数据类型的支持还得看具体的数据库,详细的信息请参考具体数据库手册或者更方便的直接看代码有无报错。

OTL里面默认的数据类型对绝大多数的程序来说都是可用的,只有少数的情况会出错需要人工明确类型。

在4.0.117及以上版本里面,对于ORACLE的游标和ODBC/DB2 CLI的结果集,以上的明确绑定变量同样也适用。

明确输出变量替代默认方案是可选的,如果明确后没有覆盖,则还是会使用原来默认的类型关联。

 

声明PLSQL的表

对于OCI从OTL3.0版本开始,OTL开始支持otl_stream里面带有表,通过PL/SQL表容器实现。这个特性仅是针对SQL块或存储过程。例如,在一个存储过程里面,表名作为参数,被作为一个SQL块调用的时候,OTL能够写入或读取流里面的表名。这个技术在OCI或PROC里面是一个比较常用的,只是用接口实现稍有复杂。

在OTL4.0及以后版本里面,表名可以作为输入/输出/输入输出参数。例如:

 BEGIN
   my_pkg.my_proc(:salary<float,in[100]>,  
                  :ID<int,inout[200]>, 
                  :name<char[32],out[150]>
                 );
 END;

上面的示例中,salary是一个最大为100位的输入参数,ID是最大为200位的输入输出参数,name是150位的输出参数。

因为存储过程是不能直接放置在代码里面的,所以上面的示例中的otl_stream大小必须设置为1。但是上面的参数并不是标量,而是预先定义好了的矢量。

从OTL4.0.115及以后版本,表的最大长度已经不再局限于32767。但是为了限制表的最大长度,仍可以通过定义OTL_STREAM_LEGACY_BUFFER_SIZE_TYPE宏来实现。

更详细的实现请见例:49/50/51/52

 

为ORACLE声明绑定变量的替代方法

OTL4.0.209及以上版本可以通过替代的绑定变量来同时支持ORACLE的SQL工具和OTL。这里“同时支持”意思指的是同一个SQL语句即可以通过OTL来调用,也可以通过SQL工具运行,所有的OTL的绑定变量这里都被定义为注释。如下:

INSERT INTO TABLE VALUES ( :F1,:F2);

一般都会把原来的绑定占位符进行如上例中的替换方法进行替换(变量与括号之间仍不能有空格)。这规则的目的是为了能为OTL提供一个轻量级的SQL解析器。对于SELECT语句,该功能也可以支持,只不过在SELECT里面是把空格换成注释。如下:

原来的:

SELECT F1, #1<INT>,F2 :#2<INT> FROM TABLE

替换后的:

SELECT F2,,F2 FROM TABLE;

上面这样替换后的SQL语句就可以直接传送给SQL工具执行啦,并且还支持“EXPLAIN PLAN”分析。

 

otl_connect

这个类封装了连接的功能,如连接、断开连接、提交、回滚等。otl_connect也就是一个用来创建连接对象并进行管理的类。

序号

方法、变量

说明

1

int connected

数据库是否已经连接的标志。

该标志只是在数据库连接成功后才标志为1(成功)。

如果一个已经连接成功数据库的连接在长时间没有数据库操作的情况下,由数据库主动断开了连接,该标志不会改为0,还是为1(真)。所以为了保证该标志一直有效,需要为该标志建一个“心跳”,以判断数据库是否仍旧连接为真。

如发送一个简单的SELECT CURRENT TIME FROM DUAL的请求。

2

static int otl_initialize(const int threaded_mode = 0)

用于初始化OTL连接库的环境的静态函数。

它仅需要在程序首次连接数据库之前调用一次即可。threaded_mode参数是为了表明是否在多线程的环境下运行。但是OTL并不保证线程安全,因为OTL里面不提供任何的线程锁或临界区。

threaded_mode = 1:多线程

threaded_mode = 0:单线程

3

static int otl_terminate(void)

用于中止ORACLE OCI8、9的数据库环境。

它需要在程序最后连接数据库连接后被执行一次。

该函数仅是对OCITerminate()函数的一个简单封装。

在多线程环境里面,为了能够把主线程从数据库断开,该函数必须被调用,因为它会释放一些客户端并且处理其他的一些事情。

4

void cancel(void)

仅用于OCI8/9/10/11版本。

用于中断SQL语句的执行。

或者说从一个线程里面异步的中断一个正在执行中的线程。

对于被中止的线程中将会返回一个“user requested cancel the current operation”异常。

5

void change_password(…)

序号

参数

说明

1

const char * user_name

用户名

2

const char * old_password

旧密码

3

const char * new_password

新密码

 

仅用于OCI8/9/10/11版本。

更改ORACLE用户的密码。

程序必须在连接在ORACLE服务端的时候被调用。

6

void set_transaction_isolation_level(const long int level)

仅用于DB2 CLI和ODBC。

设置事务的隔离级别。

该方法允许用户设置事务为:读提交、读未提交、可重复读、可串行化。

更多的事务隔离请见数据库手册。

OTL为事务级别定义了如下常变量

otl_tran_read_uncommied

otl_tran_read_commited

otl_tran_repetable_read

otl_tran_serializable

7

void set_max_long_size(const int amax_size)

为大对象设置最大的缓冲区大小。

如:varchar_long/raw_long/clob/blob对象。

该函数仅用于扩大缓冲区大小的时候使用。

默认的大小为:32767.

8

int get_max_long_size(void)

取得大对象的缓冲区大小。

9

void set_cursor_type(const int acursor_type = 0)

该函数仅用于DB2 CLI和ODBC,但也可以对OCI有些影响。

一旦设置好了某个类型后,通过该连接的所有的otl_stream流的SQL操作都会被影响。

支持的游标类型如下(详细的请见ODBC或DB2 CLI手册):

SQL_CURSOR_FORWARD_ONLY(DEFAULT SETTING)

SQL_CURSOR_STATIC

SQL_CURSOR_KEYSET_DRIVEN

SQL_CURSOR_DYNAMIC

10

void set_timeout(const int atimeout = 0)

仅适用于ODBC,对OCI或DB2 CLI没有作用。

用于设置连接的超时时间,一旦设置后,通过该连接的所有的SQL语句都将受影响。

单位为秒。

在OCI里面也可以通过另外一种方式实现该功能,如通过一个线程进行SQL操作,另一个线程作计时,如果时间到了,SQL还未执行完成,则调用calcel()函数强制中断。

在DB2 CLI里面类似上面的方式也可以用,只是把otl_connect::cancel()换成otl_stram::cancel()即可。

在将来,如果OCI或DB2 CLI支持该功能,那么该函数将会被复用。

11

otl_connect(const char * connect_str,const int auto_commit = 0)

构造函数。

创建一个OTL连接对象,并调用rlogon()函数。

12

void rlogon(…)

序号

参数

说明

1

const char * connect_str

数据库连接串

2

const int auto_commit=0

是否自动提交标志

 

连接数据库。

 

对于OCI、ODBC和DB2 CLI都有不同格式的连接串。

OCI:

USERNAME/PASSWORD(对本地数据库)

USERNAME/PASSWORD@TNS_NAME(远程数据库通过SQL*NET)

 

ODBC和DB2 CLI

USER/PASSWORD@DSN(类ORACLE格式)

DSN=VALUE;UID=VALUE;PWD=VALUED(ODBC格式)

 

在某些情况下,密码还可能包括有@符号,如果需要增加该符号,则需要通过”\”标志进行转义。

auto_commit标志是用来设置连接的自动提交标志。它意味着,每执行一个SQL语句,都将会自动提交该事务。但是与otl_stream里面的自动提交是两码事。

如果需要设置自动提交,则将该参数设置为1,否则默认为0(不自动提交)。

在ORACLE7、ODBC或DB2 CLI版本里面,自动提交意味着每执行完都提交,但是在ORACLE8及以后版本里面,该标志则是执行成功后才提交。

13

void rlogon(Lda_Def * lda)

连接到某个第过第三方库或嵌入式SQL连接的数据库里面。

该函数仅用于OCI7。

详细请见例:58

14

void rlogon(…)

序号

参数

说明

1

HENV henv

数据库环境句柄

2

HDBC hdbc

数据库连接句柄

3

const int auto_commit = 0

自动提交标志

 

通过其他的ODBC或第三方库连接数据库。

它仅用于ODBC或DB2 CLI。

15

void rlogon(…)

序号

参数

说明

1

const OTL_UNICODE_CHAR_TYPE *

username

用户名

2

const OTL_UNICODE_CHAR_TYPE *

password

密码

3

const OTL_UNICODE_CHAR_TYPE *

dsn

数据源名称

4

const int auto_commit = 0

自动提交标志

 

仅用于ODBC或DB2 CLI。

必须定义OTL_UNICODE_EXCEPTION_AND_RLOGON宏。

连接数据库。

该函数在定义了UNICODE情况下使用,它能够通过UNICODE的用户名和密码连接数据库。

16

otl_connect(…)

序号

参数

说明

1

HEVN henv

数据库环境句柄

2

HDBC hdbv

数据库连接句柄

3

const int auto_commit=0

自动提交标志

 

仅适用于ODBC或DB2 CLI。

通过ODBC或第三方库进行数据库连接。

17

void rlogon(…)

序号

参数

说明

1

OCIEnv *envhp

指向通过SQLEnvGet()函数获得的返回值的指针。

2

OCISvcCtx*svchp

指向通过SQLSvcCtxGet()函数返回的结果的指针

 

仅适用于OCI8i/9i/10g/11g。

通过PRO*C或第三方库连接数据库。

它必须在定义了OTL_ORA8_PROC宏的情况下使用。

18

void rlogon(…)

序号

参数

说明

1

const char * connect_str

数据库连接串

2

const int auto_commit = 0

自动提交标志

3

const char * xa_server_external_name = 0

XA外部服务器名

4

const char * xa_server_internal_name = 0

XA内部服务器名

5

bool threaded_mode = false

需要定义宏OTL_ORA_OCI_ENV_CREATE

 

仅适用于OCI 8/8i/9i/10g/11g。

连接数据库,并且设置XA库需要的的外部和内部连接名。

19

void logoff()

断开数据库连接。

如果OTL是通过PRO*C或第三方库连接的数据库,则么该函数只是断开与PRO*C的关系,而不是实际上断开数据库连接。

20

void server_attach(…)

序号

参数

说明

1

const char *

tnsname = 0

TNS名

2

const char *

xa_server_external_name = 0

XA服务器外部名

3

const char *

xa_server_internal_name = 0

XA服务器内部名

4

bool

threaded_mode = false

需要定义宏OTL_ORA_OCI_ENV_CREATE

 

仅适用于OCI 8/8i/9i/10g/11g。

该函数为对ServerAttach()函数的封装。

主要功能是开始一个session,结合session_begin()和sessin_end()使用。

主的优点在于相比于传统的连接池,性能更佳。tnsname主要是用来连接远程服务器的,对于本地服务默认可以设置为0。

21

void server_detach()

仅适用于OCI8/8i/9i/10g/11g。

断开ORACLE连接。

22

void session_begin(…)

序号

参数

说明

1

const char *

username

用户名

2

const char *

password

密码

3

const int auto_commit = 0

自动提交标志

4

const int

session_mode = OCI_DEFAULT

OCI_SYSDBA:在这种模式下,采用SYSDBA方式认证;

OCI_SYSOPER:这种模式下采用SYSOPER方式认证。

 

仅适用于OCI 8/8i/9i/10g/11g。

开始一段数据库的SESSION,主要功能在于通过attach/detach函数来开始一个SESSION。

主要的目的在于通过SESSION来执行一系列的函数比传统的连接池执行起来性能上要快不少。

23

void session_end()

仅适用于OCI 8/8i/9i/10g/11g。

结束一个ORACLE的SESSION

24

void session_reopen(…)

序号

参数

说明

1

const int aauto_commit = 0

session的自动提交标志

 

仅适用于OCI 8/8i/9i/10g/11g。

重新打开一个已经被session_end()关闭过的session。

重新打开一个已经关闭过的session的优点在于,重新打开速度上要快5-10%。

因为用户名和密码在前面的session_begin()里面已经初始化过,所以不需要重新再处理。

详细请见例:61

25

void commit()

提交一个事务。

对于ORACLE/ODBC/DB2 CLI来说,默认的自动提交为否,那么对于所有执行过的事务都需要手工的调用该函数进行事务提交。

如果设置了自动提交,则不需要再调用该函数。

26

void commit_nowait()

在定义了宏OTL_ORA10_R2或OTL_ORA11G宏下有用。

异步提交。

仅适用于ORACLE10.2及以后版本。

27

void rollback()

回滚当前事务。

28

void auto_commit_off()

void auto_commit_on()

设置自动提交为开或关。

对连接或SESSION都有效。

注:该函数仅部分的向后兼容。

29

void

set_stream_pool_size

(const int max_size = otl_max_default_pool_size)

设置otl_stream的缓冲区大小。

使用该函数必须定义OTL_STREAM_POOLING_ON、OTL_STL或OTL_ACE宏。

如果OTL_STREAM_POOLING_ON宏定义了,该函数体才被包含进代码里面。

同时,一个默认的流缓冲区将被作为otl_connce一部分自动分配。

然后如果调用了这个函数,那么先前分配的将会被释放,然后进行重新分配。

30

void

set_character_set

(const int char_set = SQLCS_IMPLICIT)

仅适用于定义了OTL_UNICODE宏的ORACLE OCI8i/9i/10g/11g环境。

SQLCS_IMPLICIT:数据库默认的字符集

SQLCS_NCHAR:数据库国际字符集

当使用了VARCHAR2/CHAR/LONG/CLOB类型的时候,则需要默认的字符集;

当使用了NVARCHAR2/NCHAR/NCLOB字段类型的情况下,则需要设置为国际字符集。

SQLCS_IMPLICIT/SQLCS_NCHAR是在ORACLE的OCI头文件里面被定义的。

 

一旦该函数设置了字符集,那么所有的通过该函数设置过的otl_connect连接的流都将使用该字符集。

在使用了UNICODE后,字符的定义也将被一同进行了扩展。

如CHAR[20]代表的是容纳一个双字节的19个字符,还加上两个字节的空字符。

这样做的主要目的是为了跟数据库里面兼容。

31

void

set_throw_on_sql_success_with_info

(const bool throw_flag = false)

仅适用于ODBC和DB2 CLI。

必须定义宏OTL_THROW_ON_SQL_SUCCESS_WITH_INFO。

在定义了该标志为真为,对于执行SQLExecDirect()/SQLExecute()函数成功后,仍抛出一个异常。

这对某些需要获取更多信息的执行非常有帮助,如调用一个存储过程。

32

otl_connect

& operator<<(const char * str)

往otl_connect对象写入一个字符串。

如果该对象未连接至数据库,那么该字符串将被作为连接的用户名密码格式被otl_connect对象用来连接数据库;

如果已经连接成功数据库,则该字符串将被作为SQL语句立刻被执行。

33

otl_connect &

operator<<=(const char *str)

往otl_connect对象写入字符串,该字符串其实就是一个将要被otl_stream执行的SQL语句。

34

otl_connect &

operator>>(otl_stream & s)

把通过otl_connect<<=()传进来的SQL语句交给otl_stream执行。

如果没有传入的SQL语句,那么将会抛出一个“***INVALID COMAND ***”异常。

35

long direct_exec(…)

序号

参数

说明

1

const char *

sqlstm

SQL语句

2

int

ignore_error = otl_exception::enabled

忽略错误标志

 

执行一段不带占位符的SQL语句,返回该语句执行的记录数。

该函数返回下面两种情况的返回值:

-1:如果异常被关闭了,但是数据库API返回一个错误。

>=0:如果SQL执行成功。

36

void

syntax_check

(const char * sqlstm);

检查SQL语句,如果有错误则会抛出一个异常。

37

void

set_connection_mode

(const int connection_mode)

在定义了OTL_ODBC_MULTI_MODE宏的情况下,OTL可以通过不用定义相关数据为的宏,而通过ODBC进行多种数据库连接。

它必须在数据库连接之前进行调用。

下面这些OTL定义的常量为OTL支持的数据库连接类型。

OTL_DEFAULT_ODBC_CONNECT:等同于设置了OTL_ODBC宏。

下面的这些数据库都可以进行连接DB2/FIREBIRD/INFORMIX/MS ACCESS/ORACLE/SAP/MAXDB/SQLITE/SYBASE/其它兼容ODBC数据库的数据库。

OTL_TIMESTEN_ODBC_CONNECT:

OTL_MSSQL_2005_ODBC_CONNECT:

OTL_POSTGRESQL_ODBC_CONNECT:

OTL_ENTERPRISE_DB_ODBC_CONNECT:

OTL_MYODBC35_ODBC_CONNECT:

OTL_MSSQL_2008_ODBC_CONNECT:

38

int

get_connection_mode()

仅在定义了OTL_ODBC_MULTI_MODE宏情况下适用。

取得数据库连接类型。

39

void

set_prog_name(const char * prog_name)

仅适用于OTL_DB2_CLI宏定义了的情况下。

设置程序的名称,该名称是在数据库“list application”命令调用时候显示的名称。

它必须在连接之前调用。

如下:

otl_connect db;

db.set_prog_name(“myapp”);

db.rlogon(“usr/pass@db”);

 

otl_exception

这个类是OTL用来抛出异常的类。如果数据库API返回一个非0的错误值,则OTL会将会抛出一个otl_exception的异常。一个otl_exception异常有可能是一个数据库错误或是一个OTL定义的错误。

序号

函数、成员变量

说明

1

char stm_text[2048

or

OTL_EXCEPTION_STM_TEXT_SIZE]

OTL异常里面SQL语句的前2047个字符。

当设置了stream label(在otl_stream或open()函数里面的sqlstm_label设置)后,它就被SQL的数据成员替代了SQL语句。

2

char var_info[256]

如果抛出了“Incompatible data types in stream operation”异常,则该变量被用来填充绑定变量和字段信息。

如:bind variable name/select output column number <datatype>

3

#if defined(OTL_UNICODE_EXCEPTION_AND_RLOGON)

SQLWCHAR msg[1000];

#else

unsigned char msg[1000];

#endif

数据库错误信息或是OTL错误信息。

4

int code

数据库错误的编码或是OTL错误编码

5

#if defined(OTL_UNICODE_EXCEPTION_AND_RLOGON)

SQLWCHAR sqlstate[1000];

#else

unsigned char sqlstate[1000];

#endif

仅适用于ODBC或DB2 CLI。

对于OCI它始终为空。

用来存放SQL的状态信息,详细请见ODBC或DB2 CLI手册。

6

#if defined(OTL_EXTENED_EXCEPTION)

#if defined(OTL_UNICODE_EXCEPTION_AND_RLOGON)

int arr_len;

SQLWCHAR *msg_arr[];

SQLWCHAR *sqlstate_arr[];

int code_arr[]

#else

int arr_len;

char * msg_arr[];

char * sqlstate_arr[];

int code_arr[];

#endif

#endif

扩展字段信息。

通过SQLGetDiagRec()函数,获取所有的ODBC/DB2 CLI动态记录信息。

OTL的异常往往只取第一条信息,但对于ODBC、DB2 CLI在某些情况下,它会带有多条动态的信息,此时该变量里面包含有所有的信息。

arr_len是信息数量。

msg_arr里面是消息;

sqlstate_arr里面是sqlstate;

code_arr里面是错误码。

7

#if defined(OTL_EXCEPTION_ENABLE_ERROR_OFFSET)

int error_offset

#endif

仅适用于OCI。

SQL语句解析错误码。

8

enum

{

disabled = 0,

enabled = 1

};

定义两个常量用于静态的SQL语句。

 

otl_long_string/olt_long_unicode_string

这两个类主要用来处理大对象数据。从OTL4.0版本开始,otl_long_string还可以处理任何类型的RAW/BIANRY类型。下面列出了常见数据库的一些大对象类型:

  • Oracle 7: LONG, RAW, LONG RAW
  • Oracle 8, 8i, 9i, 10g, 11g: LONG, RAW, LONG RAW; CLOB, BLOB
  • MS SQL Server: TEXT, IMAGE, VARBINARY, BINARY, VARCHAR(MAX), VARBINARY(MAX)
  • DB2: CLOB, BLOB
  • Sybase: TEXT, IMAGE, VARBINARY, BINARY
  • PostgreSQL: TEXT, BYTEA,
  • SAP/MAX DB: CHAR() BYTE, VARCHAR() BYTE, LONG VARCHAR, LONG VARCHAR BYTE
  • MySQL: LONGTEXT, LONGBLOB, VARBINARY, BINARY

otl_long_unicode_string是用来处理UNICODE字符的大对象类型,它可以处理下面这些类型:

  • Oracle 8i, 9i, 10g: LONG,  CLOB; the database default character set may be set to ASCII, or UTF-8, etc
  • Oracle 8i, 9i, 10g: NCLOB; the database national character set may be set to whatever is allowed for a concrete version of the database (8i and 9i/10g differ / are not the same in that regard, as far as supporting different versions of Unicode, and what sets are allowed for national character data types)
  • MS SQL NTEXT
  • DB2 CLOB / DBCLOB when the database supports Unicode (UTF-8, UCS-2, etc.)

如果定义了OTL_UNICODE宏,那么对于ORACLE的LONG RAWS/BLOB,MS SQL IMAGES,DB2 BLOBS等仍要通过otl_long_string来处理。因为他们仍然是大对象。

OTL还定义了下列类型用于处理LOBS类型。

  • varchar_long for Oracle 7/8/8i/9i/10g LONG, MS SQL Server/Sybase TEXT/NTEXT, DB2 CLOB/DBCLOB
  • raw_long for Oracle 7/8/8i/9i/10g RAW, LONG RAW, MS SQL Server/Sybase IMAGE, DB2 BLOB
  • clob for Oracle 8/8i/9i/10g CLOB, NCLOB (if #define OTL_UNICODE is enabled).
  • blob for Oracle 8/8i/9i/10g BLOB

 

大对象和NULL

大对象和NULL值的操作,与其他类型的字段有很大的区别。对于大对象与NULL的处理方式分为下面两种情况:

一、Oracle 7/8/8i/9i/10g's LONG, Oracle 7/8's LONG RAW, MS SQL Server/Sybase's TEXT, MS SQL Server/Sybase's IMAGE, DB2's CLOB/BLOB:

相对于一般的数据库类型,以上这些大对象可以通过两种方式设置为空。一是往流里面写入一个otl_null()值;二是通过调用otl_long_string::set_len(0)把大对象值设置为0.

对于输出,也有两种方式用来检测是否为空。一是通过is_null()进行判断;二是通过otl_long_string::len()获取结果后与0进行比较。

二、Oracle 8/8i/9i/10g's CLOB, Oracle 8/8i/9i/10g's BLOB:

对于以上的数据库类型,对于大对象空值的判断,在输入参数上,与上面的是同样的具有两川方式处理。但是对于输出参数的处理上,则只能通过otl_long_string::len()返回值与0进行比较。所以推荐使用otl_long_string::len()操作来判断空值。

下面分别介绍一个otl_long_string类和otl_long_unicode_string类。

 

otl_long_string

序号

函数、成员变量

说明

1

unsigned char * v;

指向LOB值的指针。

2

otl_long_string(…)

序号

参数

说明

1

const int

buffer_size

= 32760

定义LOB缓冲区大小

2

const int  

input_length

= 0

定义实际的输入字符串长度,如果这个使用了,那么set_len()就可以不必调用

 

构造函数。

创建一个otl_long_string的实例。

主要是分配内存,并设置内部变量。

为了保证能分配到正确的大小,otl_connect::set_max_long_size()必须声明的大于或等于otl_long_string的缓冲区大小。

3

otl_long_string(…)

序号

参数

说明

1

const void *

external_buffer

指向外部缓冲区的指针

2

 const int

buffer_size

= 32760

定义LOB缓冲区大小

3

const int

input_length

= 0

定义实际的输入字符串长度,如果这个使用了,那么set_len()就可以不必调用

 

构造函数。

该函数通过定义一个指针指向外部的一个缓冲区来替代默认的缓冲区。

同时原来的缓冲区不再分配空间。

4

void set_len(const int len = 0)

动态的设置缓冲区大小。

它必须在写LOB值之前调用。

5

void

set_last_piece(const bool last_piece = false)

仅对OCI8i/9i/10g/11g有效。

对于ODBC和DB2 CLI不起作用。

当otl_long_string与otl_lob_stream同时使用的时候,该函数表明otl_string_string是写入otl_stream里面的最后一个序列。

6

int len()

返回缓冲区的大小。

7

unsigned char & operator[](int ndx)

读取LOB里面非法的字节。

8

otl_long_string &

operator =(const otl_long_string&)

赋值构造函数

9

otl_long_string(const otl_long_string&)

拷贝构造函数

 

  otl_long_unicode_string

序号

函数、成员变量

说明

1

otl_long_unicode_string(…)

序号

参数

说明

1

const int

buffer_size

= 32760

 

定义LOB缓冲区大小

2

const int

input_length

= 0

定义实际的输入字符串长度,如果这个使用了,那么set_len()就可以不必调用

 

构造函数。

创建一个otl_long_unicode_string的实例。

主要是分配内存,并设置内部变量。

为了保证能分配到正确的大小,otl_connect::set_max_long_size()必须声明的大于或等于otl_long_string的缓冲区大小。

2

otl_long_unicode_string(…)

序号

参数

说明

1

const void *

external_buffer

指向外部缓冲区的指针

2

const int

buffer_size

= 32760

定义LOB缓冲区大小

3

const int

input_length

= 0

定义实际的输入字符串长度,如果这个使用了,那么set_len()就可以不必调用

 

构造函数。

该函数通过定义一个指针指向外部的一个缓冲区来替代默认的缓冲区。

同时原来的缓冲区不再分配空间。

3

void set_len(const int len = 0)

动态的设置缓冲区大小。

它必须在写LOB值之前调用。

4

int len(void)

返回缓冲区的大小。

5

unsigned short & operator[](int ndx)

读取LOB里面非法的字节。

6

otl_long_unicode_string &

operator =(const otl_long_unicode_string)

赋值构造函数

7

otl_long_unicode_string

(const otl_long_unicode_string&)

拷贝构造函数

 

常量的SQL语句

一个没有绑定变量的SQL语句、SQL语句块或是存储过程就被称为常量的SQL语句。OTL通过一个静态的函数来执行这样的SQL语句。

例如:

// static otl_cursor::direct_exec()
otl_cursor::direct_exec
(
 db, // connect object
 "create table test_tab(f1 int, f2 varchar(30))"  // create table
);

otl_cursor::direct_exec
(
 db, // connect object
 "drop table test_tab",  // SQL statement or PL/SQL block
 otl_exception::disabled // disable OTL exceptions,
                         // in other words, ignore any
                         // database error
); // drop table
// or otl_connect::direct_exec()
db.direct_exec // connect object  
(
 "create table test_tab(f1 int, f2 varchar(30))"  // create table
);

db.direct_exec // connect object  
(
 "drop table test_tab",     // SQL statement or PL/SQL block
 otl_exception::disabled    // disable OTL exceptions,
                            // in other words, ignore any
                            // database error
); // drop table
// or otl_connect::operator<<(const char*)
db<<"create table test_tab(f1 number, f2 varchar2(30))";
try
{
     db<<"drop table test_tab""; // SQL statement or PL/SQL block 
}
catch(otl_exception&)
{
   // ignore a database error
}

otl_cursor是OTL的一个内部类。它是对direct_exec()函数的一个底层类。因为以后版本该类可能不再对外提供,所以不建议使用。

下面这个例子为direct_exe()返回结果值的例子:

// static otl_cursor::direct_exec
long rpc=otl_cursor::direct_exec
(
 db, // connect object
 "delete from test_tab where f1>=95"
);
cout<<"Rows deleted: "<<rpc<<endl;


// or otl_connect:direct_exec
long rpc=db.direct_exec // connect object
(
 "delete from test_tab where f1>=95"
);
cout<<"Rows deleted: "<<rpc<<endl;

 

OTL的流缓冲池

一般来讲,流一般作为一个局部的变量被使用,当使用完毕后就立刻关闭,如果需要再次使用就需要再次的声明变量,如此循环。OTL流的缓冲池(内存池)是一个解决以往的流性能低下的一个机制。当流被关闭后,实际上流的相关变量被保存在一个流缓冲池里面,以便再利用。

每一个流在解析SQL或与数据库层打交道的时候都存在着巨大的资源开销。OTL通过流缓冲池机制来解决这个不必要的开销以提高性能。

当一个流“关闭”后,实际上,它被保存在一个流缓冲池里面。如果后面再需要一个类似的流,那么就只需要把流缓冲池里面的流取出来赋给相应的流变量即可再使用。不管该变量是局部还是全局的变量。相似的地方在于流的缓冲区大小与流相关的SQL语句是相同的。它们被保存在流缓冲池里面。

比如说有三个已经被关闭了的相似(缓冲区大小与SQL语句类型相同)的流已经被分配了内存资源。但实际上,在流的缓冲池里面只有一个入口,也就是说只有这三个流的一个副本。如果后面再需要相似的流,那么就会从中把取出该副本赋给对应的变量使用。如果有一个循环里面要不停的使用这个相同的流的话,那实际上流的主体总是这个相同的流。它被从流缓冲池里面取出来后赋给相应的变量再续使用。

在某些时候,某个流可能就真的只使用一次就关闭,这个时候otl_stream::close()有一个对应的扩展函数提供给开发者强制关闭流而不放在流缓冲池里面。

如果在某些情况下的确不想使用流缓冲池技术,我们还可以通过宏来关闭流缓冲池。这个需要在编译的时候确定下来。

通过上面的介绍,很明显,流缓冲池是一个otl_connect对象,同样,它还有一个最大容量限制,我们可以通过otl_connect::set_stream_pool_size()函数进行设置。

因为流缓冲池使用了map和vector,所以在使用流缓冲池的时候,必须要定义OTL_STL(或OTL_ACE)宏。

当一个新的流被要求加入到流缓冲池中,但是流缓冲池已满了,这个时候,用的最少的那个流将被从流缓冲池中清除,而把最新的这个流放进来。

从Sergei Kuchin统计的信息来看,流缓冲池还是相对有一个些开销的,这个主要原因是因为STL里面的MAP容器的开销导致。

下面为流缓冲池的一个简单图例:

OTL翻译(11) <wbr>-- <wbr>OTL的流缓冲池
 

 

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值