1 /************************************************************************ 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 #include "odbc/OTools.hxx" 31 #include "odbc/OFunctions.hxx" 32 #include <com/sun/star/sdbc/DataType.hpp> 33 #include <osl/diagnose.h> 34 #include "odbc/OConnection.hxx" 35 #include "diagnose_ex.h" 36 #include <rtl/logfile.hxx> 37 #include <rtl/ustrbuf.hxx> 38 39 40 #include <string.h> 41 #include <string> 42 #include <algorithm> 43 44 using namespace connectivity::odbc; 45 using namespace com::sun::star::uno; 46 using namespace com::sun::star::sdbc; 47 using namespace com::sun::star::util; 48 49 void OTools::getValue( OConnection* _pConnection, 50 SQLHANDLE _aStatementHandle, 51 sal_Int32 columnIndex, 52 SQLSMALLINT _nType, 53 sal_Bool &_bWasNull, 54 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, 55 void* _pValue, 56 SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) 57 { 58 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getValue" ); 59 SQLLEN pcbValue = SQL_NULL_DATA; 60 OTools::ThrowException(_pConnection, 61 (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 62 (SQLUSMALLINT)columnIndex, 63 _nType, 64 _pValue, 65 _nSize, 66 &pcbValue), 67 _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False); 68 _bWasNull = pcbValue == SQL_NULL_DATA; 69 } 70 // ----------------------------------------------------------------------------- 71 void OTools::bindParameter( OConnection* _pConnection, 72 SQLHANDLE _hStmt, 73 sal_Int32 nPos, 74 sal_Int8*& pDataBuffer, 75 sal_Int8* pLenBuffer, 76 SQLSMALLINT _nODBCtype, 77 sal_Bool _bUseWChar, 78 sal_Bool _bUseOldTimeDate, 79 const void* _pValue, 80 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, 81 rtl_TextEncoding _nTextEncoding) 82 throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) 83 { 84 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindParameter" ); 85 SQLRETURN nRetcode; 86 SQLSMALLINT fSqlType; 87 SQLSMALLINT fCType; 88 SQLLEN nMaxLen = 0; 89 // void*& pData = pDataBuffer; 90 SQLLEN* pLen = (SQLLEN*)pLenBuffer; 91 SQLULEN nColumnSize=0; 92 SQLSMALLINT nDecimalDigits=0; 93 94 OTools::getBindTypes(_bUseWChar,_bUseOldTimeDate,_nODBCtype,fCType,fSqlType); 95 96 OTools::bindData(_nODBCtype,_bUseWChar,pDataBuffer,pLen,_pValue,_nTextEncoding,nColumnSize); 97 if ((nColumnSize == 0) && (fSqlType == SQL_CHAR || fSqlType == SQL_VARCHAR || fSqlType == SQL_LONGVARCHAR)) 98 nColumnSize = 1; 99 100 if(fSqlType == SQL_LONGVARCHAR || fSqlType == SQL_LONGVARBINARY) 101 memcpy(pDataBuffer,&nPos,sizeof(nPos)); 102 103 // 20.09.2001 OJ: Problems with mysql. mysql returns only CHAR as parameter type 104 // nRetcode = (*(T3SQLDescribeParam)_pConnection->getOdbcFunction(ODBC3SQLDescribeParam))(_hStmt,(SQLUSMALLINT)nPos,&fSqlType,&nColumnSize,&nDecimalDigits,&nNullable); 105 106 nRetcode = (*(T3SQLBindParameter)_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(_hStmt, 107 (SQLUSMALLINT)nPos, 108 SQL_PARAM_INPUT, 109 fCType, 110 fSqlType, 111 nColumnSize, 112 nDecimalDigits, 113 pDataBuffer, 114 nMaxLen, 115 pLen); 116 117 OTools::ThrowException(_pConnection,nRetcode,_hStmt,SQL_HANDLE_STMT,_xInterface); 118 } 119 // ----------------------------------------------------------------------------- 120 void OTools::bindData( SQLSMALLINT _nOdbcType, 121 sal_Bool _bUseWChar, 122 sal_Int8 *&_pData, 123 SQLLEN*& pLen, 124 const void* _pValue, 125 rtl_TextEncoding _nTextEncoding, 126 SQLULEN& _nColumnSize) 127 { 128 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindData" ); 129 _nColumnSize = 0; 130 131 switch (_nOdbcType) 132 { 133 case SQL_CHAR: 134 case SQL_VARCHAR: 135 case SQL_DECIMAL: 136 if(_bUseWChar) 137 { 138 *pLen = SQL_NTS; 139 ::rtl::OUString sStr(*(::rtl::OUString*)_pValue); 140 _nColumnSize = sStr.getLength(); 141 *((rtl::OUString*)_pData) = sStr; 142 143 // Zeiger auf Char* 144 _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); 145 } 146 else 147 { 148 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); 149 *pLen = SQL_NTS; 150 _nColumnSize = aString.getLength(); 151 memcpy(_pData,aString.getStr(),aString.getLength()); 152 ((sal_Int8*)_pData)[aString.getLength()] = '\0'; 153 } 154 break; 155 156 case SQL_BIGINT: 157 *((sal_Int64*)_pData) = *(sal_Int64*)_pValue; 158 *pLen = sizeof(sal_Int64); 159 _nColumnSize = *pLen; 160 break; 161 162 case SQL_NUMERIC: 163 if(_bUseWChar) 164 { 165 ::rtl::OUString aString = rtl::OUString::valueOf(*(double*)_pValue); 166 _nColumnSize = aString.getLength(); 167 *pLen = _nColumnSize; 168 *((rtl::OUString*)_pData) = aString; 169 // Zeiger auf Char* 170 _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); 171 } 172 else 173 { 174 ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue); 175 _nColumnSize = aString.getLength(); 176 *pLen = _nColumnSize; 177 memcpy(_pData,aString.getStr(),aString.getLength()); 178 ((sal_Int8*)_pData)[_nColumnSize] = '\0'; 179 } break; 180 case SQL_BIT: 181 case SQL_TINYINT: 182 *((sal_Int8*)_pData) = *(sal_Int8*)_pValue; 183 *pLen = sizeof(sal_Int8); 184 break; 185 186 case SQL_SMALLINT: 187 *((sal_Int16*)_pData) = *(sal_Int16*)_pValue; 188 *pLen = sizeof(sal_Int16); 189 break; 190 case SQL_INTEGER: 191 *((sal_Int32*)_pData) = *(sal_Int32*)_pValue; 192 *pLen = sizeof(sal_Int32); 193 break; 194 case SQL_FLOAT: 195 *((float*)_pData) = *(float*)_pValue; 196 *pLen = sizeof(float); 197 break; 198 case SQL_REAL: 199 case SQL_DOUBLE: 200 *((double*)_pData) = *(double*)_pValue; 201 *pLen = sizeof(double); 202 break; 203 case SQL_BINARY: 204 case SQL_VARBINARY: 205 { 206 const ::com::sun::star::uno::Sequence< sal_Int8 >* pSeq = static_cast< const ::com::sun::star::uno::Sequence< sal_Int8 >* >(_pValue); 207 OSL_ENSURE(pSeq,"OTools::bindData: Sequence is null!"); 208 209 if(pSeq) 210 { 211 _pData = (sal_Int8*)pSeq->getConstArray(); 212 *pLen = pSeq->getLength(); 213 } 214 } 215 break; 216 case SQL_LONGVARBINARY: 217 { 218 sal_Int32 nLen = 0; 219 nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); 220 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); 221 } 222 break; 223 case SQL_LONGVARCHAR: 224 { 225 sal_Int32 nLen = 0; 226 if(_bUseWChar) 227 nLen = sizeof(sal_Unicode) * ((::rtl::OUString*)_pValue)->getLength(); 228 else 229 { 230 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); 231 nLen = aString.getLength(); 232 } 233 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); 234 } break; 235 case SQL_DATE: 236 *(DATE_STRUCT*)_pData = *(DATE_STRUCT*)_pValue; 237 *pLen = (SQLLEN)sizeof(DATE_STRUCT); 238 _nColumnSize = 10; 239 break; 240 case SQL_TIME: 241 *(TIME_STRUCT*)_pData = *(TIME_STRUCT*)_pValue; 242 *pLen = (SQLLEN)sizeof(TIME_STRUCT); 243 _nColumnSize = 8; 244 break; 245 case SQL_TIMESTAMP: 246 *(TIMESTAMP_STRUCT*)_pData = *(TIMESTAMP_STRUCT*)_pValue; 247 *pLen = (SQLLEN)sizeof(TIMESTAMP_STRUCT); 248 _nColumnSize = 19; 249 break; 250 } 251 } 252 // ------------------------------------------------------------------------- 253 void OTools::bindValue( OConnection* _pConnection, 254 SQLHANDLE _aStatementHandle, 255 sal_Int32 columnIndex, 256 SQLSMALLINT _nType, 257 SQLSMALLINT _nMaxLen, 258 const void* _pValue, 259 void* _pData, 260 SQLLEN *pLen, 261 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, 262 rtl_TextEncoding _nTextEncoding, 263 sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) 264 { 265 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindValue" ); 266 SQLRETURN nRetcode; 267 SQLSMALLINT fSqlType; 268 SQLSMALLINT fCType; 269 SQLLEN nMaxLen = _nMaxLen; 270 271 OTools::getBindTypes( sal_False, 272 _bUseOldTimeDate, 273 _nType, 274 fCType, 275 fSqlType); 276 277 if (columnIndex != 0 && !_pValue) 278 { 279 *pLen = SQL_NULL_DATA; 280 nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle, 281 (SQLUSMALLINT)columnIndex, 282 fCType, 283 _pData, 284 nMaxLen, 285 pLen 286 ); 287 } 288 else 289 { 290 try 291 { 292 switch (_nType) 293 { 294 case SQL_CHAR: 295 case SQL_VARCHAR: 296 //if(GetODBCConnection()->m_bUserWChar) 297 // { 298 // _nMaxLen = rCol.GetPrecision(); 299 // *pLen = SQL_NTS; 300 // *((rtl::OUString*)pData) = (rtl::OUString)_aValue; 301 // 302 // // Zeiger auf Char* 303 // pData = (void*)((rtl::OUString*)pData)->getStr(); 304 // } 305 // else 306 { 307 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); 308 *pLen = SQL_NTS; 309 *((::rtl::OString*)_pData) = aString; 310 _nMaxLen = (SQLSMALLINT)aString.getLength(); 311 312 // Zeiger auf Char* 313 _pData = (void*)aString.getStr(); 314 } break; 315 case SQL_BIGINT: 316 *((sal_Int64*)_pData) = *(sal_Int64*)_pValue; 317 *pLen = sizeof(sal_Int64); 318 break; 319 case SQL_DECIMAL: 320 case SQL_NUMERIC: 321 //if(GetODBCConnection()->m_bUserWChar) 322 // { 323 // rtl::OUString aString(rtl::OUString(SdbTools::ToString(ODbTypeConversion::toDouble(*pVariable),rCol.GetScale()))); 324 // *pLen = _nMaxLen; 325 // *((rtl::OUString*)_pData) = aString; 326 // // Zeiger auf Char* 327 // _pData = (void*)((rtl::OUString*)_pData)->getStr(); 328 // } 329 // else 330 { 331 ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue); 332 _nMaxLen = (SQLSMALLINT)aString.getLength(); 333 *pLen = _nMaxLen; 334 *((::rtl::OString*)_pData) = aString; 335 // Zeiger auf Char* 336 _pData = (void*)((::rtl::OString*)_pData)->getStr(); 337 } break; 338 case SQL_BIT: 339 case SQL_TINYINT: 340 *((sal_Int8*)_pData) = *(sal_Int8*)_pValue; 341 *pLen = sizeof(sal_Int8); 342 break; 343 344 case SQL_SMALLINT: 345 *((sal_Int16*)_pData) = *(sal_Int16*)_pValue; 346 *pLen = sizeof(sal_Int16); 347 break; 348 case SQL_INTEGER: 349 *((sal_Int32*)_pData) = *(sal_Int32*)_pValue; 350 *pLen = sizeof(sal_Int32); 351 break; 352 case SQL_FLOAT: 353 *((float*)_pData) = *(float*)_pValue; 354 *pLen = sizeof(float); 355 break; 356 case SQL_REAL: 357 case SQL_DOUBLE: 358 *((double*)_pData) = *(double*)_pValue; 359 *pLen = sizeof(double); 360 break; 361 case SQL_BINARY: 362 case SQL_VARBINARY: 363 // if (_pValue == ::getCppuType((const ::com::sun::star::uno::Sequence< sal_Int8 > *)0)) 364 { 365 _pData = (void*)((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getConstArray(); 366 *pLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); 367 } break; 368 case SQL_LONGVARBINARY: 369 { 370 _pData = (void*)(columnIndex); 371 sal_Int32 nLen = 0; 372 nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); 373 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); 374 } 375 break; 376 case SQL_LONGVARCHAR: 377 { 378 _pData = (void*)(columnIndex); 379 sal_Int32 nLen = 0; 380 nLen = ((::rtl::OUString*)_pValue)->getLength(); 381 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); 382 } break; 383 case SQL_DATE: 384 *pLen = sizeof(DATE_STRUCT); 385 *((DATE_STRUCT*)_pData) = *(DATE_STRUCT*)_pValue; 386 break; 387 case SQL_TIME: 388 *pLen = sizeof(TIME_STRUCT); 389 *((TIME_STRUCT*)_pData) = *(TIME_STRUCT*)_pValue; 390 break; 391 case SQL_TIMESTAMP: 392 *pLen = sizeof(TIMESTAMP_STRUCT); 393 *((TIMESTAMP_STRUCT*)_pData) = *(TIMESTAMP_STRUCT*)_pValue; 394 break; 395 } 396 } 397 catch ( ... ) 398 { 399 } 400 401 nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle, 402 (SQLUSMALLINT)columnIndex, 403 fCType, 404 _pData, 405 nMaxLen, 406 pLen 407 ); 408 } 409 410 OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface); 411 } 412 // ----------------------------------------------------------------------------- 413 void OTools::ThrowException(OConnection* _pConnection, 414 SQLRETURN _rRetCode, 415 SQLHANDLE _pContext, 416 SQLSMALLINT _nHandleType, 417 const Reference< XInterface >& _xInterface, 418 sal_Bool _bNoFound, 419 rtl_TextEncoding _nTextEncoding) throw(SQLException) 420 { 421 switch(_rRetCode) 422 { 423 case SQL_NEED_DATA: 424 case SQL_STILL_EXECUTING: 425 case SQL_SUCCESS: 426 427 case SQL_SUCCESS_WITH_INFO: 428 return; 429 case SQL_NO_DATA_FOUND: 430 if(_bNoFound) 431 return; // no need to throw a exception 432 case SQL_ERROR: break; 433 434 435 case SQL_INVALID_HANDLE: OSL_ENSURE(0,"SdbODBC3_SetStatus: SQL_INVALID_HANDLE"); 436 throw SQLException(); 437 } 438 439 440 // Zusaetliche Informationen zum letzten ODBC-Funktionsaufruf vorhanden. 441 // SQLError liefert diese Informationen. 442 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::ThrowException" ); 443 444 SDB_ODBC_CHAR szSqlState[5]; 445 SQLINTEGER pfNativeError; 446 SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH]; 447 szErrorMessage[0] = '\0'; 448 SQLSMALLINT pcbErrorMsg = 0; 449 450 // Informationen zur letzten Operation: 451 // wenn hstmt != SQL_NULL_HSTMT ist (Benutzung von SetStatus in SdbCursor, SdbTable, ...), 452 // dann wird der Status des letzten Statements erfragt, sonst der Status des letzten 453 // Statements zu dieser Verbindung [was in unserem Fall wahrscheinlich gleichbedeutend ist, 454 // aber das Reference Manual drueckt sich da nicht so klar aus ...]. 455 // Entsprechend bei hdbc. 456 SQLRETURN n = (*(T3SQLGetDiagRec)_pConnection->getOdbcFunction(ODBC3SQLGetDiagRec))(_nHandleType,_pContext,1, 457 szSqlState, 458 &pfNativeError, 459 szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg); 460 OSL_UNUSED( n ); 461 OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE"); 462 OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed"); 463 464 // Zum Return Code von SQLError siehe ODBC 2.0 Programmer's Reference Seite 287ff 465 throw SQLException( ::rtl::OUString((char *)szErrorMessage,pcbErrorMsg,_nTextEncoding), 466 _xInterface, 467 ::rtl::OUString((char *)szSqlState,5,_nTextEncoding), 468 pfNativeError, 469 Any() 470 ); 471 472 } 473 // ------------------------------------------------------------------------- 474 Sequence<sal_Int8> OTools::getBytesValue(OConnection* _pConnection, 475 SQLHANDLE _aStatementHandle, 476 sal_Int32 columnIndex, 477 SQLSMALLINT _fSqlType, 478 sal_Bool &_bWasNull, 479 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) 480 { 481 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBytesValue" ); 482 char aCharArray[2048]; 483 // Erstmal versuchen, die Daten mit dem kleinen Puffer 484 // abzuholen: 485 SQLLEN nMaxLen = sizeof aCharArray - 1; 486 // GETDATA(SQL_C_CHAR,aCharArray,nMaxLen); 487 SQLLEN pcbValue = 0; 488 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 489 (SQLUSMALLINT)columnIndex, 490 _fSqlType, 491 (SQLPOINTER)aCharArray, 492 nMaxLen, 493 &pcbValue), 494 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 495 496 _bWasNull = pcbValue == SQL_NULL_DATA; 497 if(_bWasNull) 498 return Sequence<sal_Int8>(); 499 500 SQLINTEGER nBytes = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : nMaxLen; 501 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nBytes-1] == 0 && nBytes > 0 ) 502 --nBytes; 503 Sequence<sal_Int8> aData((sal_Int8*)aCharArray, nBytes); 504 505 506 // Es handelt sich um Binaerdaten, um einen String, der fuer 507 // StarView zu lang ist oder der Treiber kann die Laenge der 508 // Daten nicht im voraus bestimmen - also als MemoryStream 509 // speichern. 510 while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) 511 { 512 // Bei Strings wird der Puffer nie ganz ausgenutzt 513 // (das letzte Byte ist immer ein NULL-Byte, das 514 // aber bei pcbValue nicht mitgezaehlt wird) 515 if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen) 516 nBytes = pcbValue - nMaxLen; 517 else 518 nBytes = nMaxLen; 519 520 // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen 521 // GETDATA(SQL_C_CHAR,aCharArray, nLen + 1); 522 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 523 (SQLUSMALLINT)columnIndex, 524 SQL_C_BINARY, 525 &aCharArray, 526 (SQLINTEGER)nBytes, 527 &pcbValue), 528 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 529 sal_Int32 nLen = aData.getLength(); 530 aData.realloc(nLen + nBytes); 531 memcpy(aData.getArray() + nLen, aCharArray, nBytes); 532 } 533 return aData; 534 } 535 // ------------------------------------------------------------------------- 536 ::rtl::OUString OTools::getStringValue(OConnection* _pConnection, 537 SQLHANDLE _aStatementHandle, 538 sal_Int32 columnIndex, 539 SQLSMALLINT _fSqlType, 540 sal_Bool &_bWasNull, 541 const Reference< XInterface >& _xInterface, 542 rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException) 543 { 544 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getStringValue" ); 545 ::rtl::OUStringBuffer aData; 546 switch(_fSqlType) 547 { 548 case SQL_WVARCHAR: 549 case SQL_WCHAR: 550 case SQL_WLONGVARCHAR: 551 { 552 sal_Unicode waCharArray[2048]; 553 // read the unicode data 554 SQLLEN nMaxLen = (sizeof(waCharArray) / sizeof(sal_Unicode)) - 1; 555 // GETDATA(SQL_C_WCHAR, waCharArray, nMaxLen + sizeof(sal_Unicode)); 556 557 SQLLEN pcbValue=0; 558 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 559 (SQLUSMALLINT)columnIndex, 560 SQL_C_WCHAR, 561 &waCharArray, 562 (SQLLEN)nMaxLen*sizeof(sal_Unicode), 563 &pcbValue), 564 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 565 _bWasNull = pcbValue == SQL_NULL_DATA; 566 if(_bWasNull) 567 return ::rtl::OUString(); 568 // Bei Fehler bricht der GETDATA-Makro mit return ab, 569 // bei NULL mit break! 570 SQLLEN nRealSize = 0; 571 if ( pcbValue > -1 ) 572 nRealSize = pcbValue / sizeof(sal_Unicode); 573 SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1); 574 waCharArray[nLen] = 0; 575 aData.append(waCharArray,nLen); 576 577 // Es handelt sich um Binaerdaten, um einen String, der fuer 578 // StarView zu lang ist oder der Treiber kann die Laenge der 579 // Daten nicht im voraus bestimmen - also als MemoryStream 580 // speichern. 581 while ((pcbValue == SQL_NO_TOTAL ) || nLen > nMaxLen) 582 { 583 // Bei Strings wird der Puffer nie ganz ausgenutzt 584 // (das letzte Byte ist immer ein NULL-Byte, das 585 // aber bei pcbValue nicht mitgezaehlt wird) 586 if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen) 587 nLen = pcbValue - nMaxLen; 588 else 589 nLen = nMaxLen; 590 591 // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen 592 // GETDATA(SQL_C_CHAR,waCharArray, nLen + 1); 593 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 594 (SQLUSMALLINT)columnIndex, 595 SQL_C_WCHAR, 596 &waCharArray, 597 (SQLLEN)nLen+1, 598 &pcbValue), 599 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 600 nRealSize = 0; 601 if ( pcbValue > -1 ) 602 nRealSize = pcbValue / sizeof(sal_Unicode); 603 nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1); 604 waCharArray[nLen] = 0; 605 606 aData.append(::rtl::OUString(waCharArray)); 607 } 608 } 609 break; 610 default: 611 { 612 char aCharArray[2048]; 613 // Erstmal versuchen, die Daten mit dem kleinen Puffer 614 // abzuholen: 615 SQLLEN nMaxLen = sizeof aCharArray - 1; 616 // GETDATA(SQL_C_CHAR,aCharArray,nMaxLen); 617 SQLLEN pcbValue = 0; 618 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 619 (SQLUSMALLINT)columnIndex, 620 SQL_C_CHAR, 621 &aCharArray, 622 nMaxLen, 623 &pcbValue), 624 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 625 _bWasNull = pcbValue == SQL_NULL_DATA; 626 if(_bWasNull) 627 return ::rtl::OUString(); 628 629 SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1); 630 aCharArray[nLen] = 0; 631 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 ) 632 --nLen; 633 aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen, _nTextEncoding)); 634 635 // Es handelt sich um Binaerdaten, um einen String, der fuer 636 // StarView zu lang ist oder der Treiber kann die Laenge der 637 // Daten nicht im voraus bestimmen - also als MemoryStream 638 // speichern. 639 while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) 640 { 641 // Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen 642 // GETDATA(SQL_C_CHAR,aCharArray, nLen + 1); 643 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle, 644 (SQLUSMALLINT)columnIndex, 645 SQL_C_CHAR, 646 &aCharArray, 647 (SQLINTEGER)nMaxLen, 648 &pcbValue), 649 _aStatementHandle,SQL_HANDLE_STMT,_xInterface); 650 nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1); 651 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 ) 652 --nLen; 653 aCharArray[nLen] = 0; 654 655 aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen,_nTextEncoding)); 656 } 657 658 // delete all blanks 659 // aData.EraseTrailingChars(); 660 } 661 } 662 663 return aData.makeStringAndClear(); 664 } 665 // ------------------------------------------------------------------------- 666 void OTools::GetInfo(OConnection* _pConnection, 667 SQLHANDLE _aConnectionHandle, 668 SQLUSMALLINT _nInfo, 669 ::rtl::OUString &_rValue, 670 const Reference< XInterface >& _xInterface, 671 rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException) 672 { 673 char aValue[512]; 674 SQLSMALLINT nValueLen=0; 675 OTools::ThrowException(_pConnection, 676 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen), 677 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); 678 679 _rValue = ::rtl::OUString(aValue,nValueLen,_nTextEncoding); 680 } 681 // ------------------------------------------------------------------------- 682 void OTools::GetInfo(OConnection* _pConnection, 683 SQLHANDLE _aConnectionHandle, 684 SQLUSMALLINT _nInfo, 685 sal_Int32 &_rValue, 686 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) 687 { 688 SQLSMALLINT nValueLen; 689 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) 690 OTools::ThrowException(_pConnection, 691 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), 692 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); 693 } 694 // ------------------------------------------------------------------------- 695 void OTools::GetInfo(OConnection* _pConnection, 696 SQLHANDLE _aConnectionHandle, 697 SQLUSMALLINT _nInfo, 698 SQLUINTEGER &_rValue, 699 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) 700 { 701 SQLSMALLINT nValueLen; 702 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) 703 OTools::ThrowException(_pConnection, 704 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), 705 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); 706 } 707 // ------------------------------------------------------------------------- 708 void OTools::GetInfo(OConnection* _pConnection, 709 SQLHANDLE _aConnectionHandle, 710 SQLUSMALLINT _nInfo, 711 SQLUSMALLINT &_rValue, 712 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) 713 { 714 SQLSMALLINT nValueLen; 715 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION) 716 OTools::ThrowException(_pConnection, 717 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), 718 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); 719 } 720 // ------------------------------------------------------------------------- 721 void OTools::GetInfo(OConnection* _pConnection, 722 SQLHANDLE _aConnectionHandle, 723 SQLUSMALLINT _nInfo, 724 sal_Bool &_rValue, 725 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException) 726 { 727 SQLSMALLINT nValueLen; 728 OTools::ThrowException(_pConnection, 729 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen), 730 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); 731 } 732 // ------------------------------------------------------------------------- 733 sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) 734 { 735 sal_Int32 nValue = DataType::VARCHAR; 736 switch(_nType) 737 { 738 case SQL_BIT: 739 nValue = DataType::BIT; 740 break; 741 case SQL_TINYINT: 742 nValue = DataType::TINYINT; 743 break; 744 case SQL_SMALLINT: 745 nValue = DataType::SMALLINT; 746 break; 747 case SQL_INTEGER: 748 nValue = DataType::INTEGER; 749 break; 750 case SQL_BIGINT: 751 nValue = DataType::BIGINT; 752 break; 753 case SQL_FLOAT: 754 nValue = DataType::FLOAT; 755 break; 756 case SQL_REAL: 757 nValue = DataType::REAL; 758 break; 759 case SQL_DOUBLE: 760 nValue = DataType::DOUBLE; 761 break; 762 case SQL_NUMERIC: 763 nValue = DataType::NUMERIC; 764 break; 765 case SQL_DECIMAL: 766 nValue = DataType::DECIMAL; 767 break; 768 case SQL_WCHAR: 769 case SQL_CHAR: 770 nValue = DataType::CHAR; 771 break; 772 case SQL_WVARCHAR: 773 case SQL_VARCHAR: 774 nValue = DataType::VARCHAR; 775 break; 776 case SQL_WLONGVARCHAR: 777 case SQL_LONGVARCHAR: 778 nValue = DataType::LONGVARCHAR; 779 break; 780 case SQL_TYPE_DATE: 781 case SQL_DATE: 782 nValue = DataType::DATE; 783 break; 784 case SQL_TYPE_TIME: 785 case SQL_TIME: 786 nValue = DataType::TIME; 787 break; 788 case SQL_TYPE_TIMESTAMP: 789 case SQL_TIMESTAMP: 790 nValue = DataType::TIMESTAMP; 791 break; 792 case SQL_BINARY: 793 nValue = DataType::BINARY; 794 break; 795 case SQL_VARBINARY: 796 case SQL_GUID: 797 nValue = DataType::VARBINARY; 798 break; 799 case SQL_LONGVARBINARY: 800 nValue = DataType::LONGVARBINARY; 801 break; 802 default: 803 OSL_ASSERT(!"Invalid type"); 804 } 805 return nValue; 806 } 807 //-------------------------------------------------------------------- 808 // jdbcTypeToOdbc 809 // Convert the JDBC SQL type to the correct ODBC type 810 //-------------------------------------------------------------------- 811 sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) 812 { 813 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" ); 814 // For the most part, JDBC types match ODBC types. We'll 815 // just convert the ones that we know are different 816 817 sal_Int32 odbcType = jdbcType; 818 819 switch (jdbcType) 820 { 821 case DataType::DATE: 822 odbcType = SQL_DATE; 823 break; 824 case DataType::TIME: 825 odbcType = SQL_TIME; 826 break; 827 case DataType::TIMESTAMP: 828 odbcType = SQL_TIMESTAMP; 829 break; 830 } 831 832 return odbcType; 833 } 834 //----------------------------------------------------------------------------- 835 void OTools::getBindTypes(sal_Bool _bUseWChar, 836 sal_Bool _bUseOldTimeDate, 837 SQLSMALLINT _nOdbcType, 838 SQLSMALLINT& fCType, 839 SQLSMALLINT& fSqlType 840 ) 841 { 842 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBindTypes" ); 843 switch(_nOdbcType) 844 { 845 case SQL_CHAR: if(_bUseWChar) 846 { 847 fCType = SQL_C_WCHAR; 848 fSqlType = SQL_WCHAR; 849 } 850 else 851 { 852 fCType = SQL_C_CHAR; 853 fSqlType = SQL_CHAR; 854 } 855 break; 856 case SQL_VARCHAR: if(_bUseWChar) 857 { 858 fCType = SQL_C_WCHAR; 859 fSqlType = SQL_WVARCHAR; 860 } 861 else 862 { 863 fCType = SQL_C_CHAR; 864 fSqlType = SQL_VARCHAR; 865 } 866 break; 867 case SQL_LONGVARCHAR: if(_bUseWChar) 868 { 869 fCType = SQL_C_WCHAR; 870 fSqlType = SQL_WLONGVARCHAR; 871 } 872 else 873 { 874 fCType = SQL_C_CHAR; 875 fSqlType = SQL_LONGVARCHAR; 876 } 877 break; 878 case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR; 879 fSqlType = SQL_DECIMAL; break; 880 case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR; 881 fSqlType = SQL_NUMERIC; break; 882 case SQL_BIT: fCType = SQL_C_TINYINT; 883 fSqlType = SQL_INTEGER; break; 884 case SQL_TINYINT: fCType = SQL_C_TINYINT; 885 fSqlType = SQL_TINYINT; break; 886 case SQL_SMALLINT: fCType = SQL_C_SHORT; 887 fSqlType = SQL_SMALLINT; break; 888 case SQL_INTEGER: fCType = SQL_C_LONG; 889 fSqlType = SQL_INTEGER; break; 890 case SQL_BIGINT: fCType = SQL_C_SBIGINT; 891 fSqlType = SQL_BIGINT; break; 892 case SQL_FLOAT: fCType = SQL_C_FLOAT; 893 fSqlType = SQL_FLOAT; break; 894 case SQL_REAL: fCType = SQL_C_DOUBLE; 895 fSqlType = SQL_REAL; break; 896 case SQL_DOUBLE: fCType = SQL_C_DOUBLE; 897 fSqlType = SQL_DOUBLE; break; 898 case SQL_BINARY: fCType = SQL_C_BINARY; 899 fSqlType = SQL_BINARY; break; 900 case SQL_VARBINARY: 901 fCType = SQL_C_BINARY; 902 fSqlType = SQL_VARBINARY; break; 903 case SQL_LONGVARBINARY: fCType = SQL_C_BINARY; 904 fSqlType = SQL_LONGVARBINARY; break; 905 case SQL_DATE: 906 if(_bUseOldTimeDate) 907 { 908 fCType = SQL_C_DATE; 909 fSqlType = SQL_DATE; 910 } 911 else 912 { 913 fCType = SQL_C_TYPE_DATE; 914 fSqlType = SQL_TYPE_DATE; 915 } 916 break; 917 case SQL_TIME: 918 if(_bUseOldTimeDate) 919 { 920 fCType = SQL_C_TIME; 921 fSqlType = SQL_TIME; 922 } 923 else 924 { 925 fCType = SQL_C_TYPE_TIME; 926 fSqlType = SQL_TYPE_TIME; 927 } 928 break; 929 case SQL_TIMESTAMP: 930 if(_bUseOldTimeDate) 931 { 932 fCType = SQL_C_TIMESTAMP; 933 fSqlType = SQL_TIMESTAMP; 934 } 935 else 936 { 937 fCType = SQL_C_TYPE_TIMESTAMP; 938 fSqlType = SQL_TYPE_TIMESTAMP; 939 } 940 break; 941 default: fCType = SQL_C_BINARY; 942 fSqlType = SQL_LONGVARBINARY; break; 943 } 944 } 945 946 947