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