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