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