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