# Oracle, Odbc and DB2-CLI Template Library, Version 4.0

# What's New

# Current release number of the OTL header file

Current release number of the OTL header file is 4.0.149.
If you need the up-to-date version of the OTL header file, see the download instructions.

# OTL 4.0.149 is now released.

# For more detail, see the summary of new features. The archived version of the OTL Web pages is available.

# From OTL 3.0.0 to OTL 4.0.149: summary of new features and bug fixes

Feature | Comment
New (in OTL 4.0.149):

- A memory leak was reported in otl_stream, which turned out to be a call to otl_stream::open() in a loop without a matching call to otl_stream::close(). In order to simplify debugging of problems like that, this release introduces the following two new OTL defined exceptions:
  - code 32030, otl_stream is already open
  - code 32031, otl_connect is already connected
- DB2 zOS does not normally release row locks on a SELECT statement, even after all the rows were already fetched, and even the underlying cursor was closed. In order to release the row locks, the SELECT statement has to be "committed" with an explicit otl_connect::commit() call. The thing gets worse when on the DB2 zOS side, a timeout on "inactive DB2 threads that lock resources" is set, which results in a forced disconnect. DB2 CLI manual recommends to explicitly set the SQL statement's SQL_ATTR_CLOSE_BEHAVIOR attribute to SQL_CC_RELEASE (read locks are released), in which case the DB2 server attempts to release read locks. No guarantees, of course.
  This release sets the SQL statement's attribute to the recommended value in case if the SELECT statement's isolation level was either uncommitted read (UR), or cursor stability (CS, aka "read committed").
- In this release, for DB2 CLI, all calls to SQLFreeStmt(hstmt,SQL_CLOSE) were replaced with SQLCloseCursor(hstmt). The difference between the two types of calls is that the latter will return a DB2 CLI error if the call is made on a closed cursor. SQLFreeStmt(hstmt,SQL_CLOSE) will return a "success". This was done in order to simplify debugging of potential problems with cursor management.

New (in OTL 4.0.148):

- #define OTL_TRACE_ENABLE_STREAM_LABELS. When this #define is enabled, OTL trace records SQL statement labels instead of the bodies of the SQL statements. It is useful for reducing the size of the OTL trace.
- #define OTL_NO_TMPL_MEMBER_FUNC_SUPPORT was introduced in OTL 4.0.127. The problem was reported that Visual C++ 7.0 (2002) does not support / has a bug in template member functions. The OTL header file will automatically enable the #define for Visual C++ 7.0 from this release and on. Visual C++ 7.1, and 8.0 do not have the same problem / bug.

New (in OTL 4.0.147):

- Internal code cleanup. Also, otl_stream::flush() function has been optimized by 2-2.5%. Mileage may vary from one C++ compiler to another.
- Following new #defines have been introduced: OTL_ORA7_TIMESTAMP_TO_STRING,OTL_ORA7_STRING_TO_TIMESTAMP.
  The #defines should be used when there is a need to use OCI7 and Oracle 9i/10g TIMESTAMPs in order to enhance legacy applications. See also example 473.
- Examples for SQLite have been updated to match what's available in SQLite 3.3.x, and SQLite ODBC driver 0.71.

New (in OTL 4.0.146):

- OTL/ODBC didn't compile with the Polyhedra ODBC header files. The bug has been fixed in this release.
- Description of #define OTL_ODBC_POSTGRESQL as well as the PostgreSQL examples have been changed.
- The F.A.Q. has more answers the following questions:

- Why nested queries with bind variables do not work in MS SQL Server?
- How do I connect to my database without creating an ODBC DSN?

New (in OTL 4.0.145):

- Basic support for MS SQL 2005 VARCHAR(MAX) and VARBINARY(MAX) is introduced in this release. VARCHAR(MAX) and VARBINARY(MAX) data types are "replacements" for "old" TEXT and IMAGE. The new types are not quite backward compatible as far as MS SQL ODBC is concerned. Basically it works, only the OTL LOB stream mode doesn't work. I'd appreciate very much if somebody could point me to an ODBC based code example that demonstrates how to use VARCHAR(MAX) / VARBINARY(MAX) in piece-wise read/write modes.
- The following code examples have been introduced to demonstrate more [new] features and code techniques:

- Example 468 (MS SQL Server 2005 and VARCHAR(MAX))
- Example 469 (MS SQL Server 2005 and VARBINARY(MAX))
- Example 470 (MS SQL Server 2005, INSERT with OUTPUT clause)
- Example 471 (DB2, stored procedure with output parameters and a return code)
- Example 472 (DB2, Insert/Implicit Result Set (Stored Proc) /Update)

