1 /************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include "odbc/OTools.hxx"
31 #include "odbc/OFunctions.hxx"
32 #include <com/sun/star/sdbc/DataType.hpp>
33 #include <osl/diagnose.h>
34 #include "odbc/OConnection.hxx"
35 #include "diagnose_ex.h"
36 #include <rtl/logfile.hxx>
37 #include <rtl/ustrbuf.hxx>
38 
39 
40 #include <string.h>
41 #include <string>
42 #include <algorithm>
43 
44 using namespace connectivity::odbc;
45 using namespace com::sun::star::uno;
46 using namespace com::sun::star::sdbc;
47 using namespace com::sun::star::util;
48 
49 void OTools::getValue(	OConnection* _pConnection,
50 						SQLHANDLE _aStatementHandle,
51 						sal_Int32 columnIndex,
52 						SQLSMALLINT _nType,
53 						sal_Bool &_bWasNull,
54 						const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
55 						void* _pValue,
56 						SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
57 {
58     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getValue" );
59 	SQLLEN pcbValue = SQL_NULL_DATA;
60 	OTools::ThrowException(_pConnection,
61 							(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
62 										(SQLUSMALLINT)columnIndex,
63 										_nType,
64 										_pValue,
65 										_nSize,
66 										&pcbValue),
67 							_aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False);
68 	_bWasNull = pcbValue == SQL_NULL_DATA;
69 }
70 // -----------------------------------------------------------------------------
71 void OTools::bindParameter(	OConnection* _pConnection,
72 							SQLHANDLE _hStmt,
73 							sal_Int32 nPos,
74 							sal_Int8*& pDataBuffer,
75 							sal_Int8* pLenBuffer,
76 							SQLSMALLINT _nODBCtype,
77 							sal_Bool _bUseWChar,
78 							sal_Bool _bUseOldTimeDate,
79 							const void* _pValue,
80 							const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
81 							rtl_TextEncoding _nTextEncoding)
82 							 throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
83 {
84     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindParameter" );
85 	SQLRETURN nRetcode;
86 	SQLSMALLINT fSqlType;
87 	SQLSMALLINT fCType;
88 	SQLLEN  nMaxLen = 0;
89 	//	void*&   pData   = pDataBuffer;
90 	SQLLEN* pLen    = (SQLLEN*)pLenBuffer;
91 	SQLULEN nColumnSize=0;
92 	SQLSMALLINT	nDecimalDigits=0;
93 
94 	OTools::getBindTypes(_bUseWChar,_bUseOldTimeDate,_nODBCtype,fCType,fSqlType);
95 
96 	OTools::bindData(_nODBCtype,_bUseWChar,pDataBuffer,pLen,_pValue,_nTextEncoding,nColumnSize);
97 	if ((nColumnSize == 0) && (fSqlType == SQL_CHAR || fSqlType == SQL_VARCHAR || fSqlType == SQL_LONGVARCHAR))
98 		nColumnSize = 1;
99 
100 	if(fSqlType == SQL_LONGVARCHAR || fSqlType == SQL_LONGVARBINARY)
101 		memcpy(pDataBuffer,&nPos,sizeof(nPos));
102 
103 	// 20.09.2001 OJ: Problems with mysql. mysql returns only CHAR as parameter type
104 	//	nRetcode = (*(T3SQLDescribeParam)_pConnection->getOdbcFunction(ODBC3SQLDescribeParam))(_hStmt,(SQLUSMALLINT)nPos,&fSqlType,&nColumnSize,&nDecimalDigits,&nNullable);
105 
106 	nRetcode = (*(T3SQLBindParameter)_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(_hStmt,
107 				  (SQLUSMALLINT)nPos,
108 				  SQL_PARAM_INPUT,
109 				  fCType,
110 				  fSqlType,
111 				  nColumnSize,
112 				  nDecimalDigits,
113 				  pDataBuffer,
114 				  nMaxLen,
115 				  pLen);
116 
117 	OTools::ThrowException(_pConnection,nRetcode,_hStmt,SQL_HANDLE_STMT,_xInterface);
118 }
119 // -----------------------------------------------------------------------------
120 void OTools::bindData(	SQLSMALLINT _nOdbcType,
121 						sal_Bool _bUseWChar,
122 						sal_Int8 *&_pData,
123 						SQLLEN*& pLen,
124 						const void* _pValue,
125 						rtl_TextEncoding _nTextEncoding,
126 						SQLULEN& _nColumnSize)
127 {
128     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindData" );
129 	_nColumnSize = 0;
130 
131 	switch (_nOdbcType)
132 	{
133 		case SQL_CHAR:
134 		case SQL_VARCHAR:
135 		case SQL_DECIMAL:
136 			if(_bUseWChar)
137 			{
138 				*pLen = SQL_NTS;
139 				::rtl::OUString sStr(*(::rtl::OUString*)_pValue);
140 				_nColumnSize = sStr.getLength();
141 				*((rtl::OUString*)_pData) = sStr;
142 
143 				// Zeiger auf Char*
144 				_pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr();
145 			}
146 			else
147 			{
148 				::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
149 				*pLen = SQL_NTS;
150 				_nColumnSize = aString.getLength();
151                 memcpy(_pData,aString.getStr(),aString.getLength());
152 				((sal_Int8*)_pData)[aString.getLength()] = '\0';
153 			}
154 			break;
155 
156 		case SQL_BIGINT:
157 			*((sal_Int64*)_pData) = *(sal_Int64*)_pValue;
158 			*pLen = sizeof(sal_Int64);
159 			_nColumnSize = *pLen;
160 			break;
161 
162 		case SQL_NUMERIC:
163 			if(_bUseWChar)
164 			{
165 				::rtl::OUString aString = rtl::OUString::valueOf(*(double*)_pValue);
166 				_nColumnSize = aString.getLength();
167 				*pLen = _nColumnSize;
168 				*((rtl::OUString*)_pData) = aString;
169 				// Zeiger auf Char*
170 				_pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr();
171 			}
172 			else
173 			{
174 				::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue);
175 				_nColumnSize = aString.getLength();
176 				*pLen = _nColumnSize;
177                 memcpy(_pData,aString.getStr(),aString.getLength());
178 				((sal_Int8*)_pData)[_nColumnSize] = '\0';
179 			}	break;
180 		case SQL_BIT:
181 		case SQL_TINYINT:
182 			*((sal_Int8*)_pData) = *(sal_Int8*)_pValue;
183 			*pLen = sizeof(sal_Int8);
184 			break;
185 
186 		case SQL_SMALLINT:
187 			*((sal_Int16*)_pData) = *(sal_Int16*)_pValue;
188 			*pLen = sizeof(sal_Int16);
189 			break;
190 		case SQL_INTEGER:
191 			*((sal_Int32*)_pData) = *(sal_Int32*)_pValue;
192 			*pLen = sizeof(sal_Int32);
193 			break;
194 		case SQL_FLOAT:
195 			*((float*)_pData) = *(float*)_pValue;
196 			*pLen = sizeof(float);
197 			break;
198 		case SQL_REAL:
199 		case SQL_DOUBLE:
200 			*((double*)_pData) = *(double*)_pValue;
201 			*pLen = sizeof(double);
202 			break;
203 		case SQL_BINARY:
204 		case SQL_VARBINARY:
205 			{
206 				const ::com::sun::star::uno::Sequence< sal_Int8 >* pSeq = static_cast< const ::com::sun::star::uno::Sequence< sal_Int8 >* >(_pValue);
207 				OSL_ENSURE(pSeq,"OTools::bindData: Sequence is null!");
208 
209 				if(pSeq)
210 				{
211 					_pData = (sal_Int8*)pSeq->getConstArray();
212 					*pLen = pSeq->getLength();
213 				}
214 			}
215 			break;
216 		case SQL_LONGVARBINARY:
217 			{
218 				sal_Int32 nLen = 0;
219                 nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
220 				*pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
221 			}
222 			break;
223 		case SQL_LONGVARCHAR:
224 		{
225 			sal_Int32 nLen = 0;
226 			if(_bUseWChar)
227 				nLen = sizeof(sal_Unicode) * ((::rtl::OUString*)_pValue)->getLength();
228 			else
229 			{
230 				::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
231 				nLen = aString.getLength();
232 			}
233 			*pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
234 		}   break;
235 		case SQL_DATE:
236 			*(DATE_STRUCT*)_pData = *(DATE_STRUCT*)_pValue;
237 			*pLen = (SQLLEN)sizeof(DATE_STRUCT);
238 			_nColumnSize = 10;
239 			break;
240 		case SQL_TIME:
241 			*(TIME_STRUCT*)_pData = *(TIME_STRUCT*)_pValue;
242 			*pLen = (SQLLEN)sizeof(TIME_STRUCT);
243 			_nColumnSize = 8;
244 			break;
245 		case SQL_TIMESTAMP:
246 			*(TIMESTAMP_STRUCT*)_pData = *(TIMESTAMP_STRUCT*)_pValue;
247 			*pLen = (SQLLEN)sizeof(TIMESTAMP_STRUCT);
248 			_nColumnSize = 19;
249 			break;
250 	}
251 }
252 // -------------------------------------------------------------------------
253 void OTools::bindValue(	OConnection* _pConnection,
254 						SQLHANDLE _aStatementHandle,
255 						sal_Int32 columnIndex,
256 						SQLSMALLINT _nType,
257 						SQLSMALLINT _nMaxLen,
258 						const void* _pValue,
259 						void* _pData,
260 						SQLLEN *pLen,
261 						const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
262 						rtl_TextEncoding _nTextEncoding,
263 						sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
264 {
265     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindValue" );
266 	SQLRETURN nRetcode;
267 	SQLSMALLINT   fSqlType;
268 	SQLSMALLINT   fCType;
269 	SQLLEN nMaxLen = _nMaxLen;
270 
271 	OTools::getBindTypes(	sal_False,
272 							_bUseOldTimeDate,
273 							_nType,
274 							fCType,
275 							fSqlType);
276 
277 	if (columnIndex != 0 && !_pValue)
278 	{
279 		*pLen = SQL_NULL_DATA;
280 		nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
281 								(SQLUSMALLINT)columnIndex,
282 								fCType,
283 								_pData,
284 								nMaxLen,
285 								pLen
286 								);
287 	}
288 	else
289 	{
290 		try
291 		{
292 			switch (_nType)
293 			{
294 				case SQL_CHAR:
295 				case SQL_VARCHAR:
296 				//if(GetODBCConnection()->m_bUserWChar)
297 //				{
298 //					_nMaxLen = rCol.GetPrecision();
299 //					*pLen = SQL_NTS;
300 //					*((rtl::OUString*)pData) = (rtl::OUString)_aValue;
301 //
302 //					// Zeiger auf Char*
303 //					pData = (void*)((rtl::OUString*)pData)->getStr();
304 //				}
305 //				else
306 				{
307 					::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding));
308 					*pLen = SQL_NTS;
309 					*((::rtl::OString*)_pData) = aString;
310 					_nMaxLen = (SQLSMALLINT)aString.getLength();
311 
312 					// Zeiger auf Char*
313 					_pData = (void*)aString.getStr();
314 				}	break;
315 				case SQL_BIGINT:
316 					*((sal_Int64*)_pData) = *(sal_Int64*)_pValue;
317 					*pLen = sizeof(sal_Int64);
318 					break;
319 				case SQL_DECIMAL:
320 				case SQL_NUMERIC:
321 				//if(GetODBCConnection()->m_bUserWChar)
322 //				{
323 //					rtl::OUString aString(rtl::OUString(SdbTools::ToString(ODbTypeConversion::toDouble(*pVariable),rCol.GetScale())));
324 //					*pLen = _nMaxLen;
325 //					*((rtl::OUString*)_pData) = aString;
326 //					// Zeiger auf Char*
327 //					_pData = (void*)((rtl::OUString*)_pData)->getStr();
328 //				}
329 //				else
330 				{
331 					::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue);
332 					_nMaxLen = (SQLSMALLINT)aString.getLength();
333 					*pLen = _nMaxLen;
334 					*((::rtl::OString*)_pData) = aString;
335 					// Zeiger auf Char*
336 					_pData = (void*)((::rtl::OString*)_pData)->getStr();
337 				}	break;
338 				case SQL_BIT:
339 				case SQL_TINYINT:
340 					*((sal_Int8*)_pData) = *(sal_Int8*)_pValue;
341 					*pLen = sizeof(sal_Int8);
342 					break;
343 
344 				case SQL_SMALLINT:
345 					*((sal_Int16*)_pData) = *(sal_Int16*)_pValue;
346 					*pLen = sizeof(sal_Int16);
347 					break;
348 				case SQL_INTEGER:
349 					*((sal_Int32*)_pData) = *(sal_Int32*)_pValue;
350 					*pLen = sizeof(sal_Int32);
351 					break;
352 				case SQL_FLOAT:
353 					*((float*)_pData) = *(float*)_pValue;
354 					*pLen = sizeof(float);
355 					break;
356 				case SQL_REAL:
357 				case SQL_DOUBLE:
358 					*((double*)_pData) = *(double*)_pValue;
359 					*pLen = sizeof(double);
360 					break;
361 				case SQL_BINARY:
362 				case SQL_VARBINARY:
363                                                 //      if (_pValue == ::getCppuType((const ::com::sun::star::uno::Sequence< sal_Int8 > *)0))
364 					{
365                         _pData = (void*)((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getConstArray();
366                         *pLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
367 					}	break;
368 				case SQL_LONGVARBINARY:
369 				{
370 					_pData = (void*)(columnIndex);
371 					sal_Int32 nLen = 0;
372                     nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength();
373 					*pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
374 				}
375 					break;
376 				case SQL_LONGVARCHAR:
377 				{
378 					_pData = (void*)(columnIndex);
379 					sal_Int32 nLen = 0;
380 					nLen = ((::rtl::OUString*)_pValue)->getLength();
381 					*pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen);
382 				}   break;
383 				case SQL_DATE:
384 					*pLen = sizeof(DATE_STRUCT);
385 					*((DATE_STRUCT*)_pData) = *(DATE_STRUCT*)_pValue;
386 					break;
387 				case SQL_TIME:
388 					*pLen = sizeof(TIME_STRUCT);
389 					*((TIME_STRUCT*)_pData) = *(TIME_STRUCT*)_pValue;
390 					break;
391 				case SQL_TIMESTAMP:
392 					*pLen = sizeof(TIMESTAMP_STRUCT);
393 					*((TIMESTAMP_STRUCT*)_pData) = *(TIMESTAMP_STRUCT*)_pValue;
394                     break;
395 			}
396 		}
397 		catch ( ... )
398 		{
399 		}
400 
401 		nRetcode = (*(T3SQLBindCol)_pConnection->getOdbcFunction(ODBC3SQLBindCol))(_aStatementHandle,
402 								(SQLUSMALLINT)columnIndex,
403 								fCType,
404 								_pData,
405 								nMaxLen,
406 								pLen
407 								);
408 	}
409 
410 	OTools::ThrowException(_pConnection,nRetcode,_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
411 }
412 // -----------------------------------------------------------------------------
413 void OTools::ThrowException(OConnection* _pConnection,
414 							SQLRETURN _rRetCode,
415 							SQLHANDLE _pContext,
416 							SQLSMALLINT _nHandleType,
417 							const Reference< XInterface >& _xInterface,
418 							sal_Bool _bNoFound,
419 							rtl_TextEncoding _nTextEncoding) throw(SQLException)
420 {
421 	switch(_rRetCode)
422 	{
423 		case SQL_NEED_DATA:
424 		case SQL_STILL_EXECUTING:
425 		case SQL_SUCCESS:
426 
427 		case SQL_SUCCESS_WITH_INFO:
428 						return;
429 		case SQL_NO_DATA_FOUND:
430 								if(_bNoFound)
431 									return; // no need to throw a exception
432 		case SQL_ERROR:             break;
433 
434 
435 		case SQL_INVALID_HANDLE:    OSL_ENSURE(0,"SdbODBC3_SetStatus: SQL_INVALID_HANDLE");
436 									throw SQLException();
437 	}
438 
439 
440 	// Zusaetliche Informationen zum letzten ODBC-Funktionsaufruf vorhanden.
441 	// SQLError liefert diese Informationen.
442     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::ThrowException" );
443 
444 	SDB_ODBC_CHAR szSqlState[5];
445 	SQLINTEGER pfNativeError;
446 	SDB_ODBC_CHAR szErrorMessage[SQL_MAX_MESSAGE_LENGTH];
447 	szErrorMessage[0] = '\0';
448 	SQLSMALLINT pcbErrorMsg = 0;
449 
450 	// Informationen zur letzten Operation:
451 	// wenn hstmt != SQL_NULL_HSTMT ist (Benutzung von SetStatus in SdbCursor, SdbTable, ...),
452 	// dann wird der Status des letzten Statements erfragt, sonst der Status des letzten
453 	// Statements zu dieser Verbindung [was in unserem Fall wahrscheinlich gleichbedeutend ist,
454 	// aber das Reference Manual drueckt sich da nicht so klar aus ...].
455 	// Entsprechend bei hdbc.
456 	SQLRETURN n = (*(T3SQLGetDiagRec)_pConnection->getOdbcFunction(ODBC3SQLGetDiagRec))(_nHandleType,_pContext,1,
457 						 szSqlState,
458 						 &pfNativeError,
459 						 szErrorMessage,sizeof szErrorMessage - 1,&pcbErrorMsg);
460     OSL_UNUSED( n );
461 	OSL_ENSURE(n != SQL_INVALID_HANDLE,"SdbODBC3_SetStatus: SQLError returned SQL_INVALID_HANDLE");
462 	OSL_ENSURE(n == SQL_SUCCESS || n == SQL_SUCCESS_WITH_INFO || n == SQL_NO_DATA_FOUND || n == SQL_ERROR,"SdbODBC3_SetStatus: SQLError failed");
463 
464 	// Zum Return Code von SQLError siehe ODBC 2.0 Programmer's Reference Seite 287ff
465 	throw SQLException(	::rtl::OUString((char *)szErrorMessage,pcbErrorMsg,_nTextEncoding),
466 									_xInterface,
467 									::rtl::OUString((char *)szSqlState,5,_nTextEncoding),
468 									pfNativeError,
469 									Any()
470 								);
471 
472 }
473 // -------------------------------------------------------------------------
474 Sequence<sal_Int8> OTools::getBytesValue(OConnection* _pConnection,
475 										 SQLHANDLE _aStatementHandle,
476 										 sal_Int32 columnIndex,
477 										 SQLSMALLINT _fSqlType,
478 										 sal_Bool &_bWasNull,
479 										 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
480 {
481     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBytesValue" );
482 	char aCharArray[2048];
483 	// Erstmal versuchen, die Daten mit dem kleinen Puffer
484 	// abzuholen:
485 	SQLLEN nMaxLen = sizeof aCharArray - 1;
486 	//	GETDATA(SQL_C_CHAR,aCharArray,nMaxLen);
487 	SQLLEN pcbValue = 0;
488 	OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
489 										(SQLUSMALLINT)columnIndex,
490 										_fSqlType,
491 										(SQLPOINTER)aCharArray,
492 										nMaxLen,
493 										&pcbValue),
494 							_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
495 
496 	_bWasNull = pcbValue == SQL_NULL_DATA;
497 	if(_bWasNull)
498 		return Sequence<sal_Int8>();
499 
500 	SQLINTEGER nBytes = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : nMaxLen;
501 	if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nBytes-1] == 0  && nBytes > 0 )
502 		--nBytes;
503 	Sequence<sal_Int8> aData((sal_Int8*)aCharArray, nBytes);
504 
505 
506 	// Es handelt sich um Binaerdaten, um einen String, der fuer
507 	// StarView zu lang ist oder der Treiber kann die Laenge der
508 	// Daten nicht im voraus bestimmen - also als MemoryStream
509 	// speichern.
510 	while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen)
511 	{
512 		// Bei Strings wird der Puffer nie ganz ausgenutzt
513 		// (das letzte Byte ist immer ein NULL-Byte, das
514 		// aber bei pcbValue nicht mitgezaehlt wird)
515 		if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen)
516 			nBytes = pcbValue - nMaxLen;
517 		else
518 			nBytes = nMaxLen;
519 
520 		// Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen
521 		//	GETDATA(SQL_C_CHAR,aCharArray, nLen + 1);
522 		OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
523 										(SQLUSMALLINT)columnIndex,
524 										SQL_C_BINARY,
525 										&aCharArray,
526 										(SQLINTEGER)nBytes,
527 										&pcbValue),
528 							_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
529 		sal_Int32 nLen = aData.getLength();
530 		aData.realloc(nLen + nBytes);
531         memcpy(aData.getArray() + nLen, aCharArray, nBytes);
532 	}
533 	return aData;
534 }
535 // -------------------------------------------------------------------------
536 ::rtl::OUString OTools::getStringValue(OConnection* _pConnection,
537 									   SQLHANDLE _aStatementHandle,
538 									   sal_Int32 columnIndex,
539 									   SQLSMALLINT _fSqlType,
540 									   sal_Bool &_bWasNull,
541 									   const Reference< XInterface >& _xInterface,
542 									   rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
543 {
544     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getStringValue" );
545 	::rtl::OUStringBuffer aData;
546 	switch(_fSqlType)
547 	{
548 	case SQL_WVARCHAR:
549 	case SQL_WCHAR:
550 	case SQL_WLONGVARCHAR:
551 		{
552 			sal_Unicode waCharArray[2048];
553 			// read the unicode data
554 			SQLLEN nMaxLen = (sizeof(waCharArray) / sizeof(sal_Unicode)) - 1;
555 			//	GETDATA(SQL_C_WCHAR, waCharArray, nMaxLen + sizeof(sal_Unicode));
556 
557 			SQLLEN pcbValue=0;
558 			OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
559 												(SQLUSMALLINT)columnIndex,
560 												SQL_C_WCHAR,
561 												&waCharArray,
562 												(SQLLEN)nMaxLen*sizeof(sal_Unicode),
563 												&pcbValue),
564 									_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
565 			_bWasNull = pcbValue == SQL_NULL_DATA;
566 			if(_bWasNull)
567 				return ::rtl::OUString();
568 			// Bei Fehler bricht der GETDATA-Makro mit return ab,
569 			// bei NULL mit break!
570             SQLLEN nRealSize = 0;
571             if ( pcbValue > -1 )
572                 nRealSize = pcbValue / sizeof(sal_Unicode);
573 			SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1);
574 			waCharArray[nLen] = 0;
575 			aData.append(waCharArray,nLen);
576 
577 			// Es handelt sich um Binaerdaten, um einen String, der fuer
578 			// StarView zu lang ist oder der Treiber kann die Laenge der
579 			// Daten nicht im voraus bestimmen - also als MemoryStream
580 			// speichern.
581 			while ((pcbValue == SQL_NO_TOTAL ) || nLen > nMaxLen)
582 			{
583 				// Bei Strings wird der Puffer nie ganz ausgenutzt
584 				// (das letzte Byte ist immer ein NULL-Byte, das
585 				// aber bei pcbValue nicht mitgezaehlt wird)
586 				if (pcbValue != SQL_NO_TOTAL && (pcbValue - nMaxLen) < nMaxLen)
587 					nLen = pcbValue - nMaxLen;
588 				else
589 					nLen = nMaxLen;
590 
591 				// Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen
592 				//	GETDATA(SQL_C_CHAR,waCharArray, nLen + 1);
593 				OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
594 												(SQLUSMALLINT)columnIndex,
595 												SQL_C_WCHAR,
596 												&waCharArray,
597 												(SQLLEN)nLen+1,
598 												&pcbValue),
599 									_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
600                 nRealSize = 0;
601                 if ( pcbValue > -1 )
602                     nRealSize = pcbValue / sizeof(sal_Unicode);
603 				nLen = pcbValue != SQL_NO_TOTAL ? std::min(nRealSize, nMaxLen) : (nMaxLen-1);
604 				waCharArray[nLen] = 0;
605 
606 				aData.append(::rtl::OUString(waCharArray));
607 			}
608 		}
609 		break;
610 		default:
611 		{
612 			char aCharArray[2048];
613 			// Erstmal versuchen, die Daten mit dem kleinen Puffer
614 			// abzuholen:
615 			SQLLEN nMaxLen = sizeof aCharArray - 1;
616 			//	GETDATA(SQL_C_CHAR,aCharArray,nMaxLen);
617 			SQLLEN pcbValue = 0;
618 			OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
619 												(SQLUSMALLINT)columnIndex,
620 												SQL_C_CHAR,
621 												&aCharArray,
622 												nMaxLen,
623 												&pcbValue),
624 									_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
625 			_bWasNull = pcbValue == SQL_NULL_DATA;
626 			if(_bWasNull)
627 				return ::rtl::OUString();
628 
629 			SQLLEN nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1);
630 			aCharArray[nLen] = 0;
631 			if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 )
632 				--nLen;
633 			aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen, _nTextEncoding));
634 
635 			// Es handelt sich um Binaerdaten, um einen String, der fuer
636 			// StarView zu lang ist oder der Treiber kann die Laenge der
637 			// Daten nicht im voraus bestimmen - also als MemoryStream
638 			// speichern.
639 			while ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen)
640 			{
641 				// Solange eine "truncation"-Warnung vorliegt, weiter Daten abholen
642 				//	GETDATA(SQL_C_CHAR,aCharArray, nLen + 1);
643 				OTools::ThrowException(_pConnection,(*(T3SQLGetData)_pConnection->getOdbcFunction(ODBC3SQLGetData))(_aStatementHandle,
644 												(SQLUSMALLINT)columnIndex,
645 												SQL_C_CHAR,
646 												&aCharArray,
647 												(SQLINTEGER)nMaxLen,
648 												&pcbValue),
649 									_aStatementHandle,SQL_HANDLE_STMT,_xInterface);
650 				nLen = pcbValue != SQL_NO_TOTAL ? std::min(pcbValue, nMaxLen) : (nMaxLen-1);
651 				if ( ((pcbValue == SQL_NO_TOTAL) || pcbValue > nMaxLen) && aCharArray[nLen-1] == 0 && nLen > 0 )
652 					--nLen;
653 				aCharArray[nLen] = 0;
654 
655 				aData.append(::rtl::OUString((const sal_Char*)aCharArray,nLen,_nTextEncoding));
656 			}
657 
658 			// delete all blanks
659 			//	aData.EraseTrailingChars();
660 		}
661 	}
662 
663 	return aData.makeStringAndClear();
664 }
665 // -------------------------------------------------------------------------
666 void OTools::GetInfo(OConnection* _pConnection,
667 					 SQLHANDLE _aConnectionHandle,
668 					 SQLUSMALLINT _nInfo,
669 					 ::rtl::OUString &_rValue,
670 					 const Reference< XInterface >& _xInterface,
671 					 rtl_TextEncoding _nTextEncoding) throw(SQLException, RuntimeException)
672 {
673 	char aValue[512];
674 	SQLSMALLINT nValueLen=0;
675 	OTools::ThrowException(_pConnection,
676 		(*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,aValue,(sizeof aValue)-1,&nValueLen),
677 		_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
678 
679 	_rValue = ::rtl::OUString(aValue,nValueLen,_nTextEncoding);
680 }
681 // -------------------------------------------------------------------------
682 void OTools::GetInfo(OConnection* _pConnection,
683 					 SQLHANDLE _aConnectionHandle,
684 					 SQLUSMALLINT _nInfo,
685 					 sal_Int32 &_rValue,
686 					 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
687 {
688 	SQLSMALLINT nValueLen;
689 	_rValue = 0;	// in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
690 	OTools::ThrowException(_pConnection,
691 		(*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
692 		_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
693 }
694 // -------------------------------------------------------------------------
695 void OTools::GetInfo(OConnection* _pConnection,
696 					 SQLHANDLE _aConnectionHandle,
697 					 SQLUSMALLINT _nInfo,
698 					 SQLUINTEGER &_rValue,
699 					 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
700 {
701 	SQLSMALLINT nValueLen;
702 	_rValue = 0;	// in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
703 	OTools::ThrowException(_pConnection,
704 		(*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
705 		_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
706 }
707 // -------------------------------------------------------------------------
708 void OTools::GetInfo(OConnection* _pConnection,
709 					 SQLHANDLE _aConnectionHandle,
710 					 SQLUSMALLINT _nInfo,
711 					 SQLUSMALLINT &_rValue,
712 					 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
713 {
714 	SQLSMALLINT nValueLen;
715 	_rValue = 0;	// in case the driver uses only 16 of the 32 bits (as it does, for example, for SQL_CATALOG_LOCATION)
716 	OTools::ThrowException(_pConnection,
717 		(*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
718 		_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
719 }
720 // -------------------------------------------------------------------------
721 void OTools::GetInfo(OConnection* _pConnection,
722 					 SQLHANDLE _aConnectionHandle,
723 					 SQLUSMALLINT _nInfo,
724 					 sal_Bool &_rValue,
725 					 const Reference< XInterface >& _xInterface) throw(SQLException, RuntimeException)
726 {
727 	SQLSMALLINT nValueLen;
728 	OTools::ThrowException(_pConnection,
729 							(*(T3SQLGetInfo)_pConnection->getOdbcFunction(ODBC3SQLGetInfo))(_aConnectionHandle,_nInfo,&_rValue,sizeof _rValue,&nValueLen),
730 							_aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
731 }
732 // -------------------------------------------------------------------------
733 sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType)
734 {
735 	sal_Int32 nValue = DataType::VARCHAR;
736 	switch(_nType)
737 	{
738 		case SQL_BIT:
739 			nValue = DataType::BIT;
740 			break;
741 		case SQL_TINYINT:
742 			nValue = DataType::TINYINT;
743 			break;
744 		case SQL_SMALLINT:
745 			nValue = DataType::SMALLINT;
746 			break;
747 		case SQL_INTEGER:
748 			nValue = DataType::INTEGER;
749 			break;
750 		case SQL_BIGINT:
751 			nValue = DataType::BIGINT;
752 			break;
753 		case SQL_FLOAT:
754 			nValue = DataType::FLOAT;
755 			break;
756 		case SQL_REAL:
757 			nValue = DataType::REAL;
758 			break;
759 		case SQL_DOUBLE:
760 			nValue = DataType::DOUBLE;
761 			break;
762 		case SQL_NUMERIC:
763 			nValue = DataType::NUMERIC;
764 			break;
765 		case SQL_DECIMAL:
766 			nValue = DataType::DECIMAL;
767 			break;
768 		case SQL_WCHAR:
769 		case SQL_CHAR:
770 			nValue = DataType::CHAR;
771 			break;
772 		case SQL_WVARCHAR:
773 		case SQL_VARCHAR:
774 			nValue = DataType::VARCHAR;
775 			break;
776 		case SQL_WLONGVARCHAR:
777 		case SQL_LONGVARCHAR:
778 			nValue = DataType::LONGVARCHAR;
779 			break;
780 		case SQL_TYPE_DATE:
781 		case SQL_DATE:
782 			nValue = DataType::DATE;
783 			break;
784 		case SQL_TYPE_TIME:
785 		case SQL_TIME:
786 			nValue = DataType::TIME;
787 			break;
788 		case SQL_TYPE_TIMESTAMP:
789 		case SQL_TIMESTAMP:
790 			nValue = DataType::TIMESTAMP;
791 			break;
792 		case SQL_BINARY:
793 			nValue = DataType::BINARY;
794 			break;
795 		case SQL_VARBINARY:
796 		case SQL_GUID:
797 			nValue = DataType::VARBINARY;
798 			break;
799 		case SQL_LONGVARBINARY:
800 			nValue = DataType::LONGVARBINARY;
801 			break;
802 		default:
803 			OSL_ASSERT(!"Invalid type");
804 	}
805 	return nValue;
806 }
807 //--------------------------------------------------------------------
808 // jdbcTypeToOdbc
809 // Convert the JDBC SQL type to the correct ODBC type
810 //--------------------------------------------------------------------
811 sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
812 {
813     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" );
814 	// For the most part, JDBC types match ODBC types.  We'll
815 	// just convert the ones that we know are different
816 
817 	sal_Int32 odbcType = jdbcType;
818 
819 	switch (jdbcType)
820 	{
821 	case DataType::DATE:
822 		odbcType = SQL_DATE;
823 		break;
824 	case DataType::TIME:
825 		odbcType = SQL_TIME;
826 		break;
827 	case DataType::TIMESTAMP:
828 		odbcType = SQL_TIMESTAMP;
829 		break;
830 	}
831 
832 	return odbcType;
833 }
834 //-----------------------------------------------------------------------------
835 void OTools::getBindTypes(sal_Bool _bUseWChar,
836 						  sal_Bool _bUseOldTimeDate,
837 						  SQLSMALLINT _nOdbcType,
838 						  SQLSMALLINT& fCType,
839 						  SQLSMALLINT& fSqlType
840 						  )
841 {
842     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::getBindTypes" );
843 	switch(_nOdbcType)
844 	{
845 		case SQL_CHAR:				if(_bUseWChar)
846 									{
847 										fCType   = SQL_C_WCHAR;
848 										fSqlType = SQL_WCHAR;
849 									}
850 									else
851 									{
852 										fCType   = SQL_C_CHAR;
853 										fSqlType = SQL_CHAR;
854 									}
855 									break;
856 		case SQL_VARCHAR:			if(_bUseWChar)
857 									{
858 										fCType   = SQL_C_WCHAR;
859 										fSqlType = SQL_WVARCHAR;
860 									}
861 									else
862 									{
863 										fCType   = SQL_C_CHAR;
864 										fSqlType = SQL_VARCHAR;
865 									}
866 									break;
867 		case SQL_LONGVARCHAR:		if(_bUseWChar)
868 									{
869 										fCType   = SQL_C_WCHAR;
870 										fSqlType = SQL_WLONGVARCHAR;
871 									}
872 									else
873 									{
874 										fCType	 = SQL_C_CHAR;
875 										fSqlType = SQL_LONGVARCHAR;
876 									}
877 									break;
878 		case SQL_DECIMAL:			fCType		= _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
879 									fSqlType	= SQL_DECIMAL; break;
880 		case SQL_NUMERIC:			fCType		= _bUseWChar ? SQL_C_WCHAR : SQL_C_CHAR;
881 									fSqlType	= SQL_NUMERIC; break;
882 		case SQL_BIT:				fCType		= SQL_C_TINYINT;
883 									fSqlType	= SQL_INTEGER; break;
884 		case SQL_TINYINT:			fCType		= SQL_C_TINYINT;
885 									fSqlType	= SQL_TINYINT; break;
886 		case SQL_SMALLINT:			fCType		= SQL_C_SHORT;
887 									fSqlType	= SQL_SMALLINT; break;
888 		case SQL_INTEGER:			fCType		= SQL_C_LONG;
889 									fSqlType	= SQL_INTEGER; break;
890 		case SQL_BIGINT:			fCType		= SQL_C_SBIGINT;
891 									fSqlType	= SQL_BIGINT; break;
892 		case SQL_FLOAT:				fCType		= SQL_C_FLOAT;
893 									fSqlType	= SQL_FLOAT; break;
894 		case SQL_REAL:				fCType		= SQL_C_DOUBLE;
895 									fSqlType	= SQL_REAL; break;
896 		case SQL_DOUBLE:			fCType		= SQL_C_DOUBLE;
897 									fSqlType	= SQL_DOUBLE; break;
898 		case SQL_BINARY:			fCType		= SQL_C_BINARY;
899 									fSqlType	= SQL_BINARY; break;
900 		case SQL_VARBINARY:
901 									fCType		= SQL_C_BINARY;
902 									fSqlType	= SQL_VARBINARY; break;
903 		case SQL_LONGVARBINARY: 	fCType		= SQL_C_BINARY;
904 									fSqlType	= SQL_LONGVARBINARY; break;
905 		case SQL_DATE:
906 									if(_bUseOldTimeDate)
907 									{
908 										fCType		= SQL_C_DATE;
909 										fSqlType	= SQL_DATE;
910 									}
911 									else
912 									{
913 										fCType		= SQL_C_TYPE_DATE;
914 										fSqlType	= SQL_TYPE_DATE;
915 									}
916 									break;
917 		case SQL_TIME:
918 									if(_bUseOldTimeDate)
919 									{
920 										fCType		= SQL_C_TIME;
921 										fSqlType	= SQL_TIME;
922 									}
923 									else
924 									{
925 										fCType		= SQL_C_TYPE_TIME;
926 										fSqlType	= SQL_TYPE_TIME;
927 									}
928 									break;
929 		case SQL_TIMESTAMP:
930 									if(_bUseOldTimeDate)
931 									{
932 										fCType		= SQL_C_TIMESTAMP;
933 										fSqlType	= SQL_TIMESTAMP;
934 									}
935 									else
936 									{
937 										fCType		= SQL_C_TYPE_TIMESTAMP;
938 										fSqlType	= SQL_TYPE_TIMESTAMP;
939 									}
940 									break;
941 		default:						fCType		= SQL_C_BINARY;
942 										fSqlType	= SQL_LONGVARBINARY; break;
943 	}
944 }
945 
946 
947