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