Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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 "odbc/OConnection.hxx"
25 : #include "diagnose_ex.h"
26 : #include <rtl/ustrbuf.hxx>
27 : #include <boost/static_assert.hpp>
28 :
29 :
30 : #include <string.h>
31 : #include <string>
32 : #include <algorithm>
33 :
34 : using namespace connectivity::odbc;
35 : using namespace com::sun::star::uno;
36 : using namespace com::sun::star::sdbc;
37 : using namespace com::sun::star::util;
38 :
39 : namespace {
40 0 : size_t sqlTypeLen ( SQLSMALLINT _nType )
41 : {
42 0 : switch (_nType)
43 : {
44 : case SQL_C_SSHORT:
45 : case SQL_C_SHORT:
46 0 : return sizeof(SQLSMALLINT);
47 : case SQL_C_USHORT:
48 0 : return sizeof(SQLUSMALLINT);
49 : case SQL_C_SLONG:
50 : case SQL_C_LONG:
51 0 : return sizeof(SQLINTEGER);
52 : case SQL_C_ULONG:
53 0 : return sizeof(SQLUINTEGER);
54 : case SQL_C_FLOAT:
55 0 : return sizeof(SQLREAL);
56 : case SQL_C_DOUBLE:
57 : OSL_ENSURE(sizeof(SQLDOUBLE) == sizeof(SQLFLOAT), "SQLDOUBLE/SQLFLOAT confusion");
58 0 : return sizeof(SQLDOUBLE);
59 : case SQL_C_BIT:
60 0 : return sizeof(SQLCHAR);
61 : case SQL_C_STINYINT:
62 : case SQL_C_TINYINT:
63 0 : return sizeof(SQLSCHAR);
64 : case SQL_C_UTINYINT:
65 0 : return sizeof(SQLCHAR);
66 : case SQL_C_SBIGINT:
67 0 : return sizeof(SQLBIGINT);
68 : case SQL_C_UBIGINT:
69 0 : return sizeof(SQLUBIGINT);
70 : /* UnixODBC gives this the same value as SQL_C_UBIGINT
71 : case SQL_C_BOOKMARK:
72 : return sizeof(BOOKMARK); */
73 : case SQL_C_TYPE_DATE:
74 : case SQL_C_DATE:
75 0 : return sizeof(SQL_DATE_STRUCT);
76 : case SQL_C_TYPE_TIME:
77 : case SQL_C_TIME:
78 0 : return sizeof(SQL_TIME_STRUCT);
79 : case SQL_C_TYPE_TIMESTAMP:
80 : case SQL_C_TIMESTAMP:
81 0 : return sizeof(SQL_TIMESTAMP_STRUCT);
82 : case SQL_C_NUMERIC:
83 0 : return sizeof(SQL_NUMERIC_STRUCT);
84 : case SQL_C_GUID:
85 0 : return sizeof(SQLGUID);
86 : case SQL_C_INTERVAL_YEAR:
87 : case SQL_C_INTERVAL_MONTH:
88 : case SQL_C_INTERVAL_DAY:
89 : case SQL_C_INTERVAL_HOUR:
90 : case SQL_C_INTERVAL_MINUTE:
91 : case SQL_C_INTERVAL_SECOND:
92 : case SQL_C_INTERVAL_YEAR_TO_MONTH:
93 : case SQL_C_INTERVAL_DAY_TO_HOUR:
94 : case SQL_C_INTERVAL_DAY_TO_MINUTE:
95 : case SQL_C_INTERVAL_DAY_TO_SECOND:
96 : case SQL_C_INTERVAL_HOUR_TO_MINUTE:
97 : case SQL_C_INTERVAL_HOUR_TO_SECOND:
98 : case SQL_C_INTERVAL_MINUTE_TO_SECOND:
99 0 : return sizeof(SQL_INTERVAL_STRUCT);
100 : // ** Variable-sized datatypes -> cannot predict length
101 : case SQL_C_CHAR:
102 : case SQL_C_WCHAR:
103 : case SQL_C_BINARY:
104 : // UnixODBC gives this the same value as SQL_C_BINARY
105 : //case SQL_C_VARBOOKMARK:
106 : // Unknown datatype -> cannot predict length
107 : default:
108 0 : return static_cast<size_t>(-1);
109 : }
110 : }
111 : }
112 :
113 :
114 0 : void OTools::getValue( OConnection* _pConnection,
115 : SQLHANDLE _aStatementHandle,
116 : sal_Int32 columnIndex,
117 : SQLSMALLINT _nType,
118 : sal_Bool &_bWasNull,
119 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
120 : void* _pValue,
121 : SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
122 : {
123 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::getValue" );
124 0 : const size_t properSize = sqlTypeLen(_nType);
125 0 : if ( properSize == static_cast<size_t>(-1) )
126 : SAL_WARN( "connectivity.drivers", "connectivity::odbc::OTools::getValue: unknown SQL type - cannot check buffer size");
127 : else
128 : {
129 : OSL_ENSURE(static_cast<size_t>(_nSize) == properSize, "connectivity::odbc::OTools::getValue got wrongly sized memory region to write result to");
130 0 : if ( static_cast<size_t>(_nSize) > properSize )
131 : {
132 : SAL_WARN( "connectivity.drivers", "memory region is too big - trying to fudge it");
133 0 : memset(_pValue, 0, _nSize);
134 : #ifdef OSL_BIGENDIAN
135 : // This is skewed in favour of integer types
136 : _pValue += _nSize - properSize;
137 : #endif
138 : }
139 : }
140 : OSL_ENSURE(static_cast<size_t>(_nSize) >= properSize, "memory region is too small");
141 0 : SQLLEN pcbValue = SQL_NULL_DATA;
142 : OTools::ThrowException(_pConnection,
143 0 : (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
144 : (SQLUSMALLINT)columnIndex,
145 : _nType,
146 : _pValue,
147 : _nSize,
148 0 : &pcbValue),
149 0 : _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False);
150 0 : _bWasNull = pcbValue == SQL_NULL_DATA;
151 0 : }
152 :
153 0 : void OTools::bindValue( OConnection* _pConnection,
154 : SQLHANDLE _aStatementHandle,
155 : sal_Int32 columnIndex,
156 : SQLSMALLINT _nType,
157 : SQLSMALLINT _nMaxLen,
158 : const void* _pValue,
159 : void* _pData,
160 : SQLLEN * const pLen,
161 : const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
162 : rtl_TextEncoding _nTextEncoding,
163 : sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
164 : {
165 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::bindValue" );
166 : SQLRETURN nRetcode;
167 : SQLSMALLINT fSqlType;
168 : SQLSMALLINT fCType;
169 0 : SQLLEN nMaxLen = _nMaxLen;
170 :
171 : OTools::getBindTypes( sal_False,
172 : _bUseOldTimeDate,
173 : _nType,
174 : fCType,
175 0 : fSqlType);
176 :
177 0 : if (columnIndex != 0 && !_pValue)
178 : {
179 0 : *pLen = SQL_NULL_DATA;
180 0 : nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
181 : (SQLUSMALLINT)columnIndex,
182 : fCType,
183 : _pData,
184 : nMaxLen,
185 : pLen
186 0 : );
187 : }
188 : else
189 : {
190 : try
191 : {
192 0 : switch (_nType)
193 : {
194 : case SQL_CHAR:
195 : case SQL_VARCHAR:
196 : {
197 0 : OString aString(OUStringToOString(*(OUString*)_pValue,_nTextEncoding));
198 0 : *pLen = SQL_NTS;
199 0 : *((OString*)_pData) = aString;
200 0 : _nMaxLen = (SQLSMALLINT)aString.getLength();
201 :
202 : // Pointer on Char*
203 0 : _pData = (void*)aString.getStr();
204 0 : } break;
205 : case SQL_BIGINT:
206 0 : *((sal_Int64*)_pData) = *(sal_Int64*)_pValue;
207 0 : *pLen = sizeof(sal_Int64);
208 0 : break;
209 : case SQL_DECIMAL:
210 : case SQL_NUMERIC:
211 : {
212 0 : OString aString = OString::number(*(double*)_pValue);
213 0 : _nMaxLen = (SQLSMALLINT)aString.getLength();
214 0 : *pLen = _nMaxLen;
215 0 : *((OString*)_pData) = aString;
216 : // Pointer on Char*
217 0 : _pData = (void*)((OString*)_pData)->getStr();
218 0 : } break;
219 : case SQL_BIT:
220 : case SQL_TINYINT:
221 0 : *((sal_Int8*)_pData) = *(sal_Int8*)_pValue;
222 0 : *pLen = sizeof(sal_Int8);
223 0 : break;
224 :
225 : case SQL_SMALLINT:
226 0 : *((sal_Int16*)_pData) = *(sal_Int16*)_pValue;
227 0 : *pLen = sizeof(sal_Int16);
228 0 : break;
229 : case SQL_INTEGER:
230 0 : *((sal_Int32*)_pData) = *(sal_Int32*)_pValue;
231 0 : *pLen = sizeof(sal_Int32);
232 0 : break;
233 : case SQL_FLOAT:
234 0 : *((float*)_pData) = *(float*)_pValue;
235 0 : *pLen = sizeof(float);
236 0 : break;
237 : case SQL_REAL:
238 : case SQL_DOUBLE:
239 0 : *((double*)_pData) = *(double*)_pValue;
240 0 : *pLen = sizeof(double);
241 0 : break;
242 : case SQL_BINARY:
243 : case SQL_VARBINARY:
244 : {
245 0 : _pData = (void*)((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getConstArray();
246 0 : *pLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
247 0 : } break;
248 : case SQL_LONGVARBINARY:
249 : {
250 0 : _pData = (void*)(sal_IntPtr)(columnIndex);
251 0 : sal_Int32 nLen = 0;
252 0 : nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
253 0 : *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
254 : }
255 0 : break;
256 : case SQL_LONGVARCHAR:
257 : {
258 0 : _pData = (void*)(sal_IntPtr)(columnIndex);
259 0 : sal_Int32 nLen = 0;
260 0 : nLen = ((OUString*)_pValue)->getLength();
261 0 : *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
262 0 : } break;
263 : case SQL_DATE:
264 0 : *pLen = sizeof(DATE_STRUCT);
265 0 : *((DATE_STRUCT*)_pData) = *(DATE_STRUCT*)_pValue;
266 0 : break;
267 : case SQL_TIME:
268 0 : *pLen = sizeof(TIME_STRUCT);
269 0 : *((TIME_STRUCT*)_pData) = *(TIME_STRUCT*)_pValue;
270 0 : break;
271 : case SQL_TIMESTAMP:
272 0 : *pLen = sizeof(TIMESTAMP_STRUCT);
273 0 : *((TIMESTAMP_STRUCT*)_pData) = *(TIMESTAMP_STRUCT*)_pValue;
274 0 : break;
275 : }
276 : }
277 0 : catch ( ... )
278 : {
279 : }
280 :
281 0 : nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
282 : (SQLUSMALLINT)columnIndex,
283 : fCType,
284 : _pData,
285 : nMaxLen,
286 : pLen
287 0 : );
288 : }
289 :
290 0 : OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
291 0 : }
292 :
293 0 : void OTools::ThrowException(const OConnection* _pConnection,
294 : const SQLRETURN _rRetCode,
295 : const SQLHANDLE _pContext,
296 : const SQLSMALLINT _nHandleType,
297 : const Reference< XInterface >& _xInterface,
298 : const sal_Bool _bNoFound,
299 : const rtl_TextEncoding _nTextEncoding) throw(SQLException)
300 : {
301 0 : switch(_rRetCode)
302 : {
303 : case SQL_NEED_DATA:
304 : case SQL_STILL_EXECUTING:
305 : case SQL_SUCCESS:
306 :
307 : case SQL_SUCCESS_WITH_INFO:
308 0 : return;
309 : case SQL_NO_DATA_FOUND:
310 0 : if(_bNoFound)
311 0 : return; // no need to throw a exception
312 0 : case SQL_ERROR: break;
313 :
314 :
315 : case SQL_INVALID_HANDLE: SAL_WARN( "connectivity.drivers", "SdbODBC3_SetStatus: SQL_INVALID_HANDLE");
316 0 : throw SQLException();
317 : }
318 :
319 : // Additional Information on the latest ODBC-functioncall available
320 : // SQLError provides this Information.
321 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::ThrowException" );
322 :
323 : SDB_ODBC_CHAR szSqlState[5];
324 : SQLINTEGER pfNativeError;
325 : SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
326 0 : szErrorMessage[0] = '\0';
327 0 : SQLSMALLINT pcbErrorMsg = 0;
328 :
329 : // Information for latest operation:
330 : // when hstmt != SQL_NULL_HSTMT is (Used from SetStatus in SdbCursor, SdbTable, ...),
331 : // then the status of the latest statements will be fetched, without the Status of the last
332 : // statements of this connection [what in this case will probably be the same, but the Reference
333 : // Manual isn't totally clear in this...].
334 : // corresponding for hdbc.
335 0 : SQLRETURN n = (*(T3SQLGetDiagRec)_pConnection->getOdbcFunction(ODBC3SQLGetDiagRec))(_nHandleType,_pContext,1,
336 : szSqlState,
337 : &pfNativeError,
338 0 : szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg);
339 : OSL_UNUSED( n );
340 : OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE");
341 : OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed");
342 :
343 : // For the Return Code of SQLError see ODBC 2.0 Programmer's Reference Page 287ff
344 : throw SQLException( OUString((char *)szErrorMessage,pcbErrorMsg,_nTextEncoding),
345 : _xInterface,
346 : OUString((char *)szSqlState,5,_nTextEncoding),
347 : pfNativeError,
348 : Any()
349 0 : );
350 :
351 : }
352 :
353 0 : Sequence<sal_Int8> OTools::getBytesValue(const OConnection* _pConnection,
354 : const SQLHANDLE _aStatementHandle,
355 : const sal_Int32 columnIndex,
356 : const SQLSMALLINT _fSqlType,
357 : sal_Bool &_bWasNull,
358 : const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
359 : {
360 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::getBytesValue" );
361 : sal_Int8 aCharArray[2048];
362 : // First try to fetch the data with the little Buffer:
363 0 : const SQLLEN nMaxLen = sizeof aCharArray;
364 0 : SQLLEN pcbValue = SQL_NO_TOTAL;
365 0 : Sequence<sal_Int8> aData;
366 :
367 : OSL_ENSURE( _fSqlType != SQL_CHAR && _fSqlType != SQL_VARCHAR && _fSqlType != SQL_LONGVARCHAR &&
368 : _fSqlType != SQL_WCHAR && _fSqlType != SQL_WVARCHAR && _fSqlType != SQL_WLONGVARCHAR,
369 : "connectivity::odbc::OTools::getBytesValue called with character _fSqlType");
370 :
371 0 : while (pcbValue == SQL_NO_TOTAL || pcbValue > nMaxLen)
372 : {
373 : OTools::ThrowException(_pConnection,
374 0 : (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(
375 : _aStatementHandle,
376 : (SQLUSMALLINT)columnIndex,
377 : _fSqlType,
378 : (SQLPOINTER)aCharArray,
379 : nMaxLen,
380 0 : &pcbValue),
381 0 : _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
382 :
383 0 : _bWasNull = pcbValue == SQL_NULL_DATA;
384 0 : if(_bWasNull)
385 0 : return Sequence<sal_Int8>();
386 :
387 : SQLLEN nReadBytes;
388 : // After the SQLGetData that wrote out to aCharArray the last byte of the data,
389 : // pcbValue will not be SQL_NO_TOTAL -> we have a reliable count
390 0 : if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxLen) )
391 : {
392 : // we filled the buffer
393 0 : nReadBytes = nMaxLen;
394 : }
395 : else
396 : {
397 0 : nReadBytes = pcbValue;
398 : }
399 0 : const sal_Int32 nLen = aData.getLength();
400 0 : aData.realloc(nLen + nReadBytes);
401 0 : memcpy(aData.getArray() + nLen, aCharArray, nReadBytes);
402 : }
403 0 : return aData;
404 : }
405 :
406 0 : OUString OTools::getStringValue(OConnection* _pConnection,
407 : SQLHANDLE _aStatementHandle,
408 : sal_Int32 columnIndex,
409 : SQLSMALLINT _fSqlType,
410 : sal_Bool &_bWasNull,
411 : const Reference< XInterface >& _xInterface,
412 : rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
413 : {
414 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::getStringValue" );
415 0 : OUStringBuffer aData;
416 0 : switch(_fSqlType)
417 : {
418 : case SQL_WVARCHAR:
419 : case SQL_WCHAR:
420 : case SQL_WLONGVARCHAR:
421 : {
422 : sal_Unicode waCharArray[2048];
423 : // we assume everyone (LibO & ODBC) uses UTF-16; see OPreparedStatement::setParameter
424 : BOOST_STATIC_ASSERT(sizeof(sal_Unicode) == 2);
425 : BOOST_STATIC_ASSERT(sizeof(SQLWCHAR) == 2);
426 : BOOST_STATIC_ASSERT(sizeof(waCharArray) % 2 == 0);
427 : // Size == number of bytes, Len == number of UTF-16 code units
428 0 : const SQLLEN nMaxSize = sizeof(waCharArray);
429 0 : const SQLLEN nMaxLen = sizeof(waCharArray) / sizeof(sal_Unicode);
430 : BOOST_STATIC_ASSERT(nMaxLen * sizeof(sal_Unicode) == nMaxSize);
431 :
432 : // read the unicode data
433 0 : SQLLEN pcbValue = SQL_NO_TOTAL;
434 0 : while ((pcbValue == SQL_NO_TOTAL ) || (pcbValue >= nMaxSize) )
435 : {
436 : OTools::ThrowException(_pConnection,
437 0 : (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(
438 : _aStatementHandle,
439 : (SQLUSMALLINT)columnIndex,
440 : SQL_C_WCHAR,
441 : &waCharArray,
442 : (SQLLEN)nMaxLen*sizeof(sal_Unicode),
443 0 : &pcbValue),
444 0 : _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
445 0 : _bWasNull = pcbValue == SQL_NULL_DATA;
446 0 : if(_bWasNull)
447 0 : return OUString();
448 :
449 : SQLLEN nReadChars;
450 : OSL_ENSURE( (pcbValue < 0) || (pcbValue % 2 == 0),
451 : "ODBC: SQLGetData of SQL_C_WCHAR returned odd number of bytes");
452 0 : if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxSize) )
453 : {
454 : // we filled the buffer; remove the terminating null character
455 0 : nReadChars = nMaxLen-1;
456 0 : if ( waCharArray[nReadChars] != 0)
457 : {
458 : SAL_WARN( "connectivity.drivers", "Buggy ODBC driver? Did not null-terminate (variable length) data!");
459 0 : ++nReadChars;
460 0 : }
461 : }
462 : else
463 : {
464 0 : nReadChars = pcbValue/sizeof(sal_Unicode);
465 : }
466 :
467 0 : aData.append(waCharArray, nReadChars);
468 :
469 : }
470 0 : break;
471 : }
472 : default:
473 : {
474 : char aCharArray[2048];
475 : // read the unicode data
476 0 : const SQLLEN nMaxLen = sizeof(aCharArray);
477 0 : SQLLEN pcbValue = SQL_NO_TOTAL;
478 :
479 0 : while ((pcbValue == SQL_NO_TOTAL ) || (pcbValue >= nMaxLen) )
480 : {
481 : OTools::ThrowException(_pConnection,
482 0 : (*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(
483 : _aStatementHandle,
484 : (SQLUSMALLINT)columnIndex,
485 : SQL_C_CHAR,
486 : &aCharArray,
487 : nMaxLen,
488 0 : &pcbValue),
489 0 : _aStatementHandle,SQL_HANDLE_STMT,_xInterface);
490 0 : _bWasNull = pcbValue == SQL_NULL_DATA;
491 0 : if(_bWasNull)
492 0 : return OUString();
493 :
494 : SQLLEN nReadChars;
495 0 : if ( (pcbValue == SQL_NO_TOTAL) || (pcbValue >= nMaxLen) )
496 : {
497 : // we filled the buffer; remove the terminating null character
498 0 : nReadChars = nMaxLen-1;
499 0 : if ( aCharArray[nReadChars] != 0)
500 : {
501 : SAL_WARN( "connectivity.drivers", "Buggy ODBC driver? Did not null-terminate (variable length) data!");
502 0 : ++nReadChars;
503 0 : }
504 : }
505 : else
506 : {
507 0 : nReadChars = pcbValue;
508 : }
509 :
510 0 : aData.append(OUString(aCharArray, nReadChars, _nTextEncoding));
511 :
512 : }
513 0 : break;
514 : }
515 : }
516 :
517 0 : return aData.makeStringAndClear();
518 : }
519 :
520 0 : void OTools::GetInfo(OConnection* _pConnection,
521 : SQLHANDLE _aConnectionHandle,
522 : SQLUSMALLINT _nInfo,
523 : OUString &_rValue,
524 : const Reference< XInterface >& _xInterface,
525 : rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
526 : {
527 : char aValue[512];
528 0 : SQLSMALLINT nValueLen=0;
529 : OTools::ThrowException(_pConnection,
530 0 : (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen),
531 0 : _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
532 :
533 0 : _rValue = OUString(aValue,nValueLen,_nTextEncoding);
534 0 : }
535 :
536 0 : void OTools::GetInfo(OConnection* _pConnection,
537 : SQLHANDLE _aConnectionHandle,
538 : SQLUSMALLINT _nInfo,
539 : sal_Int32 &_rValue,
540 : const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
541 : {
542 : SQLSMALLINT nValueLen;
543 0 : _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
544 : OTools::ThrowException(_pConnection,
545 0 : (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
546 0 : _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
547 0 : }
548 :
549 0 : void OTools::GetInfo(OConnection* _pConnection,
550 : SQLHANDLE _aConnectionHandle,
551 : SQLUSMALLINT _nInfo,
552 : SQLUINTEGER &_rValue,
553 : const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
554 : {
555 : SQLSMALLINT nValueLen;
556 0 : _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
557 : OTools::ThrowException(_pConnection,
558 0 : (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
559 0 : _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
560 0 : }
561 :
562 0 : void OTools::GetInfo(OConnection* _pConnection,
563 : SQLHANDLE _aConnectionHandle,
564 : SQLUSMALLINT _nInfo,
565 : SQLUSMALLINT &_rValue,
566 : const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
567 : {
568 : SQLSMALLINT nValueLen;
569 0 : _rValue = 0; // in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
570 : OTools::ThrowException(_pConnection,
571 0 : (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
572 0 : _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
573 0 : }
574 :
575 0 : void OTools::GetInfo(OConnection* _pConnection,
576 : SQLHANDLE _aConnectionHandle,
577 : SQLUSMALLINT _nInfo,
578 : sal_Bool &_rValue,
579 : const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
580 : {
581 : SQLSMALLINT nValueLen;
582 : OTools::ThrowException(_pConnection,
583 0 : (*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
584 0 : _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
585 0 : }
586 :
587 0 : sal_Int32 OTools::MapOdbcType2Jdbc(SQLSMALLINT _nType)
588 : {
589 0 : sal_Int32 nValue = DataType::VARCHAR;
590 0 : switch(_nType)
591 : {
592 : case SQL_BIT:
593 0 : nValue = DataType::BIT;
594 0 : break;
595 : case SQL_TINYINT:
596 0 : nValue = DataType::TINYINT;
597 0 : break;
598 : case SQL_SMALLINT:
599 0 : nValue = DataType::SMALLINT;
600 0 : break;
601 : case SQL_INTEGER:
602 0 : nValue = DataType::INTEGER;
603 0 : break;
604 : case SQL_BIGINT:
605 0 : nValue = DataType::BIGINT;
606 0 : break;
607 : case SQL_FLOAT:
608 0 : nValue = DataType::FLOAT;
609 0 : break;
610 : case SQL_REAL:
611 0 : nValue = DataType::REAL;
612 0 : break;
613 : case SQL_DOUBLE:
614 0 : nValue = DataType::DOUBLE;
615 0 : break;
616 : case SQL_NUMERIC:
617 0 : nValue = DataType::NUMERIC;
618 0 : break;
619 : case SQL_DECIMAL:
620 0 : nValue = DataType::DECIMAL;
621 0 : break;
622 : case SQL_WCHAR:
623 : case SQL_CHAR:
624 0 : nValue = DataType::CHAR;
625 0 : break;
626 : case SQL_WVARCHAR:
627 : case SQL_VARCHAR:
628 0 : nValue = DataType::VARCHAR;
629 0 : break;
630 : case SQL_WLONGVARCHAR:
631 : case SQL_LONGVARCHAR:
632 0 : nValue = DataType::LONGVARCHAR;
633 0 : break;
634 : case SQL_TYPE_DATE:
635 : case SQL_DATE:
636 0 : nValue = DataType::DATE;
637 0 : break;
638 : case SQL_TYPE_TIME:
639 : case SQL_TIME:
640 0 : nValue = DataType::TIME;
641 0 : break;
642 : case SQL_TYPE_TIMESTAMP:
643 : case SQL_TIMESTAMP:
644 0 : nValue = DataType::TIMESTAMP;
645 0 : break;
646 : case SQL_BINARY:
647 0 : nValue = DataType::BINARY;
648 0 : break;
649 : case SQL_VARBINARY:
650 : case SQL_GUID:
651 0 : nValue = DataType::VARBINARY;
652 0 : break;
653 : case SQL_LONGVARBINARY:
654 0 : nValue = DataType::LONGVARBINARY;
655 0 : break;
656 : default:
657 : OSL_FAIL("Invalid type");
658 : }
659 0 : return nValue;
660 : }
661 :
662 : // jdbcTypeToOdbc
663 : // Convert the JDBC SQL type to the correct ODBC type
664 :
665 0 : SQLSMALLINT OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
666 : {
667 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::jdbcTypeToOdbc" );
668 : // For the most part, JDBC types match ODBC types. We'll
669 : // just convert the ones that we know are different
670 :
671 0 : sal_Int32 odbcType = jdbcType;
672 :
673 0 : switch (jdbcType)
674 : {
675 : case DataType::DATE:
676 0 : odbcType = SQL_DATE;
677 0 : break;
678 : case DataType::TIME:
679 0 : odbcType = SQL_TIME;
680 0 : break;
681 : case DataType::TIMESTAMP:
682 0 : odbcType = SQL_TIMESTAMP;
683 0 : break;
684 : // ODBC doesn't have any notion of CLOB or BLOB
685 : case DataType::CLOB:
686 0 : odbcType = SQL_LONGVARCHAR;
687 0 : break;
688 : case DataType::BLOB:
689 0 : odbcType = SQL_LONGVARBINARY;
690 0 : break;
691 : }
692 :
693 0 : return odbcType;
694 : }
695 :
696 0 : void OTools::getBindTypes(sal_Bool _bUseWChar,
697 : sal_Bool _bUseOldTimeDate,
698 : SQLSMALLINT _nOdbcType,
699 : SQLSMALLINT& fCType,
700 : SQLSMALLINT& fSqlType
701 : )
702 : {
703 : SAL_INFO( "connectivity.drivers", "odbc Ocke.Janssen@sun.com OTools::getBindTypes" );
704 0 : switch(_nOdbcType)
705 : {
706 0 : case SQL_CHAR: if(_bUseWChar)
707 : {
708 0 : fCType = SQL_C_WCHAR;
709 0 : fSqlType = SQL_WCHAR;
710 : }
711 : else
712 : {
713 0 : fCType = SQL_C_CHAR;
714 0 : fSqlType = SQL_CHAR;
715 : }
716 0 : break;
717 0 : case SQL_VARCHAR: if(_bUseWChar)
718 : {
719 0 : fCType = SQL_C_WCHAR;
720 0 : fSqlType = SQL_WVARCHAR;
721 : }
722 : else
723 : {
724 0 : fCType = SQL_C_CHAR;
725 0 : fSqlType = SQL_VARCHAR;
726 : }
727 0 : break;
728 0 : case SQL_LONGVARCHAR: if(_bUseWChar)
729 : {
730 0 : fCType = SQL_C_WCHAR;
731 0 : fSqlType = SQL_WLONGVARCHAR;
732 : }
733 : else
734 : {
735 0 : fCType = SQL_C_CHAR;
736 0 : fSqlType = SQL_LONGVARCHAR;
737 : }
738 0 : break;
739 0 : case SQL_DECIMAL: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
740 0 : fSqlType = SQL_DECIMAL; break;
741 0 : case SQL_NUMERIC: fCType = _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
742 0 : fSqlType = SQL_NUMERIC; break;
743 0 : case SQL_BIT: fCType = SQL_C_TINYINT;
744 0 : fSqlType = SQL_INTEGER; break;
745 0 : case SQL_TINYINT: fCType = SQL_C_TINYINT;
746 0 : fSqlType = SQL_TINYINT; break;
747 0 : case SQL_SMALLINT: fCType = SQL_C_SHORT;
748 0 : fSqlType = SQL_SMALLINT; break;
749 0 : case SQL_INTEGER: fCType = SQL_C_LONG;
750 0 : fSqlType = SQL_INTEGER; break;
751 0 : case SQL_BIGINT: fCType = SQL_C_SBIGINT;
752 0 : fSqlType = SQL_BIGINT; break;
753 0 : case SQL_FLOAT: fCType = SQL_C_FLOAT;
754 0 : fSqlType = SQL_FLOAT; break;
755 0 : case SQL_REAL: fCType = SQL_C_DOUBLE;
756 0 : fSqlType = SQL_REAL; break;
757 0 : case SQL_DOUBLE: fCType = SQL_C_DOUBLE;
758 0 : fSqlType = SQL_DOUBLE; break;
759 0 : case SQL_BINARY: fCType = SQL_C_BINARY;
760 0 : fSqlType = SQL_BINARY; break;
761 : case SQL_VARBINARY:
762 0 : fCType = SQL_C_BINARY;
763 0 : fSqlType = SQL_VARBINARY; break;
764 0 : case SQL_LONGVARBINARY: fCType = SQL_C_BINARY;
765 0 : fSqlType = SQL_LONGVARBINARY; break;
766 : case SQL_DATE:
767 0 : if(_bUseOldTimeDate)
768 : {
769 0 : fCType = SQL_C_DATE;
770 0 : fSqlType = SQL_DATE;
771 : }
772 : else
773 : {
774 0 : fCType = SQL_C_TYPE_DATE;
775 0 : fSqlType = SQL_TYPE_DATE;
776 : }
777 0 : break;
778 : case SQL_TIME:
779 0 : if(_bUseOldTimeDate)
780 : {
781 0 : fCType = SQL_C_TIME;
782 0 : fSqlType = SQL_TIME;
783 : }
784 : else
785 : {
786 0 : fCType = SQL_C_TYPE_TIME;
787 0 : fSqlType = SQL_TYPE_TIME;
788 : }
789 0 : break;
790 : case SQL_TIMESTAMP:
791 0 : if(_bUseOldTimeDate)
792 : {
793 0 : fCType = SQL_C_TIMESTAMP;
794 0 : fSqlType = SQL_TIMESTAMP;
795 : }
796 : else
797 : {
798 0 : fCType = SQL_C_TYPE_TIMESTAMP;
799 0 : fSqlType = SQL_TYPE_TIMESTAMP;
800 : }
801 0 : break;
802 0 : default: fCType = SQL_C_BINARY;
803 0 : fSqlType = SQL_LONGVARBINARY; break;
804 : }
805 0 : }
806 :
807 :
808 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|