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 #include "dbodbc/odbcsrv.h"
00028 #include "base/vector.hpp"
00029 #include "base/list.hpp"
00030 #include "base/string.hpp"
00031 #include "base/memory.hpp"
00032 #include "base/common.hpp"
00033 #include "base/numeric.h"
00034
00035 BEGIN_TERIMBER_NAMESPACE
00036 #pragma pack(4)
00037
00038 #define check_retcode_db(x) \
00039 if (x != SQL_SUCCESS) odbc_dbserver::get_odbc_error(x, _henv, _hdbc, 0);
00040
00041 #define check_retcode(x) \
00042 if (x != SQL_SUCCESS) odbc_dbserver::get_odbc_error(x, _henv, _hdbc, _hstmt);
00043
00044
00045
00046 #ifndef SQLLEN
00047 #define SQLLEN SQLINTEGER
00048 #endif
00049 #ifndef SQLULEN
00050 #define SQLULEN SQLUINTEGER
00051 #endif
00052
00053 static const size_t MAX_CONNECT_LEN = 2048;
00054 static const char* valid_delimeters = " ,)}";
00055 static const size_t MAX_FNAME_LEN = 256;
00056
00057
00058 void
00059 odbc_dbserver::get_odbc_error(size_t code, SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt)
00060 {
00061 SWORD nOutlen;
00062 SDWORD lNative = 0;
00063 #if OS_TYPE == OS_WIN32
00064 SQLWCHAR lpszMsg[SQL_MAX_MESSAGE_LENGTH + 1] = {0};
00065 SQLWCHAR lpszState[SQL_SQLSTATE_SIZE + 1] = {0};
00066
00067 RETCODE retCode = ::SQLErrorW(henv, hdbc, hstmt, lpszState, &lNative,
00068 lpszMsg, SQL_MAX_MESSAGE_LENGTH, &nOutlen);
00069
00070
00071 if (code != SQL_SUCCESS_WITH_INFO && (!lpszState[0] || wcscmp(lpszState, L"00000") != 0))
00072 exception::_throw(lpszMsg);
00073 #else
00074 SQLCHAR lpszMsg[SQL_MAX_MESSAGE_LENGTH + 1] = {0};
00075 SQLCHAR lpszState[SQL_SQLSTATE_SIZE + 1] = {0};
00076
00077 RETCODE retCode = ::SQLError(henv, hdbc, hstmt, lpszState, &lNative,
00078 lpszMsg, SQL_MAX_MESSAGE_LENGTH, &nOutlen);
00079
00080
00081 if (code != SQL_SUCCESS_WITH_INFO && (!lpszState[0] || strcmp((const char*)lpszState, "00000") != 0))
00082 exception::_throw((const char*)lpszMsg);
00083 #endif
00084 }
00085
00087 odbc_dbserver::odbc_dbserver(size_t ident) : dbserver_impl(ident),
00088 _henv(SQL_NULL_HENV),
00089 _hdbc(SQL_NULL_HDBC),
00090 _hstmt(SQL_NULL_HSTMT),
00091 _bind_cols(false)
00092 {
00093 }
00094
00095 odbc_dbserver::~odbc_dbserver()
00096 {
00097 if (_is_open_sql())
00098 close_sql();
00099
00100
00101 if (_is_connect())
00102 disconnect();
00103 }
00104
00105
00106 void
00107 odbc_dbserver::v_connect(bool trusted_connection, const char* connection_string)
00108 {
00109
00110 RETCODE retCode = ::SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &_henv);
00111 check_retcode_db(retCode)
00112
00113 retCode = ::SQLSetEnvAttr(_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, SQL_IS_INTEGER);
00114 check_retcode_db(retCode)
00115
00116 retCode = ::SQLAllocHandle(SQL_HANDLE_DBC, _henv, &_hdbc);
00117 check_retcode_db(retCode)
00118
00119
00120 retCode = ::SQLSetConnectAttr(_hdbc,
00121 #if defined(_MSC_VER) && (_MSC_VER > 1200) // .Net
00122 SQL_COPT_SS_INTEGRATED_SECURITY,
00123 #else // VC 6.0
00124 SQL_INTEGRATED_SECURITY,
00125 #endif
00126
00127 trusted_connection ? (void*)SQL_IS_ON : (void*)SQL_IS_OFF, SQL_IS_INTEGER);
00128 check_retcode_db(retCode)
00129 SWORD nResult;
00130
00131 #if OS_TYPE == OS_WIN32
00132 SQLWCHAR szConnectOutput[MAX_CONNECT_LEN + 1];
00133
00134 retCode = ::SQLDriverConnectW(_hdbc, NULL, (SQLWCHAR*)str_template::multibyte_to_unicode( *_temp_allocator, connection_string), SQL_NTS,
00135 szConnectOutput, MAX_CONNECT_LEN, &nResult, SQL_DRIVER_NOPROMPT);
00136 #else
00137 SQLCHAR szConnectOutput[MAX_CONNECT_LEN + 1];
00138
00139 retCode = ::SQLDriverConnect(_hdbc, NULL, (SQLCHAR*)(const char*)connection_string, SQL_NTS,
00140 szConnectOutput, MAX_CONNECT_LEN, &nResult, SQL_DRIVER_NOPROMPT);
00141 #endif
00142
00143 check_retcode_db(retCode)
00144 }
00145
00146 void
00147 odbc_dbserver::v_disconnect()
00148 {
00149 _temp_allocator->clear_extra();
00150
00151 v_close();
00152
00153 if (SQL_NULL_HDBC != _hdbc)
00154 {
00155 ::SQLDisconnect(_hdbc);
00156 ::SQLFreeHandle(SQL_HANDLE_DBC, _hdbc);
00157 _hdbc = SQL_NULL_HDBC;
00158 }
00159
00160 if (SQL_NULL_HENV != _henv)
00161 {
00162 ::SQLFreeHandle(SQL_HANDLE_ENV, _henv);
00163 _henv = SQL_NULL_HENV;
00164 }
00165 }
00166
00167 void
00168 odbc_dbserver::v_start_transaction()
00169 {
00170
00171 RETCODE retCode = ::SQLSetConnectAttr(_hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);
00172 check_retcode_db(retCode)
00173 }
00174
00175 void
00176 odbc_dbserver::v_commit()
00177 {
00178
00179 RETCODE retCode = ::SQLEndTran(SQL_HANDLE_DBC, _hdbc, SQL_COMMIT);
00180
00181 ::SQLSetConnectAttr(_hdbc, SQL_AUTOCOMMIT, (void*)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
00182 check_retcode_db(retCode)
00183 }
00184
00185 void
00186 odbc_dbserver::v_rollback()
00187 {
00188
00189 RETCODE retCode = ::SQLEndTran(SQL_HANDLE_DBC, _hdbc, SQL_ROLLBACK);
00190
00191 ::SQLSetConnectAttr(_hdbc, SQL_AUTOCOMMIT, (void*)SQL_AUTOCOMMIT_ON, SQL_IS_INTEGER);
00192 check_retcode_db(retCode)
00193 }
00194
00195 bool
00196 odbc_dbserver::v_is_connect_alive()
00197 {
00198
00199 if (!_is_connect())
00200 return false;
00201
00202 SQLINTEGER value = SQL_CD_TRUE;
00203 ::SQLGetConnectAttr(_hdbc, SQL_COPT_SS_CONNECTION_DEAD, &value, SQL_IS_INTEGER, 0);
00204 return value == SQL_CD_FALSE;
00205 }
00207 void
00208 odbc_dbserver::v_before_execute()
00209 {
00210 RETCODE retCode = ::SQLAllocHandle(SQL_HANDLE_STMT, _hdbc, &_hstmt);
00211 check_retcode(retCode)
00212
00213
00214 switch (get_action())
00215 {
00216 case ACTION_OPEN_SQL:
00217 case ACTION_OPEN_SQL_ASYNC:
00218 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_STATIC, SQL_IS_INTEGER);
00219 check_retcode(retCode)
00220 break;
00221 case ACTION_OPEN_PROC:
00222 case ACTION_OPEN_PROC_ASYNC:
00223 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_INTEGER);
00224 check_retcode(retCode)
00225 break;
00226 default:
00227 break;
00228 }
00229
00230
00231 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_ROW_BIND_TYPE, (void*)SQL_BIND_BY_COLUMN, 0);
00232 check_retcode(retCode)
00233
00234
00235 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_PARAM_BIND_TYPE, (void*)SQL_BIND_BY_COLUMN, 0);
00236 check_retcode(retCode)
00237
00238
00239 SQLUINTEGER bulk = (SQLUINTEGER)_bulk_params.size();
00240 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_PARAMSET_SIZE, (void*)(bulk ? bulk : 1), 0);
00241 check_retcode(retCode)
00242 }
00243
00244 void
00245 odbc_dbserver::v_after_execute()
00246 {
00247 switch (get_action())
00248 {
00249 case ACTION_EXEC_SQL:
00250 case ACTION_EXEC_SQL_ASYNC:
00251 case ACTION_EXEC_PROC:
00252 case ACTION_EXEC_PROC_ASYNC:
00253 {
00254 size_t maxRes = 1024;
00255 while (SQL_SUCCESS == ::SQLMoreResults(_hstmt) && maxRes-- > 0);
00256 }
00257 break;
00258 case ACTION_OPEN_SQL:
00259 case ACTION_OPEN_SQL_ASYNC:
00260 case ACTION_OPEN_PROC:
00261 case ACTION_OPEN_PROC_ASYNC:
00262 {
00263 size_t maxRes = 1024;
00264 SQLLEN infoValuePtr = 0;
00265 RETCODE retCode = ::SQLRowCount(_hstmt, &infoValuePtr);
00266 while (!retCode && infoValuePtr > 0 && maxRes-- > 0)
00267 {
00268 retCode = ::SQLMoreResults(_hstmt);
00269 if (!retCode)
00270 {
00271 infoValuePtr = 0;
00272 retCode = ::SQLRowCount(_hstmt, &infoValuePtr);
00273 }
00274 else if (retCode == SQL_SUCCESS_WITH_INFO)
00275 {
00276 SWORD nOutlen;
00277 SDWORD lNative = 0;
00278 #if OS_TYPE == OS_WIN32
00279 SQLWCHAR lpszMsg[SQL_MAX_MESSAGE_LENGTH + 1] = {0};
00280 SQLWCHAR lpszState[SQL_SQLSTATE_SIZE + 1] = {0};
00281
00282 ::SQLErrorW(_henv, _hdbc, _hstmt, lpszState, &lNative,
00283 lpszMsg, SQL_MAX_MESSAGE_LENGTH, &nOutlen);
00284 #else
00285 SQLCHAR lpszMsg[SQL_MAX_MESSAGE_LENGTH + 1] = {0};
00286 SQLCHAR lpszState[SQL_SQLSTATE_SIZE + 1] = {0};
00287
00288 ::SQLError(_henv, _hdbc, _hstmt, lpszState, &lNative,
00289 lpszMsg, SQL_MAX_MESSAGE_LENGTH, &nOutlen);
00290 #endif
00291 }
00292 }
00293 }
00294 break;
00295 default:
00296 break;
00297 }
00298 }
00299
00300
00301 void
00302 odbc_dbserver::v_before_bind_columns()
00303 {
00304
00305 _bind_cols = true;
00306 bool find_blob = false;
00307 size_t cols = _cols.size();
00308 for (size_t col_ind = 0; _bind_cols && col_ind < cols; ++col_ind)
00309 {
00310 switch (_cols[col_ind]._native_type)
00311 {
00312 case SQL_LONGVARCHAR:
00313 case SQL_WLONGVARCHAR:
00314 case SQL_LONGVARBINARY:
00315 find_blob = true;
00316 break;
00317 default:
00318 if (find_blob)
00319 _bind_cols = false;
00320 break;
00321 }
00322 }
00323
00324
00325 if (!_bind_cols)
00326 _bulk_rows = 1;
00327 }
00328
00329
00330 void
00331 odbc_dbserver::v_execute()
00332 {
00333 #if OS_TYPE == OS_WIN32
00334
00335 RETCODE retCode = ::SQLExecDirectW(_hstmt, (SQLWCHAR*)str_template::multibyte_to_unicode( *_temp_allocator, _sql), SQL_NTS);
00336 #else
00337
00338 RETCODE retCode = ::SQLExecDirect(_hstmt, (SQLCHAR*)(const char*)_sql, SQL_NTS);
00339 #endif
00340 check_retcode(retCode)
00341 }
00342
00343
00344 void
00345 odbc_dbserver::v_close()
00346 {
00347 if (_hstmt != SQL_NULL_HSTMT)
00348 {
00349 ::SQLFreeHandle(SQL_HANDLE_STMT, _hstmt);
00350 _hstmt = SQL_NULL_HSTMT;
00351 }
00352 }
00353
00354
00355 void
00356 odbc_dbserver::v_fetch()
00357 {
00358 RETCODE retCode;
00359 size_t select_row = 0;
00360
00361 size_t col_count = _cols.size();
00362 SQLUINTEGER row_count = 0;
00363 SQLUINTEGER row_fetch = (SQLUINTEGER)__min(_bulk_rows, _requested_rows);
00364
00365
00366 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (void*)row_fetch, 0);
00367 check_retcode(retCode)
00368 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &row_count, 0);
00369 check_retcode(retCode)
00370
00371 SQLUSMALLINT orientation = _start_row ? SQL_FETCH_ABSOLUTE : (_forward ? SQL_FETCH_NEXT : SQL_FETCH_PRIOR);
00372
00373 SQLINTEGER offset = (SQLINTEGER)_start_row;
00374 offset *= _forward ? 1 : -1;
00375 while (_requested_rows
00376 && (retCode = ::SQLFetchScroll(_hstmt, orientation, offset)) != SQL_NO_DATA_FOUND)
00377 {
00378 check_retcode(retCode)
00379
00380 if (STATE_INTERRUPTED == get_state())
00381 exception::_throw("Fetching process is interrupted");
00382
00383
00384 for (size_t rows = 0; rows < row_count; ++rows)
00385 {
00386
00387 _vector< terimber_db_value > val;
00388 recordset_list_t::iterator iter_val = _data.push_back(*_data_allocator, val);
00389 if (iter_val == _data.end())
00390 exception::_throw("Not enough memory");
00391
00392
00393 if (!iter_val->resize(*_data_allocator, col_count))
00394 exception::_throw("Not enough memory");
00395
00396 for (size_t index = 0; index < col_count; ++index)
00397 v_convert_one_value(rows, index, (*iter_val)[index]);
00398
00399
00400 ++select_row;
00401
00402 _forward ? ++offset : --offset;
00403
00404 --_requested_rows;
00405 }
00406
00407
00408 if (_requested_rows > 0 && _requested_rows < row_fetch)
00409 {
00410 row_fetch = (SQLUINTEGER)_requested_rows;
00411 retCode = ::SQLSetStmtAttr(_hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (void*)row_fetch, 0);
00412 check_retcode(retCode)
00413 }
00414 }
00415
00416
00417 _fetched_rows = select_row;
00418 }
00419
00420
00421 void
00422 odbc_dbserver::v_form_sql_string()
00423 {
00424 size_t count_params = _params.size();
00425 switch (get_action())
00426 {
00427 case ACTION_NONE:
00428 case ACTION_EXEC_SQL:
00429 case ACTION_OPEN_SQL:
00430 case ACTION_EXEC_SQL_ASYNC:
00431 case ACTION_OPEN_SQL_ASYNC:
00432 case ACTION_FETCH:
00433 case ACTION_FETCH_ASYNC:
00434 break;
00435 case ACTION_OPEN_PROC:
00436 case ACTION_EXEC_PROC:
00437 case ACTION_OPEN_PROC_ASYNC:
00438 case ACTION_EXEC_PROC_ASYNC:
00439 {
00440 string_t val(_temp_allocator);
00441 val = "{call ";
00442 val += _sql;
00443
00444 for (size_t index = 0; index < count_params; index++)
00445 {
00446 if (is_param_out(_params[index]._in_out))
00447 {
00448 if (0 == index)
00449 val += "(:";
00450 else
00451 val += ", :";
00452 }
00453 else
00454 {
00455 if (0 == index)
00456 val += "(:";
00457 else
00458 val += ", :";
00459 }
00460 }
00461
00462 if (count_params != 0)
00463 val += ")";
00464
00465 val += "}";
00466
00467 _sql = val;
00468 }
00469 break;
00470 default:
00471 assert(false);
00472 }
00473 }
00474
00475
00476 void
00477 odbc_dbserver::v_replace_quote()
00478 {
00479 if (0 == _quote)
00480 return;
00481
00482
00483 if (!_sql.length())
00484 return;
00485
00486
00487 char* buf = (char*)check_pointer(_temp_allocator->allocate(_sql.length() + 1));
00488
00489 *buf = 0;
00490
00491 size_t count_params = 0;
00492
00493 char* new_sql = buf;
00494 const char* begin = _sql;
00495 const char* end = 0;
00496
00497
00498 while (0 != (end = strchr(begin, _quote)))
00499 {
00500 ++count_params;
00501 size_t len = end - begin;
00502
00503 str_template::strcpy(new_sql, begin, len);
00504 begin += len + 1;
00505 new_sql += len;
00506
00507 *new_sql++ = '?';
00508
00509
00510 begin += strcspn(begin, valid_delimeters);
00511 }
00512
00513
00514 if (count_params != _params.size())
00515 exception::_throw("Number of parameters doesn't match the sql statement syntax");
00516
00517
00518 str_template::strcpy(new_sql, begin, os_minus_one);
00519
00520 _sql = buf;
00521 }
00522
00523
00524 void
00525 odbc_dbserver::v_bind_one_param(size_t index)
00526 {
00527 binder& cur = _params[index];
00528 size_t num = _bulk_params.size();
00529
00530
00531 cur._real_length = (size_t)check_pointer(_temp_allocator->allocate((num ? num : 1) * sizeof(SQLINTEGER)));
00532
00533 size_t i;
00534 bulk_params_t::const_iterator iter(_bulk_params.end());
00535
00536 switch (cur._type)
00537 {
00538 case db_bool:
00539 cur._max_length = sizeof(bool);
00540 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00541 if (num)
00542 {
00543 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00544 {
00545 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00546 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.boolVal, cur._max_length);
00547 }
00548 }
00549 else
00550 {
00551 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00552 memcpy(cur._bind_buffer, &cur._value.val.boolVal, cur._max_length);
00553 }
00554
00555 cur._native_type = (size_t)SQL_BIT;
00556 cur._bind_type = (size_t)SQL_C_BIT;
00557 cur._precision = 1;
00558 cur._scale = 0;
00559 break;
00560 case db_sb1:
00561 cur._max_length = sizeof(sb1_t);
00562 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00563 if (num)
00564 {
00565 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00566 {
00567 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00568 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.cVal, cur._max_length);
00569 }
00570 }
00571 else
00572 {
00573 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00574 memcpy(cur._bind_buffer, &cur._value.val.cVal, cur._max_length);
00575 }
00576 cur._native_type = (size_t)SQL_TINYINT;
00577 cur._bind_type = (size_t)SQL_C_TINYINT;
00578 cur._precision = 3;
00579 cur._scale = 0;
00580 break;
00581 case db_ub1:
00582 cur._max_length = sizeof(ub1_t);
00583 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00584 if (num)
00585 {
00586 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00587 {
00588 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00589 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.bVal, cur._max_length);
00590 }
00591 }
00592 else
00593 {
00594 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00595 memcpy(cur._bind_buffer, &cur._value.val.bVal, cur._max_length);
00596 }
00597 cur._native_type = (size_t)SQL_TINYINT;
00598 cur._bind_type = (size_t)SQL_C_TINYINT;
00599 cur._precision = 3;
00600 cur._scale = 0;
00601 break;
00602 case db_sb2:
00603 cur._max_length = sizeof(ub2_t);
00604 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00605 if (num)
00606 {
00607 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00608 {
00609 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00610 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.iVal, cur._max_length);
00611 }
00612 }
00613 else
00614 {
00615 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00616 memcpy(cur._bind_buffer, &cur._value.val.iVal, cur._max_length);
00617 }
00618 cur._native_type = SQL_SMALLINT;
00619 cur._bind_type = SQL_C_SSHORT;
00620 cur._precision = 5;
00621 cur._scale = 0;
00622 break;
00623 case db_ub2:
00624 cur._max_length = sizeof(ub2_t);
00625 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00626 if (num)
00627 {
00628 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00629 {
00630 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00631 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.uiVal, cur._max_length);
00632 }
00633 }
00634 else
00635 {
00636 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00637 memcpy(cur._bind_buffer, &cur._value.val.uiVal, cur._max_length);
00638 }
00639 cur._native_type = SQL_SMALLINT;
00640 cur._bind_type = SQL_C_SSHORT;
00641 cur._precision = 5;
00642 cur._scale = 0;
00643 break;
00644 case db_sb4:
00645 cur._max_length = sizeof(sb4_t);
00646 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00647 if (num)
00648 {
00649 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00650 {
00651 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00652 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.lVal, cur._max_length);
00653 }
00654 }
00655 else
00656 {
00657 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00658 memcpy(cur._bind_buffer, &cur._value.val.lVal, cur._max_length);
00659 }
00660 cur._native_type = SQL_INTEGER;
00661 cur._bind_type = SQL_C_LONG;
00662 cur._precision = 10;
00663 cur._scale = 0;
00664 break;
00665 case db_ub4:
00666 cur._max_length = sizeof(ub4_t);
00667 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00668 if (num)
00669 {
00670 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00671 {
00672 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00673 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.ulVal, cur._max_length);
00674 }
00675 }
00676 else
00677 {
00678 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00679 memcpy(cur._bind_buffer, &cur._value.val.ulVal, cur._max_length);
00680 }
00681 cur._native_type = SQL_INTEGER;
00682 cur._bind_type = SQL_C_LONG;
00683 cur._precision = 10;
00684 cur._scale = 0;
00685 break;
00686 case db_float:
00687 cur._max_length = sizeof(float);
00688 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00689 if (num)
00690 {
00691 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00692 {
00693 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00694 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.fltVal, cur._max_length);
00695 }
00696 }
00697 else
00698 {
00699 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00700 memcpy(cur._bind_buffer, &cur._value.val.fltVal, cur._max_length);
00701 }
00702 cur._native_type = SQL_REAL;
00703 cur._bind_type = SQL_C_FLOAT;
00704 cur._precision = 7;
00705 cur._scale = 0;
00706 break;
00707 case db_double:
00708 cur._max_length = sizeof(double);
00709 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00710 if (num)
00711 {
00712 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00713 {
00714 #ifdef OS_64BIT
00715 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00716 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.dblVal, cur._max_length);
00717 #else
00718 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.dblVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00719 if ((*iter)[index]._value.val.dblVal)
00720 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, (*iter)[index]._value.val.dblVal, cur._max_length);
00721 else
00722 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
00723 #endif
00724 }
00725 }
00726 else
00727 {
00728 #ifdef OS_64BIT
00729 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00730 memcpy(cur._bind_buffer, &cur._value.val.dblVal, cur._max_length);
00731 #else
00732 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.dblVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00733 if (cur._value.val.dblVal)
00734 memcpy(cur._bind_buffer, cur._value.val.dblVal, cur._max_length);
00735 else
00736 memset(cur._bind_buffer, 0, cur._max_length);
00737
00738 #endif
00739 }
00740 cur._native_type = SQL_DOUBLE;
00741 cur._bind_type = SQL_C_DOUBLE;
00742 cur._precision = 15;
00743 cur._scale = 0;
00744 break;
00745 case db_sb8:
00746 cur._max_length = sizeof(sb8_t);
00747 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00748 if (num)
00749 {
00750 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00751 {
00752 #ifdef OS_64BIT
00753 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00754 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.intVal, cur._max_length);
00755 #else
00756 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.intVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00757 if ((*iter)[index]._value.val.intVal)
00758 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, (*iter)[index]._value.val.intVal, cur._max_length);
00759 else
00760 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
00761 #endif
00762 }
00763 }
00764 else
00765 {
00766 #ifdef OS_64BIT
00767 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00768 memcpy(cur._bind_buffer, &cur._value.val.intVal, cur._max_length);
00769 #else
00770 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.intVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00771 if (cur._value.val.intVal)
00772 memcpy(cur._bind_buffer, cur._value.val.intVal, cur._max_length);
00773 else
00774 memset(cur._bind_buffer, 0, cur._max_length);
00775
00776 #endif
00777 }
00778 cur._native_type = (size_t)SQL_BIGINT;
00779 cur._bind_type = (size_t)SQL_C_SBIGINT;
00780 cur._precision = 10;
00781 cur._scale = 0;
00782 break;
00783 case db_ub8:
00784 cur._max_length = sizeof(ub8_t);
00785 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00786 if (num)
00787 {
00788 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00789 {
00790 #ifdef OS_64BIT
00791 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00792 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, &(*iter)[index]._value.val.uintVal, cur._max_length);
00793 #else
00794 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.uintVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00795 if ((*iter)[index]._value.val.uintVal)
00796 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, (*iter)[index]._value.val.uintVal, cur._max_length);
00797 else
00798 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
00799 #endif
00800 }
00801 }
00802 else
00803 {
00804 #ifdef OS_64BIT
00805 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00806 memcpy(cur._bind_buffer, &cur._value.val.uintVal, cur._max_length);
00807 #else
00808 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.uintVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00809 if (cur._value.val.uintVal)
00810 memcpy(cur._bind_buffer, cur._value.val.uintVal, cur._max_length);
00811 else
00812 memset(cur._bind_buffer, 0, cur._max_length);
00813
00814 #endif
00815 }
00816 cur._native_type = (size_t)SQL_BIGINT;
00817 cur._bind_type = (size_t)SQL_C_SBIGINT;
00818 cur._precision = 10;
00819 cur._scale = 0;
00820 break;
00821 case db_date:
00822 cur._max_length = sizeof(TIMESTAMP_STRUCT);
00823 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
00824 if (num)
00825 {
00826 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00827 {
00828 #ifdef OS_64BIT
00829 *((SQLINTEGER*)cur._real_length + i) = (*iter)[index]._value.nullVal ? SQL_NULL_DATA : 0;
00830 #else
00831 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.intVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00832 #endif
00833 TIMESTAMP_STRUCT* ptds = (TIMESTAMP_STRUCT*)cur._bind_buffer + i;
00834 ub4_t year32;
00835 ub1_t month8, day8, hour8, minute8, second8, wday8;
00836 ub2_t millisec16, yday16;
00837 #ifdef OS_64BIT
00838 if (!(*iter)[index]._value.nullVal)
00839 #else
00840 if (!(*iter)[index]._value.nullVal && (*iter)[index]._value.val.intVal)
00841 #endif
00842 {
00843 date::convert_from(
00844 #ifdef OS_64BIT
00845 (*iter)[index]._value.val.intVal,
00846 #else
00847 *(*iter)[index]._value.val.intVal,
00848 #endif
00849 year32,
00850 month8,
00851 day8,
00852 hour8,
00853 minute8,
00854 second8,
00855 millisec16,
00856 wday8,
00857 yday16);
00858
00859 ptds->year = year32;
00860 ptds->month = month8;
00861 ptds->day = day8;
00862 ptds->hour = hour8;
00863 ptds->minute = minute8;
00864 ptds->second = second8;
00865 ptds->fraction = millisec16 * 1000000;
00866 }
00867 else
00868 {
00869 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
00870 }
00871 }
00872 }
00873 else
00874 {
00875 #ifdef OS_64BIT
00876 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.intVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00877 if (!cur._value.nullVal)
00878 #else
00879 *(SQLINTEGER*)cur._real_length = cur._value.nullVal ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
00880 if (!cur._value.nullVal && cur._value.val.intVal)
00881 #endif
00882 {
00883 TIMESTAMP_STRUCT* ptds = (TIMESTAMP_STRUCT*)cur._bind_buffer;
00884 ub4_t year32;
00885 ub1_t month8, day8, hour8, minute8, second8, wday8;
00886 ub2_t millisec16, yday16;
00887
00888 date::convert_from(
00889 #ifdef OS_64BIT
00890 cur._value.val.intVal,
00891 #else
00892 *cur._value.val.intVal,
00893 #endif
00894 year32,
00895 month8,
00896 day8,
00897 hour8,
00898 minute8,
00899 second8,
00900 millisec16,
00901 wday8,
00902 yday16);
00903
00904 ptds->year = year32;
00905 ptds->month = month8;
00906 ptds->day = day8;
00907 ptds->hour = hour8;
00908 ptds->minute = minute8;
00909 ptds->second = second8;
00910 ptds->fraction = millisec16 * 1000000;
00911 }
00912 else
00913 {
00914 memset((ub1_t*)cur._bind_buffer, 0, cur._max_length);
00915 }
00916 }
00917
00918 cur._native_type = SQL_TIMESTAMP;
00919 cur._bind_type = SQL_C_TIMESTAMP;
00920 cur._precision = 23;
00921 cur._scale = 3;
00922 break;
00923 case db_string:
00924
00925 if (num)
00926 {
00927 size_t max_len = 0;
00928 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00929 {
00930 size_t len = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.strVal) ? 0 : str_template::strlen((*iter)[index]._value.val.strVal);
00931 *((SQLINTEGER*)cur._real_length + i) = !len ? SQL_NULL_DATA : SQL_NTS;
00932
00933 if (len > max_len)
00934 max_len = len;
00935 }
00936
00937 if (!is_param_out(cur._in_out))
00938 cur._max_length = max_len;
00939 else
00940 cur._max_length = __max(cur._max_length, max_len);
00941 }
00942 else
00943 {
00944 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.strVal) ? SQL_NULL_DATA : SQL_NTS;
00945
00946 if (!is_param_out(cur._in_out))
00947 cur._max_length = (!cur._value.nullVal && cur._value.val.strVal) ? str_template::strlen(cur._value.val.strVal) : 0;
00948 else
00949 cur._max_length = __max(cur._max_length, (!cur._value.nullVal && cur._value.val.strVal) ? str_template::strlen(cur._value.val.strVal) : 0);
00950 }
00951
00952 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * (cur._max_length + 1)));
00953
00954 if (num)
00955 {
00956 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00957 {
00958 memset((char*)cur._bind_buffer + i * (cur._max_length + 1), 0, cur._max_length + 1);
00959 if ((*iter)[index]._value.val.strVal)
00960 str_template::strcpy((char*)cur._bind_buffer + i * (cur._max_length + 1), (*iter)[index]._value.val.strVal, os_minus_one);
00961 }
00962 }
00963 else
00964 {
00965 if (!cur._value.nullVal && cur._value.val.strVal)
00966 str_template::strcpy((char*)cur._bind_buffer, cur._value.val.strVal, os_minus_one);
00967 else
00968 memset(cur._bind_buffer, 0, cur._max_length + 1);
00969 }
00970 cur._bind_type = SQL_C_CHAR;
00971 cur._precision = cur._max_length ? cur._max_length : 1;
00972 cur._native_type = cur._precision > 4000 ? SQL_LONGVARCHAR : SQL_VARCHAR;
00973 cur._scale = 0;
00974 cur._max_length += 1;
00975 break;
00976 case db_wstring:
00977
00978 if (num)
00979 {
00980 size_t max_len = 0;
00981 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
00982 {
00983 size_t len = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.wstrVal) ? 0 : str_template::strlen((*iter)[index]._value.val.wstrVal);
00984 *((SQLINTEGER*)cur._real_length + i) = !len ? SQL_NULL_DATA : SQL_NTS;
00985
00986 if (len > max_len)
00987 max_len = len;
00988 }
00989
00990 if (!is_param_out(cur._in_out))
00991 cur._max_length = max_len;
00992 else
00993 cur._max_length = __max(cur._max_length, max_len);
00994 }
00995 else
00996 {
00997 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.wstrVal) ? SQL_NULL_DATA : SQL_NTS;
00998
00999 if (!is_param_out(cur._in_out))
01000 cur._max_length = (!cur._value.nullVal && cur._value.val.wstrVal) ? str_template::strlen(cur._value.val.wstrVal) : 0;
01001 else
01002 cur._max_length = __max(cur._max_length, (!cur._value.nullVal && cur._value.val.wstrVal) ? str_template::strlen(cur._value.val.wstrVal) : 0);
01003 }
01004
01005
01006 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * (cur._max_length + 1) * sizeof(wchar_t)));
01007
01008 if (num)
01009 {
01010 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
01011 {
01012 memset((wchar_t*)cur._bind_buffer + i * (cur._max_length + 1), 0, cur._max_length + 1);
01013 if ((*iter)[index]._value.val.wstrVal)
01014 str_template::strcpy((wchar_t*)cur._bind_buffer + i * (cur._max_length + 1), (*iter)[index]._value.val.wstrVal, os_minus_one);
01015 }
01016 }
01017 else
01018 {
01019 if (!cur._value.nullVal && cur._value.val.wstrVal)
01020 str_template::strcpy((wchar_t*)cur._bind_buffer, cur._value.val.wstrVal, os_minus_one);
01021 else
01022 memset(cur._bind_buffer, 0, sizeof(wchar_t) * (cur._max_length + 1));
01023 }
01024
01025 cur._bind_type = (size_t)SQL_C_WCHAR;
01026 cur._precision = cur._max_length ? cur._max_length : 1;
01027 cur._native_type = cur._precision > 4000 ? SQL_WLONGVARCHAR : SQL_WVARCHAR;
01028 cur._scale = 0;
01029 cur._max_length += 1;
01030 cur._max_length *= sizeof(wchar_t);
01031 break;
01032 case db_binary:
01033 if (num)
01034 {
01035 size_t max_len = 0;
01036 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
01037 {
01038 size_t len = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.bufVal) ? 0 : *(size_t*)(*iter)[index]._value.val.bufVal;
01039 *((SQLINTEGER*)cur._real_length + i) = !len ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
01040
01041 if (len > max_len)
01042 max_len = len;
01043 }
01044
01045 if (!is_param_out(cur._in_out))
01046 cur._max_length = max_len;
01047 else
01048 cur._max_length = __max(cur._max_length, max_len);
01049 }
01050 else
01051 {
01052 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.bufVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
01053
01054 if (!is_param_out(cur._in_out))
01055 cur._max_length = (!cur._value.nullVal && cur._value.val.bufVal) ? *(size_t*)cur._value.val.bufVal : 0;
01056 else
01057 cur._max_length = __max(cur._max_length, (!cur._value.nullVal && cur._value.val.bufVal) ? *(size_t*)cur._value.val.bufVal : 0);
01058 }
01059
01060 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
01061
01062 if (num)
01063 {
01064 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
01065 {
01066 if (cur._value.val.bufVal)
01067 memcpy((ub1_t*)cur._bind_buffer + i * cur._max_length, (*iter)[index]._value.val.bufVal + sizeof(size_t), *(size_t*)(*iter)[index]._value.val.bufVal);
01068 else
01069 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
01070 }
01071 }
01072 else
01073 {
01074 if (!cur._value.nullVal && cur._value.val.bufVal)
01075 memcpy(cur._bind_buffer, cur._value.val.bufVal + sizeof(size_t), *(size_t*)cur._value.val.bufVal);
01076 else
01077 memset(cur._bind_buffer, 0, cur._max_length);
01078 }
01079
01080
01081 cur._scale = 0;
01082 cur._precision = cur._max_length ? cur._max_length : 1;
01083 cur._native_type = cur._precision > 255 ? (size_t)SQL_LONGVARBINARY : (size_t)SQL_VARBINARY;
01084 cur._bind_type = (size_t)SQL_C_BINARY;
01085 break;
01086 case db_decimal:
01087 case db_numeric:
01088 cur._max_length = 40;
01089 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
01090 if (num)
01091 {
01092 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
01093 {
01094 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.bufVal) ? SQL_NULL_DATA : SQL_NTS;
01095 if ((*iter)[index]._value.val.bufVal)
01096 {
01097 numeric num(_temp_allocator);
01098 if (!num.parse_orcl((*iter)[index]._value.val.bufVal))
01099 exception::_throw("Out of range");
01100
01101
01102 if (!num.format((char*)cur._bind_buffer + i * cur._max_length, '.'))
01103 exception::_throw("Out of range");
01104
01105 *((SQLINTEGER*)cur._real_length + i) = (SQLINTEGER)str_template::strlen((const char*)cur._bind_buffer + i * cur._max_length);
01106 }
01107 else
01108 memset((ub1_t*)cur._bind_buffer + i * cur._max_length, 0, cur._max_length);
01109 }
01110
01111 cur._precision = cur._max_length;
01112 cur._scale = 0;
01113 }
01114 else
01115 {
01116 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.bufVal) ? SQL_NULL_DATA : SQL_NTS;
01117 if (cur._value.val.bufVal)
01118 {
01119 numeric num(_temp_allocator);
01120 if (!num.parse_orcl(cur._value.val.bufVal))
01121 exception::_throw("Out of range");
01122
01123
01124 if (!num.format((char*)cur._bind_buffer, '.'))
01125 exception::_throw("Out of range");
01126
01127 *(SQLINTEGER*)cur._real_length = (SQLINTEGER)str_template::strlen((const char*)cur._bind_buffer);
01128 cur._precision = num.precision();
01129 cur._scale = num.scale();
01130 }
01131 }
01132
01133 cur._native_type = SQL_NUMERIC;
01134 cur._bind_type = SQL_C_CHAR;
01135 break;
01136 case db_guid:
01137 cur._max_length = sizeof(guid_t);
01138 cur._bind_buffer = check_pointer(_temp_allocator->allocate((num ? num : 1) * cur._max_length));
01139 if (num)
01140 {
01141 for (i = 0, iter = _bulk_params.begin(); iter != _bulk_params.end(); ++iter, ++i)
01142 {
01143 *((SQLINTEGER*)cur._real_length + i) = ((*iter)[index]._value.nullVal || !(*iter)[index]._value.val.guidVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
01144 *((guid_t*)cur._bind_buffer + i) = (*iter)[index]._value.val.guidVal ? *(*iter)[index]._value.val.guidVal : null_uuid;
01145 }
01146
01147 cur._precision = cur._max_length;
01148 cur._scale = 0;
01149 }
01150 else
01151 {
01152 *(SQLINTEGER*)cur._real_length = (cur._value.nullVal || !cur._value.val.bufVal) ? SQL_NULL_DATA : (SQLINTEGER)cur._max_length;
01153 *((guid_t*)cur._bind_buffer) = (!cur._value.nullVal && cur._value.val.bufVal) ? *cur._value.val.guidVal : null_uuid;
01154
01155 }
01156
01157 cur._native_type = (size_t)SQL_GUID;
01158 cur._bind_type = (size_t)SQL_C_GUID;
01159 cur._precision = 36;
01160 cur._scale = 0;
01161 break;
01162 default:
01163 exception::_throw("Unsupported parameter type");
01164 assert(false);
01165 }
01166
01167 RETCODE retCode = ::SQLBindParameter(_hstmt, (SQLUSMALLINT)(index + 1),
01168 (SQLSMALLINT)(is_param_in(cur._in_out) ? (is_param_out(cur._in_out) ? SQL_PARAM_INPUT_OUTPUT : SQL_PARAM_INPUT) : SQL_PARAM_OUTPUT),
01169 (SQLSMALLINT)cur._bind_type, (SQLSMALLINT)cur._native_type,
01170 (SQLUINTEGER)cur._precision, (SQLSMALLINT)cur._scale,
01171 cur._bind_buffer, (SQLINTEGER)cur._max_length,
01172 (SQLLEN*)cur._real_length);
01173
01174 check_retcode(retCode)
01175 }
01176
01177
01178 void
01179 odbc_dbserver::v_bind_one_column(size_t index)
01180 {
01181 binder& cur = _cols[index];
01182 switch (cur._native_type)
01183 {
01184 case SQL_BIT:
01185 cur._bind_type = (size_t)SQL_C_BIT;
01186 cur._max_length = sizeof(bool);
01187
01188 break;
01189 case SQL_TINYINT:
01190 cur._bind_type = (size_t)SQL_C_TINYINT;
01191 cur._max_length = sizeof(ub1_t);
01192
01193 break;
01194 case SQL_SMALLINT:
01195 cur._bind_type = (size_t)SQL_C_SSHORT;
01196 cur._max_length = sizeof(ub2_t);
01197
01198 break;
01199 case SQL_INTEGER:
01200 cur._bind_type = (size_t)SQL_C_LONG;
01201 cur._max_length = sizeof(ub4_t);
01202
01203 break;
01204 case SQL_REAL:
01205 cur._bind_type = (size_t)SQL_C_FLOAT;
01206 cur._max_length = sizeof(float);
01207
01208 break;
01209 case SQL_FLOAT:
01210 case SQL_DOUBLE:
01211 cur._max_length = sizeof(double);
01212 cur._bind_type = (size_t)SQL_C_DOUBLE;
01213
01214 break;
01215 case SQL_BIGINT:
01216 cur._max_length = sizeof(sb8_t);
01217 cur._bind_buffer = check_pointer(_temp_allocator->allocate(cur._max_length));
01218
01219 break;
01220 case SQL_TIMESTAMP:
01221 case SQL_TYPE_TIMESTAMP:
01222 cur._max_length = sizeof(TIMESTAMP_STRUCT);
01223 cur._bind_type = (size_t)SQL_C_TIMESTAMP;
01224
01225 break;
01226 case SQL_TIME:
01227 case SQL_TYPE_TIME:
01228 cur._max_length = sizeof(TIME_STRUCT);
01229 cur._bind_type = (size_t)SQL_C_TIME;
01230
01231 break;
01232 case SQL_DATE:
01233 case SQL_TYPE_DATE:
01234 cur._max_length = sizeof(DATE_STRUCT);
01235 cur._bind_type = (size_t)SQL_C_DATE;
01236
01237 break;
01238 case SQL_CHAR:
01239 case SQL_VARCHAR:
01240 cur._max_length = cur._precision + 1;
01241 cur._bind_type = (size_t)SQL_C_CHAR;
01242
01243 break;
01244 case SQL_LONGVARCHAR:
01245 cur._max_length = 0;
01246 cur._bind_type = (size_t)SQL_C_CHAR;
01247
01248 break;
01249 case SQL_WCHAR:
01250 cur._max_length = 2 * (cur._precision + 1);
01251 cur._bind_type = (size_t)SQL_C_WCHAR;
01252
01253 break;
01254 case SQL_WVARCHAR:
01255 cur._max_length = 2 * (cur._precision + 1);
01256 cur._bind_type = (size_t)SQL_C_WCHAR;
01257
01258 break;
01259 case SQL_WLONGVARCHAR:
01260 cur._max_length = 0;
01261 cur._bind_type = (size_t)SQL_C_WCHAR;
01262
01263 break;
01264 case SQL_DECIMAL:
01265 case SQL_NUMERIC:
01266 cur._max_length = 40;
01267 cur._bind_type = (size_t)SQL_C_CHAR;
01268
01269 break;
01270 case SQL_BINARY:
01271 case SQL_VARBINARY:
01272 cur._max_length = cur._precision;
01273 cur._bind_type = (size_t)SQL_C_BINARY;
01274
01275 break;
01276 case SQL_LONGVARBINARY:
01277 cur._max_length = 0;
01278 cur._bind_type = (size_t)SQL_C_BINARY;
01279
01280 break;
01281 case SQL_GUID:
01282 cur._max_length = sizeof(guid_t);
01283 cur._bind_type = (size_t)SQL_C_GUID;
01284
01285 break;
01286 default:
01287 exception::_throw("Unsupported native sql type");
01288 assert(false);
01289 }
01290
01291 cur._bind_buffer = (cur._max_length ? check_pointer(_temp_allocator->allocate(cur._max_length * _bulk_rows)) : 0);
01292 cur._real_length = (size_t)check_pointer(_temp_allocator->allocate(sizeof(SQLINTEGER) * _bulk_rows));
01293
01294 check_retcode(::SQLBindCol(_hstmt, (SQLUSMALLINT)index + 1, (SQLSMALLINT)cur._bind_type,
01295 _bind_cols ? cur._bind_buffer : 0, cur._max_length, (SQLLEN*)cur._real_length))
01296
01297 }
01298
01299
01300 size_t
01301 odbc_dbserver::v_get_number_columns()
01302 {
01303 size_t count_column = 0;
01304
01305 RETCODE retCode = ::SQLNumResultCols(_hstmt, (SQLSMALLINT*)&count_column);
01306 check_retcode(retCode)
01307 return count_column;
01308 }
01309
01310
01311 void
01312 odbc_dbserver::v_convert_one_value(size_t row, size_t col, terimber_db_value& val)
01313 {
01314 SQLRETURN retCode;
01315 binder& cur = _cols[col];
01316
01317 void* buffer = (cur._bind_buffer ? ((unsigned char*)cur._bind_buffer + row * cur._max_length) : 0);
01318 size_t rlen = *((SQLINTEGER*)cur._real_length + row);
01319
01320
01321 if (!_bind_cols)
01322 {
01323 retCode = ::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, buffer ? buffer : &cur._user_code, cur._max_length, (SQLLEN*)&rlen);
01324 if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO)
01325 check_retcode(retCode)
01326 }
01327
01328 if (rlen == SQL_NULL_DATA)
01329 {
01330 memset(&val, 0, sizeof(terimber_db_value));
01331 val.nullVal = true;
01332 return;
01333 }
01334 else
01335 val.nullVal = false;
01336
01337
01338 switch (cur._native_type)
01339 {
01340 case SQL_BIT:
01341 val.val.boolVal = *(bool*)buffer;
01342 break;
01343 case SQL_TINYINT:
01344 val.val.bVal = *(ub1_t*)buffer;
01345 break;
01346 case SQL_SMALLINT:
01347 val.val.uiVal = *(ub2_t*)buffer;
01348 break;
01349 case SQL_INTEGER:
01350 val.val.ulVal = *(ub4_t*)buffer;
01351 break;
01352 case SQL_REAL:
01353 val.val.fltVal = *(float*)buffer;
01354 break;
01355 case SQL_FLOAT:
01356 case SQL_DOUBLE:
01357 #ifdef OS_64BIT
01358 val.val.dblVal = *(double*)buffer;
01359 #else
01360 val.val.dblVal = (double*)check_pointer(_data_allocator->allocate(cur._max_length));
01361 memcpy((void*)val.val.dblVal, buffer, cur._max_length);
01362 #endif
01363 break;
01364 case SQL_BIGINT:
01365 #ifdef OS_64BIT
01366 val.val.intVal = *(sb8_t*)buffer;
01367 #else
01368 val.val.intVal = (sb8_t*)check_pointer(_data_allocator->allocate(cur._max_length));
01369 memcpy((void*)val.val.intVal, buffer, cur._max_length);
01370 #endif
01371 break;
01372 case SQL_TIMESTAMP:
01373 case SQL_TYPE_TIMESTAMP:
01374 {
01375 TIMESTAMP_STRUCT* ptds = (TIMESTAMP_STRUCT*)buffer;
01376 sb8_t dummy64;
01377 ptds->fraction /= 1000000;
01378 date::convert_to(ptds->year, (ub1_t)ptds->month, (ub1_t)ptds->day, (ub1_t)ptds->hour, (ub1_t)ptds->minute, (ub1_t)ptds->second, (ub2_t)ptds->fraction, dummy64);
01379 #ifdef OS_64BIT
01380 val.val.intVal = dummy64;
01381 #else
01382 sb8_t* dummy = (sb8_t*)check_pointer(_data_allocator->allocate(sizeof(sb8_t)));
01383 *dummy = dummy64;
01384 val.val.intVal = dummy;
01385 #endif
01386 }
01387 break;
01388 case SQL_TIME:
01389 case SQL_TYPE_TIME:
01390 {
01391 TIME_STRUCT* ptds = (TIME_STRUCT*)buffer;
01392 sb8_t dummy64;
01393 date::convert_to(0, 0, 0, (ub1_t)ptds->hour, (ub1_t)ptds->minute, (ub1_t)ptds->second, 0, dummy64);
01394 #ifdef OS_64BIT
01395 val.val.intVal = dummy64;
01396 #else
01397 sb8_t* dummy = (sb8_t*)check_pointer(_data_allocator->allocate(sizeof(sb8_t)));
01398 *dummy = dummy64;
01399 val.val.intVal = dummy;
01400 #endif
01401 }
01402 break;
01403 case SQL_DATE:
01404 case SQL_TYPE_DATE:
01405 {
01406 DATE_STRUCT* ptds = (DATE_STRUCT*)buffer;
01407 sb8_t dummy64;
01408 date::convert_to(ptds->year, (ub1_t)ptds->month, (ub1_t)ptds->day, 0, 0, 0, 0, dummy64);
01409 #ifdef OS_64BIT
01410 val.val.intVal = dummy64;
01411 #else
01412 sb8_t* dummy = (sb8_t*)check_pointer(_data_allocator->allocate(sizeof(sb8_t)));
01413 *dummy = dummy64;
01414 val.val.intVal = dummy;
01415 #endif
01416 }
01417 break;
01418 case SQL_DECIMAL:
01419 case SQL_NUMERIC:
01420 {
01421 const char* buf = (const char*)buffer;
01422 size_t len = (buf) ? strlen(buf) : 0;
01423 numeric num(buf, len, '.', _temp_allocator);
01424 ub1_t* bval = (ub1_t*)check_pointer(_data_allocator->allocate(num.orcl_len()));
01425 if (!num.persist_orcl(bval))
01426 exception::_throw("Out of range");
01427 val.val.bufVal = bval;
01428 }
01429 break;
01430 case SQL_CHAR:
01431 case SQL_VARCHAR:
01432 {
01433 char* sz = (char*)check_pointer(_data_allocator->allocate(rlen + 1));
01434 sz[rlen] = 0;
01435 memcpy(sz, buffer, rlen);
01436 val.val.strVal = sz;
01437 }
01438 break;
01439 case SQL_LONGVARCHAR:
01440 {
01441 if (_bind_cols)
01442 {
01443 retCode = ::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, &cur._user_code, 0, (SQLLEN*)&rlen);
01444 switch (retCode)
01445 {
01446 case SQL_SUCCESS:
01447
01448 if (rlen == SQL_NULL_DATA)
01449 {
01450 memset(&val, 0, sizeof(terimber_db_value));
01451 val.nullVal = true;
01452 return;
01453 }
01454 break;
01455 case SQL_SUCCESS_WITH_INFO:
01456 break;
01457 default:
01458 check_retcode(retCode);
01459 }
01460 }
01461
01462
01463 char* sz = (char*)check_pointer(_data_allocator->allocate(rlen + 1));
01464 sz[rlen] = 0;
01465 size_t done = 0;
01466 size_t shift = 0;
01467 while (done < rlen)
01468 {
01469 SQLLEN available = 0;
01470 check_retcode(::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, sz + shift, rlen + 1 - shift, &available));
01471 shift += available;
01472 done += available;
01473 }
01474
01475 val.val.strVal = sz;
01476 }
01477 break;
01478 case SQL_WCHAR:
01479 case SQL_WVARCHAR:
01480 {
01481 wchar_t* wsz = (wchar_t*)check_pointer(_data_allocator->allocate((rlen + 1) * sizeof(ub2_t)));
01482 wsz[rlen] = 0;
01483 memcpy(wsz, buffer, rlen * sizeof(ub2_t));
01484 val.val.wstrVal = wsz;
01485 }
01486 break;
01487 case SQL_WLONGVARCHAR:
01488 {
01489 if (_bind_cols)
01490 {
01491 retCode = ::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, &cur._user_code, 0, (SQLLEN*)&rlen);
01492 switch (retCode)
01493 {
01494 case SQL_SUCCESS:
01495
01496 if (rlen == SQL_NULL_DATA)
01497 {
01498 memset(&val, 0, sizeof(terimber_db_value));
01499 val.nullVal = true;
01500 return;
01501 }
01502 break;
01503 case SQL_SUCCESS_WITH_INFO:
01504 break;
01505 default:
01506 check_retcode(retCode);
01507 }
01508 }
01509
01510
01511 wchar_t* wsz = (wchar_t*)check_pointer(_data_allocator->allocate(rlen + 2));
01512 wsz[rlen / 2] = 0;
01513
01514 size_t done = 0;
01515 size_t shift = 0;
01516 while (done < rlen)
01517 {
01518 SQLLEN available = 0;
01519 check_retcode(::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, wsz + shift, rlen + 2 - shift, &available));
01520 shift += available;
01521 done += available;
01522 }
01523
01524 val.val.wstrVal = wsz;
01525 }
01526 break;
01527 case SQL_BINARY:
01528 case SQL_VARBINARY:
01529 {
01530 ub1_t* bval = (ub1_t*)check_pointer(_data_allocator->allocate(rlen + sizeof(size_t)));
01531 *(ub4_t*)bval = (ub4_t)rlen;
01532 memcpy((ub1_t*)bval + sizeof(size_t), buffer, rlen);
01533 val.val.bufVal = bval;
01534 }
01535 break;
01536 case SQL_LONGVARBINARY:
01537 {
01538 if (_bind_cols)
01539 {
01540 retCode = ::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, &cur._user_code, 0, (SQLLEN*)&rlen);
01541 switch (retCode)
01542 {
01543 case SQL_SUCCESS:
01544
01545 if (rlen == SQL_NULL_DATA)
01546 {
01547 memset(&val, 0, sizeof(terimber_db_value));
01548 val.nullVal = true;
01549 return;
01550 }
01551 break;
01552 case SQL_SUCCESS_WITH_INFO:
01553 break;
01554 default:
01555 check_retcode(retCode);
01556 }
01557 }
01558
01559
01560 ub1_t* buf = (ub1_t*)check_pointer(_data_allocator->allocate(rlen + sizeof(size_t)));
01561 *(size_t*)buf = rlen;
01562
01563 size_t done = 0;
01564 size_t shift = 0;
01565 while (done < rlen)
01566 {
01567 SQLLEN available = 0;
01568 check_retcode(::SQLGetData(_hstmt, (SQLUSMALLINT)col + 1, (SQLUSMALLINT)cur._bind_type, buf + sizeof(size_t) + shift, rlen - shift, &available));
01569 shift += available;
01570 done += available;
01571 }
01572
01573 val.val.bufVal = buf;
01574 }
01575 break;
01576 case SQL_GUID:
01577 val.val.guidVal = (guid_t*)check_pointer(_data_allocator->allocate(cur._max_length));
01578 memcpy((void*)val.val.guidVal, buffer, cur._max_length);
01579 break;
01580 default:
01581 exception::_throw("Unsupported native sql type");
01582 assert(false);
01583 }
01584 }
01585
01586
01587 void
01588 odbc_dbserver::v_get_one_column_info(size_t index)
01589 {
01590 binder& cur = _cols[index];
01591 SQLSMALLINT native_type = 0, scale = 0, nullable = 0, nActualLen = 0;
01592 SQLULEN precision = 0;
01593
01594 #if OS_TYPE == OS_WIN32
01595 SQLWCHAR* szColumnName = (SQLWCHAR*)check_pointer(_temp_allocator->allocate((MAX_FNAME_LEN + 1)*sizeof(USHORT)));
01596 memset(szColumnName, 0, (MAX_FNAME_LEN + 1) * sizeof(USHORT));
01597
01598 RETCODE retCode = ::SQLDescribeColW(_hstmt, (SQLUSMALLINT)index + 1,
01599 szColumnName, MAX_FNAME_LEN, &nActualLen,
01600 &native_type,
01601 &precision,
01602 &scale,
01603 &nullable);
01604 check_retcode(retCode)
01605
01606 cur.set_name(_columns_allocator, str_template::unicode_to_multibyte( *_temp_allocator, (wchar_t*)szColumnName));
01607 #else
01608 SQLCHAR* szColumnName = (SQLCHAR*)check_pointer(_temp_allocator->allocate((MAX_FNAME_LEN + 1)));
01609 memset(szColumnName, 0, (MAX_FNAME_LEN + 1));
01610
01611 RETCODE retCode = ::SQLDescribeCol(_hstmt, index + 1,
01612 szColumnName, MAX_FNAME_LEN, &nActualLen,
01613 &native_type,
01614 &precision,
01615 &scale,
01616 &nullable);
01617 check_retcode(retCode)
01618
01619 cur.set_name(_columns_allocator, (const char*)szColumnName);
01620 #endif
01621
01622 cur._responsible = true;
01623 cur._native_type = native_type;
01624 cur._precision = precision;
01625 cur._scale = scale;
01626 cur._value.nullVal = nullable != 0;
01627 cur._max_length = cur._precision;
01628 }
01629
01630
01631 void
01632 odbc_dbserver::v_rebind_one_param(size_t index)
01633 {
01634 binder& cur = _params[index];
01635 if (!is_param_out(cur._in_out))
01636 return;
01637
01638 cur._value.nullVal = false;
01639
01640 size_t rlen = *(SQLINTEGER*)cur._real_length;
01641 if (rlen == SQL_NULL_DATA)
01642 {
01643 cur._value.nullVal = true;
01644 return;
01645 }
01646
01647 switch (cur._native_type)
01648 {
01649 case SQL_BIT:
01650 cur._value.val.boolVal = *(bool*)cur._bind_buffer;
01651 break;
01652 case SQL_TINYINT:
01653 cur._value.val.cVal = *(char*)cur._bind_buffer;
01654 break;
01655 case SQL_SMALLINT:
01656 cur._value.val.iVal = *(sb2_t*)cur._bind_buffer;
01657 break;
01658 case SQL_INTEGER:
01659 cur._value.val.lVal= *(sb4_t*)cur._bind_buffer;
01660 break;
01661 case SQL_REAL:
01662 cur._value.val.fltVal = *(float*)cur._bind_buffer;
01663 break;
01664 case SQL_FLOAT:
01665 case SQL_DOUBLE:
01666 #ifdef OS_64BIT
01667 cur._value.val.dblVal = *(double*)cur._bind_buffer;
01668 #else
01669 memcpy(check_pointer(cur.allocate_value(0)), cur._bind_buffer, cur._max_length);
01670 #endif
01671 break;
01672 case SQL_BIGINT:
01673 #ifdef OS_64BIT
01674 cur._value.val.intVal = *(sb8_t*)cur._bind_buffer;
01675 #else
01676 memcpy(check_pointer(cur.allocate_value(0)), cur._bind_buffer, cur._max_length);
01677 #endif
01678 break;
01679 case SQL_TIMESTAMP:
01680 case SQL_TYPE_TIMESTAMP:
01681 {
01682 TIMESTAMP_STRUCT* ptds = (TIMESTAMP_STRUCT*)cur._bind_buffer;
01683 sb8_t dummy64;
01684 ptds->fraction /= 1000000;
01685 date::convert_to(ptds->year, (ub1_t)ptds->month, (ub1_t)ptds->day, (ub1_t)ptds->hour, (ub1_t)ptds->minute, (ub1_t)ptds->second, (ub2_t)ptds->fraction, dummy64);
01686
01687 #ifdef OS_64BIT
01688 cur._value.val.intVal = dummy64;
01689 #else
01690 memcpy(check_pointer(cur.allocate_value(0)), &dummy64, sizeof(sb8_t));
01691 #endif
01692
01693 }
01694 break;
01695 case SQL_TIME:
01696 case SQL_TYPE_TIME:
01697 {
01698 TIME_STRUCT* ptds = (TIME_STRUCT*)cur._bind_buffer;
01699 sb8_t dummy64;
01700 date::convert_to(0, 0, 0, (ub1_t)ptds->hour, (ub1_t)ptds->minute, (ub1_t)ptds->second, 0, dummy64);
01701
01702 #ifdef OS_64BIT
01703 cur._value.val.intVal = dummy64;
01704 #else
01705 memcpy(check_pointer(cur.allocate_value(0)), &dummy64, sizeof(sb8_t));
01706 #endif
01707 }
01708 break;
01709 case SQL_DATE:
01710 case SQL_TYPE_DATE:
01711 {
01712 DATE_STRUCT* ptds = (DATE_STRUCT*)cur._bind_buffer;
01713 sb8_t dummy64;
01714 date::convert_to(ptds->year, (ub1_t)ptds->month, (ub1_t)ptds->day, 0, 0, 0, 0, dummy64);
01715 #ifdef OS_64BIT
01716 cur._value.val.intVal = dummy64;
01717 #else
01718 memcpy(check_pointer(cur.allocate_value(0)), &dummy64, sizeof(sb8_t));
01719 #endif
01720 }
01721 break;
01722 case SQL_DECIMAL:
01723 case SQL_NUMERIC:
01724 {
01725 const char* buf = (const char*)cur._bind_buffer;
01726 size_t len = (buf) ? strlen(buf) : 0;
01727 numeric num(buf, len, '.', _temp_allocator);
01728 ub1_t* bval = (ub1_t*)check_pointer(cur.allocate_value(num.orcl_len()));
01729 if (!num.persist_orcl(bval))
01730 exception::_throw("Out of range");
01731 }
01732 break;
01733 case SQL_CHAR:
01734 case SQL_VARCHAR:
01735 case SQL_LONGVARCHAR:
01736 {
01737 char* sz = (char*)check_pointer(cur.allocate_value(rlen));
01738 sz[rlen] = 0;
01739 memcpy(sz, cur._bind_buffer, rlen);
01740 }
01741 break;
01742 case SQL_WCHAR:
01743 case SQL_WVARCHAR:
01744 case SQL_WLONGVARCHAR:
01745 {
01746 wchar_t* wsz = (wchar_t*)check_pointer(cur.allocate_value(rlen));
01747 wsz[rlen] = 0;
01748 memcpy(wsz, cur._bind_buffer, rlen * sizeof(ub2_t));
01749 }
01750 break;
01751 case SQL_BINARY:
01752 case SQL_VARBINARY:
01753 case SQL_LONGVARBINARY:
01754 {
01755 ub1_t* bval = (ub1_t*)check_pointer(cur.allocate_value(rlen));
01756 memcpy(bval, cur._bind_buffer, rlen);
01757 }
01758 break;
01759 case SQL_GUID:
01760 {
01761 guid_t* gval = (guid_t*)check_pointer(cur.allocate_value(0));
01762 memcpy(gval, cur._bind_buffer, cur._max_length);
01763 }
01764 break;
01765 default:
01766 exception::_throw("Unsupported native sql type");
01767 assert(false);
01768 }
01769 }
01770
01771
01772 void
01773 odbc_dbserver::v_interrupt_async()
01774 {
01775 ::SQLCancel(_hstmt);
01776 }
01777
01778
01779 dbtypes
01780 odbc_dbserver::v_native_type_to_client_type(size_t native_type)
01781 {
01782 switch (native_type)
01783 {
01784 case SQL_BIT:
01785 return db_bool;
01786 case SQL_TINYINT:
01787 return db_ub1;
01788 case SQL_SMALLINT:
01789 return db_sb2;
01790 case SQL_INTEGER:
01791 return db_sb4;
01792 case SQL_REAL:
01793 return db_float;
01794 case SQL_FLOAT:
01795 case SQL_DOUBLE:
01796 return db_double;
01797 case SQL_BIGINT:
01798 return db_sb8;
01799 case SQL_TIMESTAMP:
01800 case SQL_TYPE_TIMESTAMP:
01801 case SQL_TIME:
01802 case SQL_TYPE_TIME:
01803 case SQL_DATE:
01804 case SQL_TYPE_DATE:
01805 return db_date;
01806 case SQL_DECIMAL:
01807 return db_decimal;
01808 case SQL_NUMERIC:
01809 return db_numeric;
01810 case SQL_CHAR:
01811 case SQL_VARCHAR:
01812 case SQL_LONGVARCHAR:
01813 return db_string;
01814 case SQL_WCHAR:
01815 case SQL_WVARCHAR:
01816 case SQL_WLONGVARCHAR:
01817 return db_wstring;
01818 case SQL_BINARY:
01819 case SQL_VARBINARY:
01820 case SQL_LONGVARBINARY:
01821 return db_binary;
01822 case SQL_GUID:
01823 return db_guid;
01824 default:
01825 assert(false);
01826 return db_unknown;
01827 }
01828 }
01829
01831
01833
01834 db_entry*
01835 odbc_db_creator::create( const db_arg& arg
01836 )
01837 {
01838 db_entry* obj = 0;
01839 if (0 != (obj = new db_entry(arg._ident, arg._trusted, arg._login_string)))
01840 {
01841 if (!(obj->_obj = new odbc_dbserver(arg._ident)))
01842 delete obj, obj = 0;
01843 }
01844
01845 return obj;
01846 }
01847 #pragma pack()
01848 END_TERIMBER_NAMESPACE