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