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