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