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