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 #include "dborcl/orclsrv.h"
00029 #include "base/vector.hpp"
00030 #include "base/list.hpp"
00031 #include "base/string.hpp"
00032 #include "base/memory.hpp"
00033 #include "base/common.hpp"
00034 #include "base/numeric.h"
00035
00036 BEGIN_TERIMBER_NAMESPACE
00037 #pragma pack(4)
00038
00039 #define check_retcode_db(x, ehandle, type) \
00040 if (x != OCI_SUCCESS) \
00041 { \
00042 ub1_t err[256] = {0}; \
00043 sword code; \
00044 OCIErrorGet(ehandle, 1, 0, &code, err, sizeof(err), type); \
00045 throw exception(code, (const char*)err); \
00046 }
00047
00048 #define check_retcode(x, ehandle, type) \
00049 if (x != OCI_SUCCESS && x != OCI_NO_DATA) \
00050 { \
00051 ub1_t err[256] = {0}; \
00052 sword code = 0; \
00053 OCIErrorGet(ehandle, 1, 0, &code, err, sizeof(err), type); \
00054 throw exception(code, (const char*)err); \
00055 }
00056
00057 static const char* valid_delimeters = " ,)}";
00058
00059 orcl_dbserver::orcl_dbserver(size_t ident) : dbserver_impl(ident),
00060 _envhp(0),
00061 _svchp(0),
00062 _errhp(0),
00063 _stmthp(0)
00064 {
00065 }
00066
00067 orcl_dbserver::~orcl_dbserver()
00068 {
00069 if (_is_open_sql())
00070 close_sql();
00071
00072 if (_is_connect())
00073 disconnect();
00074 }
00075
00076
00077 void
00078 orcl_dbserver::v_connect(bool trusted_connection, const char* connection_string)
00079 {
00080
00081 int err = 0;
00082 if (0 != (err = OCIInitialize(OCI_OBJECT | OCI_THREADED,
00083 0, 0, 0, 0)))
00084 exception::_throw("Can't initialize OCI library");
00085 if (0 != (err = OCIEnvInit(&_envhp, OCI_DEFAULT, 0, 0)))
00086 exception::_throw("Can't initialize OCI environment");
00087
00088 check_retcode_db(OCIHandleAlloc(_envhp, (void**)&_errhp, OCI_HTYPE_ERROR, 0, 0), _envhp, OCI_HTYPE_ENV)
00089
00090
00091
00092
00093 const char* sid = connection_string ? strchr(connection_string, '@') : 0;
00094
00095 const char* uid = sid != connection_string ? connection_string : 0;
00096 const char* pwd = connection_string ? strchr(connection_string, '/') : 0;
00097 if (pwd) ++pwd;
00098
00099 if (sid) ++sid;
00100
00101 size_t uid_len = uid ? (pwd ? pwd - uid - 1 : (sid ? sid - uid - 1 : strlen(uid)) ) : 0;
00102 size_t pwd_len = pwd ? (sid ? sid - pwd - 1 : strlen(pwd)) : 0;
00103 size_t sid_len = sid ? strlen(sid) : 0;
00104
00105
00106 check_retcode_db(OCILogon(_envhp, _errhp, &_svchp, (const text*)uid, (ub4)uid_len, (const text*)pwd, (ub4)pwd_len, (const text*)sid, (ub4)sid_len), _errhp, OCI_HTYPE_ERROR)
00107
00108 }
00109
00110 void
00111 orcl_dbserver::v_disconnect()
00112 {
00113 _temp_allocator->clear_extra();
00114
00115 v_close();
00116
00117 if (_svchp)
00118 {
00119
00120 check_retcode_db(OCILogoff(_svchp, _errhp), _errhp, OCI_HTYPE_ERROR)
00121 _svchp = 0;
00122 }
00123
00124 if (_errhp)
00125 {
00126 sword x = OCIHandleFree(_errhp, OCI_HTYPE_ERROR);
00127 _errhp = 0;
00128 }
00129
00130 if (_envhp)
00131 {
00132 sword x = OCIHandleFree(_envhp, OCI_HTYPE_ENV);
00133 _envhp = 0;
00134 }
00135
00136 }
00137
00138 void
00139 orcl_dbserver::v_start_transaction()
00140 {
00141
00142 check_retcode_db(OCITransCommit(_svchp, _errhp, OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00143 }
00144
00145 void
00146 orcl_dbserver::v_commit()
00147 {
00148
00149 check_retcode_db(OCITransCommit(_svchp, _errhp, OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00150 }
00151
00152 void
00153 orcl_dbserver::v_rollback()
00154 {
00155
00156 check_retcode_db(OCITransRollback(_svchp, _errhp, OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00157 }
00158
00159 bool
00160 orcl_dbserver::v_is_connect_alive()
00161 {
00162
00163 if (!_is_connect())
00164 return false;
00165
00166
00167
00168
00169 return true;
00170 }
00171
00173 void
00174 orcl_dbserver::v_before_execute()
00175 {
00176 check_retcode(OCIHandleAlloc(_envhp, (void**)&_stmthp, OCI_HTYPE_STMT, 0, 0), _envhp, OCI_HTYPE_ENV)
00177 check_retcode(OCIStmtPrepare(_stmthp, _errhp, (const text*)(const char*)_sql, (ub4)_sql.length(), OCI_NTV_SYNTAX, OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00178 }
00179
00180 void
00181 orcl_dbserver::v_after_execute()
00182 {
00183
00184 }
00185
00186
00187 void
00188 orcl_dbserver::v_execute()
00189 {
00190 ub4_t iters = 0;
00191
00192 switch (get_action())
00193 {
00194 case ACTION_EXEC_PROC:
00195 case ACTION_EXEC_PROC_ASYNC:
00196 case ACTION_EXEC_SQL:
00197 case ACTION_EXEC_SQL_ASYNC:
00198 iters = 1;
00199 break;
00200 default:
00201 break;
00202 }
00203
00204
00205 sword status = OCIStmtExecute(_svchp, _stmthp, _errhp, iters, 0, 0, 0, OCI_DEFAULT);
00206 check_retcode(status, _envhp, OCI_HTYPE_ERROR)
00207 }
00208
00209
00210 void
00211 orcl_dbserver::v_close()
00212 {
00213 if (_stmthp)
00214 {
00215 OCIHandleFree(_stmthp, OCI_HTYPE_STMT);
00216 _stmthp = 0;
00217 }
00218
00219
00220 size_t index;
00221 for (index = 0; index < _params.size(); ++index)
00222 if (_params[index]._user_code)
00223 {
00224 OCIDescriptorFree(_params[index]._user_code, OCI_DTYPE_LOB);
00225 _params[index]._user_code = 0;
00226 }
00227
00228 for (index = 0; index < _cols.size(); ++index)
00229 if (_cols[index]._user_code)
00230 {
00231 OCIDescriptorFree(_cols[index]._user_code, OCI_DTYPE_LOB);
00232 _cols[index]._user_code = 0;
00233 }
00234 }
00235
00236
00237 void
00238 orcl_dbserver::v_fetch()
00239 {
00240
00241 if (_start_row != 0)
00242 {
00243
00244 v_execute();
00245 size_t skip_rows = 0;
00246 while (skip_rows++ < _start_row
00247 && !OCIStmtFetch(_stmthp, _errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT));
00248 }
00249
00250
00251 size_t col_count = _cols.size();
00252 sword x = OCI_SUCCESS;
00253 size_t select_row = 0;
00254
00255 while (_requested_rows
00256 && ((x = OCIStmtFetch(_stmthp, _errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT)) == OCI_SUCCESS
00257 || x == OCI_SUCCESS_WITH_INFO)
00258 )
00259 {
00260 if (STATE_INTERRUPTED == get_state())
00261 exception::_throw("Fetching process is interrupted");
00262
00263 check_retcode(x, _errhp, OCI_HTYPE_ERROR)
00264
00265
00266 _vector< terimber_db_value > val;
00267 recordset_list_t::iterator iter_val = _data.push_back(*_data_allocator, val);
00268 if (iter_val == _data.end())
00269 exception::_throw("Not enough memory");
00270
00271
00272 if (!iter_val->resize(*_data_allocator, col_count))
00273 exception::_throw("Not enough memory");
00274
00275 for (size_t index = 0; index < col_count; ++index)
00276 v_convert_one_value(0, index, (*iter_val)[index]);
00277
00278 ++select_row;
00279
00280 --_requested_rows;
00281 }
00282
00283 if (x != OCI_NO_DATA)
00284 check_retcode(x, _errhp, OCI_HTYPE_ERROR)
00285
00286
00287 _fetched_rows = select_row;
00288 }
00289
00290
00291 void
00292 orcl_dbserver::v_replace_quote()
00293 {
00294 if (0 == _quote || _quote == ':')
00295 return;
00296
00297
00298 if (!_sql.length())
00299 return;
00300
00301
00302 char* buf = (char*)check_pointer(_temp_allocator->allocate(_sql.length() + 1));
00303 *buf = 0;
00304
00305 size_t count_params = 0;
00306
00307 char* new_sql = buf;
00308 const char* begin = _sql;
00309 const char* end = 0;
00310
00311
00312 while (0 != (end = strchr(begin, _quote)))
00313 {
00314 ++count_params;
00315 size_t len = end - begin;
00316
00317 str_template::strcpy(new_sql, begin, len);
00318 begin += len + 1;
00319 new_sql += len;
00320
00321 *new_sql++ = ':';
00322
00323
00324 begin += strcspn(begin, valid_delimeters);
00325 }
00326
00327
00328 str_template::strcpy(new_sql, begin, os_minus_one);
00329
00330 _sql = buf;
00331 }
00332
00333
00334 void
00335 orcl_dbserver::v_bind_one_param(size_t index)
00336 {
00337 binder& cur = _params[index];
00338
00339 cur._bind_type = cur._value.nullVal ? os_minus_one : 0;
00340
00341 switch (cur._type)
00342 {
00343 case db_bool:
00344 cur._max_length = sizeof(bool);
00345 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00346 cur._bind_buffer = &(cur._value.val.boolVal);
00347 cur._native_type = SQLT_INT;
00348 break;
00349 case db_sb1:
00350 case db_ub1:
00351 cur._max_length = sizeof(ub1_t);
00352 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00353 cur._bind_buffer = cur._type == db_sb1 ? (void*)&(cur._value.val.cVal) : (void*)&(cur._value.val.bVal);
00354 cur._native_type = SQLT_INT;
00355 break;
00356 case db_sb2:
00357 case db_ub2:
00358 cur._max_length = sizeof(ub2_t);
00359 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00360 cur._bind_buffer = cur._type == db_sb2 ? (void*)&(cur._value.val.iVal) : (void*)&(cur._value.val.uiVal);
00361 cur._real_length = cur._value.nullVal ? os_minus_one : 0;
00362 cur._native_type = SQLT_INT;
00363 break;
00364 case db_sb4:
00365 case db_ub4:
00366 cur._max_length = sizeof(ub4_t);
00367 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00368 cur._bind_buffer = cur._type == db_ub4 ? (void*)&(cur._value.val.lVal) : (void*)&(cur._value.val.ulVal);
00369 cur._native_type = SQLT_INT;
00370 break;
00371 case db_float:
00372 cur._max_length = sizeof(float);
00373 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00374 cur._bind_buffer = &(cur._value.val.fltVal);
00375 cur._native_type = SQLT_FLT;
00376 break;
00377 case db_double:
00378 cur._max_length = sizeof(double);
00379 #ifdef OS_64BIT
00380 cur._real_length = cur._value.nullVal ? 0 : cur._max_length;
00381 cur._bind_buffer = &(cur._value.val.dblVal);
00382 #else
00383
00384 cur._real_length = cur._value.nullVal || !cur._value.val.dblVal ? 0 : cur._max_length;
00385
00386 if (is_param_out(cur._in_out))
00387 {
00388 double* buf = (double*)check_pointer(_temp_allocator->allocate(sizeof(double)));
00389 *buf = cur._value.val.dblVal ? *cur._value.val.dblVal : 0.0;
00390 cur._bind_buffer = buf;
00391 }
00392 else
00393 cur._bind_buffer = (void*)cur._value.val.dblVal;
00394 #endif
00395 cur._native_type = SQLT_FLT;
00396 break;
00397 case db_sb8:
00398 case db_ub8:
00399
00400 cur._max_length = 22;
00401 {
00402 #ifdef OS_64BIT
00403 numeric conv(cur._value.val.intVal, _temp_allocator);
00404 #else
00405 numeric conv(cur._value.val.intVal ? *cur._value.val.intVal : (sb8_t)0, _temp_allocator);
00406 #endif
00407 ub1_t* bval = (ub1_t*)check_pointer(_data_allocator->allocate(is_param_out(cur._in_out) ? cur._max_length : conv.orcl_len()));
00408 if (!conv.persist_orcl(bval))
00409 exception::_throw("Out of range");
00410 cur._value.val.bufVal = bval;
00411
00412 cur._real_length = cur._value.nullVal || !cur._value.val.intVal ? 0 : cur._max_length;
00413 }
00414 cur._native_type = SQLT_NUM;
00415 break;
00416 case db_date:
00417 cur._max_length = 7;
00418 cur._real_length = cur._value.nullVal || !cur._value.val.dblVal ? 0 : cur._max_length;
00419 {
00420 ub1_t* ptds = (ub1_t*)check_pointer(_temp_allocator->allocate(7));
00421 cur._bind_buffer = ptds;
00422
00423 if (cur._value.val.dblVal)
00424 {
00425 ub4_t year32;
00426 ub1_t month8, day8, hour8, minute8, second8, wday8;
00427 ub2_t millisec16, yday16;
00428 date::convert_from(
00429 #ifdef OS_64BIT
00430 cur._value.val.intVal,
00431 #else
00432 cur._value.val.intVal ? *cur._value.val.intVal : 0,
00433 #endif
00434 year32,
00435 month8,
00436 day8,
00437 hour8,
00438 minute8,
00439 second8,
00440 millisec16,
00441 wday8,
00442 yday16);
00443
00444
00445 ptds[0] = year32 / 100 + 100;
00446 ptds[1] = year32 % 100 + 100;
00447 ptds[2] = month8;
00448 ptds[3] = day8;
00449 ptds[4] = hour8 + 1;
00450 ptds[5] = minute8 + 1;
00451 ptds[6] = second8 + 1;
00452 }
00453 else
00454 memset(ptds, 0, 7);
00455 }
00456
00457 cur._native_type = SQLT_DAT;
00458 break;
00459 case db_string:
00460 cur._max_length = __max(cur._max_length, cur._value.val.strVal ? strlen(cur._value.val.strVal) + 1 : 0);
00461 cur._real_length = cur._max_length;
00462
00463 if (is_param_out(cur._in_out))
00464 {
00465 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00466 if (cur._value.val.strVal)
00467 str_template::strcpy((char*)cur._bind_buffer, cur._value.val.strVal, os_minus_one);
00468 else
00469 memset(cur._bind_buffer, 0, cur._max_length);
00470 }
00471 else
00472 cur._bind_buffer = (void*)cur._value.val.strVal;
00473
00474
00475
00476 if (cur._real_length > 4000)
00477 cur._native_type = SQLT_LNG;
00478 else
00479 cur._native_type = SQLT_STR;
00480 break;
00481 case db_wstring:
00482 cur._max_length = 2 * __max(cur._max_length, cur._value.val.wstrVal ? wcslen(cur._value.val.wstrVal) + 1 : 0);
00483 cur._real_length = cur._max_length;
00484
00485 if (is_param_out(cur._in_out))
00486 {
00487 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00488 if (cur._value.val.strVal)
00489 str_template::strcpy((wchar_t*)cur._bind_buffer, cur._value.val.wstrVal, os_minus_one);
00490 else
00491 memset(cur._bind_buffer, 0, cur._max_length);
00492 }
00493 else
00494 cur._bind_buffer = (void*)cur._value.val.wstrVal;
00495
00496
00497
00498 if (cur._real_length > 4000)
00499 cur._native_type = SQLT_LNG;
00500 else
00501 cur._native_type = SQLT_STR;
00502 break;
00503 case db_decimal:
00504 case db_numeric:
00505 cur._max_length = 22;
00506
00507 if (is_param_out(cur._in_out))
00508 {
00509 numeric conv(_temp_allocator);
00510 if (!conv.parse_orcl(cur._value.val.bufVal))
00511 exception::_throw("Out of range");
00512
00513 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(cur._max_length));
00514 conv.persist_orcl(buf);
00515 cur._bind_buffer = buf;
00516 }
00517 else
00518 cur._bind_buffer = (void*)cur._value.val.bufVal;
00519
00520 cur._real_length = cur._value.nullVal || !cur._value.val.bufVal ? 0 : cur._max_length;
00521 cur._native_type = SQLT_NUM;
00522 break;
00523 case db_binary:
00524 cur._max_length = __max(cur._max_length, cur._value.val.bufVal ? *(size_t*)cur._value.val.bufVal : 0);
00525 cur._real_length = cur._value.nullVal || !cur._value.val.bufVal ? 0 : cur._max_length;
00526
00527 cur._bind_buffer = cur._value.val.bufVal ? (ub1_t*)cur._value.val.bufVal + sizeof(size_t) : 0;
00528
00529 if (cur._real_length > 4000)
00530 cur._native_type = SQLT_LBI;
00531 else
00532 cur._native_type = SQLT_BIN;
00533
00534 break;
00535 default:
00536 exception::_throw("Unsupported parameter type");
00537 assert(false);
00538 }
00539
00540 OCIBind* bindp = 0;
00541 check_retcode(OCIBindByPos(_stmthp, &bindp, _errhp,
00542 (ub4)index + 1, cur._bind_buffer, (ub4)cur._max_length,
00543 (ub2)cur._native_type, (ub2*)&cur._bind_type,
00544 (ub2*)&cur._real_length, 0, 0, 0,
00545 OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00546
00547 }
00548
00549 void
00550 orcl_dbserver::v_before_bind_columns()
00551 {
00552 }
00553
00554
00555 void
00556 orcl_dbserver::v_bind_one_column(size_t index)
00557 {
00558 binder& cur = _cols[index];
00559 switch (cur._native_type)
00560 {
00561 case SQLT_INT:
00562
00563 cur._max_length = sizeof(sb4_t);
00564 cur._bind_buffer = &(cur._value.val.lVal);
00565 break;
00566 case SQLT_UIN:
00567 cur._max_length = sizeof(ub4_t);
00568 cur._bind_buffer = &(cur._value.val.ulVal);
00569 break;
00570 case SQLT_FLT:
00571 cur._max_length = sizeof(double);
00572 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00573 break;
00574 case SQLT_DAT:
00575 cur._max_length = 7;
00576 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00577 break;
00578 case SQLT_VNU:
00579 cur._max_length = 23;
00580 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00581 break;
00582 case SQLT_NUM:
00583 cur._max_length = 22;
00584 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00585 break;
00586 case SQLT_VCS:
00587 case SQLT_CHR:
00588 case SQLT_STR:
00589 case SQLT_RID:
00590 case SQLT_VBI:
00591 case SQLT_BIN:
00592 case SQLT_AFC:
00593 case SQLT_AVC:
00594 cur._max_length = 4000;
00595 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
00596 break;
00597 case SQLT_LNG:
00598 case SQLT_LBI:
00599 case SQLT_LVC:
00600 case SQLT_LVB:
00601
00602 check_retcode(OCIDescriptorAlloc(_envhp, (void **)&cur._user_code, OCI_DTYPE_LOB, 0, 0), _envhp, OCI_HTYPE_ENV)
00603 cur._max_length = 0;
00604 cur._bind_buffer = &cur._user_code;
00605 break;
00606 case SQLT_BLOB:
00607 case SQLT_CLOB:
00608
00609 check_retcode(OCIDescriptorAlloc(_envhp, (void **)&cur._user_code, OCI_DTYPE_LOB, 0, 0), _envhp, OCI_HTYPE_ENV)
00610 cur._max_length = 0;
00611 cur._bind_buffer = &cur._user_code;
00612 break;
00613 default:
00614 exception::_throw("Unsupported native sql type");
00615 assert(false);
00616 }
00617
00618
00619 OCIDefine* defnp = 0;
00620
00621 check_retcode(OCIDefineByPos(_stmthp, &defnp, _errhp, (ub4)index + 1,
00622 cur._bind_buffer, (ub4)cur._max_length,
00623 (ub2)cur._native_type, (ub2*)&cur._bind_type,
00624 (ub2*)&cur._real_length,
00625 0,
00626 OCI_DEFAULT), _errhp, OCI_HTYPE_ERROR)
00627 }
00628
00629
00630 size_t
00631 orcl_dbserver::v_get_number_columns()
00632 {
00633 ub4 count_column = 0;
00634
00635 check_retcode(OCIAttrGet(_stmthp, OCI_HTYPE_STMT, (void*)&count_column, 0, OCI_ATTR_PARAM_COUNT, _errhp), _errhp, OCI_HTYPE_ERROR)
00636
00637 return count_column;
00638 }
00639
00640
00641 void
00642 orcl_dbserver::v_convert_one_value(size_t row, size_t index, terimber_db_value& val)
00643 {
00644 binder& cur = _cols[index];
00645
00646 if ((ub4)cur._bind_type == 0xffffffff || cur._real_length == 0)
00647 {
00648 memset(&val, 0, sizeof(terimber_db_value));
00649 val.nullVal = true;
00650 return;
00651 }
00652 else
00653 val.nullVal = false;
00654
00655
00656 switch (cur._native_type)
00657 {
00658 case SQLT_INT:
00659 val.val.boolVal = cur._value.val.boolVal;
00660 break;
00661 case SQLT_FLT:
00662 #ifdef OS_64BIT
00663 val.val.dblVal = cur._value.val.dblVal;
00664 #else
00665 val.val.dblVal = (double*)check_pointer(_data_allocator->allocate(cur._max_length));
00666 memcpy((void*)val.val.dblVal, cur._bind_buffer, cur._max_length);
00667 #endif
00668 break;
00669 case SQLT_DAT:
00670 {
00671 const ub1_t* ptds = (const ub1_t*)cur._bind_buffer;
00672 sb8_t dummy64;
00673 date::convert_to((ptds[0] - 100) * 100 + (ptds[1] - 100), ptds[2], ptds[3], ptds[4] - 1, ptds[5] - 1, ptds[6] - 1, 0, dummy64);
00674 #ifdef OS_64BIT
00675 val.val.intVal = dummy64;
00676 #else
00677 sb8_t* dummy = (sb8_t*)check_pointer(_data_allocator->allocate(sizeof(sb8_t)));
00678 *dummy = dummy64;
00679 val.val.intVal = dummy;
00680 #endif
00681 }
00682 break;
00683 case SQLT_LNG:
00684 case SQLT_LVC:
00685 if (*(unsigned short*)&cur._user_code == 1406)
00686 {
00687 char* sz = (char*)check_pointer(_data_allocator->allocate(cur._real_length + 1));
00688 sz[cur._real_length] = 0;
00689
00690 size_t shift = 0;
00691 ub4 gotLen = 0;
00692 while (shift < cur._real_length)
00693 {
00694 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
00695 &gotLen, (ub4)shift + 1, (sz + shift), (ub4)(cur._real_length - shift),
00696 OCI_ONE_PIECE, 0, 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
00697
00698 shift += gotLen;
00699 }
00700 val.val.strVal = sz;
00701 }
00702 else
00703 {
00704 char* sz = (char*)check_pointer(_data_allocator->allocate(cur._real_length + 1));
00705 sz[cur._real_length] = 0;
00706 memcpy(sz, cur._bind_buffer, cur._real_length);
00707 val.val.strVal = sz;
00708 }
00709 break;
00710 case SQLT_VNU:
00711 {
00712 ((ub1_t*)cur._bind_buffer)[cur._real_length] = 0;
00713 numeric conv(_temp_allocator);
00714 if (!conv.parse_orcl((const ub1_t*)cur._bind_buffer + 1))
00715 exception::_throw("Out of range");
00716
00717 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(conv.orcl_len()));
00718 conv.persist_orcl(buf);
00719 val.val.bufVal = buf;
00720 }
00721 break;
00722 case SQLT_NUM:
00723 {
00724 ((ub1_t*)cur._bind_buffer)[cur._real_length] = 0;
00725 numeric conv(_temp_allocator);
00726 if (!conv.parse_orcl((const ub1_t*)cur._bind_buffer))
00727 exception::_throw("Out of range");
00728
00729 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(conv.orcl_len()));
00730 conv.persist_orcl(buf);
00731 val.val.bufVal = buf;
00732 }
00733 break;
00734 case SQLT_VCS:
00735 case SQLT_CHR:
00736 case SQLT_STR:
00737 case SQLT_RID:
00738 case SQLT_AFC:
00739 case SQLT_AVC:
00740 {
00741 char* sz = (char*)check_pointer(_data_allocator->allocate(cur._real_length + 1));
00742 sz[cur._real_length] = 0;
00743 memcpy(sz, cur._bind_buffer, cur._real_length);
00744 val.val.strVal = sz;
00745 }
00746 break;
00747 case SQLT_LBI:
00748 case SQLT_LVB:
00749 if (*(unsigned short*)&cur._user_code == 1406)
00750 {
00751 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(cur._real_length + sizeof(size_t)));
00752 *(size_t*)buf = cur._real_length;
00753
00754 size_t shift = 0;
00755 ub1_t* start_buf = buf + sizeof(size_t);
00756 ub4 gotLen = 0;
00757 while (shift < cur._real_length)
00758 {
00759 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
00760 &gotLen, (ub4)shift + 1, (start_buf + shift), (ub4)(cur._real_length - shift),
00761 OCI_ONE_PIECE, 0, 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
00762
00763 shift += gotLen;
00764 }
00765 val.val.bufVal = buf;
00766 }
00767 else
00768 {
00769 val.val.bufVal = (ub1_t*)check_pointer(_data_allocator->allocate(cur._real_length + sizeof(size_t)));
00770 *(size_t*)val.val.bufVal = cur._real_length;
00771 memcpy((char*)val.val.bufVal + sizeof(size_t), cur._bind_buffer, cur._real_length);
00772 }
00773 break;
00774 case SQLT_VBI:
00775 case SQLT_BIN:
00776 {
00777 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(cur._real_length + sizeof(ub4_t)));
00778 *(ub4_t*)buf = (ub4_t)cur._real_length;
00779
00780 size_t shift = 0;
00781 ub1_t* start_buf = buf + sizeof(ub4_t);
00782 ub4 gotLen = 0;
00783 while (shift < cur._real_length)
00784 {
00785 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
00786 &gotLen, (ub4)shift + 1, (start_buf + shift), (ub4)(cur._real_length - shift),
00787 OCI_ONE_PIECE, 0, 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
00788
00789 shift += gotLen;
00790 }
00791 val.val.bufVal = buf;
00792 }
00793 break;
00794 default:
00795 exception::_throw("Unsupported native sql type");
00796 assert(false);
00797 }
00798 }
00799
00800
00801 void
00802 orcl_dbserver::v_get_one_column_info(size_t index)
00803 {
00804 binder& cur = _cols[index];
00805 ub2 real_length = 0;
00806 char* name = 0;
00807 ub4 name_len = 0;
00808 ub4 display_len;
00809 ub2 native_type = 0;
00810 ub1 precision = 0;
00811 b1 scale = 0;
00812 ub1 nullable = 0;
00813
00814 OCIParam* parmdp = 0;
00815 check_retcode(OCIParamGet(_stmthp, OCI_HTYPE_STMT, _errhp, (void**)&parmdp, (ub4)index + 1), _errhp, OCI_HTYPE_ERROR)
00816
00817
00818 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&name, &name_len, OCI_ATTR_NAME, _errhp), _errhp, OCI_HTYPE_ERROR)
00819
00820
00821 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&native_type, 0, OCI_ATTR_DATA_TYPE, _errhp), _errhp, OCI_HTYPE_ERROR)
00822
00823
00824 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&real_length, 0, OCI_ATTR_DATA_SIZE, _errhp), _errhp, OCI_HTYPE_ERROR)
00825
00826
00827 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&precision, 0, OCI_ATTR_PRECISION, _errhp), _errhp, OCI_HTYPE_ERROR)
00828
00829
00830 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&scale, 0, OCI_ATTR_SCALE, _errhp), _errhp, OCI_HTYPE_ERROR)
00831
00832
00833 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&display_len, 0, OCI_ATTR_DISP_SIZE, _errhp), _errhp, OCI_HTYPE_ERROR)
00834
00835
00836 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, (void*)&nullable, 0, OCI_ATTR_IS_NULL, _errhp), _errhp, OCI_HTYPE_ERROR)
00837
00838
00839 check_retcode(OCIAttrGet(parmdp, OCI_DTYPE_PARAM, &native_type, 0, OCI_ATTR_DATA_TYPE, _errhp), _errhp, OCI_HTYPE_ERROR)
00840
00841 cur._max_length = real_length;
00842 cur.set_name(_columns_allocator, name);
00843 cur._native_type = native_type;
00844 cur._scale = scale;
00845 cur._precision = precision;
00846 cur._value.nullVal = nullable != 0;
00847 cur._max_length = cur._precision;
00848 }
00849
00850
00851 void
00852 orcl_dbserver::v_form_sql_string()
00853 {
00854 size_t count_params = _params.size();
00855 switch (get_action())
00856 {
00857 case ACTION_NONE:
00858 case ACTION_EXEC_SQL:
00859 case ACTION_OPEN_SQL:
00860 case ACTION_EXEC_SQL_ASYNC:
00861 case ACTION_OPEN_SQL_ASYNC:
00862 case ACTION_FETCH:
00863 case ACTION_FETCH_ASYNC:
00864 break;
00865 case ACTION_OPEN_PROC:
00866 case ACTION_EXEC_PROC:
00867 case ACTION_OPEN_PROC_ASYNC:
00868 case ACTION_EXEC_PROC_ASYNC:
00869 {
00870
00871 string_t val(_temp_allocator);
00872 char q[2] = {_quote, 0};
00873 val = "BEGIN ";
00874 val += _sql;
00875 val += "(";
00876 for (size_t index = 0; index < count_params; ++index)
00877 {
00878 if (index)
00879 val += ", ";
00880
00881 val += q;
00882
00883 if (_params[index]._name)
00884 val += _params[index]._name;
00885 else
00886 {
00887 char buf[32];
00888 str_template::strprint(buf, 32, "%d", index + 1);
00889 val += buf;
00890 }
00891 }
00892
00893 val += "); END;";
00894 _sql = val;
00895 }
00896 break;
00897 default:
00898 assert(false);
00899 }
00900 }
00901
00902
00903 void
00904 orcl_dbserver::v_rebind_one_param(size_t index)
00905 {
00906 binder& cur = _params[index];
00907 if (!is_param_out(cur._in_out))
00908 return;
00909
00910 cur._value.nullVal = false;
00911
00912 if (cur._real_length == os_minus_one)
00913 {
00914 cur._value.nullVal = true;
00915 memset(&cur._value.val, 0, sizeof(terimber_db_value));
00916 return;
00917 }
00918
00919 switch (cur._native_type)
00920 {
00921 case SQLT_INT:
00922 break;
00923 case SQLT_FLT:
00924 memcpy((void*)cur._value.val.bufVal, cur._bind_buffer, cur._max_length);
00925 break;
00926 case SQLT_DAT:
00927 {
00928 const ub1_t* ptds = (const ub1_t*)cur._bind_buffer;
00929 sb8_t dummy64;
00930 date::convert_to((ptds[0] - 100) * 100 + (ptds[1] - 100), ptds[2], ptds[3], ptds[4] - 1, ptds[5] - 1, ptds[6] - 1, 0, dummy64);
00931 #ifdef OS_64BIT
00932 cur._value.val.intVal = dummy64;
00933 #else
00934 sb8_t* dummy = (sb8_t*)check_pointer(cur.allocate_value(0));
00935 *dummy = dummy64;
00936 #endif
00937 }
00938 break;
00939 case SQLT_LNG:
00940 case SQLT_LVC:
00941 if (*(unsigned short*)&cur._user_code == 1406)
00942 {
00943 char* sz = (char*)check_pointer(cur.allocate_value(cur._real_length));
00944 sz[cur._real_length] = 0;
00945
00946 size_t shift = 0;
00947 ub4 gotLen = 0;
00948 while (shift < cur._real_length)
00949 {
00950 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
00951 &gotLen, (ub4)shift, (sz + shift), (ub4)(cur._real_length - shift),
00952 0, 0,
00953 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
00954
00955
00956 shift += gotLen;
00957 }
00958 }
00959 else
00960 {
00961 char* sz = (char*)check_pointer(cur.allocate_value(cur._real_length));
00962 sz[cur._real_length] = 0;
00963 memcpy(sz, cur._bind_buffer, cur._real_length);
00964 }
00965 break;
00966 case SQLT_VNU:
00967 {
00968 ((ub1_t*)cur._bind_buffer)[cur._real_length] = 0;
00969 numeric conv(_temp_allocator);
00970 if (!conv.parse_orcl((const ub1_t*)cur._bind_buffer + 1))
00971 exception::_throw("Out of range");
00972
00973 ub1_t* buf = (ub1_t*)check_pointer(cur.allocate_value(conv.orcl_len()));
00974 conv.persist_orcl(buf);
00975 }
00976 break;
00977 case SQLT_NUM:
00978 {
00979 ((ub1_t*)cur._bind_buffer)[cur._real_length] = 0;
00980 numeric conv(_temp_allocator);
00981 if (!conv.parse_orcl((const ub1_t*)cur._bind_buffer))
00982 exception::_throw("Out of range");
00983
00984 ub1_t* buf = (ub1_t*)check_pointer(cur.allocate_value(conv.orcl_len()));
00985 conv.persist_orcl(buf);
00986 }
00987 break;
00988 case SQLT_VCS:
00989 case SQLT_CHR:
00990 case SQLT_STR:
00991 case SQLT_RID:
00992 case SQLT_AFC:
00993 case SQLT_AVC:
00994 {
00995 char* sz = (char*)check_pointer(cur.allocate_value(cur._real_length));
00996 sz[cur._real_length] = 0;
00997 memcpy(sz, cur._bind_buffer, cur._real_length);
00998 }
00999 break;
01000 case SQLT_LBI:
01001 case SQLT_LVB:
01002 if (*(unsigned short*)&cur._user_code == 1406)
01003 {
01004 ub1_t* buf = (ub1_t*)check_pointer(cur.allocate_value(cur._real_length));
01005
01006 size_t shift = 0;
01007 ub4 gotLen = 0;
01008 while (shift < cur._real_length)
01009 {
01010 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
01011 &gotLen, (ub4)shift, (buf + shift), (ub4)(cur._real_length - shift),
01012 0, 0,
01013 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
01014
01015
01016 shift += gotLen;
01017 }
01018 }
01019 else
01020 {
01021 ub1_t* bval = (ub1_t*)check_pointer(cur.allocate_value(cur._real_length));
01022 memcpy(bval, cur._bind_buffer, cur._real_length);
01023 }
01024 break;
01025 case SQLT_VBI:
01026 case SQLT_BIN:
01027 {
01028 ub1_t* buf = (ub1_t*)check_pointer(cur.allocate_value(cur._real_length));
01029
01030 size_t shift = 0;
01031 ub4 gotLen = 0;
01032 while (shift < cur._real_length)
01033 {
01034 check_retcode(OCILobRead(_svchp, _errhp, (OCILobLocator*)cur._user_code,
01035 &gotLen, (ub4)shift, (buf + shift), (ub4)(cur._real_length - shift),
01036 0, 0,
01037 0, SQLCS_IMPLICIT), _errhp, OCI_HTYPE_ERROR)
01038
01039 shift += gotLen;
01040 }
01041 }
01042 break;
01043 default:
01044 exception::_throw("Unsupported native sql type");
01045 assert(false);
01046 }
01047 }
01048
01049
01050 void
01051 orcl_dbserver::v_interrupt_async()
01052 {
01053
01054 v_close();
01055 }
01056
01057
01058 dbtypes
01059 orcl_dbserver::v_native_type_to_client_type(size_t native_type)
01060 {
01061 switch (native_type)
01062 {
01063 case SQLT_NON:
01064 return db_unknown;
01065 case SQLT_INT:
01066 return db_sb4;
01067 case SQLT_UIN:
01068 return db_ub4;
01069 case SQLT_FLT:
01070 return db_double;
01071 case SQLT_DAT:
01072 return db_date;
01073 case SQLT_NUM:
01074 case SQLT_VNU:
01075 case SQLT_PDN:
01076 return db_numeric;
01077 case SQLT_VCS:
01078 case SQLT_CHR:
01079 case SQLT_STR:
01080 case SQLT_RID:
01081 case SQLT_VBI:
01082 case SQLT_BIN:
01083 case SQLT_AFC:
01084 case SQLT_AVC:
01085 case SQLT_CLOB:
01086 return db_string;
01087 case SQLT_LNG:
01088 case SQLT_LBI:
01089 case SQLT_LVC:
01090 case SQLT_LVB:
01091 case SQLT_BLOB:
01092 return db_binary;
01093 case SQLT_CUR:
01094 case SQLT_SLS:
01095 default:
01096 assert(false);
01097 return db_unknown;
01098 }
01099 }
01100
01102
01104
01105 db_entry*
01106 orcl_db_creator::create( const db_arg& arg
01107 )
01108 {
01109 db_entry* obj = 0;
01110 if (0 != (obj = new db_entry(arg._ident, arg._trusted, arg._login_string)))
01111 {
01112 if (!(obj->_obj = new orcl_dbserver(arg._ident)))
01113 delete obj, obj = 0;
01114 }
01115
01116 return obj;
01117 }
01118 #pragma pack()
01119 END_TERIMBER_NAMESPACE