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

    What's New


    Feature Comment
    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