- This release enforces the minimum size of 2 characters in :var<char[xxx]> declarations. The reason is that char[1] is invalid because OTL char[xxx] variables are null terminated strings. #define OTL_ADD_NULL_TERMINATOR_TO_STRING_SIZE adds one character to the string length, which makes :var<char[1]> a valid declaration.
- OTL 4.0.138 relaxed the requirement of presetting the LOB length before the first chunk of the LOB gets written to the LOB stream (otl_lob_stream), which changed the ODBC / DB2 CLI function call sequence. A bug was reported that when a LOB stream is used for writing the LOB value, and the stream gets destroyed before the end of the row, which LOB was written to, it causes the "invaid function call sequence" error. The actual error message is different in different database types,. The bug is fixed in this release. This problem affects only ODBC and DB2 CLI applications, and only if the LOB stream is destroyed before the end of the row. The following [long] piece of code demonstrates the problem:
void insert()
// insert rows into table
{
otl_long_string f2(6000); // define long string variable
otl_stream o; // defined an otl_stream variable
o.set_lob_stream_mode(true);
// set the "lob stream mode" flag
o.open(1,
// buffer size has to be set to 1 for operations with LOBs
"insert into test_tab "
"values(:f1<int>,:f2<varchar_long>, "
":f3<varchar_long>) ",
// SQL statement
db // connect object
);
o.set_commit(0);
// setting stream "auto-commit" to "off". It is required
// when LOB stream mode is used.
int i,j;
otl_lob_stream *lob;
// LOB stream for reading/writing unlimited number
// of bytes regardless of the buffer size.
otl_lob_stream *lob2;
// LOB stream for reading/writing unlimited number
// of bytes regardless of the buffer size.
for(i=1;i<=20;++i){
lob = new otl_lob_stream;
lob2 = new otl_lob_stream;
o<<i;
o<<*lob; // Initialize otl_lob_stream by writing it
// into otl_stream.
o<<*lob2; // Initialize otl_lob_stream by writing it
// into otl_stream.
for(j=0;j<5000;++j)
f2[j]='*';
f2[5000]='?';
f2.set_len(5001);
// OTL < 4.0.138
lob->set_len(5001+2123); // setting the total size of
// the TEXT to be written.
*lob<<f2; // writing first chunk of the TEXT into lob
f2[2122]='?';
f2.set_len(2123); // setting the size of the second chunk
*lob<<f2; // writing the second chunk of the TEXT into lob
lob->close(); // closing the otl_lob_stream
delete lob;
// here is a problem (in OTL 4.0.138 - 4.0.144),
// OK in 4.0.145 (this release)
// not the end of the row yet
for(j=0;j<5000;++j)
f2[j]='*';
f2[5000]='?';
f2.set_len(5001);

// OTL < 4.0.138

lob2->set_len(5001+2123); // setting the total size of
// the TEXT to be written.
*lob2<<f2; // writing first chunk of the TEXT into lob
f2[2122]='?';
f2.set_len(2123); // setting the size of the second chunk
*lob2<<f2; // writing the second chunk of the TEXT into lob
lob2->close(); // closing the otl_lob_stream
// end of the row
//delete lob; // deleting here is OK
delete lob2;
}

New (in OTL 4.0.144):

- OTL (4.0.129 - 4.0.143) did not compile with the real OCI 8.0 header files. There was the following compilation error:
  C2065: 'OCI_PARSE_ONLY' : undeclared identifier
  The error is fixed in this release..
- PostgreSQL 8.2 is out. This release has been successfully tested with PostgreSQL 8.2.

New (in OTL 4.0.143):

- When OTL steram reads a Binary Large Object value (LONG RAW, BLOB, IMAGE, etc.) into an otl_long_string, the long string gets NULL terminated (0-byte terminated), which is not correct. It didn't matter when the otl_long_string's buffer size is greater or equal to the BLOB size + 1. In the case if the buffer size equals the BLOB size, the program crashes. The bug has been fixed in this release.
  Character Large Objects (LONG, CLOB, TEXT, etc.) do get NULL terminated for backward compatibility with NULL terminated C strings / character arrays.
- The following bind variable declaration caused some confusion: :f1<char>. The problem was that such a declaration invalid, but OTL didn't enforce it. From this realeas on, OTL is going to throw an otl_exception.
- OTL 4.0.140 introduced support for raw[XXX]. A problem was reported that when raw[XXX] is used to bind a variable to a stored procedure output parameter, OTL doesn't return values into the bind variable correctly. The problem was fixed in this release.

New (in OTL 4.0.142):

- A potential problem in OTL was found with a code analysis tool (Coverity). The problem has been fixed in this release. The problem was in the following code:
  otl_column_desc& operator=(const otl_column_desc& desc)
  {
  ...
  }else if(name_len_<desc.name_len_){
  ...
  strcpy(name,desc.name);
  }
  The code analysis tool found that desc.name can be NULL, so that the strcpy() would crash the program. In reality, if desc.name_len_ > name_len_ >= 0, desc.name_ will always be defined. So, it's a false positive. I added a check for NULL for desc.name_ anyway in order to make the tool happy:
  otl_column_desc& operator=(const otl_column_desc& desc)
  {
  ...
  }else if(name_len_<desc.name_len_ && desc.name_!=0){
  ...
- The problem was reported that when a CHAR() column is used in Oracle in a combination with OTL/OCIx, a string that doesn't have space characters at the end, can't be found by a WHERE clause in a SELECT statement. For example:
  SELECT f2 FROM test_tab WHERE f2=:f2<char[31]>
  where f2 is CHAR(30). When OTL/OCIx is being used, either the string has to be padded with space characters to the full length of the column, or the following #define needs to be enabled (accidentally, it wasn't documented, a.k.a. a bug in the manual): #define OTL_ORA_MAP_STRINGS_TO_CHARZ.

New (in OTL 4.0.141):

- When an empty PL/SQL table gets returned via STL vector based, OTL PL/SQL table containers, Visual C++ 2005 throws an "out-of-range" exception. Error is fixed in this release.
- New #define is introduced: #define OTL_DESTRUCTORS_DO_NOT_THROW.
  Here's some prehistory: "Personally I'd vote for beating every person who will write throwing destructor, one hit in the head for every such destructor. I wonder why this question always raised along with database-related code? Maybe because people who write such libraries "came" from DB world and are not competent enough to understand? I remember OTL (C++ DB access library) has issues with throwing destructors...Michael...".
  People who want OTL destructors not "to throw", from now on can enable the new #define, and happily code away all manual database resource management.
  My opinion is that for C++ compilers that support uncaught_exception() correctly, throwing destructors are acceptable, if it results in writing less code. Let the C++ gurus rest on the laurels of their superior C++ knowledege.
  Question for everybody: can anybody point me to a common C++ technique / idiom / pattern that combines RAII idiom, non-throwing destructors, and error communication / handling via exceptions? I'd appreciate any useful info on the topic very much.

New (in OTL 4.0.140):

- A few more of "type-punned" g++ warnings have been fixed in this release. Besides the type-punned warnings, other warning have been fixed. OTL compiles clean with the following g++ warnings on (g++ 4.1.1):
  -W
  -Wall
  -Wcast-align
  -Wcast-qual
  -Wcomments
  -Wconversion
  -Wctor-dtor-privacy
  -Werror
  -Wextra
  -Wformat
  -Wno-uninitialized
  -Wnon-virtual-dtor
  -Wold-style-cast
  -Woverloaded-virtual
  -Wparentheses
  -Wpointer-arith
  -Wreorder
  -Wshadow
  -Wsign-compare
  -Wsign-promo
  -Wstrict-aliasing=2
  -Wstrict-null-sentinel
  -Wundef
  -Wunused
  -Wunused-variable
  -Wwrite-strings
- OTL stream was allocating more memory than necessary for internal buffers in the PL/SQL block:
  "begin "
  " PKG_TEST.my_prc(:p_arr<char[2000],in[2000]>); "
  " PKG_TEST.proc_1(:PAR1<CHAR[32000],IN>); "
  " PKG_TEST.proc_2(:PAR2<CHAR[32000],IN>); "
  "end; "
  The problem was that the in[2000] clause was setting the internal buffer size of the corresponding PL/SQL table to 2000, and :PAR1, :PAR2 bind variables were treated as PL/SQL tables of 2000 elements each. The program didn't crash, and it even wroked correctly, but it allocated way too much memory. The bug has been fixed in this release.
- A new bind variable / placeholder data type has been introduced: raw[XXX]. The new data type is for supporting database "binary" types (Oracle RAW, MS SQL / Sybase / MySQLVARBINARY/BINARY, PostgreSQL BYTEA, etc) natively. "Raw" values can be read from / written to the database via otl_long_string's. Also, a new OTL type code contstant has been added in identify bind variable of the raw[XXX] type:
  const int otl_var_raw=23;
- A new OTL defined exception:
  Code=32029: RAW value cannot be read with otl_lob_stream, use otl_long_string instead
- Three new #defines in order to provide proper backward compatibility in the context of the new data type raw[XXX]:
  #define OTL_MAP_SQL_VARBINARY_TO_RAW_LONG,
  #define OTL_MAP_SQL_GUID_TO_CHAR,
  #define OTL_MAP_SQL_BINARY_TO_CHAR (MS SQL TIMESTAMPs)
  For more detail on how to use raw[XXX], see the following code examples:

- Oracle (446, 447, 457, 458)
- MS SQL (448, 449, 459, 460)
- Sybase (450, 451, 461, 462)
- MySQL (452, 453, 463, 464)
- PostgreSQL (454, 465)
- MAX-DB / SAP-DB (455, 456, 466, 467)

New (in OTL 4.0.139):

- The following g++ 4.1.0 compilation warnings have been fixed in this release:
  ../include/otlv4.h: In member function 'void otl_conn::error(otl_exc&)':
  ../include/otlv4.h:9126: warning: dereferencing type-punned pointer will break
  strict-aliasing rules
  ../include/otlv4.h: In member function 'void otl_cur::error(otl_exc&)':
  ../include/otlv4.h:10835: warning: dereferencing type-punned pointer will break
  strict-aliasing rules
- A set of new code examples for Sybase.

New (in OTL 4.0.138):

- A missing dependency of #define OTL_UNICODE_STRING_TYPE on #define OTL_UNICODE has been added to this release.
- otl_lob_stream required the total length of a LOB to be set before the first chunk of the LOB gets written to the LOB stream. This release has relaxed the requirement: OTL/ODBC/DB2-CLI eliminates the requirement completely, and OTL/OCI8i/9i/10g can be used with otl_long_string::set_last_piece() instead. For more detail, see examples 385 (Oracle), 386 (Oracle) 387 (DB2), 388 (DB2), 389 (MS SQL), 390 (MS SQL), 391 (MySQL), 392 (MySQL), 393 (PostgreSQL), 394 (MAX/DB), 395 (MAX/DB),

New (in OTL 4.0.137):

- The following comment was incorrect (turns out people read comments :-) )
  // in case if it's ODBC for Windows, include windows.h file
  and was changed to
  // in case if it's ODBC for Windows (!OTL_ODBC_UNIX), and windows.h is not included yet (_WINDOWS_ not defined yet), then include the file explicitly
- The following minor warning for Borland C++ 6.0 was fixed:

      "[C++ Warning] otlv4.h(19678): W8071 Conversion may cause loss of significant digits"

- OTL/ODBC/DB2-CLI, otlv4.h, line 13285, an OTL trace macro call was incorrect:
  OTL_TRACE_WRITE(n,"operator >>","BIGINT");
  and was replaced with
  OTL_TRACE_READ(n,"operator >>","BIGINT");
  The incorrect OTL trace macro call caused a program crash on AIX with DB2 CLI.
- OTL introduces two new operators >>(string&) and <<(string&) to the OTL LOB Stream for reading and writing std::strings (STL), or ACE_TStrings (ACE). For more detail. see also examples 379, 380, 381, 382, 383, 384.

New (in OTL 4.0.136), updated:

- I got the same question from a few developers about whether OTL officially supported MS SQL 2005 or not. Now the answer is Yes. I downloaded MS SQL 2005 XE, which can be freely used, installed it, and extended the OTL internal test suite to run against MS SQL 2005.

New (in OTL 4.0.136):

- This release fixes a bug similar to this old bug. The difference between the new bug and the old bug is that the new bug happens when an output parameter in a stored procedure is used.
- New code example has been added for OTL/OCI8i/9i/10g to show how to use CLOB/BLOBs with PL/SQL stored procedures and the LOB stream mode. See example 378.
- Several type cast related compilation warnings have been fixed in OCIBindByName() calls.
- When an OTL stream is being opened with a SELECT statement that contains a column of an unsupported data type, the program may crash. For example, the following SELECT crashes the program (OTL/OCI8i/OCI9i/OCI10g):
  select * from sys.ku$_library_view
  This SELECT actually contains an Oracle Object column, which OTL does not support. The problem has been fixed in this release. Instead of crashing the program, OTL will throw the following OTL defined exception:
  Unsupported column data type, code 32028
- The following new functions have been added to the otl_read_stream_interface, and to the otl_refcur_stream (the functions do the same thing as the corresponding functions in the otl_stream class):

- otl_var_desc* describe_out_vars(int& desc_len);
- otl_var_desc* describe_next_out_var(void);

New (in OTL 4.0.135): OTL had limits on how many bind variables / SELECT output columns it could handle. The limits were as follows:

- 512 for OTL/ODBC, OTL/DB2 CLI, OTL/OCI7
- 1024 for OTL / OCI8/8i/9i/10g

The OTL limits were supposed to match the actual limits of the underlying database APIs. As more versions of databases come out, the limits change. This release eliminates any practical limits on the maximum number of bind variables / SELECT output columns. The limits on the underlying database APIs still exist.When the limit on, say, database type A, is reached, OTL would throw an otl_exception. The actual error code and error message is database specific, and it's not defined by OTL.
New (in OTL 4.0.134):

- When OTL_ODBC / OTL_DB2_CLI and OTL_BIGINT are defined, OTL doesn't compile with older C++ compilers that don't have support for template member functions. The error is fixed in this release.

New (in OTL 4.0.133):

- When a DB2 BLOB table column has a smaller maximum size in its definition than the actual BLOB value being written to the BLOB column in the LOB stream mode, OTL throws an exception with no error message, and a random error code. The error is fixed in this release.
- When compiled with GNU C++ 4.1.0, OTL generates the following compilation warning:
  dereferencing type-punned pointer will
  break strict-aliasing rules

  The warning was actually fixed in OTL 4.0.132.
- When OTL is used with boost's date_time, VC++ generates the following error message: error C2668: 'isspace' : ambiguous call to overloaded function. The error is fixed in this release.

New (in OTL 4.0.132):

- OTL doesn't compile with Visual C++ 7.1 when the following #define's are enabled:
  #define OTL_ORA8I or ORA9I ORA10G or ORA10G_R2
  #define OTL_UNICODE
  #define OTL_UNICODE_CHAR_TYPE wchar_t
  #define OTL_UNICODE_STRING_TYPE std::wstring
  #define OTL_TRACE_LEVEL my_trace_level
  #define OTL_TRACE_STREAM wcerr
  #define OTL_TRACE_LINE_PREFIX "MY OTL TRACE ==> "
  Error is fixed in this release
- When Unicode is enabled for Oracle 8i/9i/10g, and the LOB stream mode is used, otl_lob_stream doesn't return a CLOB/NCLOB correctly. More specifically, if the length of a CLOB/NCLOB is at least 2-3 times larger than the buffer size which the CLOB/NCLOB is being fetched through. The error is due to the fact that the OCI returns the size of the second chunk of the CLOB/NCLOB to be fetched that is equal in size to the buffer in bytes instead of Unicode characters. The error is fixed in this release.
- When the following #define's are enabled:
  #define OTL_ORA8I or ORA9I ORA10G or ORA10G_R2
  #define OTL_UNICODE
  #define OTL_UNICODE_CHAR_TYPE wchar_t
  #define OTL_UNICODE_STRING_TYPE std::wstring
  otl_stream::operator>>(OTL_UNICODE_STRING_TYPE&) returns incorrect values of Unicode strings in the following scenario:
  ABCD
  ABC
  AB
  A
  The actual output is:
  ABCD
  ABCD
  ABCD
  ABCD
  This happens because the OCI doesn't guarantee in some very special cases Unicode strings to be null terminated. The error is fixed in this release.
- When these #defines are enabled:
  #define OTL_UNICODE
  #define OTL_UNICODE_CHAR_TYPE wchar_t
  #define OTL_UNICODE_STRING_TYPE my_wide_char_string
  In case if my_wide_char_string is not 100% compatible with std::wstring, OTL doesn't compile because it uses strng::assing(charT* c,size_t len) function to make a string value out of a raw chararcter buffer + the string length. In order to wortk around the problem, this release introduces the following new #define:
  #define OTL_UNICODE_STRING_TYPE_CAST_FROM_CHAR

New (in OTL 4.0.131):

- In this release, Oracle 9i / 10g's INTERVAL data types get mapped to char[XXX] on SELECT statements by default when #define OTL_ORA_TIMESTAMP is enabled
- OCI 8i / 9i may generate ORA-01461 error when Unicode is enabled, and when the SQL statement is a SELECT with two (or more) VARCHAR2(4000), or NVARCHAR2(2000) columns. The error was fixed in OTL 4.0.111. However, the fix prevented big VARCHAR2(4000<X<32000) / NVARCHAR2(2000<X,<16000) bindings in the case of PL/SQL blocks. As a workaround, this release introduces the following new #define OTL_ORA_MAX_UNICODE_VARCHAR_SIZE.

New (in OTL 4.0.130):

- When #define OTL_ORA9I, #define OTL_ORA_DECLARE_COMMON_READ_STREAM_INTERFACE, and #define OTL_DEFINE are enabled at the same time, the OTL header doesn't compile / has compilation error about "otl_stream being an abstract class". The error is fixed in this release.

New (in OTL 4.0.129):

- Two new functions for otl_connect:

- direct_exec(), by common sense
- syntax_check(), by the request from the TORA project people

- Updated the Links page with "Instructions on how to use OTL with PostgreSQL in Windows and Solaris from Carlos Crosetti.
- Updated my resume to better reflect reality.

New (in OTL 4.0.128):

- otl_connect& operator>>(otl_connect& connect, otl_stream& s) should have been declared as inline, but it wasn't, which caused a "duplicate symbol" linker error. The bug is fixed in this release.

New (in OTL 4.0.127):

- Code cleanup: From now on, OTL uses template member functions by default for C++ compilers that support the feature. However, some C++ compilers have no support for the feature, or have bugs in supporting the feature. The following new #define can be used to make OTL fall back on the old proven nontemplate member functions in case if OTL compiles with errors: #define OTL_NO_TMPL_MEMBER_FUNC_SUPPORT.
- OTL for OCI8/8i/9i/10g didn't map Oracle ROWID / UROWID type to a char[XXX] correctly. The bug is fixed in this release. The problem was that the OCI internal data type code for ROWID was different from what was described in the OCI reference guide.
- OTL tries to follow the latest / modern trends in C++ in cases when it makes sense. Some C++ libraries try to overload operator >> / <<, operator comma, operator parens, etc., and provide more syntax rich context for developers. Boost.org is one good example of that. Another, though a much smaller example, is soci. I've been asked a few times to introduce something similar in OTL. This release introduces several new operators in otl_connect: operator >>(otl_stream&), <<(const char*), <<=(const char*). For more detail, see example 371, 372, 373, 374, 375, 376, 377.

New (in OTL 4.0.126):

- #define OTL_ORA_OCI_ENV_CREATE, OTL_ORA_OCI_ENV_CREATE_MODE. A discussion has been going on for years about whether the old scheme of OCIInialize()+OCIEnvInit() for initializing OCI environment handles doesn't work any more, and should be replaced with the new scheme of OCIEnvCreate(). Oracle documentaion says that the old scheme should be eliminated. The old scheme seems to work fine, and the discussion has gone nowhere. In the future, when more extensive support for Unicode in OTL/OCIx gets implemented (Unicode user id, password, etc.), only then OCIEnvCreate() will become indispensible. For more detail, see otl_connect::rlogon(), server_attach().
- Following new #defines: OTL_EXCEPTION_ENABLE_ERROR_OFFSET, OTL_EXCEPTION_STM_TEXT_SIZE.
- Support for Large Unicode Objects (NTEXT, NCLOB, etc.) was overlooked for otl_stream::operators >>/<<(OTL_UNICODE_STRING_TYPE&). This release fixes the problem. For more detail, see example 366, 367, 368, 369, 370.
- A memory leak was reported when OTL stream pooling is on (#define OTL_STREAM_POOLING_ON), and there are SELECT output column overrides.
  The bug is fixed in this release.
- otl_sconnect::set_stream_pool_size() needs to check for the stream pool size. When the stream size is 1 then the program crashes. The bug is fixed in this release.
- When OTL_ACE is enabled, OTL defines otl_stream::operator >>/<< for ACE_TString. In order to assign a NULL terminated string value from the otl_stream internal buffer to the output string in operator>>(ACE_TString& s), OTL used the following assignment:
  s=<pointer to internal char* buffer>;
  It turns out that ACE_TString doesn't have operator=(const char*). So, the assignment generates a temporary variable plus 2 extra calls to the heap manager. This release fixes the inefficiency by using ACE_TString::set() instead:
  s.set(<pointer>,1);
- VC++ 8.0 (Visual Studio 2005) compiles clean now.

New (in OTL 4.0.125):

- Support for Unicode ODBC drivers was inadvertently tied up to #define OTL_UNICODE. From this release and on, when Unicode ODBC driver support is enabled in general in the ODBC header files (via #define UNICODE / _UNICODE), OTL also generates SQLxxxW calls, regardless of whether OTL_UNICODE is defined or not.
- #define OTL_DEFAULT_STRING_NULL_TO_VAL serves its purpose reasonably well. It covers operations with both char* (one-byte, Unicode) and C++ string classes (the use of which can be enabled via OTL_STL, OTL_ACE, OTL_STLPORT, OTL_USER_DEFINED_STRING_CLASS_ON, OTL_UNICODE_STRING_TYPE). Normally, string NULLs get defaulted to an empty string. In the case of C++ string classes, an actual string variable can be reinitialized more efficiently than assigning an empty string to it. This release introduces the following #define to do just that: OTL_USER_DEFINED_STRING_CLASS_DEFAULT_NULL_TO_VAL
- #define OTL_UNICODE_USE_ANSI_ODBC_FUNCS_FOR_DATA_DICT. A workaround for an MS SQL Server bug when Unicode is enabled.

New (in OTL 4.0.124):

- otl_stream_read_iterator::is_null() returns results that are the opposite to what they are supposed to be. The bug is fixed in this release.

New (in OTL 4.0.123):

- OTL 4.0.122 introduced support for the MS SQL TIMESTAMP / RowVersion data type. This release introduces support for the same data type when #define OTL_UNICODE is enabled. TIMESTAMP / RowVersion values get converted into char[17]. Only in this case the characters are 2-byte Unicode characters.
- When the same otl_stream variable gets reused multiple times, and describe_select() is used, otl_column_desc may return an incorrect name (column name). It happens when names for, say, column 1, from two consecutive calls to describe_select() had the same length. The bug is fixed in this release.
- OTL had only basic support for Unicode string data, and it didn't support Unicode userid/password@DSN, Unicode error messages, Unicode ODBC drivers, and Unicode SQL. This release takes a few steps further and implements the following features:

- Support for Unicode ODBC drivers. Unicode may be enabled for ODBC / DB2 CLI by defining #define UNICODE and/or #define _UNICODE. The #defines enable the Unicode ODBC function prototypes. Starting with this release and on, OTL uses Unicode ODBC functions when the #define UNICODE / _UNICODE is enabled / defined (for example, when a project in Visual C++ Studio enables Unicode).
- Support for Unicode userid/password@DSN. A new otl_connect::rlogon() implements the feature when #define
  OTL_UNICODE_EXCEPTION_AND_RLOGON is enabled.
  For more detail, see example 365.
- Unicode error messages, when #define OTL_UNICODE_EXCEPTION_AND_RLOGON is enabled.
  For more detail, see example 365.

- This release introduces two new #defines:

- OTL_UNICODE_CHAR_TYPE (support for operators >>/<< for Unicode characters)
- OTL_UNICODE_STRING_TYPE (support for operators >>/<< for Unicode std::wstrings)

For more detail, see the following examples:

- For Oracle: 351, 352, 353, 354.
- For DB2: 355, 356, 357, 358.
- For MS SQL: 359, 360.
- PostgreSQL: 361, 362.
- SAP/MAX DB: 363, 364.

New (int OTL 4.0.122):

- There was a typo in "otl_output_iterator<T>& operator++(int)". It should be: "otl_output_iterator<T> operator++(int)". The typo / bug is fixed in this release. The scope of this bug is not quite clear. It depends on the actual implementation of the STL library for different C++ compilers. So far, I have not seen any of my tests to crash, or deliver incorrect data sets.
- MS SQL has a rarely used data type: TIMESTAMP. It has nothing to do with calendar date/time. The TIMESTAMP type could be used to implement the optimistic locking scheme. Say, a table has a TIMESTAMP column, and a row in the table is being changed. The TIMESTAMP gets changed by the database server itself as any column in the row changes its value. The rest in the implementation of the optimistic locking scheme is clear: the row gets read once at the very beginning, then the TIMESTAMP of the row needs to be read one more time right before the change gets made in order to make sure that nobody else (no other user) has already changed the row. OTL didn't have any default support for such a data type. In this release and on, all TIMESTAMP table columns will be mapped to char[17], which will make the MS SQL ODBC driver convert the TIMESTAMP value to a 16 character, null terminated hexadecimal string. For pre-4.0.122 releases of OTL, the OTL data type for TIMESTAMP table columns could be explicitly overriden either via :#N<char[17]> notation, where N is 1,2,3..., or via otl_stream::set_column_type().
- This release introduces new "get by name" getter functions in the OTL stream read iterator template class. For more detail, see examples 339, 340, 341, 342.
- In OTL 4.0.119 the third OTLLobStream class type parameter was added to the OTL stream read iterator template class. otl_lob_stream is not supported under #define OTL_ORA7, so the stream read template class was corrected and now has only two class type parameters as before OTL 4.0.119.
- PostgreSQL 8.1 was recently released. PostgreSQL 8.1 ODBC driver seems to support the bulk interface (otl_stream buffer sizes can be > 1). ODBC Unicode driver seems to work. A few new code examples have been added in this release: 342, 345-350.
- OTL stream read iterator template class, when compiled with GNU C++ 2.95-96, or GNU C++ 4.0 on Solaris, may cause a runtime "bus error". A similar bug was fixed in OTL 4.0.114. It looks like the recent "bus error" bug is specific to GNU C++, because the exact same code runs successfully when compiled with Forte C++. The problem is in memory address alignment,. Definitely. GNU C++ does something different from Forte C++. Internal memory allocation was rewritten in the stream read iterator class in order to avoid further memory address alignment problems.

New ( in OTL 4.0.121):

- OTl 4.0.120 stopped compiling with VC++ 6.0. By popular demand, the feature is back. I didn't actually realize that until several people pointed that out.
- Under certain circumstanes, OTL/OCI8i/9i/10g in the LOB stream mode, when a CLOB/BLOB value is being updated from a bigger to a smaller size, may trim the old CLOB/BLOB value incorrectly, or not trim the value at all. The bug is fixed in this release.

New (in OTL 4.0.120):

- OTL now compiles clean under 64-bit VC++ (_WIN64).
- OTL introduces the following new function: otl_connect::commit_nowait(). The function calls the corresponding OCI 10g Release 2 (Oracle 10.2) function to perform an asynchronous commit, which is a new feature of Oracle 10.2. Also, see example 321.
- OTL introduces general support for MAX-DB / SAP-DB. See examples 322-338 for more detail.
- SQL statement parser in OTL stream didn't parse the following correctly:
  ...'foo/*'...:A<int,in> := ...
  What happens is that when a comment beginning character sequence "/*" is present inside a string literal, the parser misinterprepts it and skips the bind variable, which is part of the SQL statement.
  The bug is fixed in this release.

New (in OTL 4.0.119):

- otl_stream_read_iterator now supports otl_lob_stream's via the following get function: void get(otl_lob_stream*&). For more detail, see examples 315, 316, 317, 318, 319, 320.
  NOTE: otl_stream_read_iterator has one more class parameter: OTLLobStream. It needs to be added to the actual parameter list.

New (in OTL 4.0.118):

- When a char/string bind variable is declared as :var<char(XXX)> instead of :var<char[XXX]>, the program crashes with "Memory Access Violation" / "Segmentation Violation". What happens is that OTL tries to access memory beyond an allocated memory block. The bug is fixed in this release.
- This release of OTL and higher support char(XXX) as equivalent to char[XXX] in bind variable declarations.

New (in OTL 4.0.117):

- When #define OTL_BIGINT is enabled along with #define OTL_UNICODE and #define OTL_ORA8I/9I/10G, OTL throws the folowing exception / error:
  ORA-01458: invalid length inside variable character string
  The bug is fixed in this release.
- Explicit bind variables in output column definitions can be defined for implicit result sets (ODBC/DB2-CLI), or reference cursors (Oracle) the same way as in SELECT statements.

New (in OTL 4.0.116):

- A typo in otlv4.h in OTL 4.0.115 (line 3072) has been fixed in this release.
- otl_stream::create_stored_proc_call() has been enhanced to do the following, which actually corresponds the Oracle standard name resolution::

- sp in current schema
- private synonym for sp
- public synonym for sp

New (in OTL 4.0.115):

- OTL stream buffer size's datatype was changed in this release from short int to int. See examples 307, 308, 309, 310 for more detail.
- New #define OTL_STREAM_LEGACY_BUFFER_SIZE_TYPE is introduced. It can be used to turn the stream old short int buffer size back on.
- Maximum size of PL/SQL tables is no longer limited to 32767. See example 311, 312 for more detail. #define OTL_STREAM_LEGACY_BUFFER_SIZE_TYPE can also be used to turn the maximum size of PL/SQL tables back on.
- new charz[] datatype for PL/SQL tables of CHAR(XXX). See example 313, 314 for more detail.

New (in OTL 4.0.114):

- Visual Age C++ (AIX) issues a warning when OTL_ORA7 is enabled. The warning has been fixed in this release.
- New #define OTL_INFORMIX_CLI (Informix CLI for Unix) is introduced. It should be used in a combination with #define OTL_ODBC_UNIX.
- Basic support for TimeTen via ODBC (#define OTL_ODBC). See examples 293-299 for more detail.
- Basic support for Microoft ACCESS via ODBC (#define OTL_ODBC). See examples 300-306 for more detail.
- When OTL stream read iterator is used with Forte C++ on Solaris, the program may crash with a "bus error". The problem is that the iterator's internal buffers need to be aligned to the machine word (requirement on Solaris). The bug has been fixed in this release.

New (in OTL 4.0.113):

- The following new #define: OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE. It changes the OTL stream's default behavior for SELECT statements: SELECT gets prepared, executed, and only then the SELECT statement columns get described. New versions (PostgreSQL 8.0, MySQL 5.0 (still in beta)) of some databases require this change.
- Some fragments of redundant, conditionally compiled code were cleaned up.

New (in OTL4.0.112):

- Following new #define is introduced in this release: #define OTL_ORA_DECLARE_COMMON_READ_STREAM_INTERFACE. It enables a common interface class, which both otl_stream and otl_refcur_stream derive from. See also example 292.
- When OTL stream pooling is enabled (#define OTL_STREAM_POOLING_ON), in the case of a database error, if otl_stream::clean() gets called, it does not reset some internal flags correctly, so that the stream cannot be reused without being closed and reopened. The bug is fixed in this release.
- otl_column_desc class was extended in OTL 4.0.110 with the following fields: charset_form, char_size. The fields are enabled with OTL_UNICODE and #defines OTL_ORA8i/9i/10g. A mistake was made for OCI8i: OCI8i does not provide the "char size" information. The char_size field will be set to 0 instead. If anybody has a different opinion on this, let me know.

New (in OTL 4.0.111):

- Following new #define is introduced in this release: #define OTL_STRICT_NUMERIC_TYPE_CHECK_ON_SELECT. See also examples 288 (OCI7), 289 (OCI8i/9i/10g), 290 (DB2 CLI), 291 (MSSQL).
- When #define OTL_UNICODE is enabled for OTL/OCI8i/9i/10g, maxmium string size char[XXX] bind variables (char[4001] for VARCHAR2, and char[2001] for NVARCHAR2 data types) may cause the "Invalid length" Oracle error. The bug is fixed in this release.

New (in OTL 4.0.110):

- When #define OTL_ODBC is enabled, and when the OTL header file is being compiled in the unixODBC driver manager environment, the C++ compiler reports the following wide character related #defines as missing: SQL_WVARCHAR, SQL_WCHAR, SQL_WLONGVARCHAR, SQL_C_WCHAR. The compilation errors are fixed is this release.
- otl_column_desc class has been extended with the following fields: charset_form, char_size. The fields are enabled when OTL_UNICODE and OTL_ORA9I / OTL_ORA10G are defined. See also example 287

New (in OTL 4.0.109):

- OTL/OCI8i/9i/10g introduces the following new bind variable datatypes: nchar[], nclob. nchar[] is intended for special cases when, say, both VARCHAR2 and NVARCHAR2 need to be declared inthe SQL statement. nclob is useful for cases when both CLOB and NCLOB need to be declared in the same SQL statement.
  For more detail, see examples 285, 286.

New (in OTL 4.0.108):

- Basic support for Unicode data strings in OTL/ODBC and OTL/DB2-CLI. See the following examples for more detail:

- DB2 Unicode / CLI
- MS SQL Server Unicode / ODBC
- Oracle 8/8i/9i/10g Unicode / ODBC

- Support for SQLite via ODBC. See the examples for SQLite for more detail.
- OTL FAQ was updated.

New (in OTL 4.0.0.107):

- This release is a quick fix for a compilation bug that was introduced in OTL 4.0.106 along with the support for iODBC for BSD Unix.

New (in OTL 4.0.106):

- New #define is introduced: #define OTL_IODBC_BSD. This #define should be enabled when the iODBC ODBC driver manager is used in BSD Unix.
- OTL/ODBC now supports Firebird Database. See also the Firebird / ODBC code examples.
- New otl_exception is introduced: otl_stream::operator int() is not supported in the LOB stream mode (code 32025). This exception enforces the operator int() limits.
- otl_stream::operator>>(std::string) can read CLOB / LONG / TEXT table columns.When the actual column value is larger than the stream internal buffer size, and when the value is being read into an std::string buffer, the program crashes because it tries to read beyond the stream internal buffer. The bug is fixed in this release.
- When #define OTL_UNICODE is enabled, otl_connect::set_character_set(SQLCS_NCHAR) is called, and the Oracle database main / default character set is set to a one-byte chartacter set, double-byte characters with codes greater than 255 were converted incorretly between the database and the C++ client side. The bug is fixed in this release.

New (in OTL 4.0.105):

- "static char*" was generating compilation warnings in a few places. It was replaced with "const char*".

New (in OTL 4.0.104):

- When db2date and db2time bind variable types are used on a WHERE clause of a SELECT statement / a stored procedure that returns an implicit result set in a combination with OTL/ODBC,DB2-CLI, the otl_stream::operator<<(const otl_datetime&) operator throws the "Incompatible data types in stream operation" exception. The problem is fixed in this release.
- When throwing the "Incompatible data types in stream operation" exception under the condition described above, OTL shows the actual data type label as an empty string (""). instead of showing "DB2DATE", or "DB2TIME" as data type labels. The problem is fixed in this release.

New (in OTL 4.0.103):

- When the following set of #defines is enabled before including the OTL header file:
  #define OTL_STL
  #define OTL_ANSI_CPP
  #define OTL_FUNC_THROW_SPEC_ON

  there is a compilation error in
  ostream& operator<<(ostream&, const otl_value<T>&)

  The problem is fixed in this release.
- Several duplicate pieces of code were found in the OTL header file and reported as a bug. It does not have immediate impact on anything. Conventional wisdom says that duplication is bad, so the problem is fixed in this release.
- OTL/ODBC supports MS SQL varbinary data type via <raw_long> binding and otl_long_string containers. However, it is not possible to write a varbinary value to a SELECT...WHERE f2=:f2<raw_long>, because operator<<(otl_stream&, const otl_long_string&) in OTL does not support SELECT statements. Historically,, the reason for that was that search operations on Large Obects were not supported by relational databases. Then, OTL started supporting varbinary data type via <raw_long> bindings at some point in time. From this release on, OTL/ODBC supports writing of <raw_long>'s into a stream for SELECT statement's WHERE clauses. MS SQL requires an explicit type cast / conversiuon from "raw long" / image to a varbinary, for example:
SELECT ...
FROM test_tab
WHERE f2=cast(:f2<raw_long> as varbinary)
or
SELECT ...
FROM test_tab
WHERE f2=convert(varbinary(256),:f2<raw_long>)

New (in OTL 4.0.102):

- New #define is introduced: #define OTL_ODBC_POSTGRESQL. When PostgreSQL ODBC driver version 3.5 is connected to PostgreSQL 7.4 / 8.0 and higher, the following sequence of ODBC function calls does not work any more: SQLPrepare(), SQLDescribeCol. The SELECT statement needs to be executed before the output columns can be described: SQLPrepare(), SQLExecute(), SQLDescribeCol(). It is exactly the same sequence as in handling a stored procedure call that returns a result set. As a workaround, otl_stream(...,otl_implicit_select) can be used. The new #define does the same thing. See also PostgreSQL examples.
- When a password in the OTL connect string is longer than 255 bytes, the program crashes (a.k.a. buffer overflow). The bug has been fixed in this release.
- When #define OTL_EXPLICIT_NAMESPACES is enabled, ostream& operator<<(ostream& s, otl_value<T>) gets defined under each namespace, even though otl_value<T> is defined in the default namespace. The bug has been fixed in this release.
- When #define OTL_EXPLICIT_NAMESPACES is enabled, OTL stream read iterator does not compile. The bug has been fixed in this release. See also examples 260-264.

New (in OTL 4.0.101):

- The following new #define is defined for OTL tracing: OTL_TRACE_LINE_SUFFIX.
- OTL provides the option of deriving the otl_exception class from another class (#define OTL_EXCEPTION_DERIVED_FROM), which could be the base for a bigger exception class hierarchy. Sometimes, it is more convenient to attach the otl_exception class to another existing exception base class, and catch exceptions of the base class, instead of having multiple catch blocks for all types of exceptions, including otl_exception. However, when std::exception is used as a base class for otl_exception in the context of g++ 3.x, OTL compilation fails because of a "looser defined throw()" clause in otl_exception's constructors / destructor / other member functions. std::exception is defined with no-throw. This release fixes the problem for g++ 3.x and higher.

New (in OTL 4.0.100):

- The following things have been done to OTL tracing:

- Prior to this release, when a database connect string got logged, its password was logged as is, in plain text. Obviously, it was a security breach. This release logs the password part of database connect strings as "****".
- New tracing level is introduced: 0x20. It traces all otl_exception's raised by OTL.
- Some inconsistencies in trace formatting were reported, which made it difficult to grep for individual OTL trace/log entries. For example, number of spaces in some cases was inconsistent: "operator >> (", "operator << (", "operator >>(", "operator <<(". In this release, the formatting should always be as follows: "operator >>(", "operator <<(".

New (in OTL 4.0.99):

- This release introduces the OTL stream read iterator template class. It provides JDBC-like position based getter functions. In some cases, there is no need to read all SELECT output columns. The new iterator class addresses the issue. For more detail, see examples 260-264
- In OTL/OCI8i/9i,10g , tracing of operator>>(otl_datetime&) was missing.The bug is fixed in this release.
- OTL 4.0.98 had a fix OTL/ODBC/DB2-CLI for database passwords that contain @. Oracle user passwords may also contain @ characters. This release fixes the problem for OTL/OCI8/8i/9i/10g.

New (in OTL 4.0.98):

- OTL 4.0.97 introduced a new format for otl_column_desc. In some cases, the name of a SELECT output column does not have a null terminator character. The problem is fixed in this release.
- OTL 4.0.97 made otl_stream operator>>(bool&), operator<<(const bool), operator>>(unsigned long&), and operator<<(const unsigned long) private. The rationale was that since OTL did not support the operators, it would make sense to prevent them from being (mis)used. However, the private operators make it impossible to overload similar global operator, even though there may be legitimate use cases for doing that. This release makes it possible to overload the global operators >>/<< for bool and unsigned long by introducing the following #defines:

- OTL_STREAM_NO_PRIVATE_BOOL_OPERATORS
- OTL_STREAM_NO_PRIVATE_UNSIGNED_LONG_OPERATORS

- OTL 4.0.72 introduced OTL tracing, which enables OTL function call tracing via #define OTL_TRACE_LEVEL, and other #defines. There were complaints about the fact that level 0x4 logs too much information and that it would make more sense to split it into at least two levels. In OTL 4.0.98, trace level 0x4 has been split into two: 0x4 and 0x8. Former level 0x8 has become level 0x10. For more detail, see examples 249-252.
- In theory, it was possible that passwords in database connect strings could have "@" characters. OTL used "@" as a separator character between the password and the DSN/TNS, for example: "scott/tiger@my_db". The problem was reported when a database user defined a new password and the password had "@" in it. OTL 4.0.98 /ODBC/DB2-CLI can handle passwords that have "@" in them. I am not quite sure if Oracle user passwords can have "@".
  If anybody knows that it is possible, could you send the info, so that I could implement the same feature for OTL/OCIx?

New (in OTL 4.0.97):

- OTL was cleaned up / optimized:

- otl_stream::operator>>(unsigned long int&), otl_stream::operator<<(const unsigned long int) were made private because they are not supported by OTL, and it is difficult to debug code when the operators are used.
- Internal int otl_tmpl_cursor::eof() was changed from virtual to a normal function, which reduces the overhead of a virtual function call. This eof() function is called all over the place, and performance gain may be a few percentage points, depending on the C++ compiler.
- In class otl_column_desc, field "name" was changed from char[512] to char* in order to reduce the memory footprint. Memory for column names gets allocated dynamically instead of preallocating 512 bytes. In case if OTL streams are used properly (opened once and used and as many times as possible as opposed opened and used once, then closed)., the overhead of dynamic memory allocatioins should be minimal.

New (int OTL 4.0.96):

- OTL code was cleaned up / optimized a little bit. Performance gains, depending on the C++ compiler and its level of optimization, type of SQL statement being used, vary from 0.5% to 2%. In many cases, if-else logic was replaced with a switch(), which can be optimized more when a higher level of C++ compiler optimization is enabled.

New (in OTL 4.0.95):

- In OTL/ODBC/DB2-CLI, "SQLFreeStmt(cda,SQL_DROP);", which is a deprecated call, was replaced with a call to SQLFreeHandle() for ODBC/DB2-CLI, version 3.x.
- otl_stream::close() function was slightly modified in order to work around a bug / feature of the DB2 CLI in AIX. The problem was that under some circumstances a DB2 CLI function call returned SQL_ERROR, when there was not any error, and because of that the OTL stream closing logic caused database API resource leaks and program crashes. The modification is internal only, and it should not cause any changes in the behavior of the function.

New (in OTL 4.0.94):

- OTL code was cleaned up / optimized a little bit. Performance gains, depending on the C++ compiler and its level of optimization, type of SQL statement being used, vary from 0.5% to 4.5%. What was done in the OTL code is that internal otl_stream dispatching of operations to the underlying "In/Out" / "Select"/ "Reference Cursor" streams was optimized.

New (in OTL 4.0.93):

- OTL/OCI8/8i/9i/10g #undef's min() and max() that are defined in one of OCI header files. In some cases min() and max() are functions, defined in C++ standard header files. It worked well until now. The problem was reported that OTL does not work well with ATL because of the fact that OTL #undef's min() and max(). When the #undef min/max statements in OTL are commented out, the problem goes away. So, in order to make things a little bit more flexible, a new #define is introduced in this release: #define OTL_ORA_DOES_NOT_UNDEF_MIN_MAX.

New (in OTL 4.0.92):

- When UTF-8 is enabled on both the database and the client side, OTL/OCI8/8i/9i/10g does not handle reading CLOBs correctly, if #define OTL_UNICODE is not enabled. The problem is fixed in this release.

New (in OTL 4.0.91):

- A memory leak in otl_long_unicode_string. Memory leak occurs when #define OTL_UNICODE is defined and an external buffer is used.. Anybody who uses OTL with Orale 8i/9i/10g with Unicode, and experiences unexplained increases in memory usage, may want to consider to upgrade to this release.
- The fix for describe_next_in_var() that was introduced in OTL 4.0.90 (see below) is misplaced in the code (is put in OTL/OCI7 instead of OTL/OCI9i/10g). This release fixes it.

New (in OTL 4.0.90):

- In OTL/OCI9i/OCI10g, when #define OTL_ORA_TIMESTAMP is defined, otl_stream::describe_next_in_var() does not return correct information (does not correctly increment the "stream's next output variable") after otl_stream::operator<<(const otl_datetime&) is called. The problem is fixed in this release.
- Some databases servers support a "boolean" datatype, for example, PostgreSQL. However, ODBC does not support booleans, so there is no way to get database boolean values directly. OTL does not support booleans either. In order to make the matter less confusing, and avoid obscure runtime errors, otl_stream::operator>>(bool&) and otl_stream::operator<<(const bool) were made private in this release. When programmers try to use the operators, they would get a compilation error message saying that private functions could not be accessed.

New (in OTL 4.0.89):

- A few global operators >>/<< for reading/writing signed 64-bit integers in were introduce in OTL/OCI7/8/8i/9i/10g some time ago. Keyword "inline" was not put in place at that time, which caused linker's "duplicate symbol" errors. The bug has been fixed in this release.

New (in OTL 4.0.88):

- In OTL/OCI9i/OCI10g, when #define OTL_ORA_TIMESTAMP is defined, otl_stream::describe_next_out_var() does not return correct information (does not correctly increment the "stream's next output variable") after otl_stream::operator>>(otl_datetime&) is called. The problem is fixed in this release.

New (in OTL 4.0.87):

- Parts of the OTL code have been internally restructured / rewritten in this release.

New (in OTL 4.0.86):

- otl_connect::~otl_connect() in OTL/OCI8/8i/9i/10g may leak OCI / database server side resources, when the otl_connect object is connected to the database and no call to otl_connect::logoff() has been made. The bug is fixed is this release.

New (in OTL 4.0.85):

- OTL/OCI8/8i/9i/10g introduces the following new parameters in otl_connect::rlogon() and otl_connect::server_attach: server external name, server internal name. There are OCI + XA based programs that implement transaction monitors. OTL could be used in such program if the OCI enviroment handle (envhp) and the OCI service context handle (svchp) get passed into otl_connect::rlogon() as input parameters. In other words, OTL can accept an external connection and work with it correctly. Database connections that are required for transaction monitors need to set the same attributes that OTL sets, plus the server extrenal and internal name attributes. If the same parameters get passed into OTL's new flavors of rlogon() and server_attach(), OTL sets the required connection attributes., so that the database connection is XA compliant. Direct code in OCI that is external to OTL can be also written on top of the XA compilant database connection made by OTL. In order to write such code, the OCI environment handle (envhp) , the server handle (srvhp), the service context handle (svchp), the session handle (authp), and the error handle (errhp) can be directly accessed in the otl_connect::connect_struct structure.

New (in OTL 4.0.84):

- When OTL/OCI8/8i/9i/10g raises the "ORA-28002 the password will expire within string days" error on a database connection request, the corresponding otl_connect object is not fully initialized (otl_connect::connected == 0), even though it could be initialized and used. Oracle server allows accounts that are about to expire to be used, if the user chooses to do so. This release fixes the behavior of the otl_connect object in this situation. That is, the otl_connect::connected flag will be set to 1, and the otl_connect object will be fully initialized and usable.

New (in OTL 4.0.83):

- Some older versions of Oracle (Oracle 8.0.x, even Oracle 8.1.x) have a bug (or an undocumented / ambiguously documented feature) in the OCILObRead() function. The problem is that the OCI should not remember the address of the OCILObRead()'s "amt" paremeter, meaning that the parameter should be a transient parameter that could be allocated on stack. It is not so in some older versions of the OCI. OCILobRead() is used by the otl_lob_stream class in OTL/OCI, and this OCI "feature" results in the program's runtime crash. The trick here is that, say, if the actual "amt" variable gets allocated on stack, and if the variable's address on the stack still exists, then the OCI can use it.. If the address (on the stack) goes away because of the stack allocations / deallocations, the program may crash. The OCI manual does not indicate that the actual memory block that gets passed as the "amt" parameter into the OCILobRead() function should stay the same. So, the introduced workaround is that the actual "amt" variable that gets passed into the OCILobRead() function was made a data member of a class instead of a stack variable.

New (OTL 4.0.82):

- #define OTL_THROWS_ON_SQL_SUCCESS_WITH_INFO has been reworked in this release. Instead of a "throw flag" that the #define was supposed to pass into the OTL header file (release 4.0.81) , the #define enables the following function: otl_connect::set_throw_on_sql_success_with_info(). The function sets a database connection specific "throw flag", which makes development of multi-threaded programs that could potentially use this feature easier. See also example 259 for more detail.

New (in OTL: 4.0.81):

- OTL/ODBC, OTL/DB2-CLI: new #define OTL_THROWS_ON_SQL_SUCCESS_WITH_INFO. This #define forces OTL to throw an otl_exception when SQLExecute() / SQLDirectExec() returns SQL_SUCCESS_WITH_INFO. This kind of technique allows all diagnostic information (that would normally be retrieved via a series of calls to SQLGetDiagRec() in ODBC) to be passed back to the caller. Also, see example 259.
- OTL/OCI8,8i,9i,10g: new otl_refcur_stream::operator>>(OTL_BIGINT&)
- OTL/ODBC: otl_stream::operator>>(OTL_BIGINT&) and otl_stream::operator<<(const OTL_BIGINT) for OTL/ODBC automatically convert numeric string values to signed 64-bit integer values when the corresponding bind variable is a string (char[XXX]). This is useful when, say, the underlying database supports numeric datatypes that are larger than the "double" container can hold, for example, DECIMAL(19,0), and yet the ODBC driver does not natively support the "bigint" binding because it is an optional feature in the ODBC specification. Sybase would be an example of such database.

New (in OTL 4.0.80):

- OTL compiles clean with GNU C++ 3.x when -Wshadow is enabled.

New (in OTL 4.0.79):

- This release introduces general support for ODBC on IBM zOS via the following new #define OTL_ODBC_zOS.

New (in OTL 4.0.78):

- OTL has compilation errors when #define OTL_ACE is used. The problem is fixed in this release.

New (in OTL 4.0.77):

- This release introduces a new default: #define OTL_ANSI_CPP. The new default makes sense since most of the available C++ compilers that OTL compiles with are ANSI C++ compliant, or at least ANSI C++ friendly. The default allows OTL to be compiled cleaner (fewer compilation warnings) when higher warning levels are used in C++ compilers. Those who still use older C++ compilers can disable the #define right in the OTL header file (otlv4.h)
- As a result of a code cleanup, this release should compile clean with VC++ 7.1 .NET, when /W4 /WX /Wp64 options are used. /Wp64 gives warnings when there may be any compatiblity issues with the VC++ 64-bit compiler.
- As a result of a code cleanup, this release should compile clean with g++ 3.3 when the following warning options are used:

- -W
- -Wall
- -Wundef
- -Wpointer-arith
- -Wunused
- -ansi
- -Wreorder
- -Wcast-qual
- -Wcast-align
- -Wconversion
- -Wsign-compare
- -Wstrict-prototypes
- -Wmissing-prototypes

- A memory leak in otl_long_unicode_string. Memory leaks occurs under certain circumstances under #define OTL_UNICODE. Therefore, anybody who uses OTL with Oracle 8i/9i/10g with Unicode, and experiences unexplained increases in memory usage may want to consider to upgrade to this release. By the way, this problem has not been reported yet by anybody. The problem was uncovered during a routine test suite build / execution cycle by a memory leak detector.

New (in OTL 4.0.76):

- This release introduces general support for Oracle 10g (OCI10g) via #define OTL_ORA10G. Oracle 10g introduced the following two new numeric datatypes: BINARY_FLOAT (4-byte native floating point), BINARY_DOUBLE (8-byte native floating point). With OTL_ORA10G, OTL maps those two datatypes to "float", and "double", respectively. For now OTL_ORA10G is almost synonymous to OTL_ORA9I. In the future there may be some differences when OCI19g specific features get used.
- OTL implicitly disallowed multi-line string literals in SQL statements, for example: '12345\n 67\n 89\n'. In general, SQL allows multi-line string literals. Some old database servers, at this point it is hard to say exactly what versions of what database types, did not support multi-line string literals correctly, so the assumption was made in OTL that string literals of that sort were not allowed. This release of OTL handles multi-line string literals correctly.

New (in OTL 4.0.75):

- A few compilation warnings have been fixed in this release for VC++ 7.1 (.NET) , when OTL gets compiled with the -W4 command line option.

New (in OTL 4.0.74):

- This release introduces support for 64-bit signed integers (bigint) for OTL/OCIx: OTL_ORA7, OTL_ORA8, OTL_ORA8I, OTL_ORA9I. OCis do not have any native support for 64-bit inetegers (even in the newly released Oracle 10g), so OTL has to emulate it, which is done via string (char[XXX]) bind variables internally. On the outside, otl_stream::operator >>(OTL_BIGINT& n) and otl_stream::operator<<(const OTL_BIGINT n) work the same way for OTL/OCIx as for OTL/ODBC, or OTL/DB2-CLI, which provides portability between different databases. In order to enable this new feature for OTL/OCIx, the following #defines have to be enabled: OTL_BIGINT, OTL_STR_TO_BIGINT, OTL_BIGINT_TO_STR.
  See also examples 257, 258.
- A new list of examples by database type was added to the OTL examples, which should make it easier to look up database type and vesrion specific OTL examples.
- Several compilation warnings have been fixed for g++:

- unused function parameters / local variables
- base class should be explicitly initialized in the copy constructor

New (in OTL 4.0.73):

- otl_stream::operator int() behaves incorrectly when it is called right after a call to an otl_stream::operator<<(), that is, when a value gets written to the stream, operator int() returns an incorrect value, which may result in obscure bugs that could be very difficult to track down. In theory, operator int() in the context of OTL streams is defined / makes sense only for streams that have some output: SELECT statements, stored procedures that return result sets, etc. From the very beginning, operator int() was intended for reporting the end-of-file status of the stream, and could be typically used with SELECT statements as the following C++ idiom, similar to the while(!s.eof()) construct: while(s>>f1). A concern was raised that partially defined behavior of the operator int() is potentially dangerous and may cause nontrivial bugs. The idea was that the operator should either behave correctly, or its use should be blocked in the situations when correct behavior of the operator is not guaranted. This release does the latter: it introduces the following new OTL defined exception: otl_stream::operator>>() should have been called before otl_stream::operator int(). The exception blocks any use of the operator when correctness of its behavior is not guaranteed. When the exception gets thrown, it would normally mean that the logic of the program should be changed. In other words, operator int() should be used only after calls to otl_stream::operators >>().

- This release introduces explicit bind variables in definitions of SELECT output columns. It is an alternative, inline (right in the text of SELECT statements) mechanism for overriding the OTL default internal-database-datatype-to-external-datatype mapping in SELECT statements. The mapping works okay for the most part, except for rare cases, when it would make more sense to ovveride a default column datatype with something more specific, and in the case when the use of the otl_stream::set_column_type function is not very convenient. Also, see examples 253-256.

New (in OTL 4.0.72):

- This release introduces OTL tracing, which enables OTL function call tracing via #define OTL_TRACE_LEVEL, and other #defines. See also examples 249-252.

New (in OT 4.0..71):

- In OTL 4.0.28, OTL stream operator >>/<<(std::string/ACE_String) were extended to work with Large String Objects (Oracle LONG, Oracle/DB2 CLOB, MS SQL/Sybase TEXT, etc). In this release, when #define OTL_USER_DEFINED_STRING_CLASS_ON is used, the OTL stream string operators >>/<< can read/write Large String Objects via a user defined string class.
  Even though std::string exists, there is still a need to add your own, more scalable, sometimes even application specific, string class. See examples 244-248 for more detail.
  OTL from this release on requires more functions to be implemented by the user defined strng class: see updated example 119, 120, 121. Those who already defined their string class may want to double check their source code, when upgrading to this release of OTL.

New (in OTL 4.0.70):

- Private copy constructors and assignment operators were added to the otl_connect, and otl_stream classes (for all flavors of OTL) in order to prevent instances of otl_stream and otl_connect from being copied / put in containers. otl_connect and otl_stream objects are wrappers around database API resources, which are not really sharable.

New (in OL 4.0.69):

- OTL throws otl_exception's, catches the exceptions, and rethrows them internally (in the OTL header file). GNU C++ 3.3.1 does not compile some of the "catch(otl_exception...)" catch blocks correctly. The fix for this problem is that all the catch blocks have to catch "const otl_exception&" in order to compile okay wih G++ 3.3.1. All of the catch blocks were changed to catch "const otl_exception&" when #define OTL_ANSI_CPP is enabled, and if it is not enabled, the catch block have the original format.
  The compilation problem has been fixed in this release.

New (in OTL 4.0.68):

- It turns out that OTL/ODBC works fine with the Informix CLI (which is ODBC 2.5 compliant). However, Informix SQL allows ":" as a legimimate character in an SQL statement. ":" is treated by OTL as the prefix of a bind variable. ":" is native to the Oracle Call Interface syntax, and gets converted by OTL into "?" for DB2 CLI and ODBC. When used with OTL/ODBC, an SQL satement that has colons is parsed incorrectly, and there is a need to embed colons (literally) into the SQL statement. OTL/ODBC, starting with release 4.0.68 ad higher, supports the following notation for embedding colon literals into SQL statments: "\\:". For example:
  "SELECT * FROM xxx\\:yyy"
  In this example, \\:yyy is not treated / parsed out as a bind variable.
- The following example causes the SQL statement buffer overrun (reading / writing beyond the buffer):
  "SELECT * " // Line 1
  "FROM test_tab " // Line 2
  "WHERE f1>=:f1<int> - 2 " // Line 3
  "AND f1<=:f1" // Line 4
  This notation (:f1) is only supported for OTL/OCIx (Oracle), because it is the OCI native notation. In the example above, the second reference to :f1 (Line 4) is treated as a reference to the same bind variable :f1., that is, only one bind variable is defined in the SELECT statement above. This notation is not supported for OTL/ODBC, OTL/DB2-CLI, because :var<...> notation gets translated into the question marks("?"), which is native to ODBC and DB2-CLI.
  The buffer overrun error is fixed in this release.

New (in OTL 4.0.67):

- In OTL/OCIx, otl_stream::operator >>(otl_time0&...) may sometimes cause "memory access viloation", where otl_time0 is an internal DATE container, when stream returns a result set via a reference cursor. The problem is fixed in this release.
- This release introduces support for bigint (64-bit integer) bind variables for OTL/ODBC, OTL/DB2-CLI, when #define OTL_BIGINT is enabled. Se also examples 242, 243.
  OCI, for the reason of 64-bit integers not being a standard primitive numeric datatype, or because 64-bit integers have compiler dependent / specific implementations, does not have any native support for 64-bit integers. Here is an excerpt from the OCI manual that describes a list of OCI external numeric datatypes:

  EXTERNAL DATATYPE | TYPE OF PROGRAM VARIABLE | OCI DEFINED CONSTANT
  --- | --- | ---
  NAME | CODE
  VARCHAR2 | 1 | char[n] | SQLT_CHR
  NUMBER | 2 | unsigned char[21] | SQLT_NUM
  8-bit signed INTEGER | 3 | signed char | SQLT_INT
  16-bit signed INTEGER | 3 | signed short, signed int | SQLT_INT
  32-bit signed INTEGER | 3 | signed int, signed long | SQLT_INT
  FLOAT | 4 | float, double | SQLT_FLT

New (in OTL 4.0.66):

- In the "LOB stream mode", OTL/ODBC, when the program is connected to an MS SQL Server 2000 database, ODBC function SQLPutData() may return SQL_NO_DATA, which is a normal code and it is not an error. OTL treated the code as an error, and raised an otl_exception as a result. It is not quite clear why SQLPutData() returns SQL_NO_DATA, and it appears to an undocumented feature. Here is an excerpt from the MS ODBC manual:

#### SQLPutData Function
...
Returns

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_STILL_EXECUTING, SQL_ERROR, or SQL_INVALID_HANDLE.
The problem was fixed in this release.
- When a string literal that had "--" (dashes) inside of it was part of an SQL statement / PLSQL block / stored procedure call, the dashes were mistakenly treated as a one-line comment. The problem was fixed in this release.
- Support for Oracle 9i TIMESTAMPs WITH [LOCAL] TIME ZONE via the following new types of bind variables and the otl_datetime container when #define OTL_ORA_TIMESTAMP is enabled: tz_timestamp, ltz_timestamp. See also example 241.

New (in OTL 4.0.65):

- A few Borland C++ compilation warnings about implicit type casting were fixed in this release.

New (in OTL 4.0.64):

- The assignment operator and the copy constructor were added to the otl_long_string class did not copy a NULL terminator byte, which was actually beyond the dynamic length. However, it is convenient to have the NULL terminator for comparing string and for using C-style functions. The problem is fixed in this release
- When #define: OTL_ORA_TIMESTAMP in a combination with an otl_stream that returns a reference cursor is used, and the stream has an input bind variable of the :v<timestamp,in> type, OTL throws exception "Incompatible data types in stream operation". The problem is fixes in this release.
- otl_stream:: create_stored_proc_call() did not support Oracle 9i's TIMESTAMP data type under #define: OTL_ORA_TIMESTAMP. The problem is fixed in this release

New (in OTL 4.0.63):

- An assignment operator and a copy constructor were added to the otl_long_string class.

New (in OTL 4.0.62):

- When OTL/ODBC is used with MERANT 3.6 ODBC Driver for Progress Database, and when a SELECT otl_stream returns an empty result set, OTL goes into an infinite loop. The problem is fixed in this release. I suspect that the problem is specific to the ODBC driver, because I couldn't recreate it with any of available ODBC drivers for major databases. If anybody has experienced the same problem, some feedback would be appreciated very much.

New (in OTL 4.0.61):

- There are some compilation warnings when a high enough level of warnings is set with g++ 3.2. The warnings were fixed in this release.

New (in OTL 4.0.60):

- In OTL/ODBC, DB2-CLI, the format of SQL statements in OTL stream has been extended for calling such ODBC / DB2-CLI functions as SQLTables(), SQLColumns(), etc., in order to be able to access system data dictionaries of different ODBC / DB2-CLI data sources. For more detail, see Appendix B, and examples 237-240.

In theory, ODBC / DB2-CLI compliant data sources / drivers should implement functions for accessing system data dictionaries. Not all databases have access to their system data dictionaries via so-called system views, that is when functions like SQLTables(), SQLColumns(), etc. come into play.

New (in OTL 4.0.59):

- A new parameter has been introduced in otl_stream constructors and open functions: SQL statement label. When an SQL statement gets opened via an OTL stream and a statement label is specified, then if an otl_exception gets thrown, the otl_exception::stm_text field gets populated with the statement label instead of the actual text of the SQL statement. SQL statement labels can be used for more compact, more readable logging of failed SQL operations. In some cases, it's not desirable to expose SQL statements at all.In big / complex systems, SQL statements are normally cataloged, and it would be easier to identify an SQL statement by its index / number in the SQL catalog instead of trying to sort through the text of failed complex (say, 3Kb each) SQL statements. See also examples 234, 235, 236.

New (in OTL 4.0.58):

- otl_stream::set_all_column_types() and otl_stream::set_column_type() behave incorrectly (or crash the program), when used on the same stream variable after the stream was partly initialized with a bad SQL statement that errored out (otl_exception was raised). The problem is fixed in this release.

New (in OTL 4.0.57):

- Under OTL_ORA7, OTL_ORA8, OTL_ORA8I, OTL_ORA_9I, when OTL is compiled with Borland C++ 6.0, there are compilation warnings about implicit type casting. The warnings are fixed in this release.

New (in OTL 4.0.56):

- Some of the operators <</>>() under #define OTL_ORA8, OTL_ORA8I,OTL_ORA9I may crash the program because of a NULL pointer dereferencing. The bug was introduced in OTL 4.0.55 and is fixed in this release.

New (in OTL 4.0.55):

- On Tru64 Unix, Compad C++ v6.3, a "unused variable" compilation warning was fixed in this release
- When otl_stream::close() gets called on a stream that was already closed, the program crashes. The problem was fixed in this release. Though, an obvious workaround is as follows:

`if(my_stream.good())`
`my_stream.close();`

New (in OTL 4.0.54):

- Operator int() does not return 1 in the case of a result set of one row. The problem is fixed in this release.

New (in OTL 4.0.53):

- Operator int() does not return 1 in the case of an empty result set, so one phantom row of data can be potentially read from the stream. The problem is fixed in this release.

New (in OTL 4.0.52):

- New #define OTL_DB2_CLI_MAP_LONG_VARCHAR_TO_VARCHAR is introduced. The #define allows to map DB2 OS/390 VARCHAR table columns that are smaller than a specified by the #define numeric value to DB2 CLI's SQL_VARCHAR datatype, even though the DB2 CLI itself reports them as SQL_LONG_VARCHARs. Client DB2 CLI, when connected to a DB2 OS/390 database, reports all VARCHAR table columns that are larger than 255 bytes as SQL_LONG_VARCHARs. This new feature (in OTL) allows the developer to work around portability problems across many slightly incompatible flavors of DB2.
- In OTL/DB2-CLI, OTL/ODBC, when a SELECT statement gets opened via an otl_stream, and resulting rows [of the SELECT statement] are being fetched, the underlynig cursor gets closed as soon as possible, right after the fetch sequence is exhausted. This can be considered as a small optimization tweak. Those who are curious can run a diff on the source code and see for themselves what was done.

New (in 4.0.51):

- New #define OTL_FUNC_THROW_SPEC_ON is introduced. It should be used when #define OTL_ANSI_CPP is on, in order to enable OTL function throw specifications, introduced in OTL 4.0.50. It looks like there is no consesus on the merits of this feature of C++ in the C++ community, and I have to make it optional within the "OTL ANSI CPP" mode.

New (in 4.0.50):

- In OTL/ODBC, OTL/DB2-CLI, when #define OTL_ODBC_SQL_EXTENDED_FETCH_ON is defined, in the OTL internal "fetch" functions, there were a number of local calls to the C++ heap manager (dynamic memory allocation/deallocation calls), which degraded performance somewhat, especially in the multi-threaded mode (the heap manager in the multi-threaded mode generates critical section / mutex locks, and, unless a special multi-heap manager is used, it makes all calls to the heap manager sequential / " single threaded"). The problem is fixed in thsi release.
- Under OTL_ANSI_CPP, all OTL functions / operators have a throw clause, which specifies what exception each function may potentially throw (or not to throw anything at all). This effort is in making the OTL source code more up to date with the ANSI C++ style.
C++ compilers have some support in reporting scope exception problems (e.g., a function call may potentially throw an exception, but there is no corresponding try/catch block) at compile time. Hopefully, it will improve in the future

Also, in declaration of template classes, under OTL_ANSI_CPP, class type parameters are marked with keyword typename, not class, which is more in the letter and spirit of the ANSI C++ standard.

New (in 4.0.49):

- A bug, that was fixed in 4.0.48, introduced a new bug under #define OTL_STREAM_POOLING_ON: when the same otl_stream variable gets reused multiple times for different SQL statements, the program crashes with "Access Violation" / "Segmentation Violation" errors. The new bug is fixed in this release.
- operator int(), that was introduced in 4.0.47, returns 0 on the last row to be fetched, before the row is fetched, instead of after the row is fetched. The bug is fixed in this release.

New (in 4.0.48):

- When OTL_STREAM_POOLING_ON , OTL_UNCAUGHT_EXCEPTION_ON are defined, and an external (non-OTL) exception gets thrown, the otl_stream::~otl_stream() destructor tries to access a block of dynamic memory that was already freed. This happens only for C++ compilers that support uncaught_exception() (ANSI C++). The bug was fixed in this release.

New (in 4.0.47):

- operator int() was added to otl_stream.

New (in 4.0.46):

- In OTL/OCI8/OCI8i/OCI9i, when an otl_lob_stream was opened for reading a CLOB/BLOB from an Oracle table, if the CLOB/BLOB was not read to the end, and the LOB stream gets closed, it causes the following Oracle error message: "`ORA-03127: no new operations allowed until the active operation ends`". The problem is fixed in this release.

New (in 4.0.45):

- Support for Intel C++ 7.0 (Windows and Linux). In general, previous releases compiled with Intel C++, without the "-ansi" flag. This release of OTL compiles correctly with the "-ansi" flag. A few inherited member functions in a template class had to be qualified with "this->", in order to make the OTL header file compile with Intel C++ the "-ansi" mode.

I suspect that something similar should be the case for HP UX aCC. If somebody could provide more information of HP UX aCC problems, I would appreciate it very much.

New (in 4.0.44):

- #define OTL_VERSION_NUMBER was set incorrectly, it is fixed in this release.
- OTL SQL statement parser did not take into account one line comments (--...EOLN), and traditional comments (/* ... */) when parsing an anonymous PL/SQL block. In case if a comment contains ":" characters, the parser mistakenly recognizes them as bind variable declarations. The problem is fixed in this release.

New (in 4.0.43):

- In OTL/OCI8,OCI8i,OCI9i, when oracle:: namespace gets enabled, the actual namespace was oracel::, which was a typo. The bug is fxed in this release.

New (4.0.42):

- HP UX C++ (aCC) generates a "future error" compilation waring. Simply addition of "this->" to a reference to a dataabse member in a template class fixes the problem. The problem is fixed in this release.

New (in 4.0.41):

- Under #define OTL_BIND_VAR_STRICT_TYPE_CHECKING_ON , when the otl_stream gets instantiated with a stored procedure call (ODBC, DB2-CLI), or an anonymous PL/SQL block (OCI7, OCI8, OCI8, OCI8i, OCI9i), if a bind variable has an invalid datatype, the program crashes (Memory Access Violation, Segmentation Violation, etc.) instead of throwing otl_exception.The bug is fixed in ths release.
- New #define is introduced:: #define OTL_ORA_MAP_STRINGS_TO_CHARZe. See also, example 233.

New (in 4.0.40):

- Received an email from Germany that confirmed that OTL/ODBC worked okay with SAP DB. See the FAQ page for more detail.
- In OTL/OCI8/8i/9i: new template <T> otl_refcur_stream& operator>>(otl_refcur_stream& s, otl_value<T>& val), which was actually forgotten;
- Purify was showing a possible memory leak when #define OTL_STREAM_POOLING_ON was enabled, because std::vector::clear() function was being called inside a loop instead of outside:
`...`
`for(int j=0;j<sz;++j){`
`...`
`ce.s.clear();`
`...`
`}`
`...`
The problem has been fixed in this release.

New (in OTL 4.0.39):

- A new type of SELECT statements was introduced in OTL 4.0.36: "WITH... SELECT..." Inadvertently, the parsing of the new type of SELECT statements for DB2-CLI was coded so that the "WITH" keyword overrides the 4th parameter in the otl_stream constructor, or otl_stream::open() function: otl_implicit_select. In DB2 CLI, "WITH SELECT" can be treated both as a straight SELECT and an implicit SELECT (similar to a call to a stored procedure that returns a result set), as far as handling the actual sequence of DB2 CLI function calls. It's more appropriate to treat the "WITH...SELECT" as implicit if the SQL statement gets opened as "otl_implicit_select." This release fixes thedeviation in the behavior that was inadvertently introduced in OTL 4.0.36.

New (in OTL 4.0.38):

- A new version of otl_stream::flush() for OTL/OCI8,8i,9i. See also example 232. This new flavor of the otl_stream::flush() function allows the program to skip, say, duplicate rows in a batch of rows to be inserted, and force flushing of the rest of stream buffer. Only OCI8/8i/9i has teh necessary feature. No ODBC/DB2-CLI, sorry.

New (in OTL 4.0.37):

- When compiling OTL with aCC / HP UX, a few "Future error" compilation warnings come up because some data members in a base template class were not accessed via "this->" notataion in a derivative template class. That is a feature of aCC in the way how it looks up names in template classes. Other C++ compilers that are supported by OTL do not have that problem, and OTL compiles just fine. I hope I nailed down all of the compilation warnings. If not, let me know right away.

New (in OTL 4.0.36):

- In ANSI SQL-92, there are so called common table expressions, which are allowed as part of a full select statement. OTL did not recongnize SELECTs with common table expressions, for example: "WITH xx as (SELECT...) SELECT * from xx". It is a legitimate SELECT. This SQL construct now gets handled correctly by OTL. That is, OTL, in this release, recongnizes this kind of thing as a SELECT statement. FYI, only Oracle 9i, and DB2 UDB (non-OS/390) support this SQL construct.
- A full select statement is allowed to be enclosed into parentheses (but not by all database, MS SQL 7.0/2000 are an exception, for example): "((SELECT...FROM...))". OTL did not recognize this kind of construct as a SELECT statement, and as a result, the statement was getting instantiated by OTL as a general input/output stream, instead of a specialized SELECT stream. The problem is fixed in this release.

New (in OTL 4.0.35):

- When OTL/ODBC is being used in a combinatuion with an Oracle ODBC driver to instantiate a stream with a SELECT statement that points a nonexistant table, the program crashes with "Memory Access Violation". The real problem is in the fact that the driver deffers the parsing until the "SELECT describe" call, or even until a later stage, and the OTL internal describe_select_list() allocates an array of 0 elements, which causes the program to crash. The bug has been fixed in this release.

New (in OTL 4.0.34):

- When OTL stream pooling is used in a combination with otl_stream::set_flush(false), and a stream that has, say, an INSERT statement in it, gets saved to the stream pool and then reclamed from the pool, the stream would not flush correctly, in case if otl_stream::flush() gets called explicitly (not via close(), or stream's destructor). The bug is fixed in this release.

New (in OTL 4.0.33):

- In order to reduce amount of memory allocated on stack, some temporary buffers were moved to the heap in cases, when it does not hurt performance. It is really a minor, yet crucial change, that allows platforms like AIX, or Windows, to run bigger OTL based programs.
- Set of new examples for MySQL, MyODBC 3.51. MyODBC 3.5 supports bind variables in the WHERE clause of a SELECT statement. No bulk INSERTs / UPDATEs / DELETEs as well as transaction support, though.

Also, with MyODBC 3.5, the OTL MyODBC specific #define OTL_ODBC_MYSQL is not required any longer, because the MyODBC 3.5 driver is more compliant with the ODBC 3.5 specification than before.

New (in OTL 4.0.32):

- In OTL/OCI8,8i,9i, in otl_refcur_stream, the following #defines are supported:

- OTL_DEFAULT_NUMERIC_NULL_TO_VAL
- OTL_DEFAULT_DATETIME_NULL_TO_VAL
- OTL_DEFAULT_STRING_NULL_TO_VAL
- OTL_DEFAULT_CHAR_NULL_TO_VAL

I must have overlooked this stream class.

New (in OTL 4.0.31):

- In OTL/ODBC, OTL/DB2-CLI, the numeric bind variables' datatypes get mapped more accurately. Run a diff on OTL 4.0.30 and OTL 4.0.31 header files, and see the difference for more detail.
- More verbage was added to the description of otl_stream::set_flush(), because it seemed ambiguous to some folks, so that they misinterpreted the description and wrote incorrect code.

New (in OTL 4.0.30):

- In OTL/ODBC and OTL/DB2-CLI for Windows, otl_connect::set_timeout() did not have any effect on the otl_connect::rlogon() function. Now it does, meaning that a logon / connect request will time out correctly, if a timeout is set to something > 0.

New (in OTL 4.0.29 part III):

- A documentation bug is fixed in the otl_connect::session_begin() function. The function supports the SYSDBA, and SYSOPER modes, besides the DEFAULT mode.

New (in OTL 4.0.29, part II):

- A documentation bug is fixed in the otl_stream::get_rpc() function. This was apparently overlooked in the process of putting OTL 4.0.6 together, was a big release.

New (in OTL 4.0.29):

- Slight performance degradation was noticed in OTL 4.0.28 in operators <</>> (std::string&) after the operators had been extended to work with Large String Objects. Performance of reading/writing normal strings degraded a little bit. I had to replace some if() statements with a switch, which is, apparently, more efficient.

New (in OTL 4.0.28):

- otl_stream, otl_refcur_stream operators <<(const std::string&) / >>(std::string&), that read and write std::strings (and also, corresponding versions of the operators for ACE_TStrnigs, ACE, #define OTL_ACE), and enabled by #define OTL_STL, OTL_STLPORT, now can read Large String Objects, like TEXT, LONG, CLOB, etc., depending on the database type.

Some individuals got annoyed very much (thank you, guys, for the format of your input!) by inconvenience of operators >>(otl_long_string&) / <<(const otl_long_string&), so I had no choice but extend the std::string read/write operators to make them work with Large String Objects. Though, it may be more convenient, but it is less efficient, especially in the case of Oracle CLOBs and operator>>(std::string&), because a buffer of a fixed known size, allocated in advance, is required. What operator >>(std::string& ) has to do is to allocate the buffer, read the CLOB value into it, and then copy the value into the std::string output parameter. For multi-threaded programs, which will do a lot of Oracle CLOB reads, operator >>(std::string&) may become a bottleneck, unless a special multi-heap memory allocator is used as a substitute for the C++ default operators new() & delete().

See also examples 220-224.

New (in OTL 4.0.27):

- A new function was introduced for OTL/OCI8i,9i: otl_connect::change_password(). The function is for changing Oracle user passwords. It could be used in an application, that allows the user to change an expired password.

Also, see example 219

New (in OTL 4.0.26):

- In OTL/OCI8/8i/9i, when the reference cursor flavor of otl_streams is being used, in case if a NULL value gets entered into the stream, OTL sets the NULL indicator of the internal buffer of the stream to non-NULL . And then, the content of the internal buffer gets interpreted as a legitimte value, even thoug it's presumably random. The bug is fixed in this OTL release.

New (in OTL 4.0.25):

- In SQLBindParameter() call, for string buffers, that are used for binding with VARCHAR/CHAR columns, OTL/ODBC and OTL/DB2-CLI used the string buffer size in the "Column Size" parameter of the SQLBindParameter() function. The Big/Little Endian dilemma here was that should the null terminator byte be included into the size or not. The practical answer to this question is that it should NOT. There is another parameter in the SQLBindParameter() call: the "Buffer Size". That parameter should include the null terminator, in case of SQL_C_CHAR type of the bind variable.
The problem is fixed in this OTL release.

The problem is actually very marginal, so you could it only the case when, say, the maximum allowed size fo VARCHAR/CHAR columns is 255 and, a string bind variable is defined as char[256] to include the null terminator. Some ODBC drivers are more sensitive to this issue than others.

New (in OTL 4.0.24):

- When PL/SQL table containers (OTL/OCIx) are used as input parameters, and then reused, going from a larger string value to a smaller string value may have the effect that the smaller string gets written over the larger value without the null terminator, and the resulting string is a comnibation of the two strings. The bug is fixed in this release.

New (in OTL 4.0.23):

- New #define OTL_ADD_NULL_TERMINATOR_TO_STRING_SIZE. Also, see examples 211-216
- When OTL_UNICODE is enabled and a BLOB column is used, the output length of a BLOB value (in a SELECT statement) gets counted in Unicode charaters, instead of bytes. The bug is fixed in this release.
- New function was added to the otl_stream class: otl_stream::cancel(). The function allows executing SELECT statements to be canceled in OTL/ODBC, and OTL/DB2-CLI. See also example 217-218.

New (in OTL 4.0.22):

- New #define OTL_BIND_VAR_STRICT_TYPE_CHECKING_ON: enables bind variable strict type checking.

New (in OTL 4.0.21):

- When the OTL stream pooling is on (OTL_STREAM_POOLING_ON) , in the case of a stream with a SELECT statement, if the stream gets closed and reopened several times, otl_stream::eof() returns 0 when it should return 1 (EOF). The problem was in the fact that the stream didn't reset some of its internal variables correctly, when the fetch sequence was not complete 100%. The problem is fixed in this release.
- Courtesy of the house. The following #defines work under OTL_ORA7 starting with this release:

- OTL_DEFAULT_NUMERIC_NULL_TO_VAL
- OTL_DEFAULT_DATETIME_NULL_TO_VAL
- OTL_DEFAULT_STRING_NULL_TO_VAL
- OTL_DEFAULT_CHAR_NULL_TO_VAL

The #defines were originally introduced back in OTL 4.0.6. It turns out that there are some people who still work with Oracle 7. For more detail, see example 169

New (in OTL 4.0.20):

- A little bit of source code trimming (~ 8Kb) has been done in this release, in order to cut down redundant code, that was introduced in OTL 4.0.19.

New (in OTL 4.0.19):

- Now, OTL otl_output_iterator,otl_input_iterator compile with STLPort 4.0 and STLPort 4.5, so #define OTL_STLPORT does not impose any restrictions on use of the OTL iterators.

New (in OTL 4.0.18):

- Minor fix a problem that was introduced in OTL 4.0.17: the OTL version number was not converted correctly from decimal to hexadecimal format.

New (in OTL 4.0.17):

- A new #define is introduced: OTL_VERSION_NUMBER

New (in OTL 4.0.16):

- Basic support for Oracle's RAW datatype, which can be used in a combination with OTL's raw_long placeholder type and otl_long_string container. For more detail, see example 210

New (in OTL 4.0.15):

- Support for SQL_VARBINARY ODBC datatype (e.g. MS SQL Server's varbinary). OTL maps SQL_VARBINARY into SQL_LONGVARBINARY, which can be used in a combination with OTL's raw_long placeholder type and otl_long_string container. For more detail, see example 209.

New (in OTL 4.1.14):

- When otl_lob_stream's for OTL/OCI8/8i/9i are used, it's possble to use an anonymous PL/SQL block with a SELECT INTO statement, in order to get a LOB locator from a table, and update the LOB value. This is an alternative form of UPDATE...SET ...=empty_clob()...WHERE...RETURNING... INTO :XX<clob>
OTL didn't trim the LOB automatically, because it was assumed that the "trimming" would be done via ...=emtpy_clob(). The bug is fixed in this release of OTL. Fore more detail, see example 208

New (in OTL 4.0.13):

- A few compilation warnings were fixed for HP UX C++ (aCC).

New (in OTL 4.0.12):

New #define OTL_EXCEPTION_HAS_MEMBERS.. It allows the otl_exception class to have new members, for example, when the otl_exception class is derived from another class, which is part of an exception class hierarchy. For more details, see examples 205-207

New (in OTL 4.0.11):

- New #define OTL_EXCEPTION_DERIVED_FROM.. It allows the otl_exception class to be derived from another class, that may be part of already existing exception class hierarchy. For more details, see examples 205-207

New (in OTL 4.0.10):

- When #define OTL_UNICODE is enabled in a combination with either OTL_ORA8I, or OTL_ORA9I, and when reading a LONG, or a CLOB, or an NCLOB value into an otl_unicode_long_string, operator>>() puts a zero byte right in the middle of the otl_unicode_string. This error was due to the fact that the length of the string was calculated in bytes, instead of Unicode chractares. This release fixes the problem.
- When #define OTL_ORA_TIMESTAMP is enabled in a combination of OTL_ORA8I, or OTL_ORA9I, and external connection was instantiated via otl_connect::rlogon(OCIEnv *envhp,OCISvcCtx *svchp), in the XA environment, or in Pro*C, operations with otl_datetime fail, because "OCISession *authp" handle was used instead of the environment handle (OCIEnv *envhp). This release fixes the problem.

New (in OTL 4.0.9):

- This is a maintenance release. The technique of suppressing "unused argument" compilation warnings was changed from OTL_UNUSED_ARG(arg) in the function body to /* arg */ in the function argument list. It seems a little cleaner than the previous technique.

New (in OTL 4.0.8):

1. otl_datetime structure was extended with the second's fraction field, and with frac_precision. These new fields allow the user to specify the second down to its fraction part, say, down to milliseconds (MS SQL Server's datetime), or microseconds (DB2's, or Oracle 9i's timestamp).
2. New #define: OTL_ORA_TIMESTAMP, which enables basic support for Oracle 9i's timestamp datatype (now timestamps with [local] time zones yet, though).
3. For more detal on (1), (2), see examples 202-204.
4. Several "unused argument" warnings are fixed.

New (in OTL 4.0.7):

- A new OTL defined exception is introduced: "Stream buffer size can't be > 1 in this case." (Code 32017). This exception is for patching the loophole that allows the user to define a stream buffer size larger than 1, in case if the stream has LOB bind variables/columns, when in reality the limit is 1.

New (in OTL 4.0.6):

- In OTL/OCI, support for Unicode:

- Oracle 8i, UCS-2
- Oracle 9i, UTF-16

Basically, everything that works with / makes sense for the one-byte character OTL functionality, should work with the Unicode OTL. For more detail, see examples 174-187 for Oracle 8i, and examples 188-201 for Oracle 9i.
- New #define OTL_UNICODE, that can be used in a combinatiowith either #define OTL_ORA8I, or #define OTL_ORA9I.
- New class otl_long_unicode_string, a specialized derivative of otl_long_string, for operations with LONGs, CLOBs, and NCLOBs, the character based large object datatypes.
- New in otl_connect (for OTL/OCI8i,OCI9i) function: set_character_set(). The function is needed for proper setting of client-to-server/server-to-client character conversions when the default character [set] datatypes CHAR/VARCHAR2/LONG/CLOB are used, or the national character [set] datatypes NCHAR/NVARCHAR2/NCLOB are used.
- In OTL/OCI8i,OCI9i, in otl_connect class, the OCI internal "environment handle" (`otl_connect::connect_struct.envhp`) is available to access the Unicode OCI character transformation functions. OCI8i has about 2 dozen such functions, OCI9i -- about 4-5 dozen (see "National Language / Globalization Support Guide").
- Note: besides the Unicode OTL examples, also see "National Language Support Guide" (Oracle 8i), "Globalization Support Guide" (Oracle 9i), the "OCI Programming with Unicode" chapters of the Oracle Call Interface Programmer's Guide (both Oracle 8i, and Oracle 9i).
- A bug fix in otl_connect::server_attach(), and otl_connect::session_begin(), OTL/ORA8/8i/9i. both functions didn't reset the throw_count flags, so when they are used,and when an otl_exception gets thrown, subsequent calls to the functions fail, because of the throw_count flag.
- A workaround for a compilation problem in OTL/ORA8/8i/9i and #include <fstream.h>. oci.h defines symbol "text", which is either typedef unsigned char, or, sometimes, it is defined as a #define, depending on the platform, and the compiler. OTL introduces a new #define: #define OTL_ORA_TEXT_ON. When it is defined before the OTL header file gets included, OTL redefines the "text" symbol as a locally defined #define text OTL_ORA_TEXT, in order to mask the extrenal "text"symbol in the OTL header file itself. And, at the end of the OTL header file, the locally defined #define text OTL_ORA_TEXT gets undefined, in order to return the compilation the state of before-OTL-was-included. It has been a very annonying problem to some folks throughout the co-existance of the OCI and <fstream.h>. See examples 172, 173 for more detail.
- In a few cases, some folks expressed a need to convert database NULLs into something more C++ readable, besides a random value in the output buffer, even thouh it is a very standard behavior ni systems like Pro*C, Embedded SQL, etc. For example, a string NULL could be converted into "", a numeric NULL could be converted into 0, a DATE/TIME NULL could be a date/time value from a distant past. Under the assumption that NULL gets converted / defaulted to a value, it would be sufficient to check for the value, instead of checking for otl_stream::is_null() == true. In order to satisfy those folks' need, OTL: introduces the following new #defines:

- OTL_DEFAULT_NUMERIC_NULL_TO_VAL
- OTL_DEFAULT_DATETIME_NULL_TO_VAL
- OTL_DEFAULT_STRING_NULL_TO_VAL
- OTL_DEFAULT_CHAR_NULL_TO_VAL

These new #defines can be defined to anything: a constant, a function call, etc., that would make sense at compile time.

This new feature, even though it's generic enough, is not a shortcut for otl_stream::is_null().

For more detail, see examples 169, 170, 171.

- otl_stream::clean() function was extended to "clean" the stream that executes straight SELECT statements (all databases), implicit result sets (e.g. MS SQL Server, Sybase, or DB2 via stored procedures), referenced cursors (Oracle 7, 8, 8i, 9i), before the fetch sequence is exhausted (not all rows are yet fetched, in other words), or in the case of a database error, or any other C++ exception has occurred. Fore more detail, see examples 159-168.

New (in OTL 4.0.5):

- In OTL/ODBC, OTL/DB2-CLI, a new function and a new constructor in otl_connect: rlogon(HENV,HDBC,int),otl_connect(HENV,HDBC,int). It allows the ODBC or DB2-CLI code to be patched with OTL. In other words, if you have a piece of legacy code in straight ODBC, or DB2-CLI, you could use the primary, existing database connection (environment, and database connect handles), in order to instantiate a secondary, OTL connect. More more detail, see examples 157, 158.

New (in OTL 4.0.4):

- This is a maintenance release, which fixes a bug, recently (in 4.0.3) introduced in OTL/ODBC.

New (in OTL 4.0.3):

- This is a maintenance release, which fixes a bug, recently introduced in OTL/ODBC for ODBC 3.x. A return code of a call to ODBC was not checked for errors.

New (in OTL 4.0.2):

- In OTL/OCI8/9, a new function in otl_connect: cancel(). The function allows asynchronous cancellation of any database call, executiing through the otl_connect object. For more detail, see example 156

New (in OTL 4.0.1):

- In OTL/ODBC, and OTL/DB2-CLI, a new function in otl_connect: set_transaction_isolation_level(). It allows the user to set up the following transaction isolation level:

- READ COMMITTED
- READ UNCOMMITTED
- REPEATABLE READ
- SERIALIZABLE

For detail, see examples 154, 155

New (in OTL 4.0.0):

- It is an accumulative release that fixes a number of bugs (e.g. a bug in stream pooling and exceptions), compilation warnings and provides better support for newer compilers like GNU C++ 3.0.x, Forte C++ 6.x (successor of Sun Pro C++), aCC (ANSI C++ for HP UX), as well as xlC 5.x (IBM C++ on AIX).
- Support for Open Source Interbase 6.x via XTG Systems ' Open Source ODBC driver for Interbase. A new #define OTL_ODBC_XTG_IBASE6 was introduced in order to make OTL work correctly with the driver. A number of code examples to illustrate this new feature (133, 134, 135, 136, 137, 138, 139) were added to the list of OTL code examples.
- Support for Open Source PostgreSQL 7.x.x via the PostgreSQL ODBC driver that is also Open Source. A number of code examples to illustrate this new feature (140, 141, 142, 143, 144, 145, 146 ) were added to the list of OTL code examples.
- Better backward compatibility with ODBC 2.5 specification. When ODBCVER is set to 0x0250 (#define ODBCVER 0x0250) , OTL makes ODBC 2.5 compliant calls, instead of assuming that the level of ODBC is greater than or equal to 0x0300. See example 147 for more detail.
- Support for Oracle 9i. A new #define was introduced: #define OTL_ORA9I. Basically, everything that works for OTL_ORAXX, works for OTL_ORA9I, therefore, this new #define should be okay to use with already existing code. Later on, new, Oracle 9i specific features will be introduced under #define OTL_ORA9I. This time, no special examples are need to illustrate the new #define. Any example for OTL/OCI7, OTL/OCI8 can be used with #define OTL_ORA9I.
- Support for a new bind variable type in otl_stream for OCI8/9: :var< refcur,out[XXX]>. It allows the otl_stream to return multiple reference cursors from the same PL/SQL block/stored procedure call. This new type of bind variables allows the user to combine reference cursors with other input/output parameters in a single stored procedure call. See examples 148, 149, 150, 151 for more detail.
- New in otl_stream for OTL/OCI8/9 function: get_stream_type(). The function returns the type of SQL statement, which the stream was instantiated with. See example 152 for more detail.
- New in otl_stream for OTL/OCI8/9 function: create_stored_proc_call(), that automatically creates a stored procedure call with definitions of the procedure's parameters. See example 153, for more detail.
- New function in otl_connect: otl_terminate. This function is static in class and defined only for OTL/OCI8i,9i.
- New #define is introduced: #define OTL_ODBC_SQL_EXTENDED_FETCH_ON. Normally, if ODBC version is set to >= 3.0, SQLFetchScroll is used. However, some ODBC drivers, as well as DB2 CLI in Linux (DB2 in Linux, even in Linux/390), have a bug in SQLFetchScroll, when CLOB/BLOB fields are used. This new #define forces OTL to use SQLExtendedFetch instead, or even SQLFetch, in the case of the stream buffer size of 1.

New (in OTL 3.2.20):

- A fix for problem 62
- A fix for problem 63. Now, OTL throws a new OTL-defined exception with error code 32013.
- A group of new functions was introduced for describing the otl_stream's bind variables:

- describe_in_vars ()
- describe_out_vars ()
- describe_next_in_var ()
- describe_next_out_var ()

For more detail, see examples 130, 131, 132.

New (in OTL 3.2.19):

LOB stream mode, previously implemented in OTL 3.1.14 for OCI8 only, is extented to OTL/ODBC and OTL/DB2 CLI : now, the otl_lob_stream class implements the LOB stream mode for OTL/OCI8, OTL/ODBC, and OTL/DB2-CLI.

Also, a new function in the otl_stream class was introduced in order to support the LOB stream mode: set_lob_stream_mode().

For more detal, see examples 122 , 123, 124, 125, 126, 127 , 128, 129.

- A fix for problem 61

OTL 3.2.18 compared to OTL 3.2.17 has no visible changes. This is a maintenace release. A few changes were made under #define OTL_ACE to use more appropriate containers for better implementation of the otl_stream pooling. |
New (in OTL 3.2.17):

- New #define OTL_STLPORT was inroduced in order to fix problems 60 . Briefly, OTL_STLPORT can be used whenever OTL_STL is used, except for otl_output_iterator, otl_input_iterator .
- New #define OTL_VALUE_TEMPLATE_ON was introduced in order to make the otl_value<T> class available without turning #define OTL_STL on. Fore more detail, see examples 119 , 120,121
- New #define OTL_USER_DEFINED_STRING_CLASS_ON was introduced for specifying a string class name for reading from / writing to the otl_streamm other than STL's std::string. This feature is useful for specifynig (1) a third-party string class other than std::string, or, specifying (2) std::string class without turning on #define OTL_STL.

(1) makes sense for multi-threaded, scalable application, when a more efficient [than std::string] string class is required. For example, a string class without string reference counters, and any internal locking, with a more optimal string memory allocator.

(2) makes sense for cases when it would be nice to have operators <<(otl_stream&,...) and >>(otl_stream&,...) defined for a third-party string class, or even for std::string without turning on #define OTL_STL, since not all C++ compilers compile OTL successfully with OTL_STL on.

Fore more detail, see examples 119 , 120, 121

- New #define OTL_ACE was inroduced as an effort to integrate OTL with ACE. More precisely, STL-like features of OTL (string class in otl_stream operations, OTL_STREAM_POOLING, based on STL containers, etc.). In case with ACE, when OTL_ACE is defined, OTL_STERAM_POOLING is implemented on top of ACE's Array and Hasp_Map classes. The string class for otl_stream's operations is ACE_TString.

New (in OTL 3.2.16):

- Problems 57, 58, 59 are fixed.

New (in OTL 3.2.15):

- Problems 52, 54, 55 are fixed.
- As a fix to problem 53 , a new otl_stream function was introduced: otl_stream:: set_flush(). See also examples 116, 117,118.

New (in OTL 3.2.14):

- Problems 50, 51 are fixed.
- A new mechanism was implemented: otl_stream pooling. In order to activate it, a new #define and a function were introduced: #define OTL_STREAM_POOLING_ON, otl_connect:: set_stream_pool_size(). otl_stream:: close() was also extended with an extra parameter. For more detail, examples 113,114 , 115.

New (in OTL 3.2.13):

- Problem 45 is fixed.
- Problem 46 is fixed. A new #define was introduced to enable the fix / feature: OTL_UNCAUGHT_EXCEPTION_ON. For more detail, see examples 101, 102, 103 , and read the description of the problem 46 more carefully.
- Problem 47 is fixed. A new #define OTL_EXTENDED_EXCEPTION was introduced to enable the otl_exception's extended fields for OTL/ODBC and OTL/DB2-CLI. See also example 104.
- Problem 48 is fixed. See also example 105. If MS SQL Server is being accessed from Linux via a ODBC-to-ODBC brigde, the corresponding ODBC driver on the Linux side should be compliant with ODBC 3.5. Otherwise, support of GUIDs will not be enabled, and the result of running the example 105 will be unpredictable.
- Problem 49 is fixed. See also examples 106, 107 , 108, 109 . This actually is a new feature in OTL/ODBC and in OTL/DB2-CLI: bulk operations with LOB data types (LONG, LONG RAW, CLOB, BLOB, TEXT, IMAGE, etc.). Keep in mind, when writing portable code, that this feature is NOT compatible with with OTL/OCIx.
- New otl_stream::set_all_column_types () function, which allows to override the default mapping of column groups in SELECT otl_stream's. For example: map all numeric columns to strings, map all date columns to strings, or the combination of both.This feature provides a handier interface in case of large numbers or date-to-string handling, when the structure of the SELECT statement is unknown in advance.
See also example 110, 111, 112.

New (in OTL 3.2.12): problem 44 is fixed.Also it was reported that, in fact, problem 39 was resolved for at least DB2 7.x, xlC/Visual Age 5, in AIX. |
New (in OTL 3.2.11): problem 43 is fixed. No other changes. |
New (in OTL 3.2.10): problem 42 is fixed. The following new #define is introduced: #define OTL_STL_NOSTD_NAMESPACE. I didn't create any code samples for this. Here's how to use this new #define with aCC and #define OTL_STL: ... #define OTL_STL #define OTL_STL_NOSTD_NAMESPACE |
New (in OTL 3.2.9):

- This release fixes problem 40, that was introduced in OTL 3.2.8.
- This release also fixes problem 41. ANSI C++ standard deprecates using the keyword static as a means of forcing the scope of a function to be the current compilation module and it is recommended that unnamed namespaces be used instead.

New (in OTL 3.2.8):

- by requests from some users, otl_connect:: auto_commit_on() and otl_connect:: auto_commit_off() are back. These functions used to be in the old OTL (1.x, 2.x) and were removed in OTL 3.0. I've put them back for partial backward compatibility. However, I do NOT encourage anybody to use them because it's a bad practice.
- new template class otl_value. It integrates the scalar value container and the NULL indicator functionality in one template class. For more detail, see examples 97, 98, 99, 100.
- Problems 36, 37, 38 are fixed in this release of OTL.

New (in OTL 3.2.7). A new database backend is supported: DB2 with its native Call Level Interface (CLI) in Windows and Unix platforms. Basically, a new OTL-adaptor (OTL/DB2-CLI) was developed for DB2-CLI. Respectively, a new #define was introduced for the new OTL-adaptor: #define OTL_DB2_CLI. OTL/DB2-CLI uses both DB2-CLI's native header files and DB2-CLI's native object libaries.

Besides the OTL_DB2_CLI macro definition, another #define was introduced: OTL_EXPLICIT_NAMESPACES . It allows to overide OTL's default namespace generation: if one OTL-adaptor is enabled than no namespaces are generated, more than one -- namespaces are generated (oracle::, odbc::, db2::).

Under OTL_EXPLICIT_NAMESPACES, the namespaces always get generated.

Two new datatypes for declaring bind variables were introduced: db2time, db2date. They are required when a DB2 DATE or DB2 TIME column is used, respectively. db2time/db2date should be used with both OTL/DB2-CLI and OTL/ODBC for DB2.

This is the only thing that makes DB2 different from other ODBC data sources (e.g. MS SQL Server, Sybase, Oracle, MySQL).

The question is: Why OTL/DB2-CLI is released as OTL 3.2.7, rather than OTL 3.3.0?

On the one hand, acquiring a new database / writing a new OTL-adaptors has become a routine procedure. On the other hand, the fact that DB2's Call Level Interface (CLI) is based on the ODBC 3.0 specification plus extentions, made the task easy, and, OTL/DB2-CLI is not much different from OTL/ODBC.

In the core, it's still the same OTL-adaptor, with a couple of things, controlled by conditional compilation.

Bottom line: the OTL header file has grown only a few more kilobytes bigger, but it now supports such a new major player database as DB2.

For more detail, see examples for DB2 Call Level Interface (CLI)

In OTL 3.2.6, a couple of fixes have been made. | See problems #34, # 35 for more detail.
New (in OTL 3.2.5): STL vector based containers for PL/SQL tables (OCIx). The containers relax all possible requirements on sizes/dimensions. Instead of C-style null terminated character arrays, vectors of std::strings are supported, as well as vectors of otl_datetime, and a number of numeric vectors.

Briefly, OTL 3.2.5 is an evolutionary step toward a better handling of PL/SQL tables from C++. The interface is pretty much the same as the static or dynamic containers for PL/SQL tables, with the exception of being STL-vector based.

For more detail, see examples 85,86, 87, 88.
New (in OTL 3.2.4): OTL/ODBC supports MySQL (the Open Source SQL database server) via [the new] #define OTL_ODBC_MYSQL in the Windows platforms. Also, combined with #define OTL_ODBC_UNIX and the Open Source library, called UnixODBC, OTL/ODBC for MySQL can be used in the Linux platform. | MySQL as a new supported [by OTL] SQL database extends the series of databases, covered by the OTL umbrella. This makes it possible to write even more [than ever before] portable code, without any significant degradation in performance and readability.

For more detail, see MyODBC for MySQL

New (in OTL 3.2.3): OTL compiles clean (without annoying compiler warnings) with the KAI C++ compiler. | I was told that KAI C++ is a more solid, better, bug free C++ compiler than many others.
New (in OTL 3.2.2): "Default user"/"extrenal" authentication now works correctly in OTL/OCI8: db.rlogon("/") gets parsed as a special case and works okay with OTL/OCI8 | I missed the fact that in OCI8 "default user" authentication is done in a different way compared to OCI7. The assumption was that it was backward compatible at the level of OCI.
New (in OTL 3.2.1):

1. New #define OTL_ODBC_UNIX. It allows OTL/ODBC to be used with ODBC bridges in Unix.
2. OTL/ODBC: in order to get the row processed count, calls to SQLGetDiagField() were replaced with calls to SQLRowCount().
3. OTL/ODBC: in SQLSetConnectAttr(..., SQL_ATTR_AUTOCOMMIT, ..., SQL_NTS), SQL_NTSwasreplaced with SQL_IS_POINTER.
4. OTL/OCI7: in calls to oparse(), the enforcement of strict compliance with Oracle 6 was relaxed.

1. I didn't create any new examples on this. OTL/ODBC examples can be used.
2. This was done to streamline the use of ODBC functions. At least, it allowed to extend the list of ODBC drivers which OTL/ODBC doesn't crash.
3. This doesn't crash any ODBC drivers, that were known to be working with OTL/ODBC before, but this change allows the list of ODBC drivers that don't crash under OTL/ODBC to be extended , e.g. the ODBC driver for MS Access works fine. I've not identified the versions of MS Access ODBC drivers which OTL/ODBC fails.
4. It's about time, isn't it? I mean that Oracle 6 has been history for a long time and Oracle 7 is going down the same path (will be discontinued relatively soon).

This relaxation in the OCI7 bevahior allows OCI7 calls to be linked and successfully used with OCI8 libraries.

New (in OTL 3.2.0):

1. Support of the STL reading/writing std::string's from/to otl_stream's. This feature can be turned on with #define OTL_STL.
2. STL-compliant OTL stream iterators : otl_input_iterator, otl_output_iterators. The iterators are supposed to work with all versions of the STL, which are commercially or freely available for a variety of C++ compilers. This feature can be turned on with #define OTL_STL.
3. ANSI C++ typecasts are supported. This feature can be turned on with #define OTL_ANSI_CPP.

1. For more detail on std::string's, see also example 72, 73, 74
2. For more detail on the OTL/STL iterators, see also example 75, 76, 77
3. For more detail on #define OTL_ANSI_CPP, see also example 72, 73,74, 75, 76, 77.

Continued on page 2

Go Home

Copyright © 1996, 2007, Sergei Kuchin, email: skuchin@ispwest.com, skuchin@gmail.com
.

Permission to use, copy, modify and redistribute this document for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies.