• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

ocipl.h

Go to the documentation of this file.
00001 
00002  //
00003  // ocipl.h
00004  //
00005  // Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014, 2017 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007  // OCIPL Version 1.8
00008  //
00009 
00010  /// \file ocipl.h
00011  /// OCIPL header file
00012 
00013 
00014 /*
00015 
00016   All rights reserved.
00017 
00018   Redistribution and use in source and binary forms, with or without
00019   modification, are permitted provided that the following conditions are met:
00020 
00021   * Redistributions of source code must retain the above copyright
00022     notice, this list of conditions and the following disclaimer.
00023   * Redistributions in binary form must reproduce the above copyright
00024     notice, this list of conditions and the following disclaimer in
00025     the documentation and/or other materials provided with the
00026     distribution.
00027 
00028   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00029   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00030   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00031   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00032   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00033   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00034   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00035   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00036   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00037   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00038   POSSIBILITY OF SUCH DAMAGE.
00039 
00040 */
00041 
00042 #ifndef _OCIPL_H
00043 
00044 
00045 #ifdef UNICODE
00046 #ifndef _UNICODE
00047 #define _UNICODE
00048 #endif
00049 #else
00050 #ifdef _UNICODE
00051 #define UNICODE
00052 #endif
00053 #endif
00054 
00055 #ifdef _WIN32
00056 #define WIN32_LEAN_AND_MEAN
00057 #include <windows.h>
00058 #else
00059 #define TCHAR char
00060 #endif
00061 
00062 #ifdef _MSC_VER
00063 #pragma warning(disable: 4786)
00064 #else
00065 #define LONGLONG long long
00066 #endif
00067 
00068 
00069  // secure CRT functions
00070 #ifdef __STDC_WANT_SECURE_LIB__
00071 
00072 #ifndef _stprintf_s1
00073 #define _stprintf_s1 sprintf_s
00074 #endif
00075 
00076 #else
00077 
00078 #ifndef strcpy_s
00079 #define strcpy_s(d, l, s) strcpy(d, s)
00080 #endif
00081 
00082 #ifndef _strupr_s
00083 #define _strupr_s(b, s) strupr(b)
00084 #endif
00085 
00086 #ifndef _tcscpy_s
00087 #define _tcscpy_s(d, l, s) _tcscpy(d, s)
00088 #endif
00089 
00090 #ifndef _tcsupr_s
00091 #define _tcsupr_s(b, s) _tcsupr(b)
00092 #endif
00093 
00094 #ifndef _stprintf_s1
00095 #define _stprintf_s1(b, l, f, p1) ((b)+(l),_stprintf(b, f, p1))
00096 #endif
00097 
00098 #endif // __STDC_WANT_SECURE_LIB__
00099 
00100 
00101 #if _MSC_VER>=1400
00102 #ifndef _CRT_SECURE_NO_DEPRECATE
00103 #define __STDC_WANT_SECURE_LIB__    1
00104 #endif
00105 
00106 #ifndef COUNTOF
00107 #define COUNTOF _countof
00108 #endif
00109 
00110 #else // _MSC_VER>=1400
00111 
00112 #ifndef COUNTOF
00113 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
00114 #define _countof COUNTOF
00115 #endif
00116 
00117 #endif
00118 
00119 
00120 #include <map>
00121 #include <set>
00122 #include <string>
00123 #include <vector>
00124 #include <ostream>
00125 #include <sstream>
00126 #include <exception>
00127 
00128 #ifndef min
00129 #define min(a,b) ((a)<(b)?(a):(b))
00130 #endif
00131 
00132 
00133 #undef SQL_SUCCESS
00134 #undef SQL_ERROR
00135 
00136 #define iterator __iterator_
00137 #if !__STDC__
00138 #define __STDC__ 1  // for Oracle 8.0 header files
00139 #endif
00140 #include <oci.h>
00141 #undef iterator
00142 
00143  // determine OCI version from available constants
00144 #ifndef ORACLE_VERSION
00145 #ifdef OCI_MAJOR_VERSION    // OCI_MAJOR_VERSION/OCI_MINOR_VERSION is only available since Oracle 10.
00146 #define ORACLE_VERSION  (10*OCI_MAJOR_VERSION+OCI_MINOR_VERSION)
00147 #else
00148 #if OCI_HTYPE_LAST>=29
00149 #define ORACLE_VERSION  102 // Oracle 10g2
00150 #elif OCI_HTYPE_LAST>=27
00151 #define ORACLE_VERSION  92  // Oracle 9i2
00152 #elif OCI_HTYPE_LAST>=18
00153 #define ORACLE_VERSION  82  // Oracle 8.1.6/7
00154 #elif OCI_HTYPE_LAST>=17
00155 #define ORACLE_VERSION  81  // Oracle 8.1.5
00156 #else
00157 #define ORACLE_VERSION  80  // Oracle 8.0.x
00158 #endif
00159 #endif // OCI_MAJOR_VERSION
00160 #endif
00161 
00162 
00163  // Unicode support
00164 #ifdef _WIN32
00165 
00166 #include <tchar.h>
00167 
00168 #else // _WIN32
00169 
00170 #include <wchar.h>
00171 #ifndef UNICODE
00172 #define TEXT(x) x
00173 #endif
00174 
00175 #endif // _WIN32
00176 
00177 #ifdef UNICODE
00178 typedef utext TOraText;
00179 typedef std::wstring tstring;
00180 typedef std::wstringbuf tstringbuf;
00181 typedef std::wostringstream tostringstream;
00182 typedef std::wistream tistream;
00183 typedef std::wostream tostream;
00184 #else
00185 typedef OraText TOraText;
00186 typedef std::string tstring;
00187 typedef std::stringbuf tstringbuf;
00188 typedef std::ostringstream tostringstream;
00189 typedef std::istream tistream;
00190 typedef std::ostream tostream;
00191 #endif
00192 
00193 
00194 #ifndef _MSC_VER
00195 
00196 #ifndef UNICODE
00197 #define _stprintf sprintf
00198 #define _tcscmp strcmp
00199 #define _tcscpy strcpy
00200 #define _tcsdup _strdup
00201 #define _tcslen strlen
00202 #define _tcsnicmp strncasecmp
00203 #define _tcsupr strupr
00204 #define _tcspbrk strpbrk
00205 #endif
00206 
00207 #ifndef _strdup
00208 #define _strdup strdup
00209 #endif
00210 
00211 #ifndef _snprintf
00212 #define _snprintf snprintf
00213 #endif
00214 
00215 extern char* strupr(char*);
00216 
00217 #endif // _MSC_VER
00218 
00219 
00220 #ifdef _MSC_VER
00221 #include <minmax.h>
00222 
00223 #ifndef OCIPL_NO_COMMENT
00224 #pragma comment(lib, "oci")
00225 
00226 #if defined(_DEBUG) && defined(_DLL)    // DEBUG version only supported with MSVCRTD
00227 #if _MSC_VER==1600
00228 #pragma comment(lib, "ocipl-vc10d.lib")
00229 #elif _MSC_VER==1400
00230 #pragma comment(lib, "ocipl-vc8d.lib")
00231 #else
00232 #pragma comment(lib, "ocipl-vc6d.lib")
00233 #endif
00234 #else
00235 #ifdef _DLL
00236 #if _MSC_VER==1600
00237 #pragma comment(lib, "ocipl-vc10")
00238 #elif _MSC_VER==1400
00239 #pragma comment(lib, "ocipl-vc8")
00240 #else
00241 #pragma comment(lib, "ocipl-vc6")
00242 #endif
00243 #elif defined(_MT)
00244 #if _MSC_VER==1600
00245 #pragma comment(lib, "ocipl-vc10t")
00246 #elif _MSC_VER==1400
00247 #pragma comment(lib, "ocipl-vc8t")
00248 #else
00249 #pragma comment(lib, "ocipl-vc6t")
00250 #endif
00251 #else
00252  // -ML is no more supported by VS2005.
00253 #pragma comment(lib, "ocipl-vc6l")
00254 #endif
00255 #endif
00256 
00257 #endif // OCIPL_NO_COMMENT
00258 #endif // _MSC_VER
00259 
00260 
00261 //#include <assert.h>
00262 
00263 #ifdef OCIPL_ALLOC_EXT
00264  // extern allocation functions
00265 extern void* ocipl_alloc(size_t);
00266 extern void* ocipl_realloc(void* p, size_t l);
00267 extern void ocipl_free(void*);
00268 #else
00269  // use stdlib allocation
00270 #define ocipl_alloc malloc
00271 #define ocipl_realloc realloc
00272 #define ocipl_free free
00273 #endif
00274 
00275 extern size_t max_strlen(const char* s, size_t max_len);
00276 extern char* max_strdup(const char* s, size_t max_len);
00277 
00278 
00279 namespace OCIPL {
00280 
00281 
00282  // default bulk fetch size
00283 extern int g_OCIPL_BULK_ROWS;
00284 
00285  // default string buffer size
00286 #define OCIPL_DEFAULT_STRING_BUFFER 2000
00287 
00288 
00289 #ifndef istspace
00290 inline int istspace(TCHAR c)
00291 {
00292 #ifdef UNICODE
00293     return _istspace((unsigned short)c);
00294 #else
00295     return isspace((unsigned char)c);
00296 #endif
00297 }
00298 #endif
00299 
00300 
00301 struct SqlStatement;
00302 
00303  /// OCI Error handling
00304 struct OciException : public std::exception
00305 {
00306     typedef std::exception super;
00307 
00308     OciException(OCIEnv* envh, const char* file, int line);
00309     OciException(OCIError* errh, const char* file, int line);
00310     OciException(const char* msg, const char* file, int line);
00311     OciException(OCIError* errh, SqlStatement& stmt, const char* file, int line);
00312     OciException(const OciException&);
00313 
00314     ~OciException() throw();
00315 
00316      // return exception message text
00317     virtual const char* what() const throw()
00318     {
00319         return _msg;
00320     }
00321 
00322     int _sql_error_code;
00323     char*       _msg;
00324     const char* _file;
00325     int         _line;
00326     tstring     _last_sql;
00327     ub2 _parse_offset;
00328 };
00329 
00330  // some common Oracle error codes
00331 #define SQLCODE_DUPLICATE_KEY   1
00332 #define SQLCODE_NO_DATA_FOUND   1403
00333 #define SQLCODE_TOO_MANY_ROWS   1422
00334 
00335 
00336 enum OCI_STATE {
00337     OS_NONE,
00338     OS_PREPARE,
00339     OS_RELEASE,
00340     OS_EXECUTE,
00341     OS_FETCH,
00342     OS_TRANSACTION
00343 };
00344 
00345 
00346  /// error handling functions
00347 
00348 struct OciEnv;
00349 
00350 extern void throw_oci_exception(OCIError* errh, sword res);
00351 extern void throw_oci_exception(OCIEnv* envh, sword res);
00352 
00353 void oci_check_error(OCIError* errh, sword res);
00354 void oci_check_error(OCIEnv* envh, sword res);
00355 void oci_check_error(OciEnv& env, sword res);
00356 
00357 #define CODEPOS __FILE__, __LINE__
00358 
00359  // throw the given exception
00360 #ifdef _MSC_VER
00361 __declspec(noreturn)
00362 #endif
00363 void throw_ocipl_exception(OciException e);
00364 
00365  // macro to call throw_ocipl_exception()
00366 #define THROW_OCI_EXCEPTION(par) throw_ocipl_exception(OCIPL::OciException(par, CODEPOS))
00367 
00368 
00369  /// mapping between OCI handle types and the corresponding type and attribute constants
00370 
00371 template<typename TYPE>
00372   struct OciHandleID
00373 {
00374     static ub4 get_type_id();
00375     static ub4 get_attr_id();
00376 };
00377 
00378 inline ub4 OciHandleID<OCIEnv>::get_type_id()           {return OCI_HTYPE_ENV;}
00379 inline ub4 OciHandleID<OCIError>::get_type_id()         {return OCI_HTYPE_ERROR;}
00380 inline ub4 OciHandleID<OCISvcCtx>::get_type_id()        {return OCI_HTYPE_SVCCTX;}
00381 inline ub4 OciHandleID<OCIStmt>::get_type_id()          {return OCI_HTYPE_STMT;}
00382 inline ub4 OciHandleID<OCIBind>::get_type_id()          {return OCI_HTYPE_BIND;}
00383 inline ub4 OciHandleID<OCIDefine>::get_type_id()        {return OCI_HTYPE_DEFINE;}
00384 inline ub4 OciHandleID<OCIDescribe>::get_type_id()      {return OCI_HTYPE_DESCRIBE;}
00385 inline ub4 OciHandleID<OCIServer>::get_type_id()        {return OCI_HTYPE_SERVER;}
00386 inline ub4 OciHandleID<OCISession>::get_type_id()       {return OCI_HTYPE_SESSION;}
00387 inline ub4 OciHandleID<OCITrans>::get_type_id()         {return OCI_HTYPE_TRANS;}
00388 inline ub4 OciHandleID<OCIComplexObject>::get_type_id() {return OCI_HTYPE_COMPLEXOBJECT;}
00389 inline ub4 OciHandleID<OCISecurity>::get_type_id()      {return OCI_HTYPE_SECURITY;}
00390 #if ORACLE_VERSION>=81
00391 inline ub4 OciHandleID<OCISubscription>::get_type_id()  {return OCI_HTYPE_SUBSCRIPTION;}
00392 #endif
00393 /*
00394 inline ub4 OciHandleID<>::get_type_id() {return OCI_HTYPE_DIRPATH_CTX;}
00395 inline ub4 OciHandleID<>::get_type_id() {return OCI_HTYPE_DIRPATH_COLUMN_ARRAY;}
00396 inline ub4 OciHandleID<>::get_type_id() {return OCI_HTYPE_DIRPATH_STREAM;}
00397 inline ub4 OciHandleID<>::get_type_id() {return OCI_HTYPE_PROC;}
00398 */
00399 
00400 inline ub4 OciHandleID<OCIServer>::get_attr_id()        {return OCI_ATTR_SERVER;}
00401 inline ub4 OciHandleID<OCISession>::get_attr_id()       {return OCI_ATTR_SESSION;}
00402 
00403 
00404  /// "simple" OCI handles without OciEnv
00405 
00406 template<typename TYPE>
00407   struct OciSimpleHandle : public OciHandleID<TYPE>
00408 {
00409     typedef OciHandleID<TYPE> super;
00410     typedef TYPE HandleType;
00411 
00412      // default constructor without handle allocation
00413     OciSimpleHandle()
00414      : _handle(0), _envh(0)
00415     {
00416     }
00417 
00418      // contructor consuming the given handle
00419     OciSimpleHandle(OCIEnv* envh, HandleType* handle)
00420      : _envh(envh), _handle(handle)
00421     {
00422     }
00423 
00424      // constructor allocating a new handle of the type TYPE
00425     OciSimpleHandle(OCIEnv* envh)
00426      : _handle(0)
00427     {
00428         alloc(envh);
00429     }
00430 
00431      // The destructor destroys the attached OCI handle.
00432     ~OciSimpleHandle()
00433     {
00434         if (_handle)
00435             destroy();
00436     }
00437 
00438      // return the managed OCI handle
00439     operator HandleType*()
00440     {
00441         return _handle;
00442     }
00443 
00444      // allocate a new handle of the type TYPE
00445     void alloc(OCIEnv* envh)
00446     {
00447          // If we already manage a handle, free it.
00448         if (_handle)
00449             destroy();
00450 
00451         _envh = envh;
00452 
00453         sword res = OCIHandleAlloc(envh, (dvoid**)&_handle, super::get_type_id(), 0, 0);
00454         oci_check_error(envh, res);
00455     }
00456 
00457      // free the attached handle
00458     void destroy()
00459     {
00460         sword res = OCIHandleFree(_handle, super::get_type_id());
00461         _handle = 0;
00462 
00463         if (_envh) {
00464             oci_check_error(_envh, res);
00465             _envh = 0;
00466         }
00467     }
00468 
00469      // return the given attrtype of the attached OCI handle into *attributep
00470     void get_attribute(dvoid* attributep, ub4* sizep, ub4 attrtype, OCIError* errh)
00471     {
00472         sword res = OCIAttrGet(_handle, super::get_type_id(), attributep, sizep, attrtype, errh);
00473         oci_check_error(_envh, res);
00474     }
00475 
00476 protected:
00477     HandleType* _handle;// wrapped OCI handle
00478     OCIEnv*     _envh;  // OCI environment
00479 };
00480 
00481 
00482  /// wrapping of already existing OCI handles without freeing them in destructor
00483 
00484 template<typename TYPE>
00485   struct OciHandleWrapper : public OciHandleID<TYPE>
00486 {
00487     typedef TYPE HandleType;
00488 
00489      // create a wrapper object from the given handle
00490     OciHandleWrapper(HandleType* handle)
00491      :  _handle(handle)
00492     {
00493     }
00494 
00495      // return the managed OCI handle
00496     operator HandleType*()
00497     {
00498         return _handle;
00499     }
00500 
00501 protected:
00502     HandleType* _handle;
00503 };
00504 
00505 
00506  /// OCI Error Handles
00507 typedef OciSimpleHandle<OCIError> OciError;
00508 
00509 
00510  /// OCI Describe Handles
00511 typedef OciSimpleHandle<OCIDescribe> OciDescribe;
00512 
00513 
00514  /// OCI environment handles
00515 
00516 struct OciEnv : public OciHandleWrapper<OCIEnv>
00517 {
00518     typedef OciHandleWrapper<OCIEnv> super;
00519 
00520     OciEnv(OCIEnv* envh)
00521      :  super(envh)
00522     {
00523          // allocate error handle
00524         _errh.alloc(_handle);
00525     }
00526 
00527     OciError    _errh;  // error handle
00528 };
00529 
00530 
00531  /// wrapper for the OCIEnv handle
00532 
00533 struct OciEnvAlloc : public OciSimpleHandle<OCIEnv>
00534 {
00535     typedef OciSimpleHandle<OCIEnv> super;
00536 
00537      // constructor allocating a new environemnt handle
00538     OciEnvAlloc(ub4 oci_mode=OCI_OBJECT)    // OCI_OBJECT for OCINumber... functions
00539     {
00540 #if ORACLE_VERSION>=81
00541 #ifdef UNICODE
00542         sword res = OCIEnvNlsCreate(&_handle, oci_mode, 0/*ctxp*/, 0, 0, 0, 0/*xtramem_sz*/, 0/*usrmempp*/, OCI_UTF16ID, OCI_UTF16ID);
00543 #else
00544         sword res = OCIEnvCreate(&_handle, oci_mode, 0/*ctxp*/, 0, 0, 0, 0/*xtramem_sz*/, 0/*usrmempp*/);
00545 #endif
00546         //oci_check_error(res);
00547 #else
00548         sword res = OCIInitialize(oci_mode, 0/*ctxp*/, 0, 0, 0);
00549         //oci_check_error(res);
00550 
00551         OCIEnvInit(&_handle, OCI_DEFAULT, (size_t)0, (dvoid **) 0);
00552 #endif
00553     }
00554 };
00555 
00556 
00557  /// OCI handles
00558 
00559 template<typename TYPE>
00560   struct OciHandle : public OciHandleID<TYPE>
00561 {
00562     typedef OciHandleID<TYPE> super;
00563     typedef TYPE HandleType;
00564 
00565      // constructor without handle allocation
00566     OciHandle(OciEnv& env)
00567      :  _env(env),
00568         _handle(0)
00569     {
00570         alloc();
00571     }
00572 
00573      // contructor consuming the given handle
00574     OciHandle(OciEnv& env, HandleType* handle)
00575      :  _env(env),
00576         _handle(handle)
00577     {
00578     }
00579 
00580      // copy constructor to transfer handle ownership
00581     OciHandle(const OciHandle& other)
00582      :  _env(other._env),
00583         _handle(other._handle)
00584     {
00585         other._handle = NULL;
00586     }
00587 
00588      // The destructor destroys the attached OCI handle.
00589     ~OciHandle()
00590     {
00591         if (_handle)
00592             destroy();
00593     }
00594 
00595      // allocate a new handle of the type TYPE
00596     void alloc()
00597     {
00598         if (_handle)
00599             destroy();
00600 
00601         sword res = OCIHandleAlloc(_env, (dvoid**)&_handle, super::get_type_id(), 0, 0);
00602         oci_check_error(_env, res);
00603     }
00604 
00605      // free the attached handle
00606     void destroy()
00607     {
00608         sword res = OCIHandleFree(_handle, super::get_type_id());
00609         _handle = 0;
00610 
00611         oci_check_error(_env, res);
00612     }
00613 
00614      // set an handle attribute to the given string
00615     void set_attribute(ub4 attrtype, const tstring& str)
00616     {
00617         sword res = OCIAttrSet(_handle, super::get_type_id(), (TOraText*)str.c_str(), (ub4)str.length()*sizeof(TOraText), attrtype, _env._errh);
00618         oci_check_error(_env, res);
00619     }
00620 
00621      // set an handle attribute to the given numeric value
00622     void set_attribute(ub4 attrtype, ub4 value)
00623     {
00624         sword res = OCIAttrSet(_handle, super::get_type_id(), (OraText*)&value, (ub4)sizeof(value), attrtype, _env._errh);
00625         oci_check_error(_env, res);
00626     }
00627 
00628      // return the given attrtype of the attached OCI handle into *attributep
00629     void get_attribute(dvoid* attributep, ub4* sizep, ub4 attrtype)
00630     {
00631         sword res = OCIAttrGet(_handle, super::get_type_id(), attributep, sizep, attrtype, _env._errh);
00632         oci_check_error(_env, res);
00633     }
00634 
00635      // set an handle attribute to the given handle value
00636     void set_attribute_handle(ub4 attrtype, void* handle)
00637     {
00638         sword res = OCIAttrSet(_handle, super::get_type_id(), handle, 0, attrtype, _env._errh);
00639         oci_check_error(_env, res);
00640     }
00641 
00642      // set an handle attribute to the given handle value
00643     template<typename ATTR> void set_attribute(ATTR& attr)
00644     {
00645         sword res = OCIAttrSet(_handle, super::get_type_id(), attr, 0, ATTR::get_attr_id(), _env._errh);
00646         oci_check_error(_env, res);
00647     }
00648 
00649      // return the managed OCI handle
00650     operator HandleType*()
00651     {
00652         return _handle;
00653     }
00654 
00655 protected:
00656     HandleType* _handle;
00657 
00658 public:
00659     OciEnv&     _env;   // OCI environment
00660 };
00661 
00662 
00663  /// OCI descriptor handles
00664 
00665 template<typename TYPE>
00666   struct OciDescriptor : public OciHandleID<TYPE>
00667 {
00668     typedef OciHandleID<TYPE> super;
00669     typedef TYPE HandleType;
00670 
00671      // constructor without handle allocation
00672     OciDescriptor(OciEnv& env)
00673      : _env(env), _handle(0)
00674     {
00675     }
00676 
00677      // contructor consuming the given descriptor handle
00678     OciDescriptor(OciEnv& env, HandleType* handle)
00679      : _env(env), _handle(handle)
00680     {
00681     }
00682 
00683      // The destructor destroys the attached OCI descriptor handle.
00684     ~OciDescriptor()
00685     {
00686         if (_handle)
00687             destroy();
00688     }
00689 
00690      // return the managed OCI descriptor handle
00691     operator HandleType*()
00692     {
00693         return _handle;
00694     }
00695 
00696      // free the attached descriptor handle
00697     void destroy()
00698     {
00699         sword res = OCIDescriptorFree(_handle, super::get_type_id());
00700         _handle = 0;
00701 
00702         oci_check_error(_env, res);
00703     }
00704 
00705      // return the given attrtype of the attached OCI handle into *attributep
00706     void get_attribute(dvoid* attributep, ub4* sizep, ub4 attrtype)
00707     {
00708         sword res = OCIAttrGet(_handle, super::get_type_id(), attributep, sizep, attrtype, _env._errh);
00709         oci_check_error(_env, res);
00710     }
00711 
00712 protected:
00713     HandleType* _handle;// wrapped OCI handle
00714     OciEnv&     _env;   // OCI environment
00715 };
00716 
00717 
00718 inline ub4 OciHandleID<OCIParam>::get_type_id()         {return OCI_DTYPE_PARAM;}
00719 
00720 typedef OciDescriptor<OCIParam> OciParam;
00721 
00722 
00723  // check error result and report using an exception
00724 inline void oci_check_error(OCIError* errh, sword res)
00725 {
00726     if (res != OCI_SUCCESS)
00727         throw_oci_exception(errh, res); // doesn't throw an exception for res==OCI_SUCCESS_WITH_INFO
00728 }
00729 
00730  // check error result and report using an exception
00731 inline void oci_check_error(OCIEnv* envh, sword res)
00732 {
00733     if (res != OCI_SUCCESS)
00734         throw_oci_exception(envh, res); // doesn't throw an exception for res==OCI_SUCCESS_WITH_INFO
00735 }
00736 
00737  // check error result and report using an exception
00738 inline void oci_check_error(OciEnv& env, sword res)
00739 {
00740     oci_check_error(env._errh, res);    // doesn't throw an exception for res==OCI_SUCCESS_WITH_INFO
00741 }
00742 
00743 
00744 #if ORACLE_VERSION>=81
00745 
00746  /// reading of Oracle message files
00747 
00748 struct OciMessageFile   // needs initialization in OCI_OBJECT mode
00749 {
00750      // initialize OciMessageFile with product and facility
00751     OciMessageFile(OciEnv& env, const TCHAR* product, const TCHAR* facility)
00752      : _env(env), _msgh(0)
00753     {
00754         open(product, facility);
00755     }
00756 
00757      // free the attached message file handle
00758     ~OciMessageFile()
00759     {
00760         if (_msgh)
00761             close();
00762     }
00763 
00764      // return the managed message file handle
00765     operator OCIMsg*()
00766     {
00767         return _msgh;
00768     }
00769 
00770      // open message file for the given product and facility
00771     void open(const TCHAR* product, const TCHAR* facility, OCIDuration dur=OCI_DURATION_PROCESS)
00772     {
00773         sword res = OCIMessageOpen(_env, _env._errh, &_msgh, (OraText*)(TOraText*)product, (OraText*)(TOraText*)facility, dur);
00774         oci_check_error(_env._errh, res);
00775     }
00776 
00777      // free the attached message file handle
00778     void close()
00779     {
00780         sword res = OCIMessageClose(_env, _env._errh, _msgh);
00781         oci_check_error(_env._errh, res);
00782 
00783         _msgh = 0;
00784     }
00785 
00786      // return message text for the goven message number
00787     TOraText* get_msg(ub4 msgno) const
00788     {
00789         return (TOraText*)OCIMessageGet(_msgh, msgno, 0, 0);
00790     }
00791 
00792 protected:
00793     OCIMsg*     _msgh;  // message file handle
00794     OciEnv&     _env;   // OCI environment
00795 };
00796 
00797 #endif
00798 
00799 
00800  /// encapsulation of the OCIServer handle, used in OCIPL::OciLogin
00801 
00802 struct OracleServer : public OciHandle<OCIServer>
00803 {
00804     typedef OciHandle<OCIServer> super;
00805 
00806      // create empty OracleServer object
00807     OracleServer(OciEnv& env)
00808      :  super(env)
00809     {
00810 #if ORACLE_VERSION>=82
00811         _version = 0;
00812 #endif
00813         _version_string[0] = '\0';
00814     }
00815 
00816      // The destructor destroys the owned server handle.
00817     ~OracleServer()
00818     {
00819         if (_handle)
00820             detach();
00821     }
00822 
00823      // connect to the Oracle server using the given TNSNAME (only for backward compatibility)
00824     void attach(const tstring& tnsname)
00825     {
00826         sword res = OCIServerAttach(_handle, _env._errh, (OraText*)tnsname.c_str(), (sb4)tnsname.length()*sizeof(TOraText), OCI_DEFAULT);
00827         oci_check_error(_env, res);
00828 
00829 #if ORACLE_VERSION>=82
00830         res = OCIServerRelease(_handle, _env._errh, (OraText*)_version_string, sizeof(_version_string), OCI_HTYPE_SERVER, &_version);
00831 #else
00832         res = OCIServerVersion(_handle, _env._errh, (OraText*)_version_string, sizeof(_version_string), OCI_HTYPE_SERVER);
00833 #endif
00834         oci_check_error(_env, res);
00835     }
00836 
00837      // release the server connection
00838     void detach()
00839     {
00840         sword res = OCIServerDetach(_handle, _env._errh, OCI_DEFAULT);
00841         oci_check_error(_env, res);
00842 
00843 #if ORACLE_VERSION>=82
00844         _version = 0;
00845 #endif
00846         _version_string[0] = '\0';
00847     }
00848 
00849 #if ORACLE_VERSION>=82
00850     ub4     _version;   // numeric version identifier, e.g. 0x9200500
00851 #endif
00852     TCHAR   _version_string[2000];  // version string
00853 };
00854 
00855 
00856  /// database login parameter structure
00857 
00858 struct LoginPara
00859 {
00860     tstring _tnsname;
00861     tstring _username;
00862     tstring _password;
00863     ub4     _mode;      // mode parameter used in OCISessionBegin()
00864 
00865      // empty default constructor
00866     LoginPara()
00867      :  _mode(OCI_DEFAULT)
00868     {
00869     }
00870 
00871      // construct login structure from username, password and TNSNAME
00872     LoginPara(const TCHAR* username, const TCHAR* password, const TCHAR* tnsname)
00873      :  _username(username),
00874         _password(password),
00875         _tnsname(tnsname),
00876         _mode(OCI_DEFAULT)
00877     {
00878     }
00879 
00880      // initialize login structure from an connection string of the form USER/PASSWORD@TNSNAME
00881     void    parse(const TCHAR* conn_str);
00882 };
00883 
00884 
00885 struct OciContext : OciHandleWrapper<OCISvcCtx>
00886 {
00887     typedef OciHandleWrapper<OCISvcCtx> super;
00888 
00889     OciContext(OciEnv& env, OCISvcCtx* ctx)
00890      :  super(ctx),
00891         _state(OS_NONE),
00892         _stmt_type(0),
00893         _trans_cnt(0),
00894         _env(env)
00895     {
00896     }
00897 
00898      // Commit the current transaction.
00899     void commit(ub4 flags=OCI_DEFAULT);
00900 
00901      // Rollback the current transaction.
00902     void rollback(ub4 flags=OCI_DEFAULT);
00903 
00904     void set_state(OCI_STATE state)
00905     {
00906         //assert(_state==OS_NONE);  // problematisch bei gleichzeitigem Zugriff auf die Datenbankverbindung aus mehreren Threads
00907         _state = state;
00908     }
00909 
00910     void set_state(OCI_STATE state, int stmt_type)
00911     {
00912         //assert(_state==OS_NONE);  // problematisch bei gleichzeitigem Zugriff auf die Datenbankverbindung aus mehreren Threads
00913         _state = state;
00914         _stmt_type = stmt_type;
00915 
00916         if (state == OS_EXECUTE)
00917             if ((stmt_type>=OCI_STMT_UPDATE && stmt_type<=OCI_STMT_INSERT) ||
00918                 stmt_type==OCI_STMT_BEGIN || stmt_type==OCI_STMT_DECLARE)
00919                 ++_trans_cnt;
00920     }
00921 
00922     void reset_state()
00923     {
00924         _state = OS_NONE;
00925         _stmt_type = 0;
00926     }
00927 
00928     bool maybe_active_transaction() const
00929     {
00930         return _trans_cnt > 0;
00931     }
00932 
00933     OCI_STATE _state;   // current OCI operation
00934     int _stmt_type;     // current OCI statement type
00935     int _trans_cnt;     // counter for (possibly) transactional operations
00936 
00937 private:
00938     OciEnv& _env;   // OCI environment
00939 };
00940 
00941 
00942  /// simple OCI login to database
00943 
00944 struct OciLogin : public OciHandle<OCISvcCtx>
00945 {
00946     typedef OciHandle<OCISvcCtx> super;
00947 
00948      // constructor without login
00949     OciLogin(OciEnv& env)
00950      :  super(env),
00951         _server(env),
00952         _ctx(env, _handle),
00953         _session(env),
00954         _connected(false)
00955     {
00956     }
00957 
00958      // constructor to login using the given LoginPara struct
00959     OciLogin(OciEnv& env, const LoginPara& login_para)
00960      :  super(env),
00961         _server(env),
00962         _ctx(env, _handle),
00963         _session(env),
00964         _connected(false)
00965     {
00966         connect(login_para);
00967     }
00968 
00969      // constructor to login using name, password and TNSNAME
00970     OciLogin(OciEnv& env, const tstring& username, const tstring& password, const tstring& tnsname, ub4 mode=OCI_DEFAULT)
00971      :  super(env),
00972         _server(env),
00973         _ctx(env, _handle),
00974         _session(env),
00975         _connected(false)
00976     {
00977         connect(username, password, tnsname, mode);
00978     }
00979 
00980      // login using the given LoginPara struct
00981     void connect(const LoginPara& login_para)
00982     {
00983         connect(login_para._username, login_para._password, login_para._tnsname, login_para._mode);
00984     }
00985 
00986      // login using name, password and TNSNAME
00987     void connect(const tstring& username, const tstring& password, const tstring& tnsname, ub4 mode=OCI_DEFAULT)
00988     {
00989          // set server name
00990         _server.attach(tnsname);
00991         _tnsname = tnsname; // store database name for further reference in the application
00992 
00993          // set session parameters
00994         _session.set_attribute(OCI_ATTR_USERNAME, username);
00995         _session.set_attribute(OCI_ATTR_PASSWORD, password);
00996 
00997          // login using _server and _session
00998         set_attribute(_server);
00999 
01000         sword res = OCISessionBegin(_handle, _env._errh, _session, OCI_CRED_RDBMS, mode);
01001 
01002         if (res!=OCI_SUCCESS && res!=OCI_SUCCESS_WITH_INFO) {
01003             _server.detach();
01004             oci_check_error(_env, res);
01005         }
01006 
01007          // look for warning messages ("ORA-28002: the password will expire within ... days")
01008         if (res == OCI_SUCCESS_WITH_INFO) {
01009             TOraText buffer[1024];
01010 
01011             sb4 errorcode;
01012             sword res = OCIErrorGet(_env._errh, 1, NULL, &errorcode, (OraText*)buffer, sizeof(buffer), OCI_HTYPE_ERROR);
01013 
01014             if (res == OCI_SUCCESS)
01015                 _warnings = (const TCHAR*)buffer;
01016         }
01017 
01018         _connected = true;
01019 
01020         set_attribute(_session);
01021 
01022         /* automatically allocate and initialize server and session handles
01023         sword res = OCILogon(_env, _env._errh, &_ctx,
01024                               (TOraText*)username.c_str(), username.length(),
01025                               (TOraText*)password.c_str(), password.length(),
01026                               (TOraText*)tnsname.c_str(), tnsname.length());
01027         oci_check_error(_env, res);
01028         */
01029     }
01030 
01031      // The destructor disconnects from the connected Oracle server.
01032     ~OciLogin()
01033     {
01034         disconnect();
01035     }
01036 
01037      // disconnect from the connected Oracle server
01038     void disconnect()
01039     {
01040         if (_connected) {
01041             /* automatically free server and session handles
01042             sword res = OCILogoff(_svchp, _env._errh);
01043             _svchp = 0;
01044             */
01045             sword res = OCISessionEnd(_handle, _env._errh, _session, OCI_DEFAULT);
01046             oci_check_error(_env, res);
01047 
01048             _server.detach();
01049 
01050             _connected = false;
01051         }
01052     }
01053 
01054      // Return true for an active connection.
01055     bool connected() const
01056     {
01057         return _connected;
01058     }
01059 
01060      // Commit the current transaction.
01061     void commit(ub4 flags=OCI_DEFAULT)
01062     {
01063         _ctx.commit(flags);
01064     }
01065 
01066      // Rollback the current transaction.
01067     void rollback(ub4 flags=OCI_DEFAULT)
01068     {
01069         _ctx.rollback(flags);
01070     }
01071 
01072     OracleServer _server;
01073     tstring _warnings;
01074     tstring _tnsname;
01075 
01076 protected:
01077     OciContext _ctx;
01078     OciHandle<OCISession> _session;
01079 
01080     bool    _connected;
01081 };
01082 
01083 
01084 #if ORACLE_VERSION>=90
01085 
01086  /// a map to cache SQL statements
01087 struct StatementCache : public std::map<tstring, tstring>
01088 {
01089 };
01090 
01091 #endif
01092 
01093 
01094  /// wrap OCIEnv and OCISvcCtx together
01095 
01096 struct OciConnection
01097 {
01098     OciConnection(OCIEnv* envh, OCISvcCtx* ctx)
01099      :  _env(envh),
01100         _ctx(_env, ctx)
01101     {
01102     }
01103 
01104     static OciConnection* CreateFromESqlContext(void* context);
01105 
01106      // Commit the current transaction.
01107     void commit(ub4 flags=OCI_DEFAULT)
01108     {
01109         _ctx.commit(flags);
01110     }
01111 
01112      // Rollback the current transaction.
01113     void rollback(ub4 flags=OCI_DEFAULT)
01114     {
01115         _ctx.rollback(flags);
01116     }
01117 
01118      // cancel a pending OCI call in the worker thread
01119     void    cancel();
01120 
01121 #if ORACLE_VERSION>=81
01122      // reset() is to be called after handling the cancellation in the calling worker thread.
01123     void    reset();
01124 #endif
01125 
01126     OciEnv      _env;
01127     OciContext  _ctx;
01128 
01129 #if ORACLE_VERSION>=90
01130     StatementCache  _stmt_cache;
01131 #endif
01132 
01133      // return error handle of the environment object
01134     operator OCIError*()
01135     {
01136         return _env._errh;
01137     }
01138 
01139 private:
01140     OciConnection(const OciConnection&);    // disallow copy constructor calls
01141 };
01142 
01143 
01144  /// DatabaseConnect to encapsulate all structures needed to connect to an Oracle database
01145 
01146 struct DatabaseConnect
01147 {
01148     OciEnvAlloc     _env_alloc;
01149     OciEnv          _env;
01150     OciLogin        _oci_login;
01151     OciConnection   _conn;
01152 
01153     DatabaseConnect(const LoginPara& login_para)
01154      :  _env(_env_alloc),
01155         _oci_login(_env, login_para),
01156         _conn(_env, _oci_login)
01157     {
01158     }
01159 
01160     operator OciConnection& () {return _conn;}
01161 };
01162 
01163 
01164  /// column type information
01165 
01166 struct ColumnTypeInfo
01167 {
01168     ub2     _data_type;
01169     ub2     _width;
01170     ub1     _char_semantics;    // since Oracle 9
01171     sb1     _scale;
01172     sb2     _precision;
01173     ub1     _nullable;
01174 
01175      // return a textual representation of the column type
01176     tstring get_type_str(bool show_null=false) const;
01177 };
01178 
01179 
01180  /// column type description including name
01181 
01182 struct ColumnType : public ColumnTypeInfo
01183 {
01184     tstring _name;
01185 
01186      // The empty default constructor just initializes all member variables.
01187     ColumnType()
01188     {
01189         _data_type = 0;
01190         _width = 0;
01191         _char_semantics = 0;
01192         _precision = 0;
01193         _scale = -127;
01194         _nullable = false;
01195     }
01196 
01197      // retrieve type information from the given column handle
01198     void    init(OCIError* errh, dvoid* handle);
01199 
01200 //  static SqlVariantArray s_empty;
01201 };
01202 
01203 
01204 typedef OciHandle<OCIBind> OciBindHandle;
01205 typedef OciHandle<OCIDefine> OciDefineHandle;
01206 
01207 
01208  /// Indicator variables are used to store information about the NULL-state of bind variables and result columns.
01209 
01210 struct SqlInd
01211 {
01212      // The constructor defaults to state 'NULL'.
01213     SqlInd(OCIInd ind=OCI_IND_NULL)
01214      : _ind(ind)
01215     {
01216     }
01217 
01218     operator OCIInd() const {return _ind;}
01219     operator OCIInd*() {return &_ind;}
01220     operator const OCIInd*() const {return &_ind;}
01221 
01222     bool is_null() const {return _ind==OCI_IND_NULL;}
01223     bool is_not_null() const {return _ind!=OCI_IND_NULL;}
01224 
01225     void clear() {_ind = OCI_IND_NULL;}
01226     void set() {_ind = OCI_IND_NOTNULL;}
01227 
01228 protected:
01229     OCIInd  _ind;   // short
01230 };
01231 
01232 
01233  /// base class of bind variable structures containing the indicator variable
01234 
01235 struct SqlValue
01236 {
01237     SqlValue() {}
01238     SqlValue(OCIInd ind) : _ind(ind) {}
01239     SqlValue(const SqlValue& other) : _ind(other._ind) {}
01240 
01241     bool is_null() const {return _ind.is_null();}
01242     bool is_not_null() const {return _ind.is_not_null();}
01243 
01244     const SqlInd& ind() const {return _ind;}
01245     SqlInd& ind() {return _ind;}
01246 
01247 protected:
01248     SqlInd  _ind;
01249 };
01250 
01251 
01252 enum {INT_NULL = -1};
01253 
01254  /// array of indicator variables
01255 
01256 struct SqlIndArray
01257 {
01258      // constructor determining the array length
01259     SqlIndArray(int size=g_OCIPL_BULK_ROWS)
01260      :  _count(size),
01261         _pind(new SqlInd[size])
01262     {
01263     }
01264 
01265      // copy onstructor
01266     SqlIndArray(const SqlIndArray& other)
01267      :  _count(other._count),
01268         _pind(new SqlInd[other._count])
01269     {
01270         memcpy(_pind, other._pind, other._count*sizeof(SqlInd));
01271     }
01272 
01273      // The destructor just frees the array's allocated memory.
01274     ~SqlIndArray()
01275     {
01276         delete [] _pind;
01277     }
01278 
01279     bool is_null(int idx) const {return _pind[idx].is_null();}
01280     bool is_not_null(int idx) const {return _pind[idx].is_not_null();}
01281 
01282     const SqlInd& ind(int idx) const {return _pind[idx];}
01283     SqlInd& ind(int idx) {return _pind[idx];}
01284 
01285     int get_buffer_count() const {return _count;}
01286 
01287 protected:
01288     int     _count;
01289     SqlInd* _pind;
01290 };
01291 
01292 
01293  /// int wrapper with indicator variable
01294 
01295 struct SqlInt : public SqlValue
01296 {
01297      // The default constructor initializes the value to NULL.
01298     SqlInt()
01299     {
01300     }
01301 
01302      // constructor taking an int value
01303     SqlInt(int value)
01304      :  _value(value)
01305     {
01306         _ind.set();
01307     }
01308 
01309      // constructor taking an int value and indicator information about the NULL-state
01310     SqlInt(int value, OCIInd ind)
01311      :  SqlValue(ind),
01312         _value(value)
01313     {
01314     }
01315 
01316      // copy constructor
01317     SqlInt(const SqlInt& other)
01318      :  SqlValue(other),
01319         _value(other._value)
01320     {
01321     }
01322 
01323      // return the current integer value or INT_NULL for NULL values
01324     operator int() const
01325     {
01326         return _ind.is_not_null()? _value: INT_NULL;
01327     }
01328 
01329     int get_int(int null=INT_NULL) const
01330     {
01331         return _ind.is_not_null()? _value: null;
01332     }
01333 
01334      // return a non-const pointer to the wrapped int variable
01335     int* get_ref()
01336     {
01337         return &_value;
01338     }
01339 
01340      // return a const pointer to the wraped int variable
01341     const int* get_ptr() const
01342     {
01343         return &_value;
01344     }
01345 
01346      // return the current value as decimal string or an empty string for NULL values
01347     tstring str() const
01348     {
01349         if (_ind.is_not_null()) {
01350             TCHAR buffer[16];
01351             _stprintf_s1(buffer, sizeof(buffer)/sizeof(TCHAR), TEXT("%d"), _value);
01352             return buffer;
01353         } else
01354             return tstring();
01355     }
01356 
01357 protected:
01358     int     _value; // wrapped int variable
01359 };
01360 
01361 
01362  /// array of integer bind variable buffers
01363 
01364 struct SqlIntArray : public SqlIndArray
01365 {
01366      // constructor determining the array length
01367     SqlIntArray(int size=g_OCIPL_BULK_ROWS)
01368      :  SqlIndArray(size),
01369         _pvalues(static_cast<int*>(ocipl_alloc(size*sizeof(int))))
01370     {
01371     }
01372 
01373     SqlIntArray(const SqlIntArray& other)
01374      :  SqlIndArray(other),
01375         _pvalues(static_cast<int*>(ocipl_alloc(other._count*sizeof(int))))
01376     {
01377         if (_pvalues)
01378             memcpy(_pvalues, other._pvalues, other._count*sizeof(int));
01379     }
01380 
01381     ~SqlIntArray()
01382     {
01383         ocipl_free(_pvalues);
01384     }
01385 
01386     int get_int(int row, int null=INT_NULL) const {return _pind[row].is_not_null()? _pvalues[row]: null;}
01387 
01388     int* get_ref(int row) {return &_pvalues[row];}
01389     const int* get_ptr(int row) const {return &_pvalues[row];}
01390 
01391     tstring str(int row) const
01392     {
01393         if (_pind[row].is_not_null()) {
01394             TCHAR buffer[16];
01395             _stprintf_s1(buffer, sizeof(buffer)/sizeof(TCHAR), TEXT("%d"), _pvalues[row]);
01396             return buffer;
01397         } else
01398             return tstring();
01399     }
01400 
01401 protected:
01402     int*    _pvalues;
01403 };
01404 
01405 
01406  /// string buffer bind variable structure
01407 
01408 struct SqlString : public SqlValue
01409 {
01410     SqlString(int blen=OCIPL_DEFAULT_STRING_BUFFER)
01411      :  _blen(blen),
01412         _str(static_cast<TCHAR*>(ocipl_alloc((blen+1)*sizeof(TCHAR))))
01413     {
01414         *_str = '\0';
01415     }
01416 
01417     SqlString(const TCHAR* s)
01418      :  _blen(_tcslen(s)),
01419         _str(_tcsdup(s))
01420     {
01421         if (*s)
01422             _ind.set();
01423     }
01424 
01425     SqlString(const TCHAR* s, int blen)
01426      :  _blen(blen),
01427         _str(static_cast<TCHAR*>(ocipl_alloc((blen+1)*sizeof(TCHAR))))
01428     {
01429         ocipl_tcscpyn(_str, s, blen+1);
01430 
01431         if (*s)
01432             _ind.set();
01433     }
01434 
01435     SqlString(const SqlString& other)
01436      :  SqlValue(other),
01437         _blen(_tcslen(other._str)),
01438         _str(_tcsdup(other._str))
01439     {
01440     }
01441 
01442     ~SqlString()
01443     {
01444         ocipl_free(_str);
01445     }
01446 
01447     size_t len() const {return is_null()? 0: _tcslen(_str);}
01448     size_t blen() const {return _blen;}
01449     size_t alen() const {return _blen + 1;}
01450 
01451     void resize(size_t l) {void* new_ptr = ocipl_realloc(_str,(l+1)*sizeof(TCHAR)); if (new_ptr) {_str=(TCHAR*)new_ptr; _str[l]='\0'; _blen=l;}}
01452     void clear() {*_str = '\0'; _ind.clear();}
01453 
01454     TCHAR* str() {return _str;} // Note: _ind is not checked by this function.
01455     TCHAR* str(int l) {resize(l); return _str;} // Note: _ind is not changed by this function.
01456 
01457     const TCHAR* c_str() const {return is_null()? TEXT(""): _str;}
01458     operator const TCHAR*() const {return is_null()? TEXT(""): _str;}
01459 
01460     SqlString& operator=(const TCHAR* s);
01461     SqlString& operator=(const tstring& s);
01462 
01463     bool operator==(const TCHAR* s) const {return !_tcscmp(c_str(), s);}
01464     bool operator!=(const TCHAR* s) const {return _tcscmp(c_str(), s) != 0;}
01465     bool operator<(const TCHAR* s) const {return _tcscmp(c_str(), s) < 0;}
01466 
01467     friend tostream& operator<<(tostream& os, const SqlString& str)
01468         {if (str.is_not_null()) os << str._str; return os;}
01469 
01470     static inline TCHAR* ocipl_tcscpyn(TCHAR* dest, const TCHAR* source, size_t count)
01471     {
01472         TCHAR* d = dest;
01473 
01474         for(const TCHAR* s=source; count&&(*d++=*s++); )
01475             count--;
01476 
01477         return dest;
01478     }
01479 
01480 protected:
01481     size_t  _blen;
01482     TCHAR*  _str;
01483 };
01484 
01485 
01486  /// array of string bind variable buffers
01487 
01488 struct SqlStringArray : public SqlIndArray
01489 {
01490      // constructor determining the array length and string buffer size
01491     SqlStringArray(int size=g_OCIPL_BULK_ROWS, int blen=OCIPL_DEFAULT_STRING_BUFFER)
01492      :  SqlIndArray(size),
01493         _blen(blen),
01494         _buffer(static_cast<TCHAR*>(ocipl_alloc(size*(blen+1)*sizeof(TCHAR))))
01495     {
01496         if (_buffer)
01497             memset(_buffer, 0, size*(blen+1)*sizeof(TCHAR));
01498     }
01499 
01500     SqlStringArray(const SqlStringArray& other)
01501      :  SqlIndArray(other),
01502         _blen(other._blen),
01503         _buffer(static_cast<TCHAR*>(ocipl_alloc(other._count*(other._blen+1)*sizeof(TCHAR))))
01504     {
01505         if (_buffer)
01506             memcpy(_buffer, 0, other._count*(other._blen+1)*sizeof(TCHAR));
01507     }
01508 
01509     ~SqlStringArray()
01510     {
01511         ocipl_free(_buffer);
01512     }
01513 
01514     size_t len(int row) const {return is_not_null(row)? _tcslen(_buffer): 0;}
01515     size_t blen() const {return _blen;}
01516     size_t alen() const {return _blen+1;}
01517 
01518     void clear(int row) {*_buffer = '\0'; _pind[row].clear();}
01519 //  void assign(int row, const dvoid* ptr, sb4 size);
01520     void assign(int row, const TCHAR* s) {strcpy_s(_buffer, _blen, s);}//TODO resize buffer as needed
01521 
01522     TCHAR* str(int row) {return _buffer + row*(_blen+1);}   // Note: _ind is not checked by this function.
01523     const TCHAR* c_str(int row) const {return is_not_null(row)? _buffer + row*(_blen+1): TEXT("");}
01524 
01525 protected:
01526     size_t  _blen;
01527     TCHAR*  _buffer;
01528 };
01529 
01530 
01531 extern tstring ocidate_to_string(const OCIDate& date);
01532 extern tstring ocidate_to_short_string(const OCIDate& date);
01533 extern struct tm* ocidate_to_gmt(const OCIDate& date);
01534 extern struct tm* ocidate_to_lctime(const OCIDate& date);
01535 extern time_t ocidate_to_time_t(const OCIDate& date);
01536 
01537 #ifdef _WIN32
01538 extern bool ocidate_to_systemtime(const OCIDate& date, SYSTEMTIME* pSysTime);
01539 #endif
01540 
01541 
01542  /// internal DATE representation
01543 struct ocidatetime {
01544     ub1 century;
01545     ub1 year;
01546     ub1 month;
01547     ub1 day;
01548     ub1 hour;
01549     ub1 minute;
01550     ub1 second;
01551 };
01552 
01553 extern tstring ocidatetime_to_string(const ocidatetime& date);
01554 
01555 
01556  /// wrapper for OCI DATE type
01557 
01558 struct OciDate : public OCIDate, public SqlValue
01559 {
01560     OciDate() {}
01561     OciDate(const OCIDate& date, OCIInd ind=OCI_IND_NOTNULL);
01562     OciDate(const ocidatetime& date, OCIInd ind=OCI_IND_NOTNULL);
01563     OciDate(OCIError* errh, const TCHAR* str, const TCHAR* fmt=TEXT("dd.mm.yyyy"));
01564     OciDate(struct tm* t);
01565 
01566     tstring str() const
01567     {
01568         if (_ind.is_not_null())
01569             return ocidate_to_string(*this);
01570         else
01571             return tstring();
01572     }
01573 
01574     tstring short_str() const
01575     {
01576         if (_ind.is_not_null())
01577             return ocidate_to_short_string(*this);
01578         else
01579             return tstring();
01580     }
01581 
01582     int get_int_date() const
01583     {
01584         if (_ind.is_not_null())
01585             return ((OCIDateYYYY*100) + OCIDateMM)*100 + OCIDateDD;
01586         else
01587             return 0;
01588     }
01589 
01590     struct tm* get_gmt() const
01591     {
01592         if (_ind.is_not_null())
01593             return ocidate_to_gmt(*this);
01594         else
01595             return 0;
01596     }
01597 
01598     struct tm* get_lctime() const
01599     {
01600         if (_ind.is_not_null())
01601             return ocidate_to_lctime(*this);
01602         else
01603             return 0;
01604     }
01605 
01606     time_t get_time_t() const
01607     {
01608         if (_ind.is_not_null())
01609             return ocidate_to_time_t(*this);
01610         else
01611             return 0;
01612     }
01613 
01614 #ifdef _WIN32
01615     bool get_systemtime(SYSTEMTIME* pSysTime) const
01616     {
01617         if (_ind.is_not_null())
01618             return ocidate_to_systemtime(*this, pSysTime);
01619         else
01620             return false;
01621     }
01622 #endif
01623 
01624     int compare(const OciDate& other) const;
01625 };
01626 
01627 
01628  /// OCI DATE type bind variable array
01629 
01630 struct OciDateArray : public SqlIndArray
01631 {
01632      // constructor determining the array length
01633     OciDateArray(int size=g_OCIPL_BULK_ROWS)
01634      :  SqlIndArray(size),
01635         _buffers(static_cast<OCIDate*>(ocipl_alloc(size*sizeof(OCIDate))))
01636     {
01637     }
01638 
01639     ~OciDateArray()
01640     {
01641         ocipl_free(_buffers);
01642     }
01643 
01644     const OCIDate& get_date(int row) const {return _buffers[row];}
01645     OciDate get_oci_date(int row) const {return OciDate(_buffers[row], _pind[row]);}
01646 
01647     OCIDate* get_ref(int row) {return &_buffers[row];}
01648     const OCIDate* get_ref(int row) const {return &_buffers[row];}
01649 
01650     tstring str(int row) const
01651     {
01652         if (_pind[row].is_not_null())
01653             return ocidate_to_string(_buffers[row]);
01654         else
01655             return tstring();
01656     }
01657 
01658     tstring short_str(int row) const
01659     {
01660         if (_pind[row].is_not_null())
01661             return ocidate_to_short_string(_buffers[row]);
01662         else
01663             return tstring();
01664     }
01665 
01666     int get_int_date(int row) const
01667     {
01668         if (_pind[row].is_not_null()) {
01669             const OCIDate& date = _buffers[row];
01670             return ((date.OCIDateYYYY*100) + date.OCIDateMM)*100 + date.OCIDateDD;
01671         } else
01672             return 0;
01673     }
01674 
01675     struct tm* get_gmt(int row) const
01676     {
01677         if (_pind[row].is_not_null())
01678             return ocidate_to_gmt(_buffers[row]);
01679         else
01680             return 0;
01681     }
01682 
01683     struct tm* get_lctime(int row) const
01684     {
01685         if (_pind[row].is_not_null())
01686             return ocidate_to_lctime(_buffers[row]);
01687         else
01688             return 0;
01689     }
01690 
01691     time_t get_time_t(int row) const
01692     {
01693         if (_pind[row].is_not_null())
01694             return ocidate_to_time_t(_buffers[row]);
01695         else
01696             return 0;
01697     }
01698 
01699     void set_date(int row, const OciDate& date) {_buffers[row] = date; _pind[row] = date.ind();}
01700 
01701 protected:
01702     OCIDate* _buffers;
01703 };
01704 
01705 
01706  /// wrapper for internal Oracle DATE type
01707 
01708 struct SqlDateTime : public SqlValue
01709 {
01710     SqlDateTime() {}
01711 
01712     SqlDateTime(const ocidatetime& date, OCIInd ind=OCI_IND_NOTNULL)
01713      :  SqlValue(ind),
01714         _date(date)
01715     {
01716     }
01717 
01718     ocidatetime* get_ref() {return &_date;}
01719     const ocidatetime* get_ptr() const {return &_date;}
01720 
01721     const ocidatetime& get_datetime() const {return _date;}
01722 
01723     tstring str() const
01724     {
01725         if (_ind.is_not_null())
01726             return ocidatetime_to_string(_date);
01727         else
01728             return tstring();
01729     }
01730 
01731 protected:
01732     ocidatetime _date;
01733 };
01734 
01735 
01736  /// wrapper for internal Oracle DATE type
01737 
01738 struct SqlDateTimeArray : public SqlIndArray
01739 {
01740      // constructor determining the array length
01741     SqlDateTimeArray(int size=g_OCIPL_BULK_ROWS)
01742      :  SqlIndArray(size),
01743         _buffers(static_cast<ocidatetime*>(ocipl_alloc(size*sizeof(ocidatetime))))
01744     {
01745     }
01746 
01747     ~SqlDateTimeArray()
01748     {
01749         ocipl_free(_buffers);
01750     }
01751 
01752     const ocidatetime& get_datetime(int row) const {return _buffers[row];}
01753     SqlDateTime get_sql_date(int row) const {return SqlDateTime(_buffers[row], _pind[row]);}
01754 
01755     ocidatetime* get_ref(int row) {return &_buffers[row];}
01756     const ocidatetime* get_ptr(int row) const {return &_buffers[row];}
01757 
01758     tstring str(int row) const
01759     {
01760         if (_pind[row].is_not_null())
01761             return ocidatetime_to_string(_buffers[row]);
01762         else
01763             return tstring();
01764     }
01765 
01766     void set_datetime(int row, const SqlDateTime& datetime) {_buffers[row] = datetime.get_datetime(); _pind[row] = datetime.ind();}
01767 
01768 protected:
01769     ocidatetime* _buffers;
01770 };
01771 
01772 
01773  /// internal NUMBER representation
01774 struct oraclenumber {
01775     ub1 len;
01776     ub1 exp;
01777     ub1 mant[20];
01778 };
01779 
01780 
01781 extern int number_to_int(const oraclenumber& val, OCIError* errh);
01782 extern double number_to_double(const oraclenumber& val, OCIError* errh);
01783 extern tstring number_to_str(const oraclenumber& val, OCIError* errh, const TCHAR* fmt, const TCHAR* nls_fmt);
01784 
01785 #ifdef _MSC_VER
01786 extern LONGLONG number_to_int64(const oraclenumber& val, OCIError* errh, int null=INT_NULL);
01787 #endif
01788 
01789 
01790  /// wrapper for internal Oracle NUMBER type
01791 
01792 struct SqlNumber : public SqlValue
01793 {
01794     SqlNumber() {}
01795 
01796     SqlNumber(const oraclenumber* pnum);
01797 
01798     SqlNumber(OCIError* errh, const TCHAR* s,
01799                 const TCHAR* fmt=TEXT("99999999999999999999999999999999999999D99999999999999999999"),
01800                 const TCHAR* nls_fmt=TEXT("NLS_NUMERIC_CHARACTERS='.,'"));
01801 
01802     SqlNumber(OCIError* errh, double d)
01803     {
01804         sword res = OCINumberFromReal(errh, &d, sizeof(d), (OCINumber*)&_val);
01805         oci_check_error(errh, res);
01806         _ind.set();
01807     }
01808 
01809      // constructor taking an double value and indicator information about the NULL-state
01810     SqlNumber(OCIError* errh, double d, OCIInd ind)
01811      :  SqlValue(ind)
01812     {
01813         if (ind != OCI_IND_NULL) {
01814             sword res = OCINumberFromReal(errh, &d, sizeof(d), (OCINumber*)&_val);
01815             oci_check_error(errh, res);
01816         }
01817     }
01818 
01819     SqlNumber(OCIError* errh, int i)
01820     {
01821         sword res = OCINumberFromInt(errh, &i, sizeof(i), OCI_NUMBER_SIGNED, (OCINumber*)&_val);
01822         oci_check_error(errh, res);
01823         _ind.set();
01824     }
01825 
01826      // constructor taking an int value and indicator information about the NULL-state
01827     SqlNumber(OCIError* errh, int i, OCIInd ind)
01828      :  SqlValue(ind)
01829     {
01830         if (ind != OCI_IND_NULL) {
01831             sword res = OCINumberFromInt(errh, &i, sizeof(i), OCI_NUMBER_SIGNED, (OCINumber*)&_val);
01832             oci_check_error(errh, res);
01833         }
01834     }
01835 
01836     SqlNumber(ub1* num_ptr, ub1 num_len)
01837     {
01838         memcpy(&_val.exp, num_ptr, num_len);
01839         _val.len = num_len;
01840         _ind.set();
01841     }
01842 
01843     const oraclenumber& get_number() const {return _val;}
01844 
01845     oraclenumber* get_ref() {return &_val;}
01846     const oraclenumber* get_ptr() const {return &_val;}
01847 
01848     //tstring str(bool internal=false) const;
01849     tstring str(OCIError* errh, const TCHAR* fmt=TEXT("TM9"),//"FM99999999999999999999999999999999999999.99999999999999999999"
01850                     const TCHAR* nls_fmt=TEXT("NLS_NUMERIC_CHARACTERS='.,'")) const
01851     {
01852         if (_ind.is_not_null())
01853             return number_to_str(_val, errh, fmt, nls_fmt);
01854         else
01855             return tstring();
01856     }
01857 
01858     operator OCINumber*() {return (OCINumber*)&_val;}
01859     operator const OCINumber*() const {return (OCINumber*)&_val;}
01860 
01861     int get_int(OCIError* errh, int null=INT_NULL) const
01862     {
01863         if (is_null())
01864             return null;
01865         else
01866             return number_to_int(_val, errh);
01867     }
01868 
01869 #ifdef _MSC_VER
01870     LONGLONG get_int64(OCIError* errh, int null=INT_NULL) const
01871     {
01872         if (is_null())
01873             return null;
01874         else
01875             return number_to_int64(_val, errh, null);
01876     }
01877 #endif
01878 
01879     double get_double(OCIError* errh, double null=0.) const
01880     {
01881         if (is_null())
01882             return null;
01883         else
01884             return number_to_double(_val, errh);    // atof(str(true).c_str());
01885     }
01886 
01887 protected:
01888     oraclenumber _val;
01889 };
01890 
01891 
01892  /// array of NUMBER bind variable buffers
01893 
01894 struct SqlNumberArray : public SqlIndArray
01895 {
01896      // constructor determining the array length
01897     SqlNumberArray(int size=g_OCIPL_BULK_ROWS)
01898      :  SqlIndArray(size),
01899         _pvalues(static_cast<oraclenumber*>(ocipl_alloc(size*sizeof(oraclenumber))))
01900     {
01901     }
01902 
01903     ~SqlNumberArray()
01904     {
01905         ocipl_free(_pvalues);
01906     }
01907 
01908     const oraclenumber& get_number(int row) const {return _pvalues[row];}
01909 
01910     oraclenumber* get_ref(int row) {return &_pvalues[row];}
01911     const oraclenumber* get_ptr(int row) const {return &_pvalues[row];}
01912 
01913     //tstring str(bool internal=false) const;
01914     tstring str(int row, OCIError* errh, const TCHAR* fmt=TEXT("TM9"),//"FM99999999999999999999999999999999999999.99999999999999999999"
01915                     const TCHAR* nls_fmt=TEXT("NLS_NUMERIC_CHARACTERS='.,'")) const
01916     {
01917         if (_pind[row].is_not_null())
01918             return number_to_str(_pvalues[row], errh, fmt, nls_fmt);
01919         else
01920             return tstring();
01921     }
01922 
01923     int get_int(int row, OCIError* errh, int null=INT_NULL) const
01924     {
01925         if (is_not_null(row))
01926             return number_to_int(_pvalues[row], errh);
01927         else
01928             return null;
01929     }
01930 
01931 #ifdef _MSC_VER
01932     LONGLONG get_int64(int row, OCIError* errh, int null=INT_NULL) const
01933     {
01934         if (is_not_null(row))
01935             return number_to_int64(_pvalues[row], errh, null);
01936         else
01937             return null;
01938     }
01939 #endif
01940 
01941     double get_double(int row, OCIError* errh, double null=0.) const
01942     {
01943         if (is_not_null(row))
01944             return number_to_double(_pvalues[row], errh);
01945         else
01946             return null;
01947     }
01948 
01949     void set_number(int row, const SqlNumber& num) {_pvalues[row] = num.get_number(); _pind[row] = num.ind();}
01950 
01951 protected:
01952     oraclenumber* _pvalues;
01953 };
01954 
01955 
01956  /// base class for the BLOB/CLOB data holders OCIPL::OciLob and OCIPL::OciClob
01957 
01958 //template<typename TYPE>
01959 struct OciLob : public SqlValue
01960 {
01961 //  OciLob() : _loc(NULL) {}
01962 
01963     OciLob(OciConnection& conn)
01964      :  _conn(conn)
01965     {
01966         sword res = OCIDescriptorAlloc(conn._env, (dvoid**)&_loc, OCI_DTYPE_LOB, 0, NULL);
01967         oci_check_error(conn._env, res);
01968     }
01969 
01970     OciLob(OciConnection& conn, OCILobLocator* loc)
01971      :  _conn(conn),
01972         _loc(loc)
01973     {
01974     }
01975 
01976     OciLob(const OciLob& other)
01977      :  _conn(other._conn)
01978     {
01979         sword res = OCIDescriptorAlloc(_conn._env, (dvoid**)&_loc, OCI_DTYPE_LOB, 0, NULL);
01980         oci_check_error(_conn._env._errh, res);
01981 
01982 #if ORACLE_VERSION>=81
01983         res = OCILobLocatorAssign(_conn._ctx, _conn._env._errh, other._loc, &_loc);
01984 #else
01985         res = OCILobAssign(_conn._env, _conn._env._errh, other._loc, &_loc);    // no support for temporary LOBs
01986 #endif
01987         oci_check_error(_conn._env._errh, res);
01988 
01989         clear();
01990     }
01991 
01992     ~OciLob()
01993     {
01994 #if ORACLE_VERSION>=81
01995          // According to the Oracle 10g documentation we should try to free
01996          // implicit created temporary LOBs as soon as possible.
01997         if (is_temporary()) {
01998             sword res = OCILobFreeTemporary(_conn._ctx, _conn._env._errh, _loc);
01999             oci_check_error(_conn._env._errh, res);
02000         }
02001 #endif
02002 
02003         sword res = OCIDescriptorFree(_loc, OCI_DTYPE_LOB);
02004         oci_check_error(_conn._env._errh, res);
02005     }
02006 
02007     boolean operator==(const OciLob& other) const
02008     {
02009         boolean is_equal;
02010 
02011         sword res = OCILobIsEqual(_conn._env, _loc, other._loc, &is_equal);
02012 
02013         oci_check_error(_conn._env._errh, res);
02014 
02015         return is_equal;
02016     }
02017 
02018     void clear()
02019     {
02020         ub4 lobEmpty = 0;
02021         sword res = OCIAttrSet(_loc, OCI_DTYPE_LOB, &lobEmpty, 0, OCI_ATTR_LOBEMPTY, _conn._env._errh);
02022         oci_check_error(_conn._env._errh, res);
02023     }
02024 
02025     void* get_ref() {return &_loc;}
02026     const void* get_ptr() const {return &_loc;}
02027 
02028     //tstring str(bool internal=false) const;
02029 
02030 
02031     ub4 get_chunk_size()
02032     {
02033         ub4 len;
02034 
02035         sword res = OCILobGetLength(_conn._ctx, _conn._env._errh, _loc, &len);
02036         oci_check_error(_conn._env._errh, res);
02037 
02038         return len;
02039     }
02040 
02041 #if ORACLE_VERSION>=81
02042     ub4 get_length()
02043     {
02044         ub4 size;
02045 
02046         sword res = OCILobGetChunkSize(_conn._ctx, _conn._env._errh, _loc, &size);
02047         oci_check_error(_conn._env._errh, res);
02048 
02049         return size;
02050     }
02051 
02052     boolean is_open() const
02053     {
02054         boolean flag;
02055 
02056         sword res = OCILobIsOpen(_conn._ctx, _conn._env._errh, _loc, &flag);
02057         oci_check_error(_conn._env._errh, res);
02058 
02059         return flag;
02060     }
02061 
02062     boolean is_temporary() const
02063     {
02064         boolean flag;
02065 
02066         sword res = OCILobIsTemporary(_conn._env, _conn._env._errh, _loc, &flag);
02067         oci_check_error(_conn._env._errh, res);
02068 
02069         return flag;
02070     }
02071 #endif
02072 
02073 
02074     void    copy(const OciLob& src, ub4 amount, ub4 dst_offset, ub4 src_offset)
02075     {
02076         sword res = OCILobCopy(_conn._ctx, _conn._env._errh, _loc, src._loc, amount, dst_offset, src_offset);
02077         oci_check_error(_conn._env._errh, res);
02078     }
02079 
02080     void    append(const OciLob& src)
02081     {
02082         sword res = OCILobAppend(_conn._ctx, _conn._env._errh, _loc, src._loc);
02083         oci_check_error(_conn._env._errh, res);
02084     }
02085 
02086     void    trim(ub4 newlen=0)
02087     {
02088         sword res = OCILobTrim(_conn._ctx, _conn._env._errh, _loc, newlen);
02089         oci_check_error(_conn._env._errh, res);
02090     }
02091 
02092     ub4 erase(ub4 offset, ub4 amount)
02093     {
02094         sword res = OCILobErase(_conn._ctx, _conn._env._errh, _loc, &amount, offset);
02095         oci_check_error(_conn._env._errh, res);
02096 
02097         return amount;
02098     }
02099 
02100 
02101     void    enable_buffering()
02102     {
02103         sword res = OCILobEnableBuffering(_conn._ctx, _conn._env._errh, _loc);
02104         oci_check_error(_conn._env._errh, res);
02105     }
02106 
02107     void    disable_buffering()
02108     {
02109         sword res = OCILobDisableBuffering(_conn._ctx, _conn._env._errh, _loc);
02110         oci_check_error(_conn._env._errh, res);
02111     }
02112 
02113     void    flush(ub4 flag=OCI_LOB_BUFFER_NOFREE)
02114     {
02115         sword res = OCILobFlushBuffer(_conn._ctx, _conn._env._errh, _loc, flag);
02116         oci_check_error(_conn._env._errh, res);
02117     }
02118 
02119 protected:
02120     OciConnection&  _conn;
02121     OCILobLocator*  _loc;
02122 
02123     friend struct OciOpenLob;
02124 };
02125 
02126 
02127 #if ORACLE_VERSION>=81
02128 
02129  /// open and close LOBs using OciOpenLob for exception handling
02130  // Forgetting to close LOBs results in errors in OciLogin::disconnect().
02131 struct OciOpenLob
02132 {
02133     OciOpenLob(OciLob& lob, ub1 mode=OCI_LOB_READWRITE)
02134      :  _lob(lob)
02135     {
02136         sword res = OCILobOpen(lob._conn._ctx, lob._conn._env._errh, lob._loc, mode);
02137         oci_check_error(lob._conn._env._errh, res);
02138     }
02139 
02140     ~OciOpenLob()
02141     {
02142         sword res = OCILobClose(_lob._conn._ctx, _lob._conn._env._errh, _lob._loc);
02143         oci_check_error(_lob._conn._env._errh, res);
02144     }
02145 
02146 protected:
02147     OciLob& _lob;
02148 };
02149 
02150 
02151  /// BLOB data holder structure
02152 struct OciBlob : public OciLob
02153 {
02154     OciBlob(OciConnection& conn) : OciLob(conn) {}
02155     OciBlob(const OciLob& other) : OciLob(other) {}
02156 
02157     ub4 write(const dvoid* bufp, ub4 buflen, ub4 offset/*=1*/, ub4 amount)
02158     {
02159         sword res = OCILobWrite(_conn._ctx, _conn._env._errh, _loc,
02160                       &amount, offset, (dvoid*)bufp, buflen,
02161                       OCI_ONE_PIECE/*ub1 piece*/, NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/,
02162                       0, 0);
02163 
02164         oci_check_error(_conn._env._errh, res);
02165 
02166         return amount;
02167     }
02168 
02169     ub4 write_append(const dvoid* bufp, ub4 buflen, ub4 amount)
02170     {
02171         sword res = OCILobWriteAppend(_conn._ctx, _conn._env._errh, _loc,
02172                       &amount, (dvoid*)bufp, buflen,
02173                       OCI_ONE_PIECE/*ub1 piece*/, NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/,
02174                       0, 0);
02175 
02176         oci_check_error(_conn._env._errh, res);
02177 
02178         return amount;
02179     }
02180 
02181     ub4 read(dvoid* bufp, ub4 buflen, ub4 offset, ub4 amount)
02182     {
02183         sword res = OCILobRead(_conn._ctx, _conn._env._errh, _loc,
02184                       &amount, offset, bufp, buflen,
02185                       NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,CONST dvoid*bufp,ub4*len,ub1*piece)*/,
02186                       0, 0);
02187 
02188         oci_check_error(_conn._env._errh, res);
02189 
02190         return amount;
02191     }
02192 };
02193 
02194 struct OciTempBlob : public OciBlob
02195 {
02196     OciTempBlob(OciConnection& conn, OCIDuration dur=OCI_DURATION_SESSION)
02197      :  OciBlob(conn)
02198     {
02199         sword res = OCILobCreateTemporary(conn._ctx, conn._env._errh, _loc,
02200                                             OCI_DEFAULT, SQLCS_IMPLICIT, OCI_TEMP_BLOB, FALSE, dur);
02201 
02202         oci_check_error(_conn._env._errh, res);
02203     }
02204 
02205     ~OciTempBlob()
02206     {
02207         /*already implemented in ~OciLob
02208         sword res = OCILobFreeTemporary(_conn._ctx, _conn._env._errh, _loc);
02209         oci_check_error(_conn._env._errh, res);
02210         */
02211     }
02212 };
02213 
02214 #endif
02215 
02216 
02217  /// CLOB data holder structure
02218 
02219 struct OciClob : public OciLob
02220 {
02221     OciClob(OciConnection& conn) : OciLob(conn) {}
02222     OciClob(const OciLob& other) : OciLob(other) {}
02223 
02224     ub4 write(const dvoid* bufp, ub4 buflen, ub4 offset, ub4 amount, ub2 csid=0, ub1 csfrm=SQLCS_IMPLICIT)
02225     {
02226         sword res = OCILobWrite(_conn._ctx, _conn._env._errh, _loc,
02227                       &amount, offset, (dvoid*)bufp, buflen,
02228                       OCI_ONE_PIECE/*ub1 piece*/, NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/,
02229                       csid, csfrm);
02230 
02231         oci_check_error(_conn._env._errh, res);
02232 
02233         return amount;
02234     }
02235 
02236 #if ORACLE_VERSION>=81
02237     ub4 write_append(const dvoid* bufp, ub4 buflen, ub4 amount, ub2 csid=0, ub1 csfrm=SQLCS_IMPLICIT)
02238     {
02239         sword res = OCILobWriteAppend(_conn._ctx, _conn._env._errh, _loc,
02240                       &amount, (dvoid*)bufp, buflen,
02241                       OCI_ONE_PIECE/*ub1 piece*/, NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,dvoid*bufp,ub4*len,ub1*piece)*/,
02242                       csid, csfrm);
02243 
02244         oci_check_error(_conn._env._errh, res);
02245 
02246         return amount;
02247     }
02248 #endif
02249 
02250     ub4 read(dvoid* bufp, ub4 buflen, ub4 offset, ub4 amount, ub2 csid=0, ub1 csfrm=SQLCS_IMPLICIT)
02251     {
02252         sword res = OCILobRead(_conn._ctx, _conn._env._errh, _loc,
02253                       &amount, offset, bufp, buflen,
02254                       NULL/*dvoid* ctxp*/, NULL/*sb4 (*cbfp)(dvoid*ctxp,CONST dvoid*bufp,ub4*len,ub1*piece)*/,
02255                       csid, csfrm);
02256 
02257         oci_check_error(_conn._env._errh, res);
02258 
02259         return amount;
02260     }
02261 };
02262 
02263 #if ORACLE_VERSION>=81
02264 struct OciTempClob : public OciClob
02265 {
02266     OciTempClob(OciConnection& conn, OCIDuration dur=OCI_DURATION_SESSION)
02267      :  OciClob(conn)
02268     {
02269         sword res = OCILobCreateTemporary(conn._ctx, conn._env._errh, _loc,
02270                                             OCI_DEFAULT, SQLCS_IMPLICIT, OCI_TEMP_CLOB, FALSE, dur);
02271 
02272         oci_check_error(_conn._env._errh, res);
02273     }
02274 
02275     ~OciTempClob()
02276     {
02277         /*already implemented in ~OciLob
02278         sword res = OCILobFreeTemporary(_conn._ctx, _conn._env._errh, _loc);
02279         oci_check_error(_conn._env._errh, res);
02280         */
02281     }
02282 };
02283 #endif
02284 
02285 
02286 /* todo
02287 struct OciBFile : public OciLob
02288 {
02289     OciBFile(OciConnection& conn) : OciLob(conn) {}
02290     OciBFile(const OciLob& other) : OciLob(other) {}
02291 };
02292 
02293 struct OciCFile : public OciLob
02294 {
02295     OciCFile(OciConnection& conn) : OciLob(conn) {}
02296     OciCFile(const OciLob& other) : OciLob(other) {}
02297 };
02298 
02299 sword   OCILobFileClose (OCISvcCtx *svchp, OCIError *errhp,
02300                          OCILobLocator *filep);
02301 
02302 sword   OCILobFileExists (OCISvcCtx *svchp, OCIError *errhp,
02303                           OCILobLocator *filep,
02304                           boolean *flag);
02305 
02306 sword   OCILobFileGetName (OCIEnv *envhp, OCIError *errhp,
02307                            CONST OCILobLocator *filep,
02308                            OraText *dir_alias, ub2 *d_length,
02309                            OraText *filename, ub2 *f_length);
02310 
02311 sword   OCILobFileOpen (OCISvcCtx *svchp, OCIError *errhp,
02312                         OCILobLocator *filep,
02313                         ub1 mode);
02314 
02315 sword   OCILobFileIsOpen (OCISvcCtx *svchp, OCIError *errhp,
02316                           OCILobLocator *filep,
02317                           boolean *flag);
02318 
02319 sword   OCILobFileSetName (OCIEnv *envhp, OCIError *errhp,
02320                            OCILobLocator **filepp,
02321                            CONST OraText *dir_alias, ub2 d_length,
02322                            CONST OraText *filename, ub2 f_length);
02323 */
02324 
02325 
02326  /// factory for call parameters of OCI bind functions
02327 
02328 struct BindInput
02329 {
02330     const dvoid*    valuep;
02331     sb4             value_sz;
02332     ub2             dty;
02333     const OCIInd*   indp;
02334 
02335     BindInput(const SqlInt& var)
02336     {
02337         valuep  = var.get_ptr();
02338         value_sz= sizeof(int);
02339         dty     = SQLT_INT;
02340         indp    = var.ind();
02341     }
02342 
02343     BindInput(const int& var, OCIInd* ind=NULL)
02344     {
02345         valuep  = (void*)&var;
02346         value_sz= sizeof(int);
02347         dty     = SQLT_INT;
02348         indp    = ind;
02349     }
02350 
02351     BindInput(const unsigned int& var, OCIInd* ind=NULL)
02352     {
02353         valuep  = (void*)&var;
02354         value_sz= sizeof(unsigned int);
02355         dty     = SQLT_UIN;
02356         indp    = ind;
02357     }
02358 
02359     BindInput(const long& var, OCIInd* ind=NULL)
02360     {
02361         valuep  = (void*)&var;
02362         value_sz= sizeof(long);
02363         dty     = SQLT_INT;
02364         indp    = ind;
02365     }
02366 
02367     BindInput(const unsigned long& var, OCIInd* ind=NULL)
02368     {
02369         valuep  = (void*)&var;
02370         value_sz= sizeof(unsigned long);
02371         dty     = SQLT_UIN;
02372         indp    = ind;
02373     }
02374 
02375     BindInput(const char& var, OCIInd* ind=NULL)
02376     {
02377         valuep  = (void*)&var;
02378         value_sz= sizeof(char);
02379         dty     = SQLT_CHR;
02380         indp    = ind;
02381     }
02382 
02383     BindInput(const float& var, OCIInd* ind=NULL)
02384     {
02385         valuep  = (void*)&var;
02386         value_sz= sizeof(float);
02387         dty     = SQLT_FLT;
02388         indp    = ind;
02389     }
02390 
02391     BindInput(const double& var, OCIInd* ind=NULL)
02392     {
02393         valuep  = (void*)&var;
02394         value_sz= sizeof(double);
02395         dty     = SQLT_FLT;
02396         indp    = ind;
02397     }
02398 
02399     BindInput(const TCHAR* buffer)
02400     {
02401         valuep  = (dvoid*) buffer;
02402         value_sz= buffer? (sb4)(_tcslen(buffer)+1)*sizeof(TCHAR): 0;
02403         dty     = SQLT_STR;
02404         indp    = NULL;
02405     }
02406 
02407     BindInput(const TCHAR* buffer, size_t len, ub2 type=SQLT_AFC, OCIInd* ind=NULL)
02408     {
02409         valuep  = (dvoid*) buffer;
02410         value_sz= (sb4)len;
02411         dty     = type;
02412         indp    = ind;
02413     }
02414 
02415     BindInput(const tstring& str)
02416     {
02417         valuep  = (dvoid*) str.c_str();
02418         value_sz= (sb4)(str.length()+1)*sizeof(TCHAR);
02419         dty     = SQLT_STR;
02420         indp    = NULL;
02421     }
02422 
02423     BindInput(const SqlString& str)
02424     {
02425         valuep  = (dvoid*) str.c_str();
02426         value_sz= (sb4)str.alen()*sizeof(TCHAR);
02427         dty     = SQLT_STR;
02428         indp    = NULL;
02429     }
02430 
02431 #ifdef __ISSD_H
02432     BindInput(const String& str)
02433     {
02434         valuep  = (dvoid*) str.c_str();
02435         value_sz= (sb4)(str.length()+1)*sizeof(TCHAR);
02436         dty     = SQLT_STR;
02437         indp    = NULL;
02438     }
02439 #endif
02440 
02441 /*@todo handle OCIString*
02442     BindInput(SqlString_& str)
02443     {
02444         valuep  = (dvoid*) str.str();
02445         value_sz= str.alen()*sizeof(TCHAR);
02446         dty     = SQLT_VST;
02447         indp    = str.ind();
02448     }
02449 */
02450     BindInput(const OciDate& date)
02451     {
02452         valuep  = &date;
02453         value_sz= sizeof(OCIDate);
02454         dty     = SQLT_ODT;
02455         indp    = date.ind();
02456     }
02457 
02458     BindInput(const OCIDate& date, OCIInd* ind)
02459     {
02460         valuep  = &date;
02461         value_sz= sizeof(OCIDate);
02462         dty     = SQLT_ODT;
02463         indp    = ind;
02464     }
02465 
02466     BindInput(const SqlDateTime& date)
02467     {
02468         valuep  = date.get_ptr();
02469         value_sz= sizeof(ocidatetime);  // 7
02470         dty     = SQLT_DAT;
02471         indp    = date.ind();
02472     }
02473 
02474     BindInput(const ocidatetime& date, OCIInd* ind)
02475     {
02476         valuep  = &date;
02477         value_sz= sizeof(ocidatetime);  // 7
02478         dty     = SQLT_DAT;
02479         indp    = ind;
02480     }
02481 
02482     BindInput(const SqlNumber& num)
02483     {
02484         valuep  = num.get_ptr();
02485         value_sz= sizeof(oraclenumber); // 22
02486         dty     = SQLT_VNU;
02487         indp    = num.ind();
02488     }
02489 
02490     BindInput(const oraclenumber& num, OCIInd* ind)
02491     {
02492         valuep  = &num;
02493         value_sz= sizeof(oraclenumber); // 22
02494         dty     = SQLT_VNU;
02495         indp    = ind;
02496     }
02497 
02498 #if ORACLE_VERSION>=81
02499     BindInput(const OciBlob& blob)
02500     {
02501         valuep  = blob.get_ptr();
02502         value_sz= sizeof(OCILobLocator*);
02503         dty     = SQLT_BLOB;
02504         indp    = blob.ind();
02505     }
02506 
02507     BindInput(const OciClob& clob)
02508     {
02509         valuep  = clob.get_ptr();
02510         value_sz= sizeof(OCIClobLocator*);
02511         dty     = SQLT_CLOB;
02512         indp    = clob.ind();
02513     }
02514 #endif
02515 
02516 protected:
02517     BindInput()
02518     {
02519     }
02520 };
02521 
02522 
02523  /// factory for call parameters of OCI bind functions
02524 
02525 struct BindOutput
02526 {
02527     dvoid*  valuep;
02528     sb4     value_sz;
02529     ub2     dty;
02530     OCIInd* indp;
02531 
02532     BindOutput(SqlInt& var)
02533     {
02534         valuep  = var.get_ref();
02535         value_sz= sizeof(int);
02536         dty     = SQLT_INT;
02537         indp    = var.ind();
02538     }
02539 
02540     BindOutput(int& var, OCIInd* ind=NULL)
02541     {
02542         valuep  = (void*)&var;
02543         value_sz= sizeof(int);
02544         dty     = SQLT_INT;
02545         indp    = ind;
02546     }
02547 
02548     BindOutput(unsigned int& var, OCIInd* ind=NULL)
02549     {
02550         valuep  = (void*)&var;
02551         value_sz= sizeof(unsigned int);
02552         dty     = SQLT_UIN;
02553         indp    = ind;
02554     }
02555 
02556     BindOutput(long& var, OCIInd* ind=NULL)
02557     {
02558         valuep  = (void*)&var;
02559         value_sz= sizeof(long);
02560         dty     = SQLT_INT;
02561         indp    = ind;
02562     }
02563 
02564     BindOutput(unsigned long& var, OCIInd* ind=NULL)
02565     {
02566         valuep  = (void*)&var;
02567         value_sz= sizeof(unsigned long);
02568         dty     = SQLT_UIN;
02569         indp    = ind;
02570     }
02571 
02572     BindOutput(char& var, OCIInd* ind=NULL)
02573     {
02574         valuep  = (void*)&var;
02575         value_sz= sizeof(char);
02576         dty     = SQLT_CHR;
02577         indp    = ind;
02578     }
02579 
02580     BindOutput(float& var, OCIInd* ind=NULL)
02581     {
02582         valuep  = (void*)&var;
02583         value_sz= sizeof(float);
02584         dty     = SQLT_FLT;
02585         indp    = ind;
02586     }
02587 
02588     BindOutput(double& var, OCIInd* ind=NULL)
02589     {
02590         valuep  = (void*)&var;
02591         value_sz= sizeof(double);
02592         dty     = SQLT_FLT;
02593         indp    = ind;
02594     }
02595 
02596     BindOutput(TCHAR* buffer)
02597     {
02598         valuep  = (dvoid*) buffer;
02599         value_sz= buffer? (sb4)(_tcslen(buffer)+1)*sizeof(TCHAR): 0;
02600         dty     = SQLT_STR;
02601         indp    = NULL;
02602     }
02603 
02604     BindOutput(TCHAR* buffer, size_t len, ub2 type=SQLT_AFC, OCIInd* ind=NULL)
02605     {
02606         valuep  = (dvoid*) buffer;
02607         value_sz= (sb4)len;
02608         dty     = type;
02609         indp    = ind;
02610     }
02611 
02612     BindOutput(tstring& str)
02613     {
02614         valuep  = (dvoid*) str.c_str();
02615         value_sz= (sb4)(str.length()+1)*sizeof(TCHAR);
02616         dty     = SQLT_STR;
02617         indp    = NULL;
02618     }
02619 
02620     BindOutput(SqlString& str)
02621     {
02622         valuep  = (dvoid*) str.str();
02623         value_sz= (sb4)str.alen()*sizeof(TCHAR);
02624         dty     = SQLT_STR;
02625         indp    = str.ind();
02626     }
02627 
02628 /*@todo handle OCIString*
02629     BindOutput(SqlString_& str)
02630     {
02631         valuep  = (dvoid*) str.str();
02632         value_sz= str.alen()*sizeof(TCHAR);
02633         dty     = SQLT_VST;
02634         indp    = str.ind();
02635     }
02636 */
02637     BindOutput(OciDate& date)
02638     {
02639         valuep  = &date;
02640         value_sz= sizeof(OCIDate);
02641         dty     = SQLT_ODT;
02642         indp    = date.ind();
02643     }
02644 
02645     BindOutput(SqlDateTime& date)
02646     {
02647         valuep  = date.get_ref();
02648         value_sz= sizeof(ocidatetime);  // 7
02649         dty     = SQLT_DAT;
02650         indp    = date.ind();
02651     }
02652 
02653     BindOutput(SqlNumber& num)
02654     {
02655         valuep  = num.get_ref();
02656         value_sz= sizeof(oraclenumber); // 22
02657         dty     = SQLT_VNU;
02658         indp    = num.ind();
02659     }
02660 
02661 #if ORACLE_VERSION>=81
02662     BindOutput(OciBlob& blob)
02663     {
02664         valuep  = blob.get_ref();
02665         value_sz= sizeof(OCILobLocator*);
02666         dty     = SQLT_BLOB;
02667         indp    = blob.ind();
02668     }
02669 
02670     BindOutput(OciClob& clob)
02671     {
02672         valuep  = clob.get_ref();
02673         value_sz= sizeof(OCIClobLocator*);
02674         dty     = SQLT_CLOB;
02675         indp    = clob.ind();
02676     }
02677 #endif
02678 
02679 protected:
02680     BindOutput()
02681     {
02682     }
02683 };
02684 
02685 
02686  /// Binding of input strings with trimming to the specified maximum length
02687 
02688 struct TrimBindPar : BindInput
02689 {
02690     TrimBindPar(const TCHAR* buffer, size_t max_len)
02691     {
02692         size_t len = _tcslen(buffer);
02693 
02694         valuep  = (dvoid*) buffer;
02695         value_sz= (sb4)min(len, max_len)*sizeof(TCHAR);
02696         dty     = SQLT_AFC;
02697         indp    = NULL;
02698     }
02699 
02700     TrimBindPar(const tstring& str, size_t max_len)
02701     {
02702         size_t len = str.length();
02703 
02704         valuep  = (dvoid*) str.c_str();
02705         value_sz= (sb4)min(len, max_len)*sizeof(TCHAR);
02706         dty     = SQLT_AFC;
02707         indp    = NULL;
02708     }
02709 
02710     TrimBindPar(const SqlString& str, size_t max_len)
02711     {
02712         size_t len = str.len();
02713 
02714         valuep  = (dvoid*) str.c_str();
02715         value_sz= (sb4)min(len, max_len)*sizeof(TCHAR);
02716         dty     = SQLT_AFC;
02717         indp    = NULL;
02718     }
02719 };
02720 
02721 
02722  /// factory for call parameters for OCI define functions
02723 
02724 struct DefinePar
02725 {
02726     dvoid*  valuep;
02727     sb4     value_sz;
02728     ub2     dty;
02729     OCIInd* indp;
02730     int     buffers;
02731 
02732     DefinePar(SqlInt& var)
02733     {
02734         valuep  = var.get_ref();
02735         value_sz= sizeof(int);
02736         dty     = SQLT_INT;
02737         indp    = var.ind();
02738         buffers = 1;
02739     }
02740     DefinePar(SqlIntArray& arr)
02741     {
02742         valuep  = arr.get_ref(0);
02743         value_sz= sizeof(int);
02744         dty     = SQLT_INT;
02745         indp    = arr.ind(0);
02746         buffers = arr.get_buffer_count();
02747     }
02748 
02749     DefinePar(int& var, OCIInd* ind=NULL)
02750     {
02751         valuep  = &var;
02752         value_sz= sizeof(int);
02753         dty     = SQLT_INT;
02754         indp    = ind;
02755         buffers = 1;
02756     }
02757     DefinePar(int* arr, int count, OCIInd* ind=NULL)
02758     {
02759         valuep  = arr;
02760         value_sz= sizeof(int);
02761         dty     = SQLT_INT;
02762         indp    = ind;
02763         buffers = count;
02764     }
02765 
02766     DefinePar(unsigned int& var, OCIInd* ind=NULL)
02767     {
02768         valuep  = &var;
02769         value_sz= sizeof(unsigned int);
02770         dty     = SQLT_UIN;
02771         indp    = ind;
02772         buffers = 1;
02773     }
02774     DefinePar(unsigned int* arr, int count, OCIInd* ind=NULL)
02775     {
02776         valuep  = arr;
02777         value_sz= sizeof(unsigned int);
02778         dty     = SQLT_UIN;
02779         indp    = ind;
02780         buffers = count;
02781     }
02782 
02783     DefinePar(LONGLONG& var, OCIInd* ind=NULL)
02784     {
02785         valuep  = &var;
02786         value_sz= sizeof(LONGLONG);
02787         dty     = SQLT_INT;
02788         indp    = ind;
02789         buffers = 1;
02790     }
02791     DefinePar(LONGLONG* arr, int count, OCIInd* ind=NULL)
02792     {
02793         valuep  = arr;
02794         value_sz= sizeof(LONGLONG);
02795         dty     = SQLT_INT;
02796         indp    = ind;
02797         buffers = count;
02798     }
02799 
02800     DefinePar(long& var, OCIInd* ind=NULL)
02801     {
02802         valuep  = &var;
02803         value_sz= sizeof(long);
02804         dty     = SQLT_INT;
02805         indp    = ind;
02806         buffers = 1;
02807     }
02808     DefinePar(long* arr, int count, OCIInd* ind=NULL)
02809     {
02810         valuep  = arr;
02811         value_sz= sizeof(long);
02812         dty     = SQLT_INT;
02813         indp    = ind;
02814         buffers = count;
02815     }
02816 
02817     DefinePar(unsigned long& var, OCIInd* ind=NULL)
02818     {
02819         valuep  = &var;
02820         value_sz= sizeof(unsigned long);
02821         dty     = SQLT_UIN;
02822         indp    = ind;
02823         buffers = 1;
02824     }
02825     DefinePar(unsigned long* arr, int count, OCIInd* ind=NULL)
02826     {
02827         valuep  = arr;
02828         value_sz= sizeof(unsigned long);
02829         dty     = SQLT_UIN;
02830         indp    = ind;
02831         buffers = count;
02832     }
02833 
02834     DefinePar(double& var, OCIInd* ind=NULL)
02835     {
02836         valuep  = &var;
02837         value_sz= sizeof(double);
02838         dty     = SQLT_FLT;
02839         indp    = ind;
02840         buffers = 1;
02841     }
02842     DefinePar(double* arr, int count, OCIInd* ind=NULL)
02843     {
02844         valuep  = arr;
02845         value_sz= sizeof(double);
02846         dty     = SQLT_FLT;
02847         indp    = ind;
02848         buffers = count;
02849     }
02850 
02851 #ifdef SQLT_BFLOAT
02852     DefinePar(float& var, OCIInd* ind=NULL)
02853     {
02854         valuep  = &var;
02855         value_sz= sizeof(float);
02856         dty     = SQLT_FLT;
02857         indp    = ind;
02858         buffers = 1;
02859     }
02860     DefinePar(float* arr, int count, OCIInd* ind=NULL)
02861     {
02862         valuep  = arr;
02863         value_sz= sizeof(float);
02864         dty     = SQLT_FLT;
02865         indp    = ind;
02866         buffers = count;
02867     }
02868 #endif
02869 
02870     DefinePar(char& var, OCIInd* ind=NULL)
02871     {
02872         valuep  = (void*)&var;
02873         value_sz= sizeof(char);
02874         dty     = SQLT_CHR;
02875         indp    = ind;
02876         buffers = 1;
02877     }
02878 
02879     DefinePar(const TCHAR* buffer, size_t len, ub2 type=SQLT_STR, OCIInd* ind=NULL)
02880     {
02881         valuep  = (dvoid*) buffer;
02882         value_sz= (sb4)len*sizeof(TCHAR);
02883         dty     = type;
02884         indp    = ind;
02885         buffers = 1;
02886     }
02887 
02888     DefinePar(SqlString& str)
02889     {
02890         valuep  = str.str();
02891         value_sz= (sb4)str.alen()*sizeof(TCHAR);
02892         dty     = SQLT_STR;
02893         indp    = str.ind();
02894         buffers = 1;
02895     }
02896     DefinePar(SqlStringArray& arr)
02897     {
02898         valuep  = arr.str(0);
02899         value_sz= (sb4)arr.alen()*sizeof(TCHAR);
02900         dty     = SQLT_STR;
02901         indp    = arr.ind(0);
02902         buffers = arr.get_buffer_count();
02903     }
02904 
02905 /*@todo handle OCIString*
02906     DefinePar(SqlString& str)
02907     {
02908         valuep  = str.str();
02909         value_sz= (sb4)str.alen()*sizeof(TCHAR);
02910         dty     = SQLT_VST;
02911         indp    = str.ind();
02912         buffers = 1;
02913     }
02914 */
02915 
02916     DefinePar(OciDate& date)
02917     {
02918         valuep  = &date;
02919         value_sz= sizeof(OCIDate);
02920         dty     = SQLT_ODT;
02921         indp    = date.ind();
02922         buffers = 1;
02923     }
02924     DefinePar(OciDateArray& arr)
02925     {
02926         valuep  = arr.get_ref(0);
02927         value_sz= sizeof(OCIDate);
02928         dty     = SQLT_ODT;
02929         indp    = arr.ind(0);
02930         buffers = arr.get_buffer_count();
02931     }
02932 
02933     DefinePar(SqlDateTime& date)
02934     {
02935         valuep  = date.get_ref();
02936         value_sz= sizeof(ocidatetime);  // 7
02937         dty     = SQLT_DAT;
02938         indp    = date.ind();
02939         buffers = 1;
02940     }
02941     DefinePar(SqlDateTimeArray& arr)
02942     {
02943         valuep  = arr.get_ref(0);
02944         value_sz= sizeof(ocidatetime);  // 7
02945         dty     = SQLT_DAT;
02946         indp    = arr.ind(0);
02947         buffers = arr.get_buffer_count();
02948     }
02949 
02950     DefinePar(SqlNumber& num)
02951     {
02952         valuep  = num.get_ref();
02953         value_sz= sizeof(oraclenumber); // 22
02954         dty     = SQLT_VNU;
02955         indp    = num.ind();
02956         buffers = 1;
02957     }
02958     DefinePar(SqlNumberArray& arr)
02959     {
02960         valuep  = arr.get_ref(0);
02961         value_sz= sizeof(oraclenumber); // 22
02962         dty     = SQLT_VNU;
02963         indp    = arr.ind(0);
02964         buffers = arr.get_buffer_count();
02965     }
02966 
02967 #if ORACLE_VERSION>=81
02968     DefinePar(OciBlob& blob)
02969     {
02970         valuep  = blob.get_ref();
02971         value_sz= sizeof(OCILobLocator*);
02972         dty     = SQLT_BLOB;
02973         indp    = blob.ind();
02974         buffers = 1;
02975     }
02976 
02977     DefinePar(OciClob& clob)
02978     {
02979         valuep  = clob.get_ref();
02980         value_sz= sizeof(OCIClobLocator*);
02981         dty     = SQLT_CLOB;
02982         indp    = clob.ind();
02983         buffers = 1;
02984     }
02985 #endif
02986 };
02987 
02988 
02989 struct LocalOciState
02990 {
02991     LocalOciState(OciContext& ctx, OCI_STATE state)
02992      :  _ctx(ctx)
02993     {
02994         _ctx.set_state(state);
02995     }
02996 
02997     LocalOciState(OciContext& ctx, OCI_STATE state, int stmt_type)
02998      :  _ctx(ctx)
02999     {
03000         _ctx.set_state(state, stmt_type);
03001     }
03002 
03003     ~LocalOciState()
03004     {
03005         _ctx.reset_state();
03006     }
03007 
03008 private:
03009     OciContext& _ctx;
03010 };
03011 
03012 
03013  /// an OCI SQL statement
03014 
03015 struct SqlStatement : public OciHandle<OCIStmt>
03016 {
03017     typedef OciHandle<OCIStmt> super;
03018 
03019     SqlStatement(OciConnection& conn, int bulk_rows=g_OCIPL_BULK_ROWS)
03020      :  super(conn._env),
03021         _ctx(conn._ctx),
03022         _state(UNINITIALIZED),
03023         _last_file(NULL),
03024         _last_line(-1),
03025         _res(NULL),
03026         _stmt_type(-1),
03027         _bulk_rows(bulk_rows),
03028         _result_buffers(0),
03029         _last_row((ub4)-1),
03030         _last_fetched_row((ub4)-1)
03031     {
03032     }
03033 
03034 #ifndef FORCE_CODEPOS
03035     SqlStatement(OciConnection& conn, const tstring& sql, ub4 lang=OCI_NTV_SYNTAX, int bulk_rows=g_OCIPL_BULK_ROWS)
03036      :  super(conn._env),
03037         _ctx(conn._ctx),
03038         _state(UNINITIALIZED),
03039         _last_file(NULL),
03040         _last_line(-1),
03041         _res(NULL),
03042         _stmt_type(-1),
03043         _bulk_rows(bulk_rows),
03044         _result_buffers(0),
03045         _last_row((ub4)-1),
03046         _last_fetched_row((ub4)-1)
03047     {
03048         prepare(sql, lang);
03049     }
03050 #endif
03051 
03052     SqlStatement(OciConnection& conn, const tstring& sql, const char* file, int line, ub4 lang=OCI_NTV_SYNTAX, int bulk_rows=g_OCIPL_BULK_ROWS)
03053      :  super(conn._env),
03054         _ctx(conn._ctx),
03055         _state(UNINITIALIZED),
03056         _last_file(NULL),
03057         _last_line(-1),
03058         _res(NULL),
03059         _stmt_type(-1),
03060         _bulk_rows(bulk_rows),
03061         _result_buffers(0),
03062         _last_row((ub4)-1),
03063         _last_fetched_row((ub4)-1)
03064     {
03065         prepare(sql, file, line, lang);
03066     }
03067 
03068     virtual ~SqlStatement();
03069 
03070 
03071 protected:
03072 
03073     enum _NO_ALLOC_ {NO_HANDLE_ALLOC};
03074 
03075     SqlStatement(OciConnection& conn, int bulk_rows, _NO_ALLOC_)
03076      :  super(conn._env, NULL),
03077         _ctx(conn._ctx),
03078         _state(UNINITIALIZED),
03079         _last_file(NULL),
03080         _last_line(-1),
03081         _res(NULL),
03082         _stmt_type(-1),
03083         _bulk_rows(bulk_rows),
03084         _result_buffers(0),
03085         _last_row((ub4)-1),
03086         _last_fetched_row((ub4)-1)
03087     {
03088     }
03089 
03090     OciContext& _ctx;
03091 
03092     enum STATE {
03093         UNINITIALIZED=0,
03094         PREPARED=1, DEFINED=2, EXECUTED=4, FETCHED=8,
03095         EOF_DATA=16, STMT_ERROR=32
03096     };
03097     int _state;
03098 
03099     tstring _last_sql;
03100     const char* _last_file;
03101     int         _last_line;
03102 
03103     struct SqlResult* _res;
03104 
03105     mutable int _stmt_type;
03106 
03107     int _bulk_rows;
03108     int _result_buffers;
03109 
03110 
03111 public:
03112 
03113     bool eof() const {return _state >= EOF_DATA;}
03114 
03115 
03116      // Preparation of a SQL statement
03117 
03118 #ifndef FORCE_CODEPOS
03119     void    prepare(const tstring& sql, ub4 lang=OCI_NTV_SYNTAX);
03120 #endif
03121 
03122     virtual void prepare(const tstring& sql, const char* file, int line, ub4 lang=OCI_NTV_SYNTAX);
03123 
03124 
03125      // get type of prepared statement
03126 
03127     int get_stmt_type() const;  // return OCI_STMT_SELECT, OCI_STMT_UPDATE, ...
03128 
03129 
03130     const tstring& get_last_sql() const
03131     {
03132         return _last_sql;
03133     }
03134 
03135     const char* get_last_file() const
03136     {
03137         return _last_file;
03138     }
03139 
03140     int get_last_line() const
03141     {
03142         return _last_line;
03143     }
03144 
03145 
03146      // get number of fetched rows in the last call
03147 
03148     ub4 fetched_rows() const;
03149 
03150 
03151      // get total number of processed rows of this statement
03152 
03153     ub4 row_count() const;
03154 
03155 
03156      // get size of result buffer in data rows
03157 
03158     int result_buffers() const
03159     {
03160         return _result_buffers;
03161     }
03162 
03163 
03164      // Binding of input variables
03165 
03166     OCIBind* bind_input(int idx, BindInput par, OCIBind* bindp=NULL)                // binding by position
03167     {
03168         sword res = OCIBindByPos(_handle/*stmtp*/, &bindp, _env._errh, idx+1,
03169                                     const_cast<void*>(par.valuep), par.value_sz, par.dty,
03170                                     const_cast<OCIInd*>(par.indp), 0/*alenp*/, 0/*rcodep*/,
03171                                     0/*maxarr_len*/, 0/*curelep*/, OCI_DEFAULT);
03172         oci_check_error(_env, res);
03173 
03174         return bindp;   // Implicitly allocated bind handles are freed automatically with the statement handle.
03175     }
03176 
03177     OCIBind* bind_input(const tstring& name, BindInput par, OCIBind* bindp=NULL)    // binding by name
03178     {
03179         sword res = OCIBindByName(_handle/*stmtp*/, &bindp, _env._errh, (OraText*)name.c_str(), (sb4)name.length()*sizeof(TOraText),
03180                                     const_cast<void*>(par.valuep), par.value_sz, par.dty,
03181                                     const_cast<OCIInd*>(par.indp), 0/*alenp*/, 0/*rcodep*/,
03182                                     0/*maxarr_len*/, 0/*curelep*/, OCI_DEFAULT);
03183         oci_check_error(_env, res);
03184 
03185         return bindp;   // Implicitly allocated bind handles are freed automatically with the statement handle.
03186     }
03187 
03188 
03189      // Binding of output variables
03190 
03191     OCIBind* bind_output(int idx, BindOutput par, OCIBind* bindp=NULL)              // binding by position
03192     {
03193         sword res = OCIBindByPos(_handle/*stmtp*/, &bindp, _env._errh, idx+1,
03194                                     par.valuep, par.value_sz, par.dty,
03195                                     par.indp, 0/*alenp*/, 0/*rcodep*/,
03196                                     0/*maxarr_len*/, 0/*curelep*/, OCI_DEFAULT);
03197         oci_check_error(_env, res);
03198 
03199         return bindp;   // Implicitly allocated bind handles are freed automatically with the statement handle.
03200     }
03201 
03202     OCIBind* bind_output(const tstring& name, BindOutput par, OCIBind* bindp=NULL)  // binding by name
03203     {
03204         sword res = OCIBindByName(_handle/*stmtp*/, &bindp, _env._errh, (OraText*)name.c_str(), (sb4)name.length()*sizeof(TOraText),
03205                                     par.valuep, par.value_sz, par.dty,
03206                                     par.indp, 0/*alenp*/, 0/*rcodep*/,
03207                                     0/*maxarr_len*/, 0/*curelep*/, OCI_DEFAULT);
03208         oci_check_error(_env, res);
03209 
03210         return bindp;   // Implicitly allocated bind handles are freed automatically with the statement handle.
03211     }
03212 
03213     OCIBind* bind_inout(int idx, BindOutput par, OCIBind* bindp=NULL)
03214     {
03215         return bind_output(idx, par, bindp);
03216     }
03217 
03218     OCIBind* bind_inout(const tstring& name, BindOutput par, OCIBind* bindp=NULL)
03219     {
03220         return bind_output(name, par, bindp);
03221     }
03222 
03223 
03224      // Definition of variables to receive query results
03225 
03226     OCIDefine* bind_result(int idx, DefinePar par, OCIDefine* defnp=NULL);
03227 
03228 
03229      // define all columns of a complete recordset
03230 
03231     void bind_result(struct SqlRecord& rec);
03232 
03233 
03234      // execute a prepared SQL statement
03235 
03236     void execute()
03237     {
03238         int rows = get_stmt_type()==OCI_STMT_SELECT? 0: 1;
03239 
03240         execute(rows);
03241     }
03242 
03243     void execute(ub4 rows, ub4 mode=OCI_DEFAULT);
03244 
03245 #ifndef FORCE_CODEPOS
03246     void execute(const tstring& sql)
03247     {
03248         prepare(sql);
03249 
03250         int rows = get_stmt_type()==OCI_STMT_SELECT? 0: 1;
03251 
03252         execute(rows);
03253     }
03254 #endif
03255 
03256     void execute(const tstring& sql, const char* file, int line)
03257     {
03258         prepare(sql, file, line);
03259 
03260         int rows = get_stmt_type()==OCI_STMT_SELECT? 0: 1;
03261 
03262         execute(rows);
03263     }
03264 
03265 #ifndef FORCE_CODEPOS
03266     void execute(const tstring& sql, ub4 rows)
03267     {
03268         prepare(sql);
03269 
03270         execute(rows);
03271     }
03272 #endif
03273 
03274     void execute(const tstring& sql, const char* file, int line, ub4 rows)
03275     {
03276         prepare(sql, file, line);
03277 
03278         execute(rows);
03279     }
03280 
03281     void ensure_execute()
03282     {
03283         if (!(_state & EXECUTED))
03284             execute();
03285     }
03286 
03287 
03288      // execute a SQL statement and fetch rows of the result set (default number of rows: _bulk_rows)
03289 
03290     void execute_fetch(ub4 mode=OCI_DEFAULT);
03291 
03292 #ifndef FORCE_CODEPOS
03293     void execute_fetch(const tstring& sql, ub4 lang=OCI_NTV_SYNTAX, ub4 mode=OCI_DEFAULT)
03294     {
03295         prepare(sql, lang);
03296 
03297         execute_fetch(mode);
03298     }
03299 #endif
03300 
03301     void execute_fetch(const tstring& sql, const char* file, int line, ub4 lang=OCI_NTV_SYNTAX, ub4 mode=OCI_DEFAULT)
03302     {
03303         prepare(sql, file, line, lang);
03304 
03305         execute_fetch(mode);
03306     }
03307 
03308 
03309      // fetch the next rows of a result set (default number of rows: _bulk_rows)
03310     void fetch(ub4 rows=(ub4)-1);
03311 
03312 
03313      // next() is used to iterate through result sets without using bulk mode fetching.
03314 
03315     bool next()
03316     {
03317         if (!eof()) {
03318             fetch(1);
03319 
03320             return fetched_rows() > 0;
03321         } else
03322             return false;
03323     }
03324 
03325 
03326      // utility functions for bulk mode fetching
03327 
03328     int first_bulk()
03329     {
03330         if (_state & EXECUTED)
03331             fetch();
03332         else
03333             execute_fetch();
03334 
03335         return fetched_rows();
03336     }
03337 
03338     int next_bulk()
03339     {
03340         if (!eof()) {
03341             fetch();
03342 
03343             return fetched_rows();
03344         } else
03345             return 0;
03346     }
03347 
03348 
03349     ub4 get_column_count() const
03350     {
03351         ub4 count;
03352         ub4 size = sizeof(count);
03353 
03354         sword res = OCIAttrGet(_handle, super::get_type_id(), &count, &size, OCI_ATTR_PARAM_COUNT, _env._errh);
03355         oci_check_error(_env, res);
03356 
03357         return count;
03358     }
03359 
03360     void get_column_type(int idx, ColumnType& info) const;
03361 
03362 
03363     void print_results(tostream& out, bool header=true);
03364 
03365     void print_results(const tstring& sql, tostream& out, bool header=true)
03366     {
03367         execute(sql, CODEPOS);
03368 
03369         if (!eof())
03370             print_results(out, header);
03371     }
03372 
03373 
03374     const SqlResult& get_result()
03375     {
03376         if (!(_state & EXECUTED))
03377             execute();
03378 
03379         return *_res;
03380     }
03381 
03382 
03383 #ifdef _XMLSTORAGE_H
03384     void dump_results(XMLStorage::XMLPos& pos, const XMLStorage::XS_String& element_name);
03385     void dump_results(XMLStorage::XMLWriter& writer, const XMLStorage::XS_String& element_name);
03386 
03387     void dump_results(const tstring& sql, XMLStorage::XMLPos& pos, const XMLStorage::XS_String& element_name)
03388     {
03389         execute(sql, CODEPOS);
03390 
03391         if (!eof())
03392             dump_results(pos, element_name);
03393     }
03394 
03395     void dump_results(const tstring& sql, XMLStorage::XMLWriter& writer, const XMLStorage::XS_String& element_name)
03396     {
03397         execute(sql, CODEPOS);
03398 
03399         if (!eof())
03400             dump_results(writer, element_name);
03401     }
03402 #endif
03403 
03404 
03405     SqlResult* operator->()
03406     {
03407         if (!_res)
03408             fetch();
03409 
03410         return _res;
03411     }
03412 
03413 protected:
03414     void execute_internal(ub4 rows, ub4 mode);
03415 
03416     ub4 _last_row;
03417     ub4 _last_fetched_row;
03418 };
03419 
03420 
03421 #if ORACLE_VERSION>=90
03422 
03423 struct SqlCacheStmt : public SqlStatement
03424 {
03425     typedef SqlStatement super;
03426 
03427     SqlCacheStmt(OciConnection& conn, int bulk_rows=g_OCIPL_BULK_ROWS)
03428      :  super(conn, bulk_rows, NO_HANDLE_ALLOC),
03429         _stmt_cache(conn._stmt_cache)
03430     {
03431     }
03432 
03433 #ifndef FORCE_CODEPOS
03434     SqlCacheStmt(OciConnection& conn, const tstring& sql, ub4 lang=OCI_NTV_SYNTAX, int bulk_rows=g_OCIPL_BULK_ROWS)
03435      :  super(conn, bulk_rows, NO_HANDLE_ALLOC),
03436         _stmt_cache(conn._stmt_cache)
03437     {
03438         prepare(sql, NULL, -1, lang);
03439     }
03440 #endif
03441 
03442     SqlCacheStmt(OciConnection& conn, const tstring& sql, const char* file, int line, ub4 lang=OCI_NTV_SYNTAX, int bulk_rows=g_OCIPL_BULK_ROWS)
03443      :  super(conn, bulk_rows, NO_HANDLE_ALLOC),
03444         _stmt_cache(conn._stmt_cache)
03445     {
03446         prepare(sql, file, line, lang);
03447     }
03448 
03449     virtual ~SqlCacheStmt();
03450 
03451     void    prepare(const tstring& sql, ub4 lang=OCI_NTV_SYNTAX);
03452 
03453     virtual void prepare(const tstring& sql, const char* file, int line, ub4 lang=OCI_NTV_SYNTAX);
03454 
03455     void    release();
03456 
03457 protected:
03458     StatementCache& _stmt_cache;
03459     tstring     _tag;
03460 };
03461 
03462 #endif
03463 
03464 
03465  /// variant array to be used as bind variable buffer
03466 
03467 struct SqlVariantArray
03468 {
03469     SqlVariantArray()
03470      :  _data_type(0)
03471     {
03472         _punion_ptr = NULL;
03473     }
03474 
03475     SqlVariantArray(const ColumnTypeInfo& type, int size);
03476     SqlVariantArray(const SqlVariantArray& other);
03477     ~SqlVariantArray() {clear();}
03478 
03479     void clear();
03480     void assign(const SqlVariantArray& other);
03481 
03482     ub2 get_data_type() const
03483         {return _data_type;}
03484 
03485     SqlVariantArray& operator=(const SqlVariantArray& other) {assign(other); return *this;}
03486 
03487     tstring str(int row, OCIError* errh) const;
03488     SqlNumber number(int row, OCIError* errh) const;
03489     OciDate oci_date(int row, OCIError* errh) const;
03490     SqlDateTime sql_date(int row, OCIError* errh) const;
03491 
03492     bool is_null(int row) const {return !is_not_null(row);}
03493     bool is_not_null(int row) const;
03494 
03495     void bind_result(SqlStatement& stmt, int idx);
03496 
03497     void set_string(int row, const TCHAR* str);
03498     void set_number(int row, const SqlNumber& num);
03499     void set_date(int row, const OciDate& date);
03500     void set_datetime(int row, const SqlDateTime& datetime);
03501 #ifdef SQLT_BFLOAT
03502     void set_float(int row, float f);
03503     void set_double(int row, double d);
03504 #endif
03505 
03506     void bind_input(SqlStatement& stmt, int idx, int row);
03507 
03508 protected:
03509     union {
03510         SqlStringArray* _pstring;
03511         SqlNumberArray* _pnumber;
03512         OciDateArray*   _poci_date;
03513         SqlDateTimeArray*_psql_date;
03514 //      OciBlobArray*   _pblob;
03515 //      OciClobArray*   _pclob;
03516         void*   _punion_ptr;
03517 #ifdef SQLT_BFLOAT
03518         float*      _pfloat;
03519         double*     _pdouble;
03520 #endif
03521     };
03522 
03523     int _size;
03524     ub2 _data_type;
03525 
03526 //  static SqlVariantArray s_empty;
03527 };
03528 
03529 
03530  /// a record to hold return columns for a given statement
03531 
03532 struct SqlRecord
03533 {
03534     SqlRecord(SqlStatement& stmt, int rows);
03535     SqlRecord(OciEnv& env, size_t column_cnt) : _env(_env) {_values.resize(column_cnt);}
03536 
03537     ~SqlRecord();
03538 
03539     size_t get_column_count() const
03540         {return _values.size();}
03541 
03542     SqlVariantArray& get_column(int idx)
03543         {return *_values[idx]._pvar;}
03544     ColumnType& get_column_type(int idx)
03545         {return _values[idx]._type;}
03546 
03547     const SqlVariantArray& get_column(int idx) const
03548         {return *_values[idx]._pvar;}
03549     const ColumnType& get_column_type(int idx) const
03550         {return _values[idx]._type;}
03551 
03552     const ColumnType& get_column_type(const tstring& col_name) const;
03553     const SqlVariantArray& get_column(const tstring& col_name) const;
03554 
03555     void bind_result(SqlStatement& stmt);
03556 
03557     void alloc_column(size_t col_idx, const ColumnTypeInfo& type, int rows); // allocate buffers for bind variables
03558 
03559     void print_columns(tostream& out);
03560     void print_values(tostream& out, int row);
03561 
03562 #ifdef _XMLSTORAGE_H
03563     void dump_values(XMLStorage::XMLPos& out, int row);
03564     void dump_values(XMLStorage::XMLWriter& writer, int row);
03565 #endif
03566 
03567 protected:
03568      /// data structure for the content of single column
03569     struct Data {
03570         Data() : _pvar(NULL) {}
03571 
03572         SqlVariantArray* _pvar;
03573         ColumnType  _type;
03574 #ifdef _DEBUG
03575         tstring _col_name;
03576 #endif
03577     };
03578     typedef std::vector<Data> ColumnVector;
03579 
03580     ColumnVector _values;
03581 
03582     typedef std::map<tstring, int> NameMap;
03583     mutable NameMap _name_map;
03584 
03585     NameMap::const_iterator find_column(const tstring& col_name) const;
03586 
03587 public:
03588     OciEnv& _env;
03589 };
03590 
03591 
03592  /// class to retrieve query result values
03593 
03594 struct SqlResult : public SqlRecord
03595 {
03596     SqlResult(SqlStatement& stmt, int rows=1)
03597      :  SqlRecord(stmt, rows)
03598     {
03599         bind_result(stmt);
03600     }
03601 
03602     bool is_null(int idx, int row) const
03603     {
03604         return get_column(idx).is_null(row);
03605     }
03606     int is_null(const tstring& col_name, int row) const
03607     {
03608         return get_column(col_name).is_null(row);
03609     }
03610 
03611     bool is_not_null(int idx, int row) const
03612     {
03613         return get_column(idx).is_not_null(row);
03614     }
03615     int is_not_null(const tstring& col_name, int row) const
03616     {
03617         return get_column(col_name).is_not_null(row);
03618     }
03619 
03620     int get_int(int idx, int row, int null=INT_NULL) const
03621     {
03622         return get_column(idx).number(row, _env._errh).get_int(_env._errh, null);
03623     }
03624     int get_int(const tstring& col_name, int row, int null=INT_NULL) const
03625     {
03626         return get_column(col_name).number(row, _env._errh).get_int(_env._errh, null);
03627     }
03628 
03629 #ifdef _MSC_VER
03630     LONGLONG get_int64(int idx, int row, int null=INT_NULL) const
03631     {
03632         return get_column(idx).number(row, _env._errh).get_int64(_env._errh, null);
03633     }
03634     LONGLONG get_int64(const tstring& col_name, int row, int null=INT_NULL) const
03635     {
03636         return get_column(col_name).number(row, _env._errh).get_int64(_env._errh, null);
03637     }
03638 #endif
03639 
03640     double get_double(int idx, int row, double null=0.) const
03641     {
03642         return get_column(idx).number(row, _env._errh).get_double(_env._errh, null);
03643     }
03644     double get_double(const tstring& col_name, int row, double null=0.) const
03645     {
03646         return get_column(col_name).number(row, _env._errh).get_double(_env._errh, null);
03647     }
03648 
03649     SqlNumber get_number(int idx, int row) const
03650     {
03651         return get_column(idx).number(row, _env._errh);
03652     }
03653     SqlNumber get_number(const tstring& col_name, int row) const
03654     {
03655         return get_column(col_name).number(row, _env._errh);
03656     }
03657 
03658     tstring get_string(int idx, int row) const
03659     {
03660         return get_column(idx).str(row, _env._errh);
03661     }
03662     tstring get_string(const tstring& col_name, int row) const
03663     {
03664         return get_column(col_name).str(row, _env._errh);
03665     }
03666 
03667     OciDate get_oci_date(int idx, int row) const
03668     {
03669         return get_column(idx).oci_date(row, _env._errh);
03670     }
03671     OciDate get_oci_date(const tstring& col_name, int row) const
03672     {
03673         return get_column(col_name).oci_date(row, _env._errh);
03674     }
03675 
03676     SqlDateTime get_sql_date(int idx, int row) const
03677     {
03678         return get_column(idx).sql_date(row, _env._errh);
03679     }
03680     SqlDateTime get_sql_date(const tstring& col_name, int row) const
03681     {
03682         return get_column(col_name).sql_date(row, _env._errh);
03683     }
03684 };
03685 
03686 
03687  /// iterator utilizing bulk mode fetching
03688 
03689 struct ResultIterator
03690 {
03691     typedef ResultIterator myType;
03692 
03693     ResultIterator(SqlStatement& stmt)
03694      :  _stmt(stmt),
03695         _row_idx(0),
03696         _row_nr(1)
03697     {
03698         _fetched = stmt.first_bulk();
03699     }
03700 
03701     int get_row_idx() const
03702     {
03703         return _row_idx;
03704     }
03705 
03706     operator int() const
03707     {
03708         return _row_idx;
03709     }
03710 
03711     int get_row_nr() const
03712     {
03713         return _row_nr;
03714     }
03715 
03716     bool has_next()
03717     {
03718         return _row_idx < _fetched;
03719     }
03720 
03721     myType& operator++()
03722     {
03723         if (++_row_idx >= _fetched) {
03724             _fetched = _stmt.next_bulk();
03725 
03726             if (_fetched) {
03727                 _row_idx = 0;
03728                 ++_row_nr;
03729             }
03730         } else
03731             ++_row_nr;
03732 
03733         return *this;
03734     }
03735 
03736     bool is_null(int idx) const
03737     {
03738         return _stmt->is_null(idx, _row_idx);
03739     }
03740     int is_null(const tstring& col_name) const
03741     {
03742         return _stmt->is_null(col_name, _row_idx);
03743     }
03744 
03745     bool is_not_null(int idx) const
03746     {
03747         return _stmt->is_not_null(idx, _row_idx);
03748     }
03749     int is_not_null(const tstring& col_name) const
03750     {
03751         return _stmt->is_not_null(col_name, _row_idx);
03752     }
03753 
03754     int get_int(int idx) const
03755     {
03756         return _stmt->get_int(idx, _row_idx);
03757     }
03758     int get_int(const tstring& col_name) const
03759     {
03760         return _stmt->get_int(col_name, _row_idx);
03761     }
03762 
03763 #ifdef _MSC_VER
03764     LONGLONG get_int64(int idx) const
03765     {
03766         return _stmt->get_int64(idx, _row_idx);
03767     }
03768     LONGLONG get_int64(const tstring& col_name) const
03769     {
03770         return _stmt->get_int64(col_name, _row_idx);
03771     }
03772 #endif
03773 
03774     double get_double(int idx) const
03775     {
03776         return _stmt->get_double(idx, _row_idx);
03777     }
03778     double get_double(const tstring& col_name) const
03779     {
03780         return _stmt->get_double(col_name, _row_idx);
03781     }
03782 
03783     SqlNumber get_number(int idx) const
03784     {
03785         return _stmt->get_number(idx, _row_idx);
03786     }
03787     SqlNumber get_number(const tstring& col_name) const
03788     {
03789         return _stmt->get_number(col_name, _row_idx);
03790     }
03791 
03792     tstring get_string(int idx) const
03793     {
03794         return _stmt->get_string(idx, _row_idx);
03795     }
03796     tstring get_string(const tstring& col_name) const
03797     {
03798         return _stmt->get_string(col_name, _row_idx);
03799     }
03800 
03801     OciDate get_oci_date(int idx) const
03802     {
03803         return _stmt->get_oci_date(idx, _row_idx);
03804     }
03805     OciDate get_oci_date(const tstring& col_name) const
03806     {
03807         return _stmt->get_oci_date(col_name, _row_idx);
03808     }
03809 
03810     SqlDateTime get_sql_date(int idx) const
03811     {
03812         return _stmt->get_sql_date(idx, _row_idx);
03813     }
03814     SqlDateTime get_sql_date(const tstring& col_name) const
03815     {
03816         return _stmt->get_sql_date(col_name, _row_idx);
03817     }
03818 
03819 protected:
03820     SqlStatement&   _stmt;
03821 
03822     int _fetched;
03823     int _row_idx;
03824     int _row_nr;
03825 };
03826 
03827 
03828 inline void SqlStatement::bind_result(SqlRecord& rec)
03829     {rec.bind_result(*this);}
03830 
03831 
03832 #if ORACLE_VERSION>=81
03833 
03834 struct BlobWriterBuffer : public tstringbuf
03835 {
03836     typedef tstringbuf super;
03837     typedef OciBlob LOB;
03838 
03839     BlobWriterBuffer(LOB& lob)
03840      :  _lob(lob)
03841     {
03842         _offset = 1;
03843     }
03844 
03845     virtual ~BlobWriterBuffer()
03846     {
03847         sync();
03848     }
03849 
03850     virtual int sync()
03851     {
03852         const tstring& s = str();
03853         size_t l = s.length();
03854 
03855         if (l > 0) {
03856 #if ORACLE_VERSION>=90
03857             _lob.write_append((const void*)s.c_str(), (sb4)l*sizeof(TOraText), (sb4)l);
03858 #else
03859             _lob.write((const void*)s.c_str(), (ub4)l, (ub4)_offset, (ub4)l);
03860 #endif
03861 
03862             _offset += l;
03863         }
03864 
03865         str(tstring()); // clear the string buffer
03866 
03867         return 0;
03868     }
03869 
03870 protected:
03871     LOB&    _lob;
03872     size_t  _offset;
03873 };
03874 
03875 struct ClobWriterBuffer : public tstringbuf
03876 {
03877     typedef tstringbuf super;
03878     typedef OciClob LOB;
03879 
03880     ClobWriterBuffer(LOB& lob, ub2 csid=0, ub1 csfrm=SQLCS_IMPLICIT)
03881      :  _lob(lob),
03882         _csid(csid),
03883         _csfrm(csfrm)
03884     {
03885     }
03886 
03887     virtual ~ClobWriterBuffer()
03888     {
03889         sync();
03890     }
03891 
03892     virtual int sync()
03893     {
03894         const tstring& s = str();
03895         size_t l = s.length();
03896 
03897         if (l > 0)
03898             _lob.write_append((const void*)s.c_str(), (ub4)l*sizeof(TOraText), (ub4)l, _csid, _csfrm);
03899 
03900         str(tstring()); // clear the string buffer
03901 
03902         return 0;
03903     }
03904 
03905 protected:
03906     LOB&    _lob;
03907     ub2     _csid;
03908     ub1     _csfrm;
03909 };
03910 
03911 template<typename BUFFER>
03912   struct LobWriter : public tostream
03913 {
03914     typedef tostream super;
03915 
03916     LobWriter(typename BUFFER::LOB& lob)
03917      :  super(&_buffer),
03918         _buffer(lob)
03919     {
03920     }
03921 
03922     LobWriter(typename BUFFER::LOB& lob, ub2 csid, ub1 csfrm=SQLCS_IMPLICIT)
03923      :  super(&_buffer),
03924         _buffer(lob, csid, csfrm)
03925     {
03926     }
03927 
03928     void sync()
03929     {
03930         _buffer.sync();
03931     }
03932 
03933 protected:
03934     BUFFER  _buffer;
03935 };
03936 
03937 typedef LobWriter<BlobWriterBuffer> BlobWriter;
03938 typedef LobWriter<ClobWriterBuffer> ClobWriter;
03939 
03940 
03941 struct BlobReaderBuffer : public tstringbuf
03942 {
03943     typedef tstringbuf super;
03944     typedef OciBlob LOB;
03945 
03946     BlobReaderBuffer(LOB& lob, ub4 offset=1)
03947      :  _lob(lob),
03948         _offset(offset)
03949     {
03950         _bsize = lob.get_chunk_size();
03951         _buffer = static_cast<TCHAR*>(ocipl_alloc(_bsize*sizeof(TCHAR)));
03952     }
03953 
03954     ~BlobReaderBuffer()
03955     {
03956         ocipl_free(_buffer);
03957     }
03958 
03959     virtual int_type underflow()
03960     {
03961         ub4 amount = _lob.read(_buffer, _bsize, _offset, _bsize);
03962         if (amount <= 0)
03963             return -1;
03964 
03965         setg(_buffer, _buffer, _buffer+amount);
03966         _offset += amount;
03967 
03968         return *_buffer;
03969     }
03970 
03971 protected:
03972     LOB&    _lob;
03973     ub4     _offset;
03974     TCHAR*  _buffer;
03975     int     _bsize;
03976 };
03977 
03978 struct ClobReaderBuffer : public tstringbuf
03979 {
03980     typedef tstringbuf super;
03981     typedef OciClob LOB;
03982 
03983     ClobReaderBuffer(LOB& lob, ub4 offset=1, ub2 csid=0, ub1 csfrm=SQLCS_IMPLICIT)
03984      :  _lob(lob),
03985         _offset(offset),
03986         _csid(csid),
03987         _csfrm(csfrm)
03988     {
03989         _bsize = lob.get_chunk_size();
03990         _buffer = static_cast<TCHAR*>(ocipl_alloc(_bsize*sizeof(TCHAR)));
03991     }
03992 
03993     ~ClobReaderBuffer()
03994     {
03995         ocipl_free(_buffer);
03996     }
03997 
03998     virtual int_type underflow()
03999     {
04000         ub4 amount = _lob.read(_buffer, _bsize, _offset, _bsize, _csid, _csfrm);
04001         if (amount <= 0)
04002             return -1;
04003 
04004         setg(_buffer, _buffer, _buffer+amount);
04005         _offset += amount;
04006 
04007         return *_buffer;
04008     }
04009 
04010 protected:
04011     LOB&    _lob;
04012     ub4     _offset;
04013     TCHAR*  _buffer;
04014     int     _bsize;
04015     ub2     _csid;
04016     ub1     _csfrm;
04017 };
04018 
04019 template<typename BUFFER>
04020   struct LobReader : public tistream
04021 {
04022     typedef tistream super;
04023 
04024     LobReader(typename BUFFER::LOB& lob)
04025      :  super(&_buffer),
04026         _buffer(lob)
04027     {
04028     }
04029 
04030     LobReader(typename BUFFER::LOB& lob, ub2 csid, ub1 csfrm=SQLCS_IMPLICIT)
04031      :  super(&_buffer),
04032         _buffer(lob, csid, csfrm)
04033     {
04034     }
04035 
04036 protected:
04037     BUFFER  _buffer;
04038 };
04039 
04040 typedef LobReader<BlobReaderBuffer> BlobReader;
04041 typedef LobReader<ClobReaderBuffer> ClobReader;
04042 
04043 #endif
04044 
04045 
04046 
04047 extern const TCHAR* get_oci_ptype_str(ub1 type);
04048 
04049 } // namespace OCIPL
04050 
04051 #define _OCIPL_H
04052 #endif  // _OCIPL_H

Generated on Fri Sep 22 2017 00:05:09 for OCIPL/C++ by  doxygen 1.7.2