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

Generated on Wed Sep 29 00:05:05 2010 for OCIPL/C++ by  doxygen 1.5.4