00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef OCIPL_NO_COMMENT
00043 #define OCIPL_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files -> free selection of orasql library
00044 #endif
00045
00046 #define _olint // for #define CONST const
00047 #include "ocipl.h"
00048
00049 #include <sstream>
00050 #include <locale>
00051
00052 #include <assert.h>
00053 #include <time.h>
00054
00055
00056 #ifndef _MSC_VER
00057 char* strupr(char* s)
00058 {
00059 for(char*p=s; *p; ++p)
00060 *p = toupper(*p);
00061
00062 return s;
00063 }
00064 #endif
00065
00066 size_t max_strlen(const char* s, size_t max_len)
00067 {
00068 if (!s)
00069 return 0;
00070
00071 size_t cnt = 0;
00072
00073 while(cnt<max_len && *s)
00074 ++cnt, ++s;
00075
00076 return cnt;
00077 }
00078
00079 char* max_strdup(const char* s, size_t max_len)
00080 {
00081 if (!s)
00082 return NULL;
00083
00084 size_t l = max_strlen(s, max_len);
00085 char* ret = (char*) malloc(l+1);
00086
00087 #ifdef __STDC_WANT_SECURE_LIB__
00088 strncpy_s(ret, l+1, s, l);
00089 #else
00090 strncpy(ret, s, l);
00091 #endif
00092 ret[l] = '\0';
00093
00094 return ret;
00095 }
00096
00097
00098 namespace OCIPL {
00099
00100
00101
00102 int g_OCIPL_BULK_ROWS = 100;
00103
00104
00105 void throw_oci_exception(OCIError* errh, sword res)
00106 {
00107 switch(res) {
00108 case OCI_ERROR:
00109 case OCI_NO_DATA:
00110 THROW_OCI_EXCEPTION(errh);
00111 break;
00112
00113 case OCI_INVALID_HANDLE:
00114 THROW_OCI_EXCEPTION("invalid handle");
00115 break;
00116
00117
00118
00119 }
00120 }
00121
00122 void throw_oci_exception(OCIEnv* envh, sword res)
00123 {
00124 switch(res) {
00125 case OCI_ERROR:
00126 case OCI_NO_DATA:
00127 case OCI_INVALID_HANDLE:
00128 THROW_OCI_EXCEPTION(envh);
00129
00130
00131
00132 }
00133 }
00134
00135
00136 OciException::OciException(OCIEnv* envh, const char* file, int line)
00137 {
00138 OraText buffer[1024];
00139
00140 sb4 errorcode;
00141 sword res = OCIErrorGet(envh, 1, NULL, &errorcode, buffer, sizeof(buffer), OCI_HTYPE_ENV);
00142
00143 if (res == OCI_SUCCESS) {
00144 _sql_error_code = errorcode;
00145 _msg = max_strdup((const char*)buffer, COUNTOF(buffer));
00146 } else {
00147 _sql_error_code = 0;
00148 _msg = NULL;
00149 }
00150
00151 _file = file;
00152 _line = line;
00153 _parse_offset = 0;
00154 }
00155
00156 OciException::OciException(OCIError* errh, const char* file, int line)
00157 {
00158 TCHAR buffer[1024];
00159
00160 sb4 errorcode;
00161 sword res = OCIErrorGet(errh, 1, NULL, &errorcode, (OraText*)buffer, sizeof(buffer), OCI_HTYPE_ERROR);
00162
00163 if (res == OCI_SUCCESS) {
00164 _sql_error_code = errorcode;
00165 #ifdef _UNICODE
00166 char nbuffer[2048];
00167 #ifdef _MSC_VER
00168 std::_USE(std::locale::empty(), std::ctype<wchar_t>)
00169 #else
00170 std::use_facet<std::ctype<wchar_t> >(std::locale::empty())
00171 #endif
00172 .narrow((const TCHAR*)buffer, (const TCHAR*)buffer+_tcslen((const TCHAR*)buffer)+1, 0, nbuffer);
00173 _msg = max_strdup(nbuffer, COUNTOF(nbuffer));
00174 #else
00175 _msg = max_strdup(buffer, COUNTOF(buffer));
00176 #endif
00177 } else {
00178 _sql_error_code = 0;
00179 _msg = NULL;
00180 }
00181
00182 _file = file;
00183 _line = line;
00184 _parse_offset = 0;
00185 }
00186
00187 OciException::OciException(OCIError* errh, SqlStatement& stmt, const char* file, int line)
00188 {
00189 char buffer[4096];
00190
00191 sb4 errorcode;
00192 #ifdef _UNICODE
00193 TCHAR wbuffer[4096];
00194
00195 sword res = OCIErrorGet(errh, 1, NULL, &errorcode, (OraText*)wbuffer, sizeof(wbuffer), OCI_HTYPE_ERROR);
00196
00197 #ifdef _MSC_VER
00198 std::_USE(std::locale::empty(), std::ctype<wchar_t>)
00199 #else
00200 std::use_facet<std::ctype<wchar_t> >(std::locale::empty())
00201 #endif
00202 .narrow((const TCHAR*)wbuffer, (const TCHAR*)wbuffer+_tcslen((const TCHAR*)wbuffer)+1, 0, buffer);
00203 #else
00204 sword res = OCIErrorGet(errh, 1, NULL, &errorcode, (OraText*)buffer, sizeof(buffer), OCI_HTYPE_ERROR);
00205 #endif
00206
00207 ub4 size = sizeof(_parse_offset);
00208 if (OCIAttrGet(stmt, OCI_HTYPE_STMT, &_parse_offset, &size, OCI_ATTR_PARSE_ERROR_OFFSET, errh) != OCI_SUCCESS)
00209 _parse_offset = 0;
00210
00211 if (res == OCI_SUCCESS)
00212 _sql_error_code = errorcode;
00213 else {
00214 *buffer = '\0';
00215 _sql_error_code = 0;
00216 }
00217
00218 _last_sql = stmt.get_last_sql();
00219
00220 _file = file;
00221 _line = line;
00222
00223 if (!_last_sql.empty()) {
00224 file = stmt.get_last_file();
00225
00226
00227 if (file) {
00228 _file = file;
00229 _line = stmt.get_last_line();
00230 }
00231
00232 const TCHAR* sql = _last_sql.c_str();
00233 size_t l = max_strlen(buffer, COUNTOF(buffer));
00234
00235 int line = 1;
00236 const TCHAR* s = sql;
00237 const TCHAR* e = sql + _parse_offset;
00238 const TCHAR* lp = sql;
00239
00240 while(s < e)
00241 if (*s == '\n') {
00242 ++line;
00243
00244 if (*++s == '\r')
00245 ++s;
00246
00247 lp = s;
00248 } else
00249 ++s;
00250
00251 size_t column = 1 + (s-lp);
00252
00253 #ifdef __STDC_WANT_SECURE_LIB__
00254 char* b = buffer+l + _snprintf_s(buffer+l, sizeof(buffer)-l, _TRUNCATE, "\nerror at SQL position %d [%d.%d]:\n", _parse_offset, line, column);
00255 #else
00256 char* b = buffer+l + _snprintf(buffer+l, sizeof(buffer)-l-1, "\nerror at SQL position %d [%d.%d]:\n", _parse_offset, line, column);
00257 #endif
00258 char* p = b;
00259 s = lp;
00260 while(*s && *s!='\n' && p<buffer+sizeof(buffer)-3)
00261 *p++ = *s++;
00262
00263 *p++ = '\n';
00264
00265 b = p;
00266 const TCHAR* err_ptr = sql + _parse_offset;
00267 s = lp;
00268 for(; s<err_ptr && p<buffer+sizeof(buffer)-2; ++s) {
00269 if (*s=='\n' || *sql=='\r')
00270 p = b;
00271 else if (*s == '\t')
00272 *p++ = '\t';
00273 else
00274 *p++ = ' ';
00275 }
00276
00277 *p++ = '^';
00278 *p = '\0';
00279
00280 l = max_strlen(buffer, COUNTOF(buffer));
00281 #ifdef __STDC_WANT_SECURE_LIB__
00282 _snprintf_s(buffer+l, sizeof(buffer)-l, _TRUNCATE, "\n\nlast SQL statement:\n%s", sql);
00283 #else
00284 _snprintf(buffer+l, sizeof(buffer)-l, "\n\nlast SQL statement:\n%s", sql);
00285 #endif
00286 }
00287
00288 _msg = max_strdup(buffer, COUNTOF(buffer));
00289 }
00290
00291 OciException::OciException(const char* msg, const char* file, int line)
00292 {
00293 _msg = _strdup(msg);
00294 _file = file;
00295 _line = line;
00296 }
00297
00298 OciException::OciException(const OciException& other)
00299 {
00300 _sql_error_code = other._sql_error_code;
00301 _msg = _strdup(other._msg);
00302 _file = other._file;
00303 _line = other._line;
00304 _last_sql = other._last_sql;
00305 }
00306
00307
00308 OciException::~OciException() throw()
00309 {
00310 free(_msg);
00311 }
00312
00313
00314 #ifndef _NO_ESQL
00315
00316 #include <sql2oci.h>
00317
00318 #ifdef _MSC_VER
00319 #if ORACLE_VERSION>=110
00320 #pragma comment(lib, "orasql11")
00321 #elif ORACLE_VERSION>=100
00322 #pragma comment(lib, "orasql10")
00323 #elif ORACLE_VERSION>=90
00324 #pragma comment(lib, "orasql9")
00325 #elif ORACLE_VERSION>=81 // no orasql library for Oracle 8.0 available
00326 #pragma comment(lib, "orasql8")
00327 #endif
00328 #endif
00329
00330 #if ORACLE_VERSION>=81 // no SQLEnvGet() and SQLSvcCtxGet() for Oracle 8.0.x
00331 OciConnection* OciConnection::CreateFromESqlContext(void* context)
00332 {
00333 OCIEnv* envhp = NULL;
00334 sword res = SQLEnvGet(context, &envhp);
00335
00336 if (res != OCI_SUCCESS)
00337 return NULL;
00338
00339 OCISvcCtx* svchp = NULL;
00340 res = SQLSvcCtxGet(context, NULL, 0, &svchp);
00341
00342 oci_check_error(envhp, res);
00343
00344 return new OciConnection(envhp, svchp);
00345 }
00346 #endif
00347
00348 #endif // _NO_ESQL
00349
00350
00351
00352 void OciConnection::cancel()
00353 {
00354 sword res = OCIBreak(_ctx, _env._errh);
00355
00356 oci_check_error(_env._errh, res);
00357 }
00358
00359 #if ORACLE_VERSION>=81
00360
00361 void OciConnection::reset()
00362 {
00363 sword res = OCIReset(_ctx, _env._errh);
00364
00365 oci_check_error(_env._errh, res);
00366 }
00367 #endif
00368
00369
00370
00371 void OciContext::commit(ub4 flags)
00372 {
00373 LocalOciState state(*this, OS_TRANSACTION);
00374
00375 sword res = OCITransCommit(_handle, _env._errh, flags);
00376 oci_check_error(_env, res);
00377
00378 _trans_cnt = 0;
00379 }
00380
00381
00382 void OciContext::rollback(ub4 flags)
00383 {
00384 LocalOciState state(*this, OS_TRANSACTION);
00385
00386 sword res = OCITransRollback(_handle, _env._errh, flags);
00387 oci_check_error(_env, res);
00388
00389 _trans_cnt = 0;
00390 }
00391
00392
00393 SqlString& SqlString::operator=(const TCHAR* s)
00394 {
00395 size_t l = s? _tcslen(s): 0;
00396 if (l > _blen)
00397 resize(l);
00398
00399 _tcscpy_s(_str, _blen+1, s?s:TEXT(""));
00400 _ind = l>0? 0: -1;
00401 return *this;
00402 }
00403
00404 SqlString& SqlString::operator=(const tstring& s)
00405 {
00406 if (!s.empty()) {
00407 size_t l = s.length();
00408 if (_blen < l)
00409 resize(l);
00410
00411 memcpy(_str, s.c_str(), (l+1)*sizeof(char));
00412 _ind = 0;
00413 } else {
00414 *_str = '\0';
00415 _ind = -1;
00416 }
00417
00418 return *this;
00419 }
00420
00421
00422 int number_to_int(const oraclenumber& val, OCIError* errh)
00423 {
00424 int x;
00425
00426 #if ORACLE_VERSION>=81
00427
00428 boolean isInt;
00429 sword res = OCINumberIsInt(errh, (OCINumber*)&val, &isInt);
00430
00431 if (res==OCI_SUCCESS && isInt)
00432 {
00433 res = OCINumberToInt(errh, (OCINumber*)&val, sizeof(x), OCI_NUMBER_SIGNED, &x);
00434 oci_check_error(errh, res);
00435 }
00436 else
00437 #else
00438
00439 sword res = OCINumberToInt(errh, (OCINumber*)&val, sizeof(x), OCI_NUMBER_SIGNED, &x);
00440
00441 if (res != OCI_SUCCESS)
00442 #endif
00443 {
00444 double d = number_to_double(val, errh);
00445
00446 x = int(d + .5);
00447 }
00448
00449
00450
00451 return x;
00452 }
00453
00454 #ifdef _MSC_VER
00455 LONGLONG number_to_int64(const oraclenumber& val, OCIError* errh, int null)
00456 {
00457 LONGLONG x;
00458
00459 sword res = OCINumberToInt(errh, (OCINumber*)&val, sizeof(x), OCI_NUMBER_SIGNED, &x);
00460 oci_check_error(errh, res);
00461
00462 return x;
00463 }
00464 #endif
00465
00466 double number_to_double(const oraclenumber& val, OCIError* errh)
00467 {
00468 double x;
00469
00470 sword res = OCINumberToReal(errh, (OCINumber*)&val, sizeof(x), &x);
00471 oci_check_error(errh, res);
00472
00473 return x;
00474 }
00475
00476 tstring number_to_str(const oraclenumber& val, OCIError* errh, const TCHAR* fmt, const TCHAR* nls_fmt)
00477 {
00478 OraText buffer[128];
00479 ub4 l = sizeof(buffer);
00480
00481 sword res = OCINumberToText(errh,
00482 (OCINumber*)&val,
00483 (const OraText*)fmt, (ub4)_tcslen(fmt)*sizeof(TOraText),
00484 (const OraText*)nls_fmt, (ub4)_tcslen(nls_fmt)*sizeof(TOraText),
00485 &l, buffer);
00486
00487 oci_check_error(errh, res);
00488
00489
00490
00491
00492
00493 return (const TCHAR*)buffer;
00494 }
00495
00496
00497 SqlNumber::SqlNumber(const oraclenumber* pnum)
00498 {
00499 memcpy(&_val.exp, &pnum->exp, pnum->len);
00500 _val.len = pnum->len;
00501 _ind.set();
00502 }
00503
00504 SqlNumber::SqlNumber(OCIError* errh, const TCHAR* str, const TCHAR* fmt, const TCHAR* nls_fmt)
00505 {
00506 if (str) {
00507 while(istspace(*str))
00508 ++str;
00509
00510 if (*str) {
00511 sword res = OCINumberFromText(errh,
00512 (const OraText*)str, (ub4)_tcslen(str)*sizeof(TOraText),
00513 (const OraText*)fmt, (ub4)_tcslen(fmt)*sizeof(TOraText),
00514 (const OraText*)nls_fmt, (ub4)_tcslen(nls_fmt)*sizeof(TOraText),
00515 (OCINumber*)&_val);
00516
00517 oci_check_error(errh, res);
00518
00519 _ind.set();
00520 } else
00521 _ind.clear();
00522 } else
00523 _ind.clear();
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 tstring ocidate_to_string(const OCIDate& date)
00639 {
00640 TCHAR buffer[40];
00641
00642 #ifdef __STDC_WANT_SECURE_LIB__
00643 _stprintf_s(buffer, COUNTOF(buffer),
00644 #else
00645 _stprintf(buffer,
00646 #endif
00647 TEXT("%02d.%02d.%04d %02d:%02d:%02d"),
00648 date.OCIDateDD, date.OCIDateMM, date.OCIDateYYYY,
00649 date.OCIDateTime.OCITimeHH, date.OCIDateTime.OCITimeMI, date.OCIDateTime.OCITimeSS);
00650
00651 return buffer;
00652 }
00653
00654 tstring ocidate_to_short_string(const OCIDate& date)
00655 {
00656 TCHAR buffer[40];
00657
00658 #ifdef __STDC_WANT_SECURE_LIB__
00659 _stprintf_s(buffer, COUNTOF(buffer),
00660 #else
00661 _stprintf(buffer,
00662 #endif
00663 TEXT("%02d.%02d.%04d"),
00664 date.OCIDateDD, date.OCIDateMM, date.OCIDateYYYY);
00665
00666 return buffer;
00667 }
00668
00669 struct tm* ocidate_to_gmt(const OCIDate& date)
00670 {
00671 struct tm ltime = {
00672 date.OCIDateTime.OCITimeSS,
00673 date.OCIDateTime.OCITimeMI,
00674 date.OCIDateTime.OCITimeHH,
00675 date.OCIDateDD,
00676 date.OCIDateMM - 1,
00677 date.OCIDateYYYY - 1900,
00678 -1,
00679 -1,
00680 -1
00681 };
00682
00683 time_t time = mktime(<ime);
00684
00685 #ifdef __STDC_WANT_SECURE_LIB__
00686 struct tm newtime;
00687 gmtime_s(&newtime, &time);
00688 struct tm* gmt = &newtime;
00689 #else
00690 struct tm* gmt = gmtime(&time);
00691 #endif
00692
00693 return gmt;
00694 }
00695
00696 struct tm* ocidate_to_lctime(const OCIDate& date)
00697 {
00698 struct tm ltime = {
00699 date.OCIDateTime.OCITimeSS,
00700 date.OCIDateTime.OCITimeMI,
00701 date.OCIDateTime.OCITimeHH,
00702 date.OCIDateDD,
00703 date.OCIDateMM - 1,
00704 date.OCIDateYYYY - 1900,
00705 -1,
00706 -1,
00707 -1
00708 };
00709
00710 time_t time = mktime(<ime);
00711
00712 #ifdef __STDC_WANT_SECURE_LIB__
00713 struct tm newtime;
00714 localtime_s(&newtime, &time);
00715 struct tm* lct = &newtime;
00716 #else
00717 struct tm* lct = localtime(&time);
00718 #endif
00719
00720 return lct;
00721 }
00722
00723 time_t ocidate_to_time_t(const OCIDate& date)
00724 {
00725 time_t time = mktime(ocidate_to_lctime(date));
00726
00727 return time;
00728 }
00729
00730 #ifdef _WIN32
00731 bool ocidate_to_systemtime(const OCIDate& date, SYSTEMTIME* pSysTime)
00732 {
00733 SYSTEMTIME stime;
00734
00735 stime.wYear = date.OCIDateYYYY;
00736 stime.wMonth = date.OCIDateMM;
00737 stime.wDayOfWeek = 0;
00738 stime.wDay = date.OCIDateDD;
00739 stime.wHour = date.OCIDateTime.OCITimeHH;
00740 stime.wMinute = date.OCIDateTime.OCITimeMI;
00741 stime.wSecond = date.OCIDateTime.OCITimeSS;
00742 stime.wMilliseconds = 0;
00743
00744
00745 FILETIME ftime;
00746
00747 if (!SystemTimeToFileTime(&stime, &ftime))
00748 return false;
00749
00750 if (!FileTimeToSystemTime(&ftime, pSysTime))
00751 return false;
00752
00753 return true;
00754 }
00755 #endif
00756
00757
00758 tstring ocidatetime_to_string(const ocidatetime& date)
00759 {
00760 TCHAR buffer[40];
00761
00762 #ifdef __STDC_WANT_SECURE_LIB__
00763 _stprintf_s(buffer, COUNTOF(buffer),
00764 #else
00765 _stprintf(buffer,
00766 #endif
00767 TEXT("%02d.%02d.%04d %02d:%02d:%02d"),
00768 date.day, date.month, 100*(date.century-100)+(date.year-100),
00769 date.hour-1, date.minute-1, date.second-1);
00770
00771 return buffer;
00772 }
00773
00774
00775 OciDate::OciDate(const OCIDate& date, OCIInd ind)
00776 : SqlValue(ind)
00777 {
00778 OCIDate::operator=(date);
00779 }
00780
00781 OciDate::OciDate(OCIError* errh, const TCHAR* str, const TCHAR* fmt)
00782 {
00783 if (str) {
00784 while(istspace(*str))
00785 ++str;
00786
00787 if (*str) {
00788 sword res = OCIDateFromText(errh, (const OraText*)str, (ub4)_tcslen(str)*sizeof(TOraText),
00789 (const OraText*)fmt, (ub4)_tcslen(fmt)*sizeof(TOraText), NULL, 0, this);
00790
00791 oci_check_error(errh, res);
00792
00793 _ind.set();
00794 } else
00795 _ind.clear();
00796 } else
00797 _ind.clear();
00798 }
00799
00800 OciDate::OciDate(struct tm* t)
00801 {
00802 OCIDateYYYY = t->tm_year + 1900;
00803 OCIDateMM = t->tm_mon + 1;
00804 OCIDateDD = t->tm_mday;
00805 OCIDateTime.OCITimeHH = t->tm_hour;
00806 OCIDateTime.OCITimeMI = t->tm_min;
00807 OCIDateTime.OCITimeSS = t->tm_sec;
00808
00809 ind().set();
00810 }
00811
00812 int OciDate::compare(const OciDate& other) const
00813 {
00814 if (OCIDateYYYY < other.OCIDateYYYY)
00815 return -1;
00816 else if (OCIDateYYYY > other.OCIDateYYYY)
00817 return 1;
00818
00819 if (OCIDateMM < other.OCIDateMM)
00820 return -1;
00821 else if (OCIDateMM > other.OCIDateMM)
00822 return 1;
00823
00824 if (OCIDateDD < other.OCIDateDD)
00825 return -1;
00826 else if (OCIDateDD > other.OCIDateDD)
00827 return 1;
00828
00829 if (OCIDateTime.OCITimeHH < other.OCIDateTime.OCITimeHH)
00830 return -1;
00831 else if (OCIDateTime.OCITimeHH > other.OCIDateTime.OCITimeHH)
00832 return 1;
00833
00834 if (OCIDateTime.OCITimeMI < other.OCIDateTime.OCITimeMI)
00835 return -1;
00836 else if (OCIDateTime.OCITimeMI > other.OCIDateTime.OCITimeMI)
00837 return 1;
00838
00839 if (OCIDateTime.OCITimeSS < other.OCIDateTime.OCITimeSS)
00840 return -1;
00841 else if (OCIDateTime.OCITimeSS > other.OCIDateTime.OCITimeSS)
00842 return 1;
00843
00844 return 0;
00845 }
00846
00847
00848 tstring ColumnTypeInfo::get_type_str(bool show_null) const
00849 {
00850 tostringstream str;
00851
00852 switch(_data_type) {
00853 case OCI_TYPECODE_CHAR:
00854 str << TEXT("CHAR(") << _width << TEXT(")");
00855 break;
00856
00857 case OCI_TYPECODE_VARCHAR:
00858 str << TEXT("VARCHAR(") << _width << TEXT(")");
00859 break;
00860
00861 case OCI_TYPECODE_VARCHAR2:
00862 str << TEXT("VARCHAR2(") << _width << TEXT(")");
00863 break;
00864
00865 case OCI_TYPECODE_NUMBER:
00866 if (_precision == 0)
00867 str << TEXT("NUMBER");
00868 else if (_scale == -127) {
00869 if (_precision == 126)
00870 str << TEXT("FLOAT");
00871 else
00872 str << TEXT("FLOAT(") << (int)_precision << TEXT(")");
00873 } else if (_scale)
00874 str << TEXT("NUMBER(") << (int)_precision << TEXT(",") << (int)_scale << TEXT(")");
00875 else
00876 str << TEXT("NUMBER(") << (int)_precision << TEXT(")");
00877 break;
00878
00879 #ifdef SQLT_BFLOAT
00880 case OCI_TYPECODE_BFLOAT:
00881 str << TEXT("BINARY_FLOAT");
00882 break;
00883
00884 case OCI_TYPECODE_BDOUBLE:
00885 str << TEXT("BINARY_DOUBLE");
00886 break;
00887 #endif
00888
00889 case OCI_TYPECODE_DATE:
00890 str << TEXT("DATE");
00891 break;
00892
00893 #if ORACLE_VERSION>=81
00894 case OCI_TYPECODE_TIMESTAMP:
00895 str << TEXT("TIMESTAMP");
00896 break;
00897 #endif
00898
00899 case OCI_TYPECODE_BLOB:
00900 str << TEXT("BLOB");
00901 break;
00902
00903 case OCI_TYPECODE_BFILE:
00904 str << TEXT("BFILE");
00905 break;
00906
00907 case OCI_TYPECODE_CLOB:
00908 str << TEXT("CLOB");
00909 break;
00910
00911 case OCI_TYPECODE_CFILE:
00912 str << TEXT("CFILE");
00913 break;
00914
00915 case SQLT_LNG:
00916 str << TEXT("LONG");
00917 break;
00918
00919 default:
00920 str << TEXT("unknown");
00921 }
00922
00923 if (show_null)
00924 if (!_nullable)
00925 str << TEXT(" NOT NULL");
00926 else
00927 str << TEXT(" NULL");
00928
00929 return str.str();
00930 }
00931
00932
00933 SqlStatement::~SqlStatement()
00934 {
00935 delete _res;
00936 _res = NULL;
00937 }
00938
00939
00940 #ifndef FORCE_CODEPOS
00941 void SqlStatement::prepare(const tstring& sql, ub4 lang)
00942 {
00943 prepare(sql, NULL, -1, lang);
00944 }
00945 #endif
00946
00947 void SqlStatement::prepare(const tstring& sql, const char* file, int line, ub4 lang)
00948 {
00949 delete _res;
00950 _res = NULL;
00951
00952 _last_sql = sql;
00953 _last_file = file;
00954 _last_line = line;
00955
00956 LocalOciState state(_ctx, OS_PREPARE);
00957
00958 sword res = OCIStmtPrepare(_handle, _env._errh, (OraText*)sql.c_str(), (ub4)sql.length()*sizeof(TOraText), lang, OCI_DEFAULT);
00959 oci_check_error(_env, res);
00960
00961 _state = PREPARED;
00962 _stmt_type = -1;
00963 _result_buffers = 0;
00964 }
00965
00966
00967 #if ORACLE_VERSION>=90
00968
00969 #ifndef FORCE_CODEPOS
00970 void SqlCacheStmt::prepare(const tstring& sql, ub4 lang)
00971 {
00972 prepare(sql, NULL, -1, lang);
00973 }
00974 #endif
00975
00976 void SqlCacheStmt::prepare(const tstring& sql, const char* file, int line, ub4 lang)
00977 {
00978 if (!_tag.empty())
00979 release();
00980
00981 tstring& tag = _stmt_cache[sql];
00982
00983 if (tag.empty()) {
00984 TCHAR buffer[16];
00985 #ifdef __STDC_WANT_SECURE_LIB__
00986 _stprintf_s(buffer, COUNTOF(buffer),
00987 #else
00988 _stprintf(buffer,
00989 #endif
00990 TEXT("%x"), _stmt_cache.size());
00991 tag = buffer;
00992 }
00993
00994 _last_sql = sql;
00995 _last_file = file;
00996 _last_line = line;
00997 _tag = tag;
00998
00999 LocalOciState state(_ctx, OS_PREPARE);
01000
01001 sword res = OCIStmtPrepare2(_ctx, &_handle, _env._errh,
01002 (OraText*)sql.c_str(), (ub4)sql.length()*sizeof(TOraText),
01003 (OraText*)_tag.c_str(), (ub4)_tag.length()*sizeof(TOraText), lang, OCI_DEFAULT);
01004 oci_check_error(_env, res);
01005
01006 _state = PREPARED;
01007 _stmt_type = -1;
01008 _result_buffers = 0;
01009 }
01010
01011 void SqlCacheStmt::release()
01012 {
01013 delete _res;
01014 _res = NULL;
01015
01016 LocalOciState state(_ctx, OS_RELEASE);
01017
01018 sword res = OCIStmtRelease(_handle, _env._errh, (OraText*)_tag.c_str(), (ub4)_tag.length()*sizeof(TOraText), OCI_DEFAULT);
01019 _handle = 0;
01020
01021 oci_check_error(_env, res);
01022 }
01023
01024 SqlCacheStmt::~SqlCacheStmt()
01025 {
01026 release();
01027 }
01028
01029 #endif
01030
01031
01032 int SqlStatement::get_stmt_type() const
01033 {
01034 if (_stmt_type == -1) {
01035 ub2 stmt_type;
01036 ub4 size = sizeof(stmt_type);
01037
01038 sword res = OCIAttrGet(_handle, get_type_id(), &stmt_type, &size, OCI_ATTR_STMT_TYPE, _env._errh);
01039 oci_check_error(_env, res);
01040
01041 _stmt_type = stmt_type;
01042 }
01043
01044 return _stmt_type;
01045 }
01046
01047
01048 ub4 SqlStatement::fetched_rows() const
01049 {
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 return _last_fetched_row - _last_row;
01062 }
01063
01064
01065 ub4 SqlStatement::row_count() const
01066 {
01067 ub4 row_count;
01068 ub4 size = sizeof(row_count);
01069
01070 sword res = OCIAttrGet(_handle, get_type_id(), &row_count, &size, OCI_ATTR_ROW_COUNT, _env._errh);
01071 oci_check_error(_env, res);
01072
01073 return row_count;
01074 }
01075
01076
01077 OCIDefine* SqlStatement::bind_result(int idx, DefinePar par, OCIDefine* defnp)
01078 {
01079 sword res = OCIDefineByPos(_handle, &defnp, _env._errh, idx+1,
01080 par.valuep, par.value_sz, par.dty, par.indp,
01081 (ub2*)0, (ub2*)0, OCI_DEFAULT);
01082 oci_check_error(_env, res);
01083
01084 if (_state & DEFINED)
01085 assert(_result_buffers==par.buffers);
01086
01087 if (_state & EXECUTED) {
01088 delete _res;
01089 _res = NULL;
01090
01091 _state = (_state|DEFINED) & ~(FETCHED|EOF_DATA);
01092 } else
01093 _state |= DEFINED;
01094
01095 _result_buffers = par.buffers;
01096
01097 return defnp;
01098 }
01099
01100
01101 void SqlStatement::execute(ub4 rows, ub4 mode)
01102 {
01103
01104 if (!(_state&DEFINED) && get_stmt_type()==OCI_STMT_SELECT) {
01105 execute_internal(0, mode);
01106
01107
01108 assert(!_res);
01109
01110 if (rows > 0) {
01111 _res = new SqlResult(*this, rows);
01112 fetch(rows);
01113 } else {
01114 _res = new SqlResult(*this, _bulk_rows);
01115 }
01116 } else
01117 execute_internal(rows, mode);
01118 }
01119
01120
01121 void SqlStatement::execute_fetch(ub4 mode)
01122 {
01123
01124 if (!(_state&DEFINED) && get_stmt_type()==OCI_STMT_SELECT) {
01125 execute_internal(0, mode);
01126
01127
01128 assert(!_res);
01129 _res = new SqlResult(*this, _bulk_rows);
01130
01131 fetch(_result_buffers);
01132 } else
01133 execute_internal(_result_buffers, mode);
01134 }
01135
01136
01137 void SqlStatement::execute_internal(ub4 rows, ub4 mode)
01138 {
01139 int stmt_type = get_stmt_type();
01140
01141 LocalOciState state(_ctx, OS_EXECUTE, stmt_type);
01142
01143 if (rows==0 && stmt_type==OCI_STMT_SELECT) {
01144
01145 try {
01146
01147 set_attribute(OCI_ATTR_PREFETCH_ROWS, 10);
01148 } catch(std::exception&) {
01149
01150 }
01151 }
01152
01153
01154 sword res = OCIStmtExecute(_ctx, _handle, _env._errh, rows, 0,
01155 (CONST OCISnapshot*)0, (OCISnapshot*)0, mode);
01156
01157 _last_row = 0;
01158 _last_fetched_row = row_count();
01159
01160 if (res==OCI_NO_DATA && stmt_type>=OCI_STMT_SELECT && stmt_type<=OCI_STMT_INSERT) {
01161 _state |= EOF_DATA;
01162
01163
01164 } else if (res == OCI_ERROR) {
01165 _state = STMT_ERROR;
01166
01167 throw_ocipl_exception(OciException(_env._errh, *this, CODEPOS));
01168 } else {
01169 if (rows > 0)
01170 _state |= EXECUTED|FETCHED;
01171 else
01172 _state = (_state|EXECUTED) & ~(FETCHED|EOF_DATA);
01173
01174 oci_check_error(_env, res);
01175
01176
01177 }
01178 }
01179
01180
01181 void SqlStatement::fetch(ub4 rows)
01182 {
01183 if (!(_state & EXECUTED)) {
01184 if (rows == (ub4)-1)
01185 if (!(_state & DEFINED))
01186 rows = _bulk_rows;
01187 else
01188 rows = _result_buffers;
01189
01190 execute(rows);
01191 } else {
01192 if (rows == (ub4)-1)
01193 rows = _result_buffers;
01194
01195 LocalOciState state(_ctx, OS_FETCH);
01196
01197 #if ORACLE_VERSION>=90
01198 sword res = OCIStmtFetch2(_handle, _env._errh, rows, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
01199 #else
01200 sword res = OCIStmtFetch(_handle, _env._errh, rows, OCI_FETCH_NEXT, OCI_DEFAULT);
01201 #endif
01202
01203 _last_row = _last_fetched_row;
01204 _last_fetched_row = row_count();
01205
01206 if (res != OCI_NO_DATA) {
01207 _state |= FETCHED;
01208 oci_check_error(_env, res);
01209
01210
01211 } else {
01212 _state |= EOF_DATA;
01213
01214
01215 }
01216 }
01217 }
01218
01219
01220
01221 void SqlStatement::get_column_type(int idx, ColumnType& info) const
01222 {
01223 dvoid* parmdp;
01224
01225 sword res = OCIParamGet(_handle, get_type_id(), _env._errh, &parmdp, idx+1);
01226 oci_check_error(_env, res);
01227
01228 info.init(_env._errh, parmdp);
01229
01230 res = OCIDescriptorFree(parmdp, OCI_DTYPE_PARAM);
01231 oci_check_error(_env, res);
01232 }
01233
01234 void ColumnType::init(OCIError* errh, dvoid* handle)
01235 {
01236
01237 TOraText* pcol_name = NULL;
01238 ub4 size = sizeof(pcol_name);
01239
01240 sword res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &pcol_name, &size, OCI_ATTR_NAME, errh);
01241 oci_check_error(errh, res);
01242 _name.assign((const TCHAR*)pcol_name, size);
01243
01244
01245 size = sizeof(_data_type);
01246 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_data_type, &size, OCI_ATTR_DATA_TYPE, errh);
01247 oci_check_error(errh, res);
01248
01249
01250 size = sizeof(_nullable);
01251 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_nullable, &size, OCI_ATTR_IS_NULL, errh);
01252 oci_check_error(errh, res);
01253
01254 #if ORACLE_VERSION>=90
01255
01256 size = sizeof(_char_semantics);
01257 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_char_semantics, &size, OCI_ATTR_CHAR_USED, errh);
01258 if (res != OCI_SUCCESS)
01259 _char_semantics = 0;
01260
01261 size = sizeof(_width);
01262 if (_char_semantics)
01263
01264 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_width, &size, OCI_ATTR_CHAR_SIZE, errh);
01265 else
01266 #endif
01267
01268 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_width, &size, OCI_ATTR_DATA_SIZE, errh);
01269
01270 oci_check_error(errh, res);
01271
01272 switch(_data_type) {
01273 default:
01274 _precision = 0;
01275 _scale = -127;
01276 break;
01277
01278 case OCI_TYPECODE_NUMBER:
01279 #ifdef SQLT_BFLOAT
01280 case OCI_TYPECODE_BFLOAT:
01281 case OCI_TYPECODE_BDOUBLE:
01282 #endif
01283 size = sizeof(_precision);
01284 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_precision, &size, OCI_ATTR_PRECISION, errh);
01285 oci_check_error(errh, res);
01286
01287 size = sizeof(_scale);
01288 res = OCIAttrGet(handle, OCI_DTYPE_PARAM, &_scale, &size, OCI_ATTR_SCALE, errh);
01289 oci_check_error(errh, res);
01290 break;
01291
01292 case OCI_TYPECODE_DATE:
01293 #if ORACLE_VERSION>=81
01294
01295
01296 #endif
01297 _precision = 0;
01298 _scale = -127;
01299 break;
01300 }
01301 }
01302
01303
01304 void SqlStatement::print_results(tostream& out, bool header)
01305 {
01306 if (!(_state & EXECUTED))
01307 execute();
01308 else if (!(_state & FETCHED))
01309 fetch(_result_buffers);
01310
01311 if (header)
01312 _res->print_columns(out);
01313
01314 int row_cnt = 0;
01315
01316 for(ResultIterator it(*this); it.has_next(); ++it) {
01317 ++row_cnt;
01318
01319 out << TEXT("row ") << row_cnt << TEXT(":\n");
01320
01321 _res->print_values(out, it);
01322
01323 out << TEXT("\n");
01324 }
01325 }
01326
01327
01328 SqlRecord::SqlRecord(SqlStatement& stmt, int rows)
01329 : _env(stmt._env)
01330 {
01331 stmt.ensure_execute();
01332
01333 int column_cnt = stmt.get_column_count();
01334
01335 _values.resize(column_cnt);
01336 ColumnVector::iterator it = _values.begin();
01337
01338 for(int idx=0; idx<column_cnt; ++idx,++it) {
01339 stmt.get_column_type(idx, it->_type);
01340
01341 it->_pvar = new SqlVariantArray(it->_type, rows);
01342 }
01343
01344
01345 }
01346
01347 SqlRecord::~SqlRecord()
01348 {
01349 for(ColumnVector::iterator it=_values.begin(); it!=_values.end(); ++it)
01350 delete it->_pvar;
01351 }
01352
01353 void SqlRecord::alloc_column(size_t col_idx, const ColumnTypeInfo& type, int rows)
01354 {
01355 Data& data = _values[col_idx];
01356
01357
01358 delete data._pvar;
01359 data._pvar = new SqlVariantArray(type, rows);
01360 }
01361
01362 const ColumnType& SqlRecord::get_column_type(const tstring& col_name) const
01363 {
01364
01365
01366
01367
01368
01369 NameMap::const_iterator found = find_column(col_name);
01370
01371 if (found != _name_map.end()) {
01372 int idx = found->second;
01373 return _values[idx]._type;
01374 } else {
01375 THROW_OCI_EXCEPTION("column not found");
01376 return *(ColumnType*)NULL;
01377 }
01378 }
01379
01380 const SqlVariantArray& SqlRecord::get_column(const tstring& col_name) const
01381 {
01382
01383
01384
01385
01386
01387 NameMap::const_iterator found = find_column(col_name);
01388
01389 if (found != _name_map.end()) {
01390 int idx = found->second;
01391 return *_values[idx]._pvar;
01392 } else {
01393 THROW_OCI_EXCEPTION("column not found");
01394 return *(SqlVariantArray*)NULL;
01395 }
01396 }
01397
01398 SqlRecord::NameMap::const_iterator SqlRecord::find_column(const tstring& col_name) const
01399 {
01400 tstring upper_name;
01401
01402
01403 if (_name_map.empty()) {
01404 int idx = 0;
01405
01406 for(ColumnVector::const_iterator it=_values.begin(); it!=_values.end(); ++it,++idx) {
01407 upper_name = it->_type._name.c_str();
01408 _tcsupr_s((TCHAR*)upper_name.data(), upper_name.length()+1);
01409
01410 _name_map[upper_name] = idx;
01411 }
01412 }
01413
01414 upper_name = col_name;
01415 _tcsupr_s((TCHAR*)upper_name.data(), upper_name.length()+1);
01416
01417 return _name_map.find(upper_name);
01418 }
01419
01420
01421 void SqlRecord::bind_result(SqlStatement& stmt)
01422 {
01423 int idx = 0;
01424
01425 for(ColumnVector::iterator it=_values.begin(); it!=_values.end(); ++it,++idx)
01426 it->_pvar->bind_result(stmt, idx);
01427 }
01428
01429 void SqlRecord::print_columns(tostream& out)
01430 {
01431 for(ColumnVector::const_iterator it=_values.begin(); it!=_values.end(); ++it)
01432 out << it->_type._name << TEXT(": ") << it->_type.get_type_str() << TEXT("\n");
01433
01434 out << TEXT("\n");
01435 }
01436
01437 void SqlRecord::print_values(tostream& out, int row)
01438 {
01439 ColumnVector::const_iterator it_type = _values.begin();
01440
01441 for(ColumnVector::const_iterator it=_values.begin(); it!=_values.end(); ++it,++it_type)
01442 out << it->_type._name << TEXT("=") << it->_pvar->str(row, _env._errh) << TEXT("\n");
01443 }
01444
01445
01446 SqlVariantArray::SqlVariantArray(const ColumnTypeInfo& type, int size)
01447 : _size(size),
01448 _data_type(type._data_type)
01449 {
01450 switch(type._data_type) {
01451 case OCI_TYPECODE_CHAR:
01452 _data_type = OCI_TYPECODE_VARCHAR;
01453
01454
01455 case OCI_TYPECODE_VARCHAR:
01456 _pstring = new SqlStringArray(size, type._width);
01457 break;
01458
01459 case OCI_TYPECODE_NUMBER:
01460 _pnumber = new SqlNumberArray(size);
01461 break;
01462
01463 #ifdef SQLT_BFLOAT
01464 case OCI_TYPECODE_BFLOAT:
01465 _pfloat = new float[size];
01466 break;
01467
01468 case OCI_TYPECODE_BDOUBLE:
01469 _pdouble = new double[size];
01470 break;
01471 #endif
01472
01473 case OCI_TYPECODE_DATE:
01474 _poci_date = new OciDateArray(size);
01475 break;
01476
01477 #if ORACLE_VERSION>=81
01478 case OCI_TYPECODE_TIME:
01479 case OCI_TYPECODE_TIMESTAMP:
01480 _psql_date = new SqlDateTimeArray(size);
01481 break;
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491 #endif
01492 case SQLT_LNG:
01493 _pstring = new SqlStringArray(size, type._width);
01494 break;
01495
01496 default:
01497 THROW_OCI_EXCEPTION("unsupported datatype");
01498 }
01499 }
01500
01501 SqlVariantArray::SqlVariantArray(const SqlVariantArray& other)
01502 : _size(0),
01503 _data_type(0)
01504 {
01505 assign(other);
01506 }
01507
01508 void SqlVariantArray::assign(const SqlVariantArray& other)
01509 {
01510 clear();
01511
01512 _size = other._size;
01513 _data_type = other._data_type;
01514
01515 switch(other._data_type) {
01516 case 0:
01517 break;
01518
01519 case OCI_TYPECODE_VARCHAR:
01520 _pstring = new SqlStringArray(*other._pstring);
01521 break;
01522
01523 case OCI_TYPECODE_NUMBER:
01524 _pnumber = new SqlNumberArray(*other._pnumber);
01525 break;
01526
01527 #ifdef SQLT_BFLOAT
01528 case OCI_TYPECODE_BFLOAT:
01529 _pfloat = new float[_size];
01530 memcpy(_pfloat, other._pfloat, sizeof(float)*_size);
01531 break;
01532
01533 case OCI_TYPECODE_BDOUBLE:
01534 _pdouble = new double[_size];
01535 memcpy(_pfloat, other._pfloat, sizeof(double)*_size);
01536 break;
01537 #endif
01538
01539 case OCI_TYPECODE_DATE:
01540 _poci_date = new OciDateArray(*other._poci_date);
01541 break;
01542
01543 #if ORACLE_VERSION>=81
01544 case OCI_TYPECODE_TIME:
01545 case OCI_TYPECODE_TIMESTAMP:
01546 _psql_date = new SqlDateTimeArray(*other._psql_date);
01547 break;
01548 #endif
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558 case SQLT_LNG:
01559 _pstring = new SqlStringArray(*other._pstring);
01560 break;
01561
01562 default:
01563 assert(0);
01564 }
01565 }
01566
01567 void SqlVariantArray::clear()
01568 {
01569 switch(_data_type) {
01570 case 0:
01571 break;
01572
01573 case OCI_TYPECODE_VARCHAR:
01574 delete _pstring;
01575 break;
01576
01577 case OCI_TYPECODE_NUMBER:
01578 delete _pnumber;
01579 break;
01580
01581 #ifdef SQLT_BFLOAT
01582 case OCI_TYPECODE_BFLOAT:
01583 delete _pfloat;
01584 break;
01585
01586 case OCI_TYPECODE_BDOUBLE:
01587 delete _pfloat;
01588 break;
01589 #endif
01590
01591 case OCI_TYPECODE_DATE:
01592 delete _poci_date;
01593 break;
01594
01595 #if ORACLE_VERSION>=81
01596 case OCI_TYPECODE_TIME:
01597 case OCI_TYPECODE_TIMESTAMP:
01598 delete _psql_date;
01599 break;
01600 #endif
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 case SQLT_LNG:
01611 delete _pstring;
01612 break;
01613
01614 default:
01615 assert(0);
01616 }
01617
01618 _size = 0;
01619 _data_type = 0;
01620 }
01621
01622 tstring SqlVariantArray::str(int row, OCIError* errh) const
01623 {
01624 #ifdef SQLT_BFLOAT
01625 TCHAR buffer[16];
01626 #endif
01627
01628 switch(_data_type) {
01629 case 0:
01630 return TEXT("");
01631
01632 case OCI_TYPECODE_VARCHAR:
01633 return _pstring->c_str(row);
01634
01635
01636 case OCI_TYPECODE_NUMBER:
01637 return _pnumber->str(row, errh);
01638
01639 #ifdef SQLT_BFLOAT
01640 case OCI_TYPECODE_BFLOAT:
01641 #ifdef __STDC_WANT_SECURE_LIB__
01642 _stprintf_s(buffer, COUNTOF(buffer),
01643 #else
01644 _stprintf(buffer,
01645 #endif
01646 TEXT("%f"), _pfloat[row]);
01647 return buffer;
01648
01649 case OCI_TYPECODE_BDOUBLE:
01650 #ifdef __STDC_WANT_SECURE_LIB__
01651 _stprintf_s(buffer, COUNTOF(buffer),
01652 #else
01653 _stprintf(buffer,
01654 #endif
01655 TEXT("%f"), _pdouble[row]);
01656 return buffer;
01657 #endif
01658
01659 case OCI_TYPECODE_DATE:
01660 return _poci_date->str(row);
01661
01662 #if ORACLE_VERSION>=81
01663 case OCI_TYPECODE_TIME:
01664 case OCI_TYPECODE_TIMESTAMP:
01665 return _psql_date->str(row);
01666 #endif
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 case SQLT_LNG:
01681 return _pstring->c_str(row);
01682
01683 default:
01684 assert(0);
01685 return TEXT("");
01686 }
01687 }
01688
01689 void SqlVariantArray::set_string(int row, const TCHAR* str)
01690 {
01691 if (_data_type != OCI_TYPECODE_VARCHAR)
01692 THROW_OCI_EXCEPTION("invalid variant data type");
01693
01694 _pstring->assign(row, str);
01695 }
01696
01697
01698 SqlNumber SqlVariantArray::number(int row, OCIError* errh) const
01699 {
01700 switch(_data_type) {
01701 case 0:
01702 return SqlNumber();
01703
01704 case OCI_TYPECODE_VARCHAR:
01705 return SqlNumber(errh, _pstring->c_str(row));
01706
01707 case OCI_TYPECODE_NUMBER:
01708 if (_pnumber->is_not_null(row))
01709 return _pnumber->get_ref(row);
01710 else
01711 return SqlNumber();
01712
01713 #ifdef SQLT_BFLOAT
01714 case OCI_TYPECODE_BFLOAT:
01715 return SqlNumber(errh, _pfloat[row]);
01716
01717 case OCI_TYPECODE_BDOUBLE:
01718 return SqlNumber(errh, _pdouble[row]);
01719 #endif
01720
01721
01722
01723
01724 default:
01725 THROW_OCI_EXCEPTION("no conversion to number");
01726
01727 }
01728 }
01729
01730 void SqlVariantArray::set_number(int row, const SqlNumber& num)
01731 {
01732 if (_data_type != OCI_TYPECODE_NUMBER)
01733 THROW_OCI_EXCEPTION("invalid variant data type");
01734
01735 _pnumber->set_number(row, num);
01736 }
01737
01738
01739 OciDate SqlVariantArray::oci_date(int row, OCIError* errh) const
01740 {
01741 switch(_data_type) {
01742 case 0:
01743 return OciDate();
01744
01745 case OCI_TYPECODE_VARCHAR:
01746 return OciDate(errh, _pstring->c_str(row));
01747
01748 case OCI_TYPECODE_DATE:
01749 if (_poci_date->is_not_null(row))
01750 return *_poci_date->get_ref(row);
01751 else
01752 return OciDate();
01753
01754
01755
01756
01757
01758
01759
01760 default:
01761 THROW_OCI_EXCEPTION("no conversion to date");
01762
01763 }
01764 }
01765
01766 void SqlVariantArray::set_date(int row, const OciDate& date)
01767 {
01768 if (_data_type != OCI_TYPECODE_DATE)
01769 THROW_OCI_EXCEPTION("invalid variant data type");
01770
01771 _poci_date->set_date(row, date);
01772 }
01773
01774
01775 SqlDateTime SqlVariantArray::sql_date(int row, OCIError* errh) const
01776 {
01777 switch(_data_type) {
01778 case 0:
01779 return SqlDateTime();
01780
01781
01782
01783
01784
01785
01786
01787
01788 #if ORACLE_VERSION>=81
01789 case OCI_TYPECODE_TIME:
01790 case OCI_TYPECODE_TIMESTAMP:
01791 if (_psql_date->is_not_null(row))
01792 return *_psql_date->get_ref(row);
01793 else
01794 return SqlDateTime();
01795 #endif
01796
01797 default:
01798 THROW_OCI_EXCEPTION("no conversion to date");
01799
01800 }
01801 }
01802
01803 void SqlVariantArray::set_datetime(int row, const SqlDateTime& datetime)
01804 {
01805 if (_data_type!=OCI_TYPECODE_TIME && _data_type!=OCI_TYPECODE_TIMESTAMP)
01806 THROW_OCI_EXCEPTION("invalid variant data type");
01807
01808 _psql_date->set_datetime(row, datetime);
01809 }
01810
01811
01812 bool SqlVariantArray::is_not_null(int row) const
01813 {
01814 switch(_data_type) {
01815 case 0:
01816 #ifdef SQLT_BFLOAT
01817 case OCI_TYPECODE_BFLOAT:
01818 case OCI_TYPECODE_BDOUBLE:
01819 #endif
01820 return true;
01821
01822 case OCI_TYPECODE_VARCHAR:
01823 return _pstring->is_not_null(row);
01824
01825 case OCI_TYPECODE_NUMBER:
01826 return _pnumber->is_not_null(row);
01827
01828 case OCI_TYPECODE_DATE:
01829 return _poci_date->is_not_null(row);
01830
01831 #if ORACLE_VERSION>=81
01832 case OCI_TYPECODE_TIME:
01833 case OCI_TYPECODE_TIMESTAMP:
01834 return _psql_date->is_not_null(row);
01835 #endif
01836
01837
01838
01839
01840
01841
01842
01843 case SQLT_LNG:
01844 return _pstring->is_not_null(row);
01845
01846 default:
01847 assert(0);
01848 return true;
01849 }
01850 }
01851
01852 void SqlVariantArray::bind_result(SqlStatement& stmt, int idx)
01853 {
01854 switch(_data_type) {
01855 case OCI_TYPECODE_VARCHAR:
01856 stmt.bind_result(idx, *_pstring);
01857 break;
01858
01859 case OCI_TYPECODE_NUMBER:
01860 stmt.bind_result(idx, *_pnumber);
01861 break;
01862
01863 #ifdef SQLT_BFLOAT
01864 case OCI_TYPECODE_BFLOAT:
01865 stmt.bind_result(idx, *_pfloat);
01866 break;
01867
01868 case OCI_TYPECODE_BDOUBLE:
01869 stmt.bind_result(idx, *_pdouble);
01870 break;
01871 #endif
01872
01873 case OCI_TYPECODE_DATE:
01874 stmt.bind_result(idx, *_poci_date);
01875 break;
01876
01877 #if ORACLE_VERSION>=81
01878 case OCI_TYPECODE_TIME:
01879 case OCI_TYPECODE_TIMESTAMP:
01880 stmt.bind_result(idx, *_psql_date);
01881 break;
01882 #endif
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 case SQLT_LNG:
01893 stmt.bind_result(idx, *_pstring);
01894 break;
01895
01896 default:
01897 assert(0);
01898 }
01899 }
01900
01901
01902 void SqlVariantArray::bind_input(SqlStatement& stmt, int idx, int row)
01903 {
01904 switch(_data_type) {
01905 case OCI_TYPECODE_VARCHAR:
01906 stmt.bind_input(idx, BindInput(_pstring->str(row), _pstring->alen(), SQLT_STR));
01907 break;
01908
01909 case OCI_TYPECODE_NUMBER:
01910 stmt.bind_input(idx, BindInput(_pnumber->get_number(row), _pnumber->ind(row)));
01911 break;
01912
01913 #ifdef SQLT_BFLOAT
01914 case OCI_TYPECODE_BFLOAT:
01915 stmt.bind_input(idx, *_pfloat);
01916 break;
01917
01918 case OCI_TYPECODE_BDOUBLE:
01919 stmt.bind_input(idx, *_pdouble);
01920 break;
01921 #endif
01922
01923 case OCI_TYPECODE_DATE:
01924 stmt.bind_input(idx, BindInput(_poci_date->get_date(row), _poci_date->ind(row)));
01925 break;
01926
01927 #if ORACLE_VERSION>=81
01928 case OCI_TYPECODE_TIME:
01929 case OCI_TYPECODE_TIMESTAMP:
01930 stmt.bind_input(idx, BindInput(_psql_date->get_datetime(row), _psql_date->ind(row)));
01931 break;
01932 #endif
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942 case SQLT_LNG:
01943 stmt.bind_input(idx, BindInput(_pstring->str(row), _pstring->alen(), SQLT_STR));
01944 break;
01945
01946 default:
01947 assert(0);
01948 }
01949 }
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963 const TCHAR* get_oci_ptype_str(ub1 type)
01964 {
01965 switch(type) {
01966 case OCI_PTYPE_TABLE: return TEXT("table");
01967 case OCI_PTYPE_VIEW: return TEXT("view");
01968 case OCI_PTYPE_PROC: return TEXT("procedure");
01969 case OCI_PTYPE_FUNC: return TEXT("function");
01970 case OCI_PTYPE_PKG: return TEXT("package");
01971 case OCI_PTYPE_TYPE: return TEXT("user-defined type");
01972 case OCI_PTYPE_SYN: return TEXT("synonym");
01973 case OCI_PTYPE_SEQ: return TEXT("sequence");
01974 case OCI_PTYPE_COL: return TEXT("column");
01975 case OCI_PTYPE_ARG: return TEXT("argument");
01976 case OCI_PTYPE_LIST: return TEXT("list");
01977 case OCI_PTYPE_TYPE_ATTR: return TEXT("user-defined type's attribute");
01978 case OCI_PTYPE_TYPE_COLL: return TEXT("collection type's element ");
01979 case OCI_PTYPE_TYPE_METHOD: return TEXT("user-defined type's method");
01980 case OCI_PTYPE_TYPE_ARG: return TEXT("user-defined type method's argument");
01981 case OCI_PTYPE_TYPE_RESULT: return TEXT("user-defined type method's result");
01982 #if ORACLE_VERSION>=81
01983 case OCI_PTYPE_SCHEMA: return TEXT("schema");
01984 case OCI_PTYPE_DATABASE: return TEXT("database");
01985 #endif
01986 }
01987
01988 return TEXT("unknown type");
01989 }
01990
01991
01992 static tstring tokenize(const TCHAR** ptr, const TCHAR* sep)
01993 {
01994 const TCHAR* start = *ptr;
01995 const TCHAR* end;
01996
01997 const TCHAR* found = _tcspbrk(*ptr, sep);
01998
01999 if (found) {
02000 end = found;
02001 *ptr = found;
02002 } else
02003 *ptr = end = start + _tcslen(start);
02004
02005 return tstring(start, end-start);
02006 }
02007
02008 static tstring tokenize(const TCHAR** ptr, const TCHAR* sep, TCHAR key)
02009 {
02010 if (**ptr != key)
02011 return TEXT("");
02012
02013 ++*ptr;
02014
02015 return tokenize(ptr, sep);
02016 }
02017
02018 void LoginPara::parse(const TCHAR* conn_str)
02019 {
02020 const TCHAR* ptr = conn_str;
02021
02022 _username = tokenize(&ptr, TEXT("/@ "));
02023 _password = tokenize(&ptr, TEXT("@ "), TEXT('/'));
02024 _tnsname = tokenize(&ptr, TEXT(" "), TEXT('@'));
02025
02026 while(istspace(*ptr))
02027 ++ptr;
02028
02029 if (!_tcsnicmp(ptr, TEXT("as sysdba"), 9)) {
02030 _mode = OCI_SYSDBA;
02031 ptr += 9;
02032 } else if (!_tcsnicmp(ptr, TEXT("as sysoper"), 10)) {
02033 _mode = OCI_SYSDBA;
02034 ptr += 10;
02035 } else if (!_tcsnicmp(ptr, TEXT("migrate"), 7)) {
02036 _mode = OCI_MIGRATE;
02037 ptr += 7;
02038 }
02039 }
02040
02041
02042 }