bump product version to 6.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / odbc / OTools.cxx
bloba4c3200c5b53c5e8d60091e2bc17d756dc6078bb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <odbc/OTools.hxx>
21 #include <odbc/OFunctions.hxx>
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <osl/diagnose.h>
24 #include <osl/endian.h>
25 #include <odbc/OConnection.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <sal/log.hxx>
29 #include <string.h>
30 #include <string>
31 #include <algorithm>
33 using namespace connectivity::odbc;
34 using namespace com::sun::star::uno;
35 using namespace com::sun::star::sdbc;
36 using namespace com::sun::star::util;
38 namespace {
39 size_t sqlTypeLen ( SQLSMALLINT _nType )
41 switch (_nType)
43 case SQL_C_SSHORT:
44 case SQL_C_SHORT:
45 return sizeof(SQLSMALLINT);
46 case SQL_C_USHORT:
47 return sizeof(SQLUSMALLINT);
48 case SQL_C_SLONG:
49 case SQL_C_LONG:
50 return sizeof(SQLINTEGER);
51 case SQL_C_ULONG:
52 return sizeof(SQLUINTEGER);
53 case SQL_C_FLOAT:
54 return sizeof(SQLREAL);
55 case SQL_C_DOUBLE:
56 static_assert(sizeof(SQLDOUBLE) == sizeof(SQLFLOAT), "SQLDOUBLE/SQLFLOAT confusion");
57 return sizeof(SQLDOUBLE);
58 case SQL_C_BIT:
59 return sizeof(SQLCHAR);
60 case SQL_C_STINYINT:
61 case SQL_C_TINYINT:
62 return sizeof(SQLSCHAR);
63 case SQL_C_UTINYINT:
64 return sizeof(SQLCHAR);
65 case SQL_C_SBIGINT:
66 return sizeof(SQLBIGINT);
67 case SQL_C_UBIGINT:
68 return sizeof(SQLUBIGINT);
69 /* UnixODBC gives this the same value as SQL_C_UBIGINT
70 case SQL_C_BOOKMARK:
71 return sizeof(BOOKMARK); */
72 case SQL_C_TYPE_DATE:
73 case SQL_C_DATE:
74 return sizeof(SQL_DATE_STRUCT);
75 case SQL_C_TYPE_TIME:
76 case SQL_C_TIME:
77 return sizeof(SQL_TIME_STRUCT);
78 case SQL_C_TYPE_TIMESTAMP:
79 case SQL_C_TIMESTAMP:
80 return sizeof(SQL_TIMESTAMP_STRUCT);
81 case SQL_C_NUMERIC:
82 return sizeof(SQL_NUMERIC_STRUCT);
83 case SQL_C_GUID:
84 return sizeof(SQLGUID);
85 case SQL_C_INTERVAL_YEAR:
86 case SQL_C_INTERVAL_MONTH:
87 case SQL_C_INTERVAL_DAY:
88 case SQL_C_INTERVAL_HOUR:
89 case SQL_C_INTERVAL_MINUTE:
90 case SQL_C_INTERVAL_SECOND:
91 case SQL_C_INTERVAL_YEAR_TO_MONTH:
92 case SQL_C_INTERVAL_DAY_TO_HOUR:
93 case SQL_C_INTERVAL_DAY_TO_MINUTE:
94 case SQL_C_INTERVAL_DAY_TO_SECOND:
95 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
96 case SQL_C_INTERVAL_HOUR_TO_SECOND:
97 case SQL_C_INTERVAL_MINUTE_TO_SECOND:
98 return sizeof(SQL_INTERVAL_STRUCT);
99 // ** Variable-sized datatypes -> cannot predict length
100 case SQL_C_CHAR:
101 case SQL_C_WCHAR:
102 case SQL_C_BINARY:
103 // UnixODBC gives this the same value as SQL_C_BINARY
104 //case SQL_C_VARBOOKMARK:
105 // Unknown datatype -> cannot predict length
106 default:
107 return static_cast<size_t>(-1);
111 void appendSQLWCHARs(OUStringBuffer & s, SQLWCHAR const * d, sal_Int32 n)
113 static_assert(
114 sizeof (SQLWCHAR) == sizeof (sal_Unicode) || sizeof (SQLWCHAR) == 4,
115 "bad SQLWCHAR");
116 if (sizeof (SQLWCHAR) == sizeof (sal_Unicode)) {
117 s.append(reinterpret_cast<sal_Unicode const *>(d), n);
118 } else {
119 for (sal_Int32 i = 0; i != n; ++i) {
120 s.appendUtf32(d[i]);
127 void OTools::getValue( OConnection const * _pConnection,
128 SQLHANDLE _aStatementHandle,
129 sal_Int32 columnIndex,
130 SQLSMALLINT _nType,
131 bool &_bWasNull,
132 const css::uno::Reference< css::uno::XInterface >& _xInterface,
133 void* _pValue,
134 SQLLEN _nSize)
136 const size_t properSize = sqlTypeLen(_nType);
137 if ( properSize == static_cast<size_t>(-1) )
138 SAL_WARN( "connectivity.drivers", "connectivity::odbc::OTools::getValue: unknown SQL type - cannot check buffer size");
139 else
141 OSL_ENSURE(static_cast<size_t>(_nSize) == properSize, "connectivity::odbc::OTools::getValue got wrongly sized memory region to write result to");
142 if ( static_cast<size_t>(_nSize) > properSize )
144 SAL_WARN( "connectivity.drivers", "memory region is too big - trying to fudge it");
145 memset(_pValue, 0, _nSize);
146 #ifdef OSL_BIGENDIAN
147 // This is skewed in favour of integer types
148 _pValue += _nSize - properSize;
149 #endif
152 OSL_ENSURE(static_cast<size_t>(_nSize) >= properSize, "memory region is too small");
153 SQLLEN pcbValue = SQL_NULL_DATA;
154 OTools::ThrowException(_pConnection,
155 (*reinterpret_cast<T3SQLGetData>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetData)))(_aStatementHandle,
156 static_cast<SQLUSMALLINT>(columnIndex),
157 _nType,
158 _pValue,
159 _nSize,
160 &pcbValue),
161 _aStatementHandle,SQL_HANDLE_STMT,_xInterface,false);
162 _bWasNull = pcbValue == SQL_NULL_DATA;
165 void OTools::bindValue( OConnection const * _pConnection,
166 SQLHANDLE _aStatementHandle,
167 sal_Int32 columnIndex,
168 SQLSMALLINT _nType,
169 SQLSMALLINT _nMaxLen,
170 const void* _pValue,
171 void* _pData,
172 SQLLEN * const pLen,
173 const css::uno::Reference< css::uno::XInterface >& _xInterface,
174 rtl_TextEncoding _nTextEncoding,
175 bool _bUseOldTimeDate)
177 SQLRETURN nRetcode;
178 SQLSMALLINT fSqlType;
179 SQLSMALLINT fCType;
181 OTools::getBindTypes( false,
182 _bUseOldTimeDate,
183 _nType,
184 fCType,
185 fSqlType);
187 if (columnIndex != 0 && !_pValue)
189 *pLen = SQL_NULL_DATA;
190 nRetcode = (*reinterpret_cast<T3SQLBindCol>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::BindCol)))(_aStatementHandle,
191 static_cast<SQLUSMALLINT>(columnIndex),
192 fCType,
193 _pData,
194 _nMaxLen,
195 pLen
198 else
202 switch (_nType)
204 case SQL_CHAR:
205 case SQL_VARCHAR:
207 OString aString(OUStringToOString(*static_cast<OUString const *>(_pValue),_nTextEncoding));
208 *pLen = SQL_NTS;
209 *static_cast<OString*>(_pData) = aString;
211 // Pointer on Char*
212 _pData = const_cast<char *>(aString.getStr());
213 } break;
214 case SQL_BIGINT:
215 *static_cast<sal_Int64*>(_pData) = *static_cast<sal_Int64 const *>(_pValue);
216 *pLen = sizeof(sal_Int64);
217 break;
218 case SQL_DECIMAL:
219 case SQL_NUMERIC:
221 OString aString = OString::number(*static_cast<double const *>(_pValue));
222 *pLen = static_cast<SQLSMALLINT>(aString.getLength());
223 *static_cast<OString*>(_pData) = aString;
224 // Pointer on Char*
225 _pData = const_cast<char *>(static_cast<OString*>(_pData)->getStr());
226 } break;
227 case SQL_BIT:
228 case SQL_TINYINT:
229 *static_cast<sal_Int8*>(_pData) = *static_cast<sal_Int8 const *>(_pValue);
230 *pLen = sizeof(sal_Int8);
231 break;
233 case SQL_SMALLINT:
234 *static_cast<sal_Int16*>(_pData) = *static_cast<sal_Int16 const *>(_pValue);
235 *pLen = sizeof(sal_Int16);
236 break;
237 case SQL_INTEGER:
238 *static_cast<sal_Int32*>(_pData) = *static_cast<sal_Int32 const *>(_pValue);
239 *pLen = sizeof(sal_Int32);
240 break;
241 case SQL_FLOAT:
242 *static_cast<float*>(_pData) = *static_cast<float const *>(_pValue);
243 *pLen = sizeof(float);
244 break;
245 case SQL_REAL:
246 case SQL_DOUBLE:
247 *static_cast<double*>(_pData) = *static_cast<double const *>(_pValue);
248 *pLen = sizeof(double);
249 break;
250 case SQL_BINARY:
251 case SQL_VARBINARY:
253 _pData = const_cast<sal_Int8 *>(static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getConstArray());
254 *pLen = static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getLength();
255 } break;
256 case SQL_LONGVARBINARY:
258 /* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
259 * for an explanation of that apparently weird cast */
260 _pData = reinterpret_cast<void*>(static_cast<uintptr_t>(columnIndex));
261 sal_Int32 nLen = static_cast<const css::uno::Sequence< sal_Int8 > *>(_pValue)->getLength();
262 *pLen = static_cast<SQLLEN>(SQL_LEN_DATA_AT_EXEC(nLen));
264 break;
265 case SQL_LONGVARCHAR:
267 /* see https://msdn.microsoft.com/en-us/library/ms716238%28v=vs.85%29.aspx
268 * for an explanation of that apparently weird cast */
269 _pData = reinterpret_cast<void*>(static_cast<uintptr_t>(columnIndex));
270 sal_Int32 nLen = static_cast<OUString const *>(_pValue)->getLength();
271 *pLen = static_cast<SQLLEN>(SQL_LEN_DATA_AT_EXEC(nLen));
272 } break;
273 case SQL_DATE:
274 *pLen = sizeof(DATE_STRUCT);
275 *static_cast<DATE_STRUCT*>(_pData) = *static_cast<DATE_STRUCT const *>(_pValue);
276 break;
277 case SQL_TIME:
278 *pLen = sizeof(TIME_STRUCT);
279 *static_cast<TIME_STRUCT*>(_pData) = *static_cast<TIME_STRUCT const *>(_pValue);
280 break;
281 case SQL_TIMESTAMP:
282 *pLen = sizeof(TIMESTAMP_STRUCT);
283 *static_cast<TIMESTAMP_STRUCT*>(_pData) = *static_cast<TIMESTAMP_STRUCT const *>(_pValue);
284 break;
287 catch ( ... )
291 nRetcode = (*reinterpret_cast<T3SQLBindCol>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::BindCol)))(_aStatementHandle,
292 static_cast<SQLUSMALLINT>(columnIndex),
293 fCType,
294 _pData,
295 _nMaxLen,
296 pLen
300 OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
303 void OTools::ThrowException(const OConnection* _pConnection,
304 const SQLRETURN _rRetCode,
305 const SQLHANDLE _pContext,
306 const SQLSMALLINT _nHandleType,
307 const Reference< XInterface >& _xInterface,
308 const bool _bNoFound)
310 switch(_rRetCode)
312 case SQL_NEED_DATA:
313 case SQL_STILL_EXECUTING:
314 case SQL_SUCCESS:
316 case SQL_SUCCESS_WITH_INFO:
317 return;
318 case SQL_NO_DATA_FOUND:
319 if(_bNoFound)
320 return; // no need to throw an exception
321 break;
322 case SQL_ERROR: break;
325 case SQL_INVALID_HANDLE: SAL_WARN( "connectivity.drivers", "SdbODBC3_SetStatus: SQL_INVALID_HANDLE");
326 throw SQLException();
329 // Additional Information on the latest ODBC-functioncall available
330 // SQLError provides this Information.
332 SDB_ODBC_CHAR szSqlState[5];
333 SQLINTEGER pfNativeError;
334 SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
335 szErrorMessage[0] = '\0';
336 SQLSMALLINT pcbErrorMsg = 0;
338 // Information for latest operation:
339 // when hstmt != SQL_NULL_HSTMT is (Used from SetStatus in SdbCursor, SdbTable, ...),
340 // then the status of the latest statements will be fetched, without the Status of the last
341 // statements of this connection [what in this case will probably be the same, but the Reference
342 // Manual isn't totally clear in this...].
343 // corresponding for hdbc.
344 SQLRETURN n = (*reinterpret_cast<T3SQLGetDiagRec>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetDiagRec)))(_nHandleType,_pContext,1,
345 szSqlState,
346 &pfNativeError,
347 szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg);
348 OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE");
349 OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed");
351 rtl_TextEncoding _nTextEncoding = osl_getThreadTextEncoding();
352 // For the Return Code of SQLError see ODBC 2.0 Programmer's Reference Page 287ff
353 throw SQLException( OUString(reinterpret_cast<char *>(szErrorMessage), pcbErrorMsg, _nTextEncoding),
354 _xInterface,
355 OUString(reinterpret_cast<char *>(szSqlState), 5, _nTextEncoding),
356 pfNativeError,
357 Any()
362 Sequence<sal_Int8> OTools::getBytesValue(const OConnection* _pConnection,
363 const SQLHANDLE _aStatementHandle,
364 const sal_Int32 columnIndex,
365 const SQLSMALLINT _fSqlType,
366 bool &_bWasNull,
367 const Reference< XInterface >& _xInterface)
369 sal_Int8 aCharArray[2048];
370 // First try to fetch the data with the little Buffer:
371 const SQLLEN nMaxLen = sizeof aCharArray;
372 SQLLEN pcbValue = SQL_NO_TOTAL;
373 Sequence<sal_Int8> aData;
375 OSL_ENSURE( _fSqlType != SQL_CHAR && _fSqlType != SQL_VARCHAR && _fSqlType != SQL_LONGVARCHAR &&
376 _fSqlType != SQL_WCHAR && _fSqlType != SQL_WVARCHAR && _fSqlType != SQL_WLONGVARCHAR,
377 "connectivity::odbc::OTools::getBytesValue called with character _fSqlType");
379 while (pcbValue == SQL_NO_TOTAL || pcbValue > nMaxLen)
381 OTools::ThrowException(_pConnection,
382 (*reinterpret_cast<T3SQLGetData>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetData)))(
383 _aStatementHandle,
384 static_cast<SQLUSMALLINT>(columnIndex),
385 _fSqlType,
386 static_cast<SQLPOINTER>(aCharArray),
387 nMaxLen,
388 &pcbValue),
389 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
391 _bWasNull = pcbValue == SQL_NULL_DATA;
392 if(_bWasNull)
393 return Sequence<sal_Int8>();
395 SQLLEN nReadBytes;
396 // After the SQLGetData that wrote out to aCharArray the last byte of the data,
397 // pcbValue will not be SQL_NO_TOTAL -> we have a reliable count
398 if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxLen) )
400 // we filled the buffer
401 nReadBytes = nMaxLen;
403 else
405 nReadBytes = pcbValue;
407 const sal_Int32 nLen = aData.getLength();
408 aData.realloc(nLen + nReadBytes);
409 memcpy(aData.getArray() + nLen, aCharArray, nReadBytes);
411 return aData;
414 OUString OTools::getStringValue(OConnection const * _pConnection,
415 SQLHANDLE _aStatementHandle,
416 sal_Int32 columnIndex,
417 SQLSMALLINT _fSqlType,
418 bool &_bWasNull,
419 const Reference< XInterface >& _xInterface,
420 const rtl_TextEncoding _nTextEncoding)
422 OUStringBuffer aData;
423 switch(_fSqlType)
425 case SQL_WVARCHAR:
426 case SQL_WCHAR:
427 case SQL_WLONGVARCHAR:
429 SQLWCHAR waCharArray[2048];
430 static_assert(sizeof(waCharArray) % sizeof(SQLWCHAR) == 0, "must fit in evenly");
431 static_assert(sizeof(SQLWCHAR) == 2 || sizeof(SQLWCHAR) == 4, "must be 2 or 4");
432 // Size == number of bytes, Len == number of UTF-16 or UCS4 code units
433 const SQLLEN nMaxSize = sizeof(waCharArray);
434 const SQLLEN nMaxLen = sizeof(waCharArray) / sizeof(SQLWCHAR);
435 static_assert(nMaxLen * sizeof(SQLWCHAR) == nMaxSize, "sizes must match");
437 // read the unicode data
438 SQLLEN pcbValue = SQL_NO_TOTAL;
439 while ((pcbValue == SQL_NO_TOTAL ) || (pcbValue >= nMaxSize) )
441 OTools::ThrowException(_pConnection,
442 (*reinterpret_cast<T3SQLGetData>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetData)))(
443 _aStatementHandle,
444 static_cast<SQLUSMALLINT>(columnIndex),
445 SQL_C_WCHAR,
446 &waCharArray,
447 SQLLEN(nMaxLen)*sizeof(sal_Unicode),
448 &pcbValue),
449 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
450 _bWasNull = pcbValue == SQL_NULL_DATA;
451 if(_bWasNull)
452 return OUString();
454 SQLLEN nReadChars;
455 OSL_ENSURE( (pcbValue < 0) || (pcbValue % 2 == 0),
456 "ODBC: SQLGetData of SQL_C_WCHAR returned odd number of bytes");
457 if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxSize) )
459 // we filled the buffer; remove the terminating null character
460 nReadChars = nMaxLen-1;
461 if ( waCharArray[nReadChars] != 0)
463 SAL_WARN( "connectivity.drivers", "Buggy ODBC driver? Did not null-terminate (variable length) data!");
464 ++nReadChars;
467 else
469 nReadChars = pcbValue/sizeof(SQLWCHAR);
472 appendSQLWCHARs(aData, waCharArray, nReadChars);
474 break;
476 default:
478 char aCharArray[2048];
479 // read the unicode data
480 const SQLLEN nMaxLen = sizeof(aCharArray);
481 SQLLEN pcbValue = SQL_NO_TOTAL;
483 while ((pcbValue == SQL_NO_TOTAL ) || (pcbValue >= nMaxLen) )
485 OTools::ThrowException(_pConnection,
486 (*reinterpret_cast<T3SQLGetData>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetData)))(
487 _aStatementHandle,
488 static_cast<SQLUSMALLINT>(columnIndex),
489 SQL_C_CHAR,
490 &aCharArray,
491 nMaxLen,
492 &pcbValue),
493 _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
494 _bWasNull = pcbValue == SQL_NULL_DATA;
495 if(_bWasNull)
496 return OUString();
498 SQLLEN nReadChars;
499 if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxLen) )
501 // we filled the buffer; remove the terminating null character
502 nReadChars = nMaxLen-1;
503 if ( aCharArray[nReadChars] != 0)
505 SAL_WARN( "connectivity.drivers", "Buggy ODBC driver? Did not null-terminate (variable length) data!");
506 ++nReadChars;
509 else
511 nReadChars = pcbValue;
514 aData.append(OUString(aCharArray, nReadChars, _nTextEncoding));
517 break;
521 return aData.makeStringAndClear();
524 void OTools::GetInfo(OConnection const * _pConnection,
525 SQLHANDLE _aConnectionHandle,
526 SQLUSMALLINT _nInfo,
527 OUString &_rValue,
528 const Reference< XInterface >& _xInterface,
529 rtl_TextEncoding _nTextEncoding)
531 char aValue[512];
532 SQLSMALLINT nValueLen=0;
533 OTools::ThrowException(_pConnection,
534 (*reinterpret_cast<T3SQLGetInfo>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetInfo)))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen),
535 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
537 _rValue = OUString(aValue,nValueLen,_nTextEncoding);
540 void OTools::GetInfo(OConnection const * _pConnection,
541 SQLHANDLE _aConnectionHandle,
542 SQLUSMALLINT _nInfo,
543 sal_Int32 &_rValue,
544 const Reference< XInterface >& _xInterface)
546 SQLSMALLINT nValueLen;
547 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
548 OTools::ThrowException(_pConnection,
549 (*reinterpret_cast<T3SQLGetInfo>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetInfo)))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
550 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
553 void OTools::GetInfo(OConnection const * _pConnection,
554 SQLHANDLE _aConnectionHandle,
555 SQLUSMALLINT _nInfo,
556 SQLUINTEGER &_rValue,
557 const Reference< XInterface >& _xInterface)
559 SQLSMALLINT nValueLen;
560 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
561 OTools::ThrowException(_pConnection,
562 (*reinterpret_cast<T3SQLGetInfo>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetInfo)))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
563 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
566 void OTools::GetInfo(OConnection const * _pConnection,
567 SQLHANDLE _aConnectionHandle,
568 SQLUSMALLINT _nInfo,
569 SQLUSMALLINT &_rValue,
570 const Reference< XInterface >& _xInterface)
572 SQLSMALLINT nValueLen;
573 _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
574 OTools::ThrowException(_pConnection,
575 (*reinterpret_cast<T3SQLGetInfo>(_pConnection->getOdbcFunction(ODBC3SQLFunctionId::GetInfo)))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
576 _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
579 sal_Int32 OTools::MapOdbcType2Jdbc(SQLSMALLINT _nType)
581 sal_Int32 nValue = DataType::VARCHAR;
582 switch(_nType)
584 case SQL_BIT:
585 nValue = DataType::BIT;
586 break;
587 case SQL_TINYINT:
588 nValue = DataType::TINYINT;
589 break;
590 case SQL_SMALLINT:
591 nValue = DataType::SMALLINT;
592 break;
593 case SQL_INTEGER:
594 nValue = DataType::INTEGER;
595 break;
596 case SQL_BIGINT:
597 nValue = DataType::BIGINT;
598 break;
599 case SQL_FLOAT:
600 nValue = DataType::FLOAT;
601 break;
602 case SQL_REAL:
603 nValue = DataType::REAL;
604 break;
605 case SQL_DOUBLE:
606 nValue = DataType::DOUBLE;
607 break;
608 case SQL_NUMERIC:
609 nValue = DataType::NUMERIC;
610 break;
611 case SQL_DECIMAL:
612 nValue = DataType::DECIMAL;
613 break;
614 case SQL_WCHAR:
615 case SQL_CHAR:
616 nValue = DataType::CHAR;
617 break;
618 case SQL_WVARCHAR:
619 case SQL_VARCHAR:
620 nValue = DataType::VARCHAR;
621 break;
622 case SQL_WLONGVARCHAR:
623 case SQL_LONGVARCHAR:
624 nValue = DataType::LONGVARCHAR;
625 break;
626 case SQL_TYPE_DATE:
627 case SQL_DATE:
628 nValue = DataType::DATE;
629 break;
630 case SQL_TYPE_TIME:
631 case SQL_TIME:
632 nValue = DataType::TIME;
633 break;
634 case SQL_TYPE_TIMESTAMP:
635 case SQL_TIMESTAMP:
636 nValue = DataType::TIMESTAMP;
637 break;
638 case SQL_BINARY:
639 nValue = DataType::BINARY;
640 break;
641 case SQL_VARBINARY:
642 case SQL_GUID:
643 nValue = DataType::VARBINARY;
644 break;
645 case SQL_LONGVARBINARY:
646 nValue = DataType::LONGVARBINARY;
647 break;
648 default:
649 OSL_FAIL("Invalid type");
651 return nValue;
654 // jdbcTypeToOdbc
655 // Convert the JDBC SQL type to the correct ODBC type
657 SQLSMALLINT OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
659 // For the most part, JDBC types match ODBC types. We'll
660 // just convert the ones that we know are different
662 sal_Int32 odbcType = jdbcType;
664 switch (jdbcType)
666 case DataType::DATE:
667 odbcType = SQL_DATE;
668 break;
669 case DataType::TIME:
670 odbcType = SQL_TIME;
671 break;
672 case DataType::TIMESTAMP:
673 odbcType = SQL_TIMESTAMP;
674 break;
675 // ODBC doesn't have any notion of CLOB or BLOB
676 case DataType::CLOB:
677 odbcType = SQL_LONGVARCHAR;
678 break;
679 case DataType::BLOB:
680 odbcType = SQL_LONGVARBINARY;
681 break;
684 return odbcType;
687 void OTools::getBindTypes(bool _bUseWChar,
688 bool _bUseOldTimeDate,
689 SQLSMALLINT _nOdbcType,
690 SQLSMALLINT& fCType,
691 SQLSMALLINT& fSqlType
694 switch(_nOdbcType)
696 case SQL_CHAR: if(_bUseWChar)
698 fCType = SQL_C_WCHAR;
699 fSqlType = SQL_WCHAR;
701 else
703 fCType = SQL_C_CHAR;
704 fSqlType = SQL_CHAR;
706 break;
707 case SQL_VARCHAR: if(_bUseWChar)
709 fCType = SQL_C_WCHAR;
710 fSqlType = SQL_WVARCHAR;
712 else
714 fCType = SQL_C_CHAR;
715 fSqlType = SQL_VARCHAR;
717 break;
718 case SQL_LONGVARCHAR: if(_bUseWChar)
720 fCType = SQL_C_WCHAR;
721 fSqlType = SQL_WLONGVARCHAR;
723 else
725 fCType = SQL_C_CHAR;
726 fSqlType = SQL_LONGVARCHAR;
728 break;
729 case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
730 fSqlType = SQL_DECIMAL; break;
731 case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
732 fSqlType = SQL_NUMERIC; break;
733 case SQL_BIT: fCType = SQL_C_TINYINT;
734 fSqlType = SQL_INTEGER; break;
735 case SQL_TINYINT: fCType = SQL_C_TINYINT;
736 fSqlType = SQL_TINYINT; break;
737 case SQL_SMALLINT: fCType = SQL_C_SHORT;
738 fSqlType = SQL_SMALLINT; break;
739 case SQL_INTEGER: fCType = SQL_C_LONG;
740 fSqlType = SQL_INTEGER; break;
741 case SQL_BIGINT: fCType = SQL_C_SBIGINT;
742 fSqlType = SQL_BIGINT; break;
743 case SQL_FLOAT: fCType = SQL_C_FLOAT;
744 fSqlType = SQL_FLOAT; break;
745 case SQL_REAL: fCType = SQL_C_DOUBLE;
746 fSqlType = SQL_REAL; break;
747 case SQL_DOUBLE: fCType = SQL_C_DOUBLE;
748 fSqlType = SQL_DOUBLE; break;
749 case SQL_BINARY: fCType = SQL_C_BINARY;
750 fSqlType = SQL_BINARY; break;
751 case SQL_VARBINARY:
752 fCType = SQL_C_BINARY;
753 fSqlType = SQL_VARBINARY; break;
754 case SQL_LONGVARBINARY: fCType = SQL_C_BINARY;
755 fSqlType = SQL_LONGVARBINARY; break;
756 case SQL_DATE:
757 if(_bUseOldTimeDate)
759 fCType = SQL_C_DATE;
760 fSqlType = SQL_DATE;
762 else
764 fCType = SQL_C_TYPE_DATE;
765 fSqlType = SQL_TYPE_DATE;
767 break;
768 case SQL_TIME:
769 if(_bUseOldTimeDate)
771 fCType = SQL_C_TIME;
772 fSqlType = SQL_TIME;
774 else
776 fCType = SQL_C_TYPE_TIME;
777 fSqlType = SQL_TYPE_TIME;
779 break;
780 case SQL_TIMESTAMP:
781 if(_bUseOldTimeDate)
783 fCType = SQL_C_TIMESTAMP;
784 fSqlType = SQL_TIMESTAMP;
786 else
788 fCType = SQL_C_TYPE_TIMESTAMP;
789 fSqlType = SQL_TYPE_TIMESTAMP;
791 break;
792 default: fCType = SQL_C_BINARY;
793 fSqlType = SQL_LONGVARBINARY; break;
798 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */