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