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