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