Bump for 3.6-28
[LibreOffice.git] / connectivity / source / drivers / odbcbase / OTools.cxx
blob99108590d241bec2f2bb095fdf5ca3a327b7e710
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "odbc/OTools.hxx"
30 #include "odbc/OFunctions.hxx"
31 #include <com/sun/star/sdbc/DataType.hpp>
32 #include <osl/diagnose.h>
33 #include "odbc/OConnection.hxx"
34 #include "diagnose_ex.h"
35 #include <rtl/logfile.hxx>
36 #include <rtl/ustrbuf.hxx>
39 #include <string.h>
40 #include <string>
41 #include <algorithm>
43 using namespace connectivity::odbc;
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::sdbc;
46 using namespace com::sun::star::util;
48 namespace {
49 size_t sqlTypeLen ( SQLSMALLINT _nType )
51 switch (_nType)
53 case SQL_C_CHAR:
54 return sizeof(SQLCHAR *);
55 case SQL_C_WCHAR:
56 return sizeof(SQLWCHAR *);
57 case SQL_C_SSHORT:
58 case SQL_C_SHORT:
59 return sizeof(SQLSMALLINT);
60 case SQL_C_USHORT:
61 return sizeof(SQLUSMALLINT);
62 case SQL_C_SLONG:
63 case SQL_C_LONG:
64 return sizeof(SQLINTEGER);
65 case SQL_C_ULONG:
66 return sizeof(SQLUINTEGER);
67 case SQL_C_FLOAT:
68 return sizeof(SQLREAL);
69 case SQL_C_DOUBLE:
70 OSL_ENSURE(sizeof(SQLDOUBLE) == sizeof(SQLFLOAT), "SQLDOUBLE/SQLFLOAT confusion");
71 return sizeof(SQLDOUBLE);
72 case SQL_C_BIT:
73 return sizeof(SQLCHAR);
74 case SQL_C_STINYINT:
75 case SQL_C_TINYINT:
76 return sizeof(SQLSCHAR);
77 case SQL_C_UTINYINT:
78 return sizeof(SQLCHAR);
79 case SQL_C_SBIGINT:
80 return sizeof(SQLBIGINT);
81 case SQL_C_UBIGINT:
82 return sizeof(SQLUBIGINT);
83 /* UnixODBC gives this the same value as SQL_C_UBIGINT
84 case SQL_C_BOOKMARK:
85 return sizeof(BOOKMARK); */
86 case SQL_C_BINARY:
87 // UnixODBC gives these the same value
88 //case SQL_C_VARBOOKMARK:
89 return sizeof(SQLCHAR*);
90 case SQL_C_TYPE_DATE:
91 case SQL_C_DATE:
92 return sizeof(SQL_DATE_STRUCT);
93 case SQL_C_TYPE_TIME:
94 case SQL_C_TIME:
95 return sizeof(SQL_TIME_STRUCT);
96 case SQL_C_TYPE_TIMESTAMP:
97 case SQL_C_TIMESTAMP:
98 return sizeof(SQL_TIMESTAMP_STRUCT);
99 case SQL_C_NUMERIC:
100 return sizeof(SQL_NUMERIC_STRUCT);
101 case SQL_C_GUID:
102 return sizeof(SQLGUID);
103 case SQL_C_INTERVAL_YEAR:
104 case SQL_C_INTERVAL_MONTH:
105 case SQL_C_INTERVAL_DAY:
106 case SQL_C_INTERVAL_HOUR:
107 case SQL_C_INTERVAL_MINUTE:
108 case SQL_C_INTERVAL_SECOND:
109 case SQL_C_INTERVAL_YEAR_TO_MONTH:
110 case SQL_C_INTERVAL_DAY_TO_HOUR:
111 case SQL_C_INTERVAL_DAY_TO_MINUTE:
112 case SQL_C_INTERVAL_DAY_TO_SECOND:
113 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
114 case SQL_C_INTERVAL_HOUR_TO_SECOND:
115 case SQL_C_INTERVAL_MINUTE_TO_SECOND:
116 return sizeof(SQL_INTERVAL_STRUCT);
117 default:
118 return static_cast<size_t>(-1);
124 void OTools::getValue( OConnection* _pConnection,
125 SQLHANDLE _aStatementHandle,
126 sal_Int32 columnIndex,
127 SQLSMALLINT _nType,
128 sal_Bool &_bWasNull,
129 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
130 void* _pValue,
131 SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
133 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getValue" );
134 const size_t properSize = sqlTypeLen(_nType);
135 if ( properSize == static_cast<size_t>(-1) )
136 OSL_FAIL("connectivity::odbc::OTools::getValue: unknown SQL type - cannot check buffer size");
137 else
139 OSL_ENSURE(static_cast<size_t>(_nSize) == properSize, "connectivity::odbc::OTools::getValue got wrongly sized memory region to write result to");
140 if ( static_cast<size_t>(_nSize) > properSize )
142 OSL_FAIL("memory region is too big - trying to fudge it");
143 memset(_pValue, 0, _nSize);
144 #ifdef OSL_BIGENDIAN
145 // This is skewed in favour of integer types
146 _pValue += _nSize - properSize;
147 #endif
150 OSL_ENSURE(static_cast<size_t>(_nSize) >= properSize, "memory region is too small");
151 SQLLEN pcbValue = SQL_NULL_DATA;
152 OTools::ThrowException(_pConnection,
153 (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
154 (SQLUSMALLINT)columnIndex,
155 _nType,
156 _pValue,
157 _nSize,
158 &pcbValue),
159 _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False);
160 _bWasNull = pcbValue == SQL_NULL_DATA;
162 // -----------------------------------------------------------------------------
163 void OTools::bindParameter( OConnection* _pConnection,
164 SQLHANDLE _hStmt,
165 sal_Int32 nPos,
166 sal_Int8*& pDataBuffer,
167 sal_Int8* pLenBuffer,
168 SQLSMALLINT _nODBCtype,
169 sal_Bool _bUseWChar,
170 sal_Bool _bUseOldTimeDate,
171 const void* _pValue,
172 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
173 rtl_TextEncoding _nTextEncoding)
174 throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
176 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindParameter" );
177 SQLRETURN nRetcode;
178 SQLSMALLINT fSqlType;
179 SQLSMALLINT fCType;
180 SQLLEN nMaxLen = 0;
181 SQLLEN* pLen = (SQLLEN*)pLenBuffer;
182 SQLULEN nColumnSize=0;
183 SQLSMALLINT nDecimalDigits=0;
184 bool atExec;
186 OTools::getBindTypes(_bUseWChar,_bUseOldTimeDate,_nODBCtype,fCType,fSqlType);
188 OTools::bindData(_nODBCtype,_bUseWChar,pDataBuffer,pLen,_pValue,_nTextEncoding,nColumnSize, atExec);
189 if ((nColumnSize == 0) && (fSqlType == SQL_CHAR || fSqlType == SQL_VARCHAR || fSqlType == SQL_LONGVARCHAR))
190 nColumnSize = 1;
192 if (atExec)
193 memcpy(pDataBuffer,&nPos,sizeof(nPos));
195 nRetcode = (*(T3SQLBindParameter)_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(_hStmt,
196 (SQLUSMALLINT)nPos,
197 SQL_PARAM_INPUT,
198 fCType,
199 fSqlType,
200 nColumnSize,
201 nDecimalDigits,
202 pDataBuffer,
203 nMaxLen,
204 pLen);
206 OTools::ThrowException(_pConnection,nRetcode,_hStmt,SQL_HANDLE_STMT,_xInterface);
208 // -----------------------------------------------------------------------------
209 void OTools::bindData( SQLSMALLINT _nOdbcType,
210 sal_Bool _bUseWChar,
211 sal_Int8 *&_pData,
212 SQLLEN*& pLen,
213 const void* _pValue,
214 rtl_TextEncoding _nTextEncoding,
215 SQLULEN& _nColumnSize,
216 bool &atExec)
218 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindData" );
219 _nColumnSize = 0;
220 atExec = false;
222 switch (_nOdbcType)
224 case SQL_CHAR:
225 case SQL_VARCHAR:
226 case SQL_DECIMAL:
227 if(_bUseWChar)
229 *pLen = SQL_NTS;
230 ::rtl::OUString sStr(*(::rtl::OUString*)_pValue);
231 _nColumnSize = sStr.getLength();
232 *((rtl::OUString*)_pData) = sStr;
234 // Pointer on Char*
235 _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr();
237 else
239 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
240 *pLen = SQL_NTS;
241 _nColumnSize = aString.getLength();
242 memcpy(_pData,aString.getStr(),aString.getLength());
243 ((sal_Int8*)_pData)[aString.getLength()] = '\0';
245 break;
247 case SQL_BIGINT:
248 *((sal_Int64*)_pData) = *(sal_Int64*)_pValue;
249 *pLen = sizeof(sal_Int64);
250 _nColumnSize = *pLen;
251 break;
253 case SQL_NUMERIC:
254 if(_bUseWChar)
256 ::rtl::OUString aString = rtl::OUString::valueOf(*(double*)_pValue);
257 _nColumnSize = aString.getLength();
258 *pLen = _nColumnSize;
259 *((rtl::OUString*)_pData) = aString;
260 // Pointer on Char*
261 _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr();
263 else
265 ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue);
266 _nColumnSize = aString.getLength();
267 *pLen = _nColumnSize;
268 memcpy(_pData,aString.getStr(),aString.getLength());
269 ((sal_Int8*)_pData)[_nColumnSize] = '\0';
270 } break;
271 case SQL_BIT:
272 case SQL_TINYINT:
273 *((sal_Int8*)_pData) = *(sal_Int8*)_pValue;
274 *pLen = sizeof(sal_Int8);
275 break;
277 case SQL_SMALLINT:
278 *((sal_Int16*)_pData) = *(sal_Int16*)_pValue;
279 *pLen = sizeof(sal_Int16);
280 break;
281 case SQL_INTEGER:
282 *((sal_Int32*)_pData) = *(sal_Int32*)_pValue;
283 *pLen = sizeof(sal_Int32);
284 break;
285 case SQL_FLOAT:
286 *((float*)_pData) = *(float*)_pValue;
287 *pLen = sizeof(float);
288 break;
289 case SQL_REAL:
290 case SQL_DOUBLE:
291 *((double*)_pData) = *(double*)_pValue;
292 *pLen = sizeof(double);
293 break;
294 case SQL_BINARY:
295 case SQL_VARBINARY:
297 const ::com::sun::star::uno::Sequence< sal_Int8 >* pSeq = static_cast< const ::com::sun::star::uno::Sequence< sal_Int8 >* >(_pValue);
298 OSL_ENSURE(pSeq,"OTools::bindData: Sequence is null!");
300 if(pSeq)
302 _pData = (sal_Int8*)pSeq->getConstArray();
303 *pLen = pSeq->getLength();
306 break;
307 case SQL_LONGVARBINARY:
309 sal_Int32 nLen = 0;
310 nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
311 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
313 atExec = true;
314 break;
315 case SQL_LONGVARCHAR:
317 sal_Int32 nLen = 0;
318 if(_bUseWChar)
319 nLen = sizeof(sal_Unicode) * ((::rtl::OUString*)_pValue)->getLength();
320 else
322 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
323 nLen = aString.getLength();
325 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
326 atExec = true;
327 } break;
328 case SQL_DATE:
329 *(DATE_STRUCT*)_pData = *(DATE_STRUCT*)_pValue;
330 *pLen = (SQLLEN)sizeof(DATE_STRUCT);
331 _nColumnSize = 10;
332 break;
333 case SQL_TIME:
334 *(TIME_STRUCT*)_pData = *(TIME_STRUCT*)_pValue;
335 *pLen = (SQLLEN)sizeof(TIME_STRUCT);
336 _nColumnSize = 8;
337 break;
338 case SQL_TIMESTAMP:
339 *(TIMESTAMP_STRUCT*)_pData = *(TIMESTAMP_STRUCT*)_pValue;
340 *pLen = (SQLLEN)sizeof(TIMESTAMP_STRUCT);
341 _nColumnSize = 19;
342 break;
345 // -------------------------------------------------------------------------
346 void OTools::bindValue( OConnection* _pConnection,
347 SQLHANDLE _aStatementHandle,
348 sal_Int32 columnIndex,
349 SQLSMALLINT _nType,
350 SQLSMALLINT _nMaxLen,
351 const void* _pValue,
352 void* _pData,
353 SQLLEN *pLen,
354 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
355 rtl_TextEncoding _nTextEncoding,
356 sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
358 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindValue" );
359 SQLRETURN nRetcode;
360 SQLSMALLINT fSqlType;
361 SQLSMALLINT fCType;
362 SQLLEN nMaxLen = _nMaxLen;
364 OTools::getBindTypes( sal_False,
365 _bUseOldTimeDate,
366 _nType,
367 fCType,
368 fSqlType);
370 if (columnIndex != 0 && !_pValue)
372 *pLen = SQL_NULL_DATA;
373 nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
374 (SQLUSMALLINT)columnIndex,
375 fCType,
376 _pData,
377 nMaxLen,
378 pLen
381 else
385 switch (_nType)
387 case SQL_CHAR:
388 case SQL_VARCHAR:
390 ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
391 *pLen = SQL_NTS;
392 *((::rtl::OString*)_pData) = aString;
393 _nMaxLen = (SQLSMALLINT)aString.getLength();
395 // Pointer on Char*
396 _pData = (void*)aString.getStr();
397 } break;
398 case SQL_BIGINT:
399 *((sal_Int64*)_pData) = *(sal_Int64*)_pValue;
400 *pLen = sizeof(sal_Int64);
401 break;
402 case SQL_DECIMAL:
403 case SQL_NUMERIC:
405 ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue);
406 _nMaxLen = (SQLSMALLINT)aString.getLength();
407 *pLen = _nMaxLen;
408 *((::rtl::OString*)_pData) = aString;
409 // Pointer on Char*
410 _pData = (void*)((::rtl::OString*)_pData)->getStr();
411 } break;
412 case SQL_BIT:
413 case SQL_TINYINT:
414 *((sal_Int8*)_pData) = *(sal_Int8*)_pValue;
415 *pLen = sizeof(sal_Int8);
416 break;
418 case SQL_SMALLINT:
419 *((sal_Int16*)_pData) = *(sal_Int16*)_pValue;
420 *pLen = sizeof(sal_Int16);
421 break;
422 case SQL_INTEGER:
423 *((sal_Int32*)_pData) = *(sal_Int32*)_pValue;
424 *pLen = sizeof(sal_Int32);
425 break;
426 case SQL_FLOAT:
427 *((float*)_pData) = *(float*)_pValue;
428 *pLen = sizeof(float);
429 break;
430 case SQL_REAL:
431 case SQL_DOUBLE:
432 *((double*)_pData) = *(double*)_pValue;
433 *pLen = sizeof(double);
434 break;
435 case SQL_BINARY:
436 case SQL_VARBINARY:
438 _pData = (void*)((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getConstArray();
439 *pLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
440 } break;
441 case SQL_LONGVARBINARY:
443 _pData = (void*)(sal_IntPtr)(columnIndex);
444 sal_Int32 nLen = 0;
445 nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
446 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
448 break;
449 case SQL_LONGVARCHAR:
451 _pData = (void*)(sal_IntPtr)(columnIndex);
452 sal_Int32 nLen = 0;
453 nLen = ((::rtl::OUString*)_pValue)->getLength();
454 *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
455 } break;
456 case SQL_DATE:
457 *pLen = sizeof(DATE_STRUCT);
458 *((DATE_STRUCT*)_pData) = *(DATE_STRUCT*)_pValue;
459 break;
460 case SQL_TIME:
461 *pLen = sizeof(TIME_STRUCT);
462 *((TIME_STRUCT*)_pData) = *(TIME_STRUCT*)_pValue;
463 break;
464 case SQL_TIMESTAMP:
465 *pLen = sizeof(TIMESTAMP_STRUCT);
466 *((TIMESTAMP_STRUCT*)_pData) = *(TIMESTAMP_STRUCT*)_pValue;
467 break;
470 catch ( ... )
474 nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
475 (SQLUSMALLINT)columnIndex,
476 fCType,
477 _pData,
478 nMaxLen,
479 pLen
483 OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
485 // -----------------------------------------------------------------------------
486 void OTools::ThrowException(OConnection* _pConnection,
487 SQLRETURN _rRetCode,
488 SQLHANDLE _pContext,
489 SQLSMALLINT _nHandleType,
490 const Reference< XInterface >& _xInterface,
491 sal_Bool _bNoFound,
492 rtl_TextEncoding _nTextEncoding) throw(SQLException)
494 switch(_rRetCode)
496 case SQL_NEED_DATA:
497 case SQL_STILL_EXECUTING:
498 case SQL_SUCCESS:
500 case SQL_SUCCESS_WITH_INFO:
501 return;
502 case SQL_NO_DATA_FOUND:
503 if(_bNoFound)
504 return; // no need to throw a exception
505 case SQL_ERROR: break;
508 case SQL_INVALID_HANDLE: OSL_FAIL("SdbODBC3_SetStatus: SQL_INVALID_HANDLE");
509 throw SQLException();
512 // Additional Information on the latest ODBC-functioncall available
513 // SQLError provides this Information.
514 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::ThrowException" );
516 SDB_ODBC_CHAR szSqlState[5];
517 SQLINTEGER pfNativeError;
518 SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
519 szErrorMessage[0] = '\0';
520 SQLSMALLINT pcbErrorMsg = 0;
522 // Information for latest operation:
523 // when hstmt != SQL_NULL_HSTMT is (Used from SetStatus in SdbCursor, SdbTable, ...),
524 // then the status of the latest statments will be fetched, without the Status of the last
525 // Statments of this connection [what in this case will probably be the same, but the Reference
526 // Manual isn't totally clear in this...].
527 // corresponding for hdbc.
528 SQLRETURN n = (*(T3SQLGetDiagRec)_pConnection->getOdbcFunction(ODBC3SQLGetDiagRec))(_nHandleType,_pContext,1,
529 szSqlState,
530 &pfNativeError,
531 szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg);
532 OSL_UNUSED( n );
533 OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE");
534 OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed");
536 // For the Return Code of SQLError see ODBC 2.0 Programmer's Reference Page 287ff
537 throw SQLException( ::rtl::OUString((char *)szErrorMessage,pcbErrorMsg,_nTextEncoding),
538 _xInterface,
539 ::rtl::OUString((char *)szSqlState,5,_nTextEncoding),
540 pfNativeError,
541 Any()
545 // -------------------------------------------------------------------------
546 Sequence<sal_Int8> OTools::getBytesValue(OConnection* _pConnection,
547 SQLHANDLE _aStatementHandle,
548 sal_Int32 columnIndex,
549 SQLSMALLINT _fSqlType,
550 sal_Bool &_bWasNull,
551 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
553 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBytesValue" );
554 char aCharArray[2048];
555 // First try to fetch the data with the little Buffer:
556 SQLLEN nMaxLen = sizeof aCharArray - 1;
557 // GETDATA(SQL_C_CHAR,aCharArray,nMaxLen);
558 SQLLEN pcbValue = 0;
559 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
560 (SQLUSMALLINT)columnIndex,
561 _fSqlType,
562 (SQLPOINTER)aCharArray,
563 nMaxLen,
564 &pcbValue),
565 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
567 _bWasNull = pcbValue == SQL_NULL_DATA;
568 if(_bWasNull)
569 return Sequence<sal_Int8>();
571 SQLINTEGER nBytes = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : nMaxLen;
572 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nBytes-1] == 0 && nBytes > 0 )
573 --nBytes;
574 Sequence<sal_Int8> aData((sal_Int8*)aCharArray, nBytes);
576 // It is about Binariy Data, a String, that for StarView is to long or
577 // the driver kan't predict the length of the data - as well as save the
578 // MemoryStream.
579 while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen)
581 // At Strings the Buffer won't be completly used
582 // (The last Byte is always a NULL-Byte, however it won't be counted with pcbValue)
583 if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen)
584 nBytes = pcbValue - nMaxLen;
585 else
586 nBytes = nMaxLen;
588 // While there is a "truncation"-Warning, proceed with fetching Data.
589 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
590 (SQLUSMALLINT)columnIndex,
591 SQL_C_BINARY,
592 &aCharArray,
593 (SQLINTEGER)nBytes,
594 &pcbValue),
595 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
596 sal_Int32 nLen = aData.getLength();
597 aData.realloc(nLen + nBytes);
598 memcpy(aData.getArray() + nLen, aCharArray, nBytes);
600 return aData;
602 // -------------------------------------------------------------------------
603 ::rtl::OUString OTools::getStringValue(OConnection* _pConnection,
604 SQLHANDLE _aStatementHandle,
605 sal_Int32 columnIndex,
606 SQLSMALLINT _fSqlType,
607 sal_Bool &_bWasNull,
608 const Reference< XInterface >& _xInterface,
609 rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
611 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getStringValue" );
612 ::rtl::OUStringBuffer aData;
613 switch(_fSqlType)
615 case SQL_WVARCHAR:
616 case SQL_WCHAR:
617 case SQL_WLONGVARCHAR:
619 sal_Unicode waCharArray[2048];
620 // read the unicode data
621 SQLLEN nMaxLen = (sizeof(waCharArray) / sizeof(sal_Unicode)) - 1;
623 SQLLEN pcbValue=0;
624 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
625 (SQLUSMALLINT)columnIndex,
626 SQL_C_WCHAR,
627 &waCharArray,
628 (SQLLEN)nMaxLen*sizeof(sal_Unicode),
629 &pcbValue),
630 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
631 _bWasNull = pcbValue == SQL_NULL_DATA;
632 if(_bWasNull)
633 return ::rtl::OUString();
634 // at failure the GETDATA-Makro will stop with returning,
635 // at NULL with break!
636 SQLLEN nRealSize = 0;
637 if ( pcbValue > -1 )
638 nRealSize = pcbValue / sizeof(sal_Unicode);
639 SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1);
640 waCharArray[nLen] = 0;
641 aData.append(waCharArray,nLen);
643 // It is about Binariy Data, a String, that for StarView is to long or
644 // the driver kan't predict the length of the data - as well as save the
645 // MemoryStream.
646 while ((pcbValue == SQL_NO_TOTAL ) || nLen > nMaxLen)
648 // At Strings the Buffer won't be completly used
649 // (The last Byte is always a NULL-Byte, however it won't be counted with pcbValue)
650 if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen)
651 nLen = pcbValue - nMaxLen;
652 else
653 nLen = nMaxLen;
655 // While there is a "truncation"-Warning, proceed with fetching Data.
656 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
657 (SQLUSMALLINT)columnIndex,
658 SQL_C_WCHAR,
659 &waCharArray,
660 (SQLLEN)nLen+1,
661 &pcbValue),
662 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
663 nRealSize = 0;
664 if ( pcbValue > -1 )
665 nRealSize = pcbValue / sizeof(sal_Unicode);
666 nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1);
667 waCharArray[nLen] = 0;
669 aData.append(::rtl::OUString(waCharArray));
672 break;
673 default:
675 char aCharArray[2048];
676 // First try to fetch the data with the little Buffer:
677 SQLLEN nMaxLen = sizeof aCharArray - 1;
678 SQLLEN pcbValue = 0;
679 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
680 (SQLUSMALLINT)columnIndex,
681 SQL_C_CHAR,
682 &aCharArray,
683 nMaxLen,
684 &pcbValue),
685 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
686 _bWasNull = pcbValue == SQL_NULL_DATA;
687 if(_bWasNull)
688 return ::rtl::OUString();
690 SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1);
691 aCharArray[nLen] = 0;
692 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 )
693 --nLen;
694 aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen, _nTextEncoding));
696 // It is about Binary Data, a String, that for StarView is too long or
697 // the driver can't predict the length of the data - as well as save the
698 // MemoryStream.
699 while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen)
701 // While there is a "truncation"-Warning, proceed with fetching Data.
702 OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
703 (SQLUSMALLINT)columnIndex,
704 SQL_C_CHAR,
705 &aCharArray,
706 (SQLINTEGER)nMaxLen,
707 &pcbValue),
708 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
709 nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1);
710 if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 )
711 --nLen;
712 aCharArray[nLen] = 0;
714 aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen,_nTextEncoding));
720 return aData.makeStringAndClear();
722 // -------------------------------------------------------------------------
723 void OTools::GetInfo(OConnection* _pConnection,
724 SQLHANDLE _aConnectionHandle,
725 SQLUSMALLINT _nInfo,
726 ::rtl::OUString &_rValue,
727 const Reference< XInterface >& _xInterface,
728 rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
730 char aValue[512];
731 SQLSMALLINT nValueLen=0;
732 OTools::ThrowException(_pConnection,
733 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen),
734 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
736 _rValue = ::rtl::OUString(aValue,nValueLen,_nTextEncoding);
738 // -------------------------------------------------------------------------
739 void OTools::GetInfo(OConnection* _pConnection,
740 SQLHANDLE _aConnectionHandle,
741 SQLUSMALLINT _nInfo,
742 sal_Int32 &_rValue,
743 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
745 SQLSMALLINT nValueLen;
746 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
747 OTools::ThrowException(_pConnection,
748 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
749 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
751 // -------------------------------------------------------------------------
752 void OTools::GetInfo(OConnection* _pConnection,
753 SQLHANDLE _aConnectionHandle,
754 SQLUSMALLINT _nInfo,
755 SQLUINTEGER &_rValue,
756 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
758 SQLSMALLINT nValueLen;
759 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
760 OTools::ThrowException(_pConnection,
761 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
762 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
764 // -------------------------------------------------------------------------
765 void OTools::GetInfo(OConnection* _pConnection,
766 SQLHANDLE _aConnectionHandle,
767 SQLUSMALLINT _nInfo,
768 SQLUSMALLINT &_rValue,
769 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
771 SQLSMALLINT nValueLen;
772 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
773 OTools::ThrowException(_pConnection,
774 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
775 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
777 // -------------------------------------------------------------------------
778 void OTools::GetInfo(OConnection* _pConnection,
779 SQLHANDLE _aConnectionHandle,
780 SQLUSMALLINT _nInfo,
781 sal_Bool &_rValue,
782 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
784 SQLSMALLINT nValueLen;
785 OTools::ThrowException(_pConnection,
786 (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
787 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
789 // -------------------------------------------------------------------------
790 sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType)
792 sal_Int32 nValue = DataType::VARCHAR;
793 switch(_nType)
795 case SQL_BIT:
796 nValue = DataType::BIT;
797 break;
798 case SQL_TINYINT:
799 nValue = DataType::TINYINT;
800 break;
801 case SQL_SMALLINT:
802 nValue = DataType::SMALLINT;
803 break;
804 case SQL_INTEGER:
805 nValue = DataType::INTEGER;
806 break;
807 case SQL_BIGINT:
808 nValue = DataType::BIGINT;
809 break;
810 case SQL_FLOAT:
811 nValue = DataType::FLOAT;
812 break;
813 case SQL_REAL:
814 nValue = DataType::REAL;
815 break;
816 case SQL_DOUBLE:
817 nValue = DataType::DOUBLE;
818 break;
819 case SQL_NUMERIC:
820 nValue = DataType::NUMERIC;
821 break;
822 case SQL_DECIMAL:
823 nValue = DataType::DECIMAL;
824 break;
825 case SQL_WCHAR:
826 case SQL_CHAR:
827 nValue = DataType::CHAR;
828 break;
829 case SQL_WVARCHAR:
830 case SQL_VARCHAR:
831 nValue = DataType::VARCHAR;
832 break;
833 case SQL_WLONGVARCHAR:
834 case SQL_LONGVARCHAR:
835 nValue = DataType::LONGVARCHAR;
836 break;
837 case SQL_TYPE_DATE:
838 case SQL_DATE:
839 nValue = DataType::DATE;
840 break;
841 case SQL_TYPE_TIME:
842 case SQL_TIME:
843 nValue = DataType::TIME;
844 break;
845 case SQL_TYPE_TIMESTAMP:
846 case SQL_TIMESTAMP:
847 nValue = DataType::TIMESTAMP;
848 break;
849 case SQL_BINARY:
850 nValue = DataType::BINARY;
851 break;
852 case SQL_VARBINARY:
853 case SQL_GUID:
854 nValue = DataType::VARBINARY;
855 break;
856 case SQL_LONGVARBINARY:
857 nValue = DataType::LONGVARBINARY;
858 break;
859 default:
860 OSL_ASSERT(!"Invalid type");
862 return nValue;
864 //--------------------------------------------------------------------
865 // jdbcTypeToOdbc
866 // Convert the JDBC SQL type to the correct ODBC type
867 //--------------------------------------------------------------------
868 sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
870 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" );
871 // For the most part, JDBC types match ODBC types. We'll
872 // just convert the ones that we know are different
874 sal_Int32 odbcType = jdbcType;
876 switch (jdbcType)
878 case DataType::DATE:
879 odbcType = SQL_DATE;
880 break;
881 case DataType::TIME:
882 odbcType = SQL_TIME;
883 break;
884 case DataType::TIMESTAMP:
885 odbcType = SQL_TIMESTAMP;
886 break;
889 return odbcType;
891 //-----------------------------------------------------------------------------
892 void OTools::getBindTypes(sal_Bool _bUseWChar,
893 sal_Bool _bUseOldTimeDate,
894 SQLSMALLINT _nOdbcType,
895 SQLSMALLINT& fCType,
896 SQLSMALLINT& fSqlType
899 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBindTypes" );
900 switch(_nOdbcType)
902 case SQL_CHAR: if(_bUseWChar)
904 fCType = SQL_C_WCHAR;
905 fSqlType = SQL_WCHAR;
907 else
909 fCType = SQL_C_CHAR;
910 fSqlType = SQL_CHAR;
912 break;
913 case SQL_VARCHAR: if(_bUseWChar)
915 fCType = SQL_C_WCHAR;
916 fSqlType = SQL_WVARCHAR;
918 else
920 fCType = SQL_C_CHAR;
921 fSqlType = SQL_VARCHAR;
923 break;
924 case SQL_LONGVARCHAR: if(_bUseWChar)
926 fCType = SQL_C_WCHAR;
927 fSqlType = SQL_WLONGVARCHAR;
929 else
931 fCType = SQL_C_CHAR;
932 fSqlType = SQL_LONGVARCHAR;
934 break;
935 case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
936 fSqlType = SQL_DECIMAL; break;
937 case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
938 fSqlType = SQL_NUMERIC; break;
939 case SQL_BIT: fCType = SQL_C_TINYINT;
940 fSqlType = SQL_INTEGER; break;
941 case SQL_TINYINT: fCType = SQL_C_TINYINT;
942 fSqlType = SQL_TINYINT; break;
943 case SQL_SMALLINT: fCType = SQL_C_SHORT;
944 fSqlType = SQL_SMALLINT; break;
945 case SQL_INTEGER: fCType = SQL_C_LONG;
946 fSqlType = SQL_INTEGER; break;
947 case SQL_BIGINT: fCType = SQL_C_SBIGINT;
948 fSqlType = SQL_BIGINT; break;
949 case SQL_FLOAT: fCType = SQL_C_FLOAT;
950 fSqlType = SQL_FLOAT; break;
951 case SQL_REAL: fCType = SQL_C_DOUBLE;
952 fSqlType = SQL_REAL; break;
953 case SQL_DOUBLE: fCType = SQL_C_DOUBLE;
954 fSqlType = SQL_DOUBLE; break;
955 case SQL_BINARY: fCType = SQL_C_BINARY;
956 fSqlType = SQL_BINARY; break;
957 case SQL_VARBINARY:
958 fCType = SQL_C_BINARY;
959 fSqlType = SQL_VARBINARY; break;
960 case SQL_LONGVARBINARY: fCType = SQL_C_BINARY;
961 fSqlType = SQL_LONGVARBINARY; break;
962 case SQL_DATE:
963 if(_bUseOldTimeDate)
965 fCType = SQL_C_DATE;
966 fSqlType = SQL_DATE;
968 else
970 fCType = SQL_C_TYPE_DATE;
971 fSqlType = SQL_TYPE_DATE;
973 break;
974 case SQL_TIME:
975 if(_bUseOldTimeDate)
977 fCType = SQL_C_TIME;
978 fSqlType = SQL_TIME;
980 else
982 fCType = SQL_C_TYPE_TIME;
983 fSqlType = SQL_TYPE_TIME;
985 break;
986 case SQL_TIMESTAMP:
987 if(_bUseOldTimeDate)
989 fCType = SQL_C_TIMESTAMP;
990 fSqlType = SQL_TIMESTAMP;
992 else
994 fCType = SQL_C_TYPE_TIMESTAMP;
995 fSqlType = SQL_TYPE_TIMESTAMP;
997 break;
998 default: fCType = SQL_C_BINARY;
999 fSqlType = SQL_LONGVARBINARY; break;
1004 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */