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/OResultSet.hxx"
31 #include "odbc/OTools.hxx"
32 #include "odbc/OResultSetMetaData.hxx"
33 #include <com/sun/star/sdbc/DataType.hpp>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
36 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
37 #include <com/sun/star/sdbc/FetchDirection.hpp>
38 #include <com/sun/star/sdbc/ResultSetType.hpp>
39 #include <comphelper/property.hxx>
40 #include <comphelper/sequence.hxx>
41 #include <cppuhelper/typeprovider.hxx>
42 #include <comphelper/extract.hxx>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <comphelper/types.hxx>
45 #include "connectivity/dbtools.hxx"
46 #include "connectivity/dbexception.hxx"
47 #include "diagnose_ex.h"
48 #include <rtl/logfile.hxx>
49 
50 using namespace ::comphelper;
51 using namespace connectivity;
52 using namespace connectivity::odbc;
53 using namespace cppu;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::beans;
57 using namespace com::sun::star::sdbc;
58 using namespace com::sun::star::sdbcx;
59 using namespace com::sun::star::container;
60 using namespace com::sun::star::io;
61 using namespace com::sun::star::util;
62 
63 #define ODBC_SQL_NOT_DEFINED    99UL
64 
65 //------------------------------------------------------------------------------
66 //	IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
67 ::rtl::OUString SAL_CALL OResultSet::getImplementationName(  ) throw ( RuntimeException)
68 {
69 	return ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.odbc.ResultSet");
70 }
71 // -------------------------------------------------------------------------
72  Sequence< ::rtl::OUString > SAL_CALL OResultSet::getSupportedServiceNames(  ) throw( RuntimeException)
73 {
74 	 Sequence< ::rtl::OUString > aSupported(2);
75 	aSupported[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbc.ResultSet");
76 	aSupported[1] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.ResultSet");
77 	return aSupported;
78 }
79 // -------------------------------------------------------------------------
80 sal_Bool SAL_CALL OResultSet::supportsService( const ::rtl::OUString& _rServiceName ) throw( RuntimeException)
81 {
82 	Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
83 	const ::rtl::OUString* pSupported = aSupported.getConstArray();
84 	const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
85 	for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
86 		;
87 
88 	return pSupported != pEnd;
89 }
90 
91 // -------------------------------------------------------------------------
92 OResultSet::OResultSet(SQLHANDLE _pStatementHandle ,OStatement_Base* pStmt) :	OResultSet_BASE(m_aMutex)
93 						,OPropertySetHelper(OResultSet_BASE::rBHelper)
94                         ,m_aStatementHandle(_pStatementHandle)
95                         ,m_aConnectionHandle(pStmt->getConnectionHandle())
96                         ,m_pStatement(pStmt)
97                         ,m_pSkipDeletedSet(NULL)
98                         ,m_xStatement(*pStmt)
99                         ,m_xMetaData(NULL)
100                         ,m_pRowStatusArray( NULL )
101                         ,m_nTextEncoding(pStmt->getOwnConnection()->getTextEncoding())
102 						,m_nRowPos(0)
103                         ,m_nLastColumnPos(0)
104                         ,m_nUseBookmarks(ODBC_SQL_NOT_DEFINED)
105                         ,m_nCurrentFetchState(0)
106                         ,m_bWasNull(sal_True)
107                         ,m_bEOF(sal_True)
108 						,m_bLastRecord(sal_False)
109 						,m_bFreeHandle(sal_False)
110 						,m_bInserting(sal_False)
111                         ,m_bFetchData(sal_True)
112 						,m_bRowInserted(sal_False)
113 						,m_bRowDeleted(sal_False)
114 						,m_bUseFetchScroll(sal_False)
115 {
116 	osl_incrementInterlockedCount( &m_refCount );
117 	try
118 	{
119 		m_pRowStatusArray = new SQLUSMALLINT[1]; // the default value
120 		N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_STATUS_PTR,m_pRowStatusArray,SQL_IS_POINTER);
121 	}
122 	catch(Exception&)
123 	{ // we don't want our result destroy here
124 	}
125 	SQLINTEGER nCurType = 0;
126 	try
127 	{
128 		N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_TYPE,&nCurType,SQL_IS_UINTEGER,0);
129 		SQLUINTEGER nValueLen = m_pStatement->getCursorProperties(nCurType,sal_False);
130 		if( (nValueLen & SQL_CA2_SENSITIVITY_DELETIONS) != SQL_CA2_SENSITIVITY_DELETIONS ||
131 			(nValueLen & SQL_CA2_CRC_EXACT) != SQL_CA2_CRC_EXACT)
132 			m_pSkipDeletedSet = new OSkipDeletedSet(this);
133 	}
134 	catch(Exception&)
135 	{ // we don't want our result destroy here
136 	}
137 	try
138 	{
139 		SQLUINTEGER nValueLen = 0;
140 		OTools::GetInfo(m_pStatement->getOwnConnection(),m_aConnectionHandle,SQL_GETDATA_EXTENSIONS,nValueLen,NULL);
141 		m_bFetchData = !((SQL_GD_ANY_ORDER & nValueLen) == SQL_GD_ANY_ORDER && nCurType != SQL_CURSOR_FORWARD_ONLY);
142 	}
143 	catch(Exception&)
144 	{ // we don't want our result destroy here
145 		m_bFetchData = sal_True;
146 	}
147 	try
148 	{
149 		if ( getOdbcFunction(ODBC3SQLGetFunctions) )
150 		{
151 			SQLUSMALLINT nSupported = 0;
152 			m_bUseFetchScroll = ( N3SQLGetFunctions(m_aConnectionHandle,SQL_API_SQLFETCHSCROLL,&nSupported) == SQL_SUCCESS && nSupported == 1 );
153 		}
154 	}
155 	catch(Exception&)
156 	{
157 		m_bUseFetchScroll = sal_False;
158 	}
159 
160 	osl_decrementInterlockedCount( &m_refCount );
161 }
162 // -------------------------------------------------------------------------
163 OResultSet::~OResultSet()
164 {
165 	delete [] m_pRowStatusArray;
166 	delete m_pSkipDeletedSet;
167 }
168 // -----------------------------------------------------------------------------
169 void OResultSet::construct()
170 {
171 	osl_incrementInterlockedCount( &m_refCount );
172 	allocBuffer();
173 	osl_decrementInterlockedCount( &m_refCount );
174 }
175 // -------------------------------------------------------------------------
176 void OResultSet::disposing(void)
177 {
178 	SQLRETURN nRet = N3SQLCloseCursor(m_aStatementHandle);
179     OSL_UNUSED( nRet );
180 	OPropertySetHelper::disposing();
181 
182 	::osl::MutexGuard aGuard(m_aMutex);
183 	if(!m_aBindVector.empty())
184 		releaseBuffer();
185 	if(m_bFreeHandle)
186 		m_pStatement->getOwnConnection()->freeStatementHandle(m_aStatementHandle);
187 
188 m_xStatement.clear();
189 m_xMetaData.clear();
190 }
191 // -------------------------------------------------------------------------
192 SQLRETURN OResultSet::unbind(sal_Bool _bUnbindHandle)
193 {
194     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::unbind" );
195 	SQLRETURN nRet = 0;
196 	if ( _bUnbindHandle )
197 		nRet = N3SQLFreeStmt(m_aStatementHandle,SQL_UNBIND);
198 
199 	if ( m_aBindVector.size() > 1 )
200 	{
201 		TVoidVector::iterator pValue = m_aBindVector.begin() + 1;
202 		TVoidVector::iterator pEnd = m_aBindVector.end();
203 		for(; pValue != pEnd; ++pValue)
204 		{
205 			switch (pValue->second)
206 			{
207 				case DataType::CHAR:
208 				case DataType::VARCHAR:
209 					delete static_cast< ::rtl::OString* >(reinterpret_cast< void * >(pValue->first));
210 					break;
211 				case DataType::BIGINT:
212 					delete static_cast< sal_Int64* >(reinterpret_cast< void * >(pValue->first));
213 					break;
214 				case DataType::DECIMAL:
215 				case DataType::NUMERIC:
216 					delete static_cast< ::rtl::OString* >(reinterpret_cast< void * >(pValue->first));
217 					break;
218 				case DataType::REAL:
219 				case DataType::DOUBLE:
220 					delete static_cast< double* >(reinterpret_cast< void * >(pValue->first));
221 					break;
222 				case DataType::LONGVARCHAR:
223 				case DataType::CLOB:
224 					delete [] static_cast< char* >(reinterpret_cast< void * >(pValue->first));
225 					break;
226 				case DataType::LONGVARBINARY:
227 				case DataType::BLOB:
228 					delete [] static_cast< char* >(reinterpret_cast< void * >(pValue->first));
229 					break;
230 				case DataType::DATE:
231 					delete static_cast< DATE_STRUCT* >(reinterpret_cast< void * >(pValue->first));
232 					break;
233 				case DataType::TIME:
234 					delete static_cast< TIME_STRUCT* >(reinterpret_cast< void * >(pValue->first));
235 					break;
236 				case DataType::TIMESTAMP:
237 					delete static_cast< TIMESTAMP_STRUCT* >(reinterpret_cast< void * >(pValue->first));
238 					break;
239 				case DataType::BIT:
240 				case DataType::TINYINT:
241 					delete static_cast< sal_Int8* >(reinterpret_cast< void * >(pValue->first));
242 					break;
243 				case DataType::SMALLINT:
244 					delete static_cast< sal_Int16* >(reinterpret_cast< void * >(pValue->first));
245 					break;
246 				case DataType::INTEGER:
247 					delete static_cast< sal_Int32* >(reinterpret_cast< void * >(pValue->first));
248 					break;
249 				case DataType::FLOAT:
250 					delete static_cast< float* >(reinterpret_cast< void * >(pValue->first));
251 					break;
252 				case DataType::BINARY:
253 				case DataType::VARBINARY:
254 					delete static_cast< sal_Int8* >(reinterpret_cast< void * >(pValue->first));
255 					break;
256 			}
257 		}
258 		m_aBindVector.clear();
259 		m_aBindVector.push_back(TVoidPtr(0,0)); // the first is reserved for the bookmark
260 	}
261 	return nRet;
262 }
263 // -------------------------------------------------------------------------
264 TVoidPtr OResultSet::allocBindColumn(sal_Int32 _nType,sal_Int32 _nColumnIndex)
265 {
266     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::allocBindColumn" );
267 	TVoidPtr aPair;
268 	switch (_nType)
269 	{
270 		case DataType::CHAR:
271 		case DataType::VARCHAR:
272 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new ::rtl::OString()),_nType);
273 			break;
274 		case DataType::BIGINT:
275 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int64(0)),_nType);
276 			break;
277 		case DataType::DECIMAL:
278 		case DataType::NUMERIC:
279 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new ::rtl::OString()),_nType);
280 			break;
281 		case DataType::REAL:
282 		case DataType::DOUBLE:
283 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new double(0.0)),_nType);
284 			break;
285 		case DataType::LONGVARCHAR:
286 		case DataType::CLOB:
287 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new char[2]),_nType);  // dient nur zum auffinden
288 			break;
289 		case DataType::LONGVARBINARY:
290 		case DataType::BLOB:
291 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new char[2]),_nType);  // dient nur zum auffinden
292 			break;
293 		case DataType::DATE:
294 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new DATE_STRUCT),_nType);
295 			break;
296 		case DataType::TIME:
297 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new TIME_STRUCT),_nType);
298 			break;
299 		case DataType::TIMESTAMP:
300 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new TIMESTAMP_STRUCT),_nType);
301 			break;
302 		case DataType::BIT:
303 		case DataType::TINYINT:
304 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int8(0)),_nType);
305 			break;
306 		case DataType::SMALLINT:
307 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int16(0)),_nType);
308 			break;
309 		case DataType::INTEGER:
310 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int32(0)),_nType);
311 			break;
312 		case DataType::FLOAT:
313 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new float(0)),_nType);
314 			break;
315 		case DataType::BINARY:
316 		case DataType::VARBINARY:
317 			aPair = TVoidPtr(reinterpret_cast< sal_Int64 >(new sal_Int8[m_aRow[_nColumnIndex].getSequence().getLength()]),_nType);
318 			break;
319 		default:
320 			OSL_ENSURE(0,"Unknown type");
321 			aPair = TVoidPtr(0,_nType);
322 	}
323 	return aPair;
324 }
325 // -------------------------------------------------------------------------
326 void OResultSet::allocBuffer()
327 {
328     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::allocBuffer" );
329 	Reference< XResultSetMetaData > xMeta = getMetaData();
330 	sal_Int32 nLen = xMeta->getColumnCount();
331 
332 	m_aBindVector.reserve(nLen+1);
333 	m_aBindVector.push_back(TVoidPtr(0,0)); // the first is reserved for the bookmark
334 	m_aRow.resize(nLen+1);
335 
336 	for(sal_Int32 i = 1;i<=nLen;++i)
337 	{
338 		sal_Int32 nType = xMeta->getColumnType(i);
339 		m_aRow[i].setTypeKind( nType );
340 	}
341 	m_aLengthVector.resize(nLen + 1);
342 }
343 // -------------------------------------------------------------------------
344 void OResultSet::releaseBuffer()
345 {
346     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::releaseBuffer" );
347 	unbind(sal_False);
348 	m_aLengthVector.clear();
349 }
350 // -------------------------------------------------------------------------
351 Any SAL_CALL OResultSet::queryInterface( const Type & rType ) throw(RuntimeException)
352 {
353 	Any aRet = OPropertySetHelper::queryInterface(rType);
354 	return aRet.hasValue() ? aRet : OResultSet_BASE::queryInterface(rType);
355 }
356 // -------------------------------------------------------------------------
357  Sequence<  Type > SAL_CALL OResultSet::getTypes(  ) throw( RuntimeException)
358 {
359 	OTypeCollection aTypes(	::getCppuType( (const  Reference< ::com::sun::star::beans::XMultiPropertySet > *)0 ),
360 												::getCppuType( (const  Reference< ::com::sun::star::beans::XFastPropertySet > *)0 ),
361 												::getCppuType( (const  Reference< ::com::sun::star::beans::XPropertySet > *)0 ));
362 
363 	return ::comphelper::concatSequences(aTypes.getTypes(),OResultSet_BASE::getTypes());
364 }
365 // -------------------------------------------------------------------------
366 
367 sal_Int32 SAL_CALL OResultSet::findColumn( const ::rtl::OUString& columnName ) throw(SQLException, RuntimeException)
368 {
369     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::findColumn" );
370 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
371 
372 
373 	::osl::MutexGuard aGuard( m_aMutex );
374 
375 	Reference< XResultSetMetaData > xMeta = getMetaData();
376 	sal_Int32 nLen = xMeta->getColumnCount();
377 	sal_Int32 i = 1;
378 	for(;i<=nLen;++i)
379 		if(xMeta->isCaseSensitive(i) ? columnName == xMeta->getColumnName(i) :
380 				columnName.equalsIgnoreAsciiCase(xMeta->getColumnName(i)))
381 			break;
382 	return i;
383 }
384 // -------------------------------------------------------------------------
385 Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
386 {
387 	::osl::MutexGuard aGuard( m_aMutex );
388 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
389 
390 
391 	// TODO use getBytes instead of
392 	return NULL;
393 }
394 // -------------------------------------------------------------------------
395 Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
396 {
397 	::osl::MutexGuard aGuard( m_aMutex );
398 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
399 
400 
401 	// TODO use getBytes instead of
402 	return NULL;
403 }
404 // -----------------------------------------------------------------------------
405 const ORowSetValue& OResultSet::getValue(sal_Int32 _nColumnIndex,SQLSMALLINT _nType,void* _pValue,SQLINTEGER _rSize)
406 {
407     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getValue" );
408 	::osl::MutexGuard aGuard( m_aMutex );
409 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
410 
411 	if(m_bFetchData)
412 	{
413 		if(_nColumnIndex > m_nLastColumnPos)
414 			fillRow(_nColumnIndex);
415 		return m_aRow[_nColumnIndex];
416 	}
417 	else
418 		OTools::getValue(m_pStatement->getOwnConnection(),m_aStatementHandle,_nColumnIndex,_nType,m_bWasNull,**this,_pValue,_rSize);
419 
420 	return m_aEmptyValue;
421 }
422 // -------------------------------------------------------------------------
423 sal_Bool SAL_CALL OResultSet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
424 {
425 	sal_Int8 nVal(0);
426 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_BIT,&nVal,sizeof nVal);
427 	return (&aValue == &m_aEmptyValue) ? (sal_Bool)nVal : (sal_Bool)aValue;
428 }
429 // -------------------------------------------------------------------------
430 
431 sal_Int8 SAL_CALL OResultSet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
432 {
433 	sal_Int8 nRet(0);
434 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_TINYINT,&nRet,sizeof nRet);
435 	return (&aValue == &m_aEmptyValue) ? nRet : (sal_Int8)aValue;
436 }
437 // -------------------------------------------------------------------------
438 
439 Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
440 {
441     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getBytes" );
442 
443 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
444 	::osl::MutexGuard aGuard( m_aMutex );
445 
446 
447 	if(m_bFetchData)
448 	{
449 		if(columnIndex > m_nLastColumnPos)
450 			fillRow(columnIndex);
451 		Sequence< sal_Int8 > nRet;
452 		switch(m_aRow[columnIndex].getTypeKind())
453 		{
454 			case DataType::BINARY:
455 			case DataType::VARBINARY:
456 			case DataType::LONGVARBINARY:
457 				nRet = m_aRow[columnIndex];
458 				break;
459 			default:
460 			{
461 				::rtl::OUString sRet;
462 				sRet = m_aRow[columnIndex].getString();
463 				nRet = Sequence<sal_Int8>(reinterpret_cast<const sal_Int8*>(sRet.getStr()),sizeof(sal_Unicode)*sRet.getLength());
464 			}
465 		}
466 		return nRet;
467 	}
468 
469     const SWORD nColumnType = impl_getColumnType_nothrow(columnIndex);
470 
471 	switch(nColumnType)
472 	{
473 		case SQL_WVARCHAR:
474         case SQL_WCHAR:
475         case SQL_WLONGVARCHAR:
476         case SQL_VARCHAR:
477         case SQL_CHAR:
478         case SQL_LONGVARCHAR:
479 		{
480 			::rtl::OUString aRet = OTools::getStringValue(m_pStatement->getOwnConnection(),m_aStatementHandle,columnIndex,nColumnType,m_bWasNull,**this,m_nTextEncoding);
481 			return Sequence<sal_Int8>(reinterpret_cast<const sal_Int8*>(aRet.getStr()),sizeof(sal_Unicode)*aRet.getLength());
482 		}
483         default:
484             ;
485 	}
486 	return OTools::getBytesValue(m_pStatement->getOwnConnection(),m_aStatementHandle,columnIndex,SQL_C_BINARY,m_bWasNull,**this);
487 }
488 // -------------------------------------------------------------------------
489 
490 Date SAL_CALL OResultSet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
491 {
492     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getDate" );
493 	DATE_STRUCT aDate;
494 	aDate.day	= 0;
495 	aDate.month = 0;
496 	aDate.year	= 0;
497 
498 	const ORowSetValue& aValue = getValue(	columnIndex,
499 							m_pStatement->getOwnConnection()->useOldDateFormat() ? SQL_C_DATE : SQL_C_TYPE_DATE,
500 											&aDate,sizeof aDate);
501 	return (&aValue == &m_aEmptyValue)  ? Date(aDate.day,aDate.month,aDate.year) : (Date)aValue;
502 }
503 // -------------------------------------------------------------------------
504 
505 double SAL_CALL OResultSet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
506 {
507 	double nRet(0);
508 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_DOUBLE,&nRet,sizeof nRet);
509 	return (&aValue == &m_aEmptyValue) ? nRet : (double)aValue;
510 }
511 // -------------------------------------------------------------------------
512 
513 float SAL_CALL OResultSet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
514 {
515 	float nRet(0);
516 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_FLOAT,&nRet,sizeof nRet);
517 	return (&aValue == &m_aEmptyValue) ? nRet : (float)aValue;
518 }
519 // -------------------------------------------------------------------------
520 
521 sal_Int32 SAL_CALL OResultSet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
522 {
523 	sal_Int32 nRet(0);
524 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_LONG,&nRet,sizeof nRet);
525 	return (&aValue == &m_aEmptyValue) ? nRet : (sal_Int32)aValue;
526 }
527 // -------------------------------------------------------------------------
528 
529 sal_Int32 SAL_CALL OResultSet::getRow(  ) throw(SQLException, RuntimeException)
530 {
531 	::osl::MutexGuard aGuard( m_aMutex );
532 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
533 
534 	return m_pSkipDeletedSet ? m_pSkipDeletedSet->getMappedPosition(getDriverPos()) : getDriverPos();
535 }
536 // -------------------------------------------------------------------------
537 
538 sal_Int64 SAL_CALL OResultSet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
539 {
540 	sal_Int64 nRet(0);
541 	try
542 	{
543 		const ORowSetValue& aValue = getValue(columnIndex,SQL_C_SBIGINT,&nRet,sizeof nRet);
544 		return (&aValue == &m_aEmptyValue) ? nRet : (sal_Int64)aValue;
545 	}
546 	catch(SQLException&)
547 	{
548 		nRet = getString(columnIndex).toInt64();
549 	}
550 	return nRet;
551 }
552 // -------------------------------------------------------------------------
553 
554 Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData(  ) throw(SQLException, RuntimeException)
555 {
556     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getMetaData" );
557 	::osl::MutexGuard aGuard( m_aMutex );
558 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
559 
560 
561 	if(!m_xMetaData.is())
562 		m_xMetaData = new OResultSetMetaData(m_pStatement->getOwnConnection(),m_aStatementHandle);
563 	return m_xMetaData;
564 }
565 // -------------------------------------------------------------------------
566 Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
567 {
568     ::dbtools::throwFunctionNotSupportedException( "XRow::getArray", *this );
569 	return NULL;
570 }
571 
572 // -------------------------------------------------------------------------
573 
574 Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
575 {
576     ::dbtools::throwFunctionNotSupportedException( "XRow::getClob", *this );
577 	return NULL;
578 }
579 // -------------------------------------------------------------------------
580 Reference< XBlob > SAL_CALL OResultSet::getBlob( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
581 {
582     ::dbtools::throwFunctionNotSupportedException( "XRow::getBlob", *this );
583 	return NULL;
584 }
585 // -------------------------------------------------------------------------
586 
587 Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException)
588 {
589     ::dbtools::throwFunctionNotSupportedException( "XRow::getRef", *this );
590 	return NULL;
591 }
592 // -------------------------------------------------------------------------
593 
594 Any SAL_CALL OResultSet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException)
595 {
596     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getObject" );
597 	::osl::MutexGuard aGuard( m_aMutex );
598 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
599 
600 	fillRow(columnIndex);
601 	return m_aRow[columnIndex].makeAny();
602 }
603 // -------------------------------------------------------------------------
604 
605 sal_Int16 SAL_CALL OResultSet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
606 {
607 	sal_Int16 nRet(0);
608 	const ORowSetValue& aValue = getValue(columnIndex,SQL_C_SHORT,&nRet,sizeof nRet);
609 	return (&aValue == &m_aEmptyValue) ? nRet : (sal_Int16)aValue;
610 }
611 // -------------------------------------------------------------------------
612 
613 
614 ::rtl::OUString SAL_CALL OResultSet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
615 {
616     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getString" );
617 	::osl::MutexGuard aGuard( m_aMutex );
618 
619 	::rtl::OUString nRet;
620 	if ( m_bFetchData )
621 		nRet = getValue(columnIndex,0,NULL,0);
622 	else
623     {
624         checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
625         const SWORD nColumnType = impl_getColumnType_nothrow(columnIndex);
626 		nRet = OTools::getStringValue(m_pStatement->getOwnConnection(),m_aStatementHandle,columnIndex,nColumnType,m_bWasNull,**this,m_nTextEncoding);
627     }
628 	return nRet;
629 }
630 // -------------------------------------------------------------------------
631 
632 Time SAL_CALL OResultSet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
633 {
634     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getTime" );
635 	TIME_STRUCT aTime={0,0,0};
636 	const ORowSetValue& aValue = getValue(columnIndex,
637 		m_pStatement->getOwnConnection()->useOldDateFormat() ? SQL_C_TIME : SQL_C_TYPE_TIME,
638 		&aTime,sizeof aTime);
639 	return (&aValue == &m_aEmptyValue) ? Time(0,aTime.second,aTime.minute,aTime.hour) : (Time)aValue;
640 }
641 // -------------------------------------------------------------------------
642 
643 
644 DateTime SAL_CALL OResultSet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
645 {
646     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getTimestamp" );
647 	TIMESTAMP_STRUCT aTime={0,0,0,0,0,0,0};
648 	const ORowSetValue& aValue = getValue(columnIndex,
649 		m_pStatement->getOwnConnection()->useOldDateFormat() ? SQL_C_TIMESTAMP : SQL_C_TYPE_TIMESTAMP,
650 		&aTime,sizeof aTime);
651 	return (&aValue == &m_aEmptyValue)
652 			?
653 			DateTime(static_cast<sal_uInt16>(aTime.fraction*1000),aTime.second,aTime.minute,aTime.hour,aTime.day,aTime.month,aTime.year)
654 			:
655 			(DateTime)aValue;
656 }
657 // -------------------------------------------------------------------------
658 
659 sal_Bool SAL_CALL OResultSet::isBeforeFirst(  ) throw(SQLException, RuntimeException)
660 {
661 	::osl::MutexGuard aGuard( m_aMutex );
662 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
663 	return m_nRowPos == 0;
664 }
665 // -------------------------------------------------------------------------
666 sal_Bool SAL_CALL OResultSet::isAfterLast(  ) throw(SQLException, RuntimeException)
667 {
668 	::osl::MutexGuard aGuard( m_aMutex );
669 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
670 
671 	return m_nRowPos != 0 && m_nCurrentFetchState == SQL_NO_DATA;
672 }
673 // -------------------------------------------------------------------------
674 sal_Bool SAL_CALL OResultSet::isFirst(  ) throw(SQLException, RuntimeException)
675 {
676 	::osl::MutexGuard aGuard( m_aMutex );
677 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
678 
679 	return m_nRowPos == 1;
680 }
681 // -------------------------------------------------------------------------
682 sal_Bool SAL_CALL OResultSet::isLast(  ) throw(SQLException, RuntimeException)
683 {
684 	::osl::MutexGuard aGuard( m_aMutex );
685 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
686 
687 
688 	return m_bEOF && m_nCurrentFetchState != SQL_NO_DATA;
689 }
690 // -------------------------------------------------------------------------
691 void SAL_CALL OResultSet::beforeFirst(  ) throw(SQLException, RuntimeException)
692 {
693     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::beforeFirst" );
694 	::osl::MutexGuard aGuard( m_aMutex );
695 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
696 
697 
698 	if(first())
699 		previous();
700 	m_nCurrentFetchState = SQL_SUCCESS;
701 }
702 // -------------------------------------------------------------------------
703 void SAL_CALL OResultSet::afterLast(  ) throw(SQLException, RuntimeException)
704 {
705     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::afterLast" );
706 	::osl::MutexGuard aGuard( m_aMutex );
707 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
708 
709 	if(last())
710 		next();
711 	m_bEOF = sal_True;
712 }
713 // -------------------------------------------------------------------------
714 
715 void SAL_CALL OResultSet::close(  ) throw(SQLException, RuntimeException)
716 {
717 	{
718 		::osl::MutexGuard aGuard( m_aMutex );
719 		checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
720 
721 	}
722 	dispose();
723 }
724 // -------------------------------------------------------------------------
725 
726 sal_Bool SAL_CALL OResultSet::first(  ) throw(SQLException, RuntimeException)
727 {
728     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::first" );
729 	return moveImpl(IResultSetHelper::FIRST,0,sal_True);
730 }
731 // -------------------------------------------------------------------------
732 
733 sal_Bool SAL_CALL OResultSet::last(  ) throw(SQLException, RuntimeException)
734 {
735     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::last" );
736 	return moveImpl(IResultSetHelper::LAST,0,sal_True);
737 }
738 // -------------------------------------------------------------------------
739 sal_Bool SAL_CALL OResultSet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException)
740 {
741     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::absolute" );
742 	return moveImpl(IResultSetHelper::ABSOLUTE,row,sal_True);
743 }
744 // -------------------------------------------------------------------------
745 sal_Bool SAL_CALL OResultSet::relative( sal_Int32 row ) throw(SQLException, RuntimeException)
746 {
747     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::relative" );
748 	return moveImpl(IResultSetHelper::RELATIVE,row,sal_True);
749 }
750 // -------------------------------------------------------------------------
751 sal_Bool SAL_CALL OResultSet::previous(  ) throw(SQLException, RuntimeException)
752 {
753     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::previous" );
754 	return moveImpl(IResultSetHelper::PRIOR,0,sal_True);
755 }
756 // -------------------------------------------------------------------------
757 Reference< XInterface > SAL_CALL OResultSet::getStatement(  ) throw(SQLException, RuntimeException)
758 {
759 	::osl::MutexGuard aGuard( m_aMutex );
760 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
761 	return m_xStatement;
762 }
763 // -------------------------------------------------------------------------
764 
765 sal_Bool SAL_CALL OResultSet::rowDeleted() throw(SQLException, RuntimeException)
766 {
767     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::rowDeleted" );
768 	::osl::MutexGuard aGuard( m_aMutex );
769 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
770 
771 	sal_Bool bRet = m_bRowDeleted;
772 	m_bRowDeleted = sal_False;
773 
774 	return bRet;
775 }
776 // -------------------------------------------------------------------------
777 sal_Bool SAL_CALL OResultSet::rowInserted(  ) throw(SQLException, RuntimeException)
778 {
779     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::rowInserted" );
780 	::osl::MutexGuard aGuard( m_aMutex );
781 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
782 
783 	sal_Bool bInserted = m_bRowInserted;
784 	m_bRowInserted = sal_False;
785 
786 	return bInserted;
787 }
788 // -------------------------------------------------------------------------
789 sal_Bool SAL_CALL OResultSet::rowUpdated(  ) throw(SQLException, RuntimeException)
790 {
791     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::rowUpdated" );
792 	::osl::MutexGuard aGuard( m_aMutex );
793 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
794 
795 
796 	return m_pRowStatusArray[0] == SQL_ROW_UPDATED;
797 }
798 // -------------------------------------------------------------------------
799 
800 sal_Bool SAL_CALL OResultSet::next(  ) throw(SQLException, RuntimeException)
801 {
802     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::next" );
803 	return moveImpl(IResultSetHelper::NEXT,1,sal_True);
804 }
805 // -------------------------------------------------------------------------
806 
807 sal_Bool SAL_CALL OResultSet::wasNull(  ) throw(SQLException, RuntimeException)
808 {
809     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::wasNull" );
810 	::osl::MutexGuard aGuard( m_aMutex );
811 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
812 
813 
814 	return m_bFetchData ? m_aRow[m_nLastColumnPos].isNull() : m_bWasNull;
815 }
816 // -------------------------------------------------------------------------
817 
818 void SAL_CALL OResultSet::cancel(  ) throw(RuntimeException)
819 {
820 	::osl::MutexGuard aGuard( m_aMutex );
821 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
822 
823 
824 	OTools::ThrowException(m_pStatement->getOwnConnection(),N3SQLCancel(m_aStatementHandle),m_aStatementHandle,SQL_HANDLE_STMT,*this);
825 }
826 // -------------------------------------------------------------------------
827 void SAL_CALL OResultSet::clearWarnings(  ) throw(SQLException, RuntimeException)
828 {
829 }
830 // -------------------------------------------------------------------------
831 Any SAL_CALL OResultSet::getWarnings(  ) throw(SQLException, RuntimeException)
832 {
833 	return Any();
834 }
835 // -------------------------------------------------------------------------
836 void SAL_CALL OResultSet::insertRow(  ) throw(SQLException, RuntimeException)
837 {
838     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::insertRow" );
839 	::osl::MutexGuard aGuard( m_aMutex );
840 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
841 
842 
843 	SQLLEN nMaxLen = 20;
844 	SQLLEN nRealLen = 0;
845 	Sequence<sal_Int8> aBookmark(nMaxLen);
846 
847 	SQLRETURN nRet = N3SQLBindCol(m_aStatementHandle,
848 								0,
849 								SQL_C_VARBOOKMARK,
850 								aBookmark.getArray(),
851 								nMaxLen,
852 								&nRealLen
853 								);
854 	//	Sequence<sal_Int8> aRealBookmark(nMaxLen);
855 
856     sal_Bool bPositionByBookmark = ( NULL != getOdbcFunction( ODBC3SQLBulkOperations ) );
857 	if ( bPositionByBookmark )
858 	{
859         nRet = N3SQLBulkOperations( m_aStatementHandle, SQL_ADD );
860         fillNeededData( nRet );
861 	}
862 	else
863 	{
864 		if(isBeforeFirst())
865 			next(); // must be done
866         nRet = N3SQLSetPos( m_aStatementHandle, 1, SQL_ADD, SQL_LOCK_NO_CHANGE );
867         fillNeededData( nRet );
868 	}
869 	try
870 	{
871 		OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
872 	}
873 	catch(SQLException e)
874 	{
875 		nRet = unbind();
876 		throw;
877 	}
878 
879 
880 	if ( bPositionByBookmark )
881 	{
882 		nRet = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_FETCH_BOOKMARK_PTR,aBookmark.getArray(),SQL_IS_POINTER); // SQL_LEN_BINARY_ATTR(aBookmark.getLength())
883 
884 		nRet = N3SQLFetchScroll(m_aStatementHandle,SQL_FETCH_BOOKMARK,0);
885 	}
886 	else
887 		nRet = N3SQLFetchScroll(m_aStatementHandle,SQL_FETCH_RELATIVE,0); // OJ 06.03.2004
888 	// sometimes we got an error but we are not interested in anymore #106047# OJ
889 	//	OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
890 	nRet = unbind();
891 	OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
892 
893 	if(m_pSkipDeletedSet)
894 	{
895 		aBookmark.realloc(nRealLen);
896 		if(moveToBookmark(makeAny(aBookmark)))
897 		{
898 			sal_Int32 nRowPos = getDriverPos();
899 			if ( -1 == m_nRowPos )
900 			{
901 				nRowPos = m_aPosToBookmarks.size() + 1;
902 			}
903 			if ( nRowPos == m_nRowPos )
904 				++nRowPos;
905 			m_nRowPos = nRowPos;
906 			m_pSkipDeletedSet->insertNewPosition(nRowPos);
907 			m_aPosToBookmarks[aBookmark] = nRowPos;
908 		}
909 	}
910 	m_bRowInserted = sal_True;
911 
912 }
913 // -------------------------------------------------------------------------
914 void SAL_CALL OResultSet::updateRow(  ) throw(SQLException, RuntimeException)
915 {
916     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::updateRow" );
917 	::osl::MutexGuard aGuard( m_aMutex );
918 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
919 
920 	SQLRETURN nRet;
921 
922     sal_Bool bPositionByBookmark = ( NULL != getOdbcFunction( ODBC3SQLBulkOperations ) );
923 	if ( bPositionByBookmark )
924 	{
925 		SQLLEN nRealLen = 0;
926 		nRet = N3SQLBindCol(m_aStatementHandle,
927 							0,
928 							SQL_C_VARBOOKMARK,
929 							m_aBookmark.getArray(),
930 							m_aBookmark.getLength(),
931 							&nRealLen
932 							);
933 		fillNeededData(nRet = N3SQLBulkOperations(m_aStatementHandle, SQL_UPDATE_BY_BOOKMARK));
934 	}
935 	else
936 		fillNeededData(nRet = N3SQLSetPos(m_aStatementHandle,1,SQL_UPDATE,SQL_LOCK_NO_CHANGE));
937 	OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
938 	// now unbind all columns so we can fetch all columns again with SQLGetData
939 	nRet = unbind();
940 	OSL_ENSURE(nRet == SQL_SUCCESS,"Could not unbind the columns!");
941 }
942 // -------------------------------------------------------------------------
943 void SAL_CALL OResultSet::deleteRow(  ) throw(SQLException, RuntimeException)
944 {
945     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::deleteRow" );
946 	SQLRETURN nRet = SQL_SUCCESS;
947 	sal_Int32 nPos = getDriverPos();
948 	nRet = N3SQLSetPos(m_aStatementHandle,1,SQL_DELETE,SQL_LOCK_NO_CHANGE);
949 	OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
950 
951     m_bRowDeleted = ( m_pRowStatusArray[0] == SQL_ROW_DELETED );
952     if ( m_bRowDeleted )
953 	{
954 		TBookmarkPosMap::iterator aIter = m_aPosToBookmarks.begin();
955 		TBookmarkPosMap::iterator aEnd = m_aPosToBookmarks.end();
956 		for (; aIter != aEnd; ++aIter)
957 		{
958 			if ( aIter->second == nPos )
959 			{
960 				m_aPosToBookmarks.erase(aIter);
961 				break;
962 			}
963 		}
964 	}
965 	if ( m_pSkipDeletedSet )
966 		m_pSkipDeletedSet->deletePosition(nPos);
967 }
968 // -------------------------------------------------------------------------
969 
970 void SAL_CALL OResultSet::cancelRowUpdates(  ) throw(SQLException, RuntimeException)
971 {
972 }
973 // -------------------------------------------------------------------------
974 
975 void SAL_CALL OResultSet::moveToInsertRow(  ) throw(SQLException, RuntimeException)
976 {
977     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::moveToInsertRow" );
978 	::osl::MutexGuard aGuard( m_aMutex );
979 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
980 
981 
982 	m_nLastColumnPos = 0;
983 	// first unbound all columns
984     OSL_VERIFY_EQUALS( unbind(), SQL_SUCCESS, "Could not unbind columns!" );
985 	//	SQLRETURN nRet = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE ,(SQLPOINTER)1,SQL_IS_INTEGER);
986 	m_bInserting = sal_True;
987 }
988 // -------------------------------------------------------------------------
989 
990 void SAL_CALL OResultSet::moveToCurrentRow(  ) throw(SQLException, RuntimeException)
991 {
992 	m_nLastColumnPos = 0;
993 }
994 // -------------------------------------------------------------------------
995 void OResultSet::updateValue(sal_Int32 columnIndex,SQLSMALLINT _nType,void* _pValue) throw(SQLException, RuntimeException)
996 {
997     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::updateValue" );
998 	::osl::MutexGuard aGuard( m_aMutex );
999 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1000 
1001 	m_aBindVector.push_back(allocBindColumn(OTools::MapOdbcType2Jdbc(_nType),columnIndex));
1002 	void* pData = reinterpret_cast<void*>(m_aBindVector.rbegin()->first);
1003 	OSL_ENSURE(pData != NULL,"Data for update is NULL!");
1004 	OTools::bindValue(	m_pStatement->getOwnConnection(),
1005 						m_aStatementHandle,
1006 						columnIndex,
1007 						_nType,
1008 						0,
1009 						_pValue,
1010 						pData,
1011 						&m_aLengthVector[columnIndex],
1012 						**this,
1013 						m_nTextEncoding,
1014 						m_pStatement->getOwnConnection()->useOldDateFormat());
1015 }
1016 // -----------------------------------------------------------------------------
1017 void SAL_CALL OResultSet::updateNull( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1018 {
1019 	::osl::MutexGuard aGuard( m_aMutex );
1020 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1021 
1022 	m_aBindVector.push_back(allocBindColumn(DataType::CHAR,columnIndex));
1023 	void* pData = reinterpret_cast<void*>(m_aBindVector.rbegin()->first);
1024 	OTools::bindValue(m_pStatement->getOwnConnection(),m_aStatementHandle,columnIndex,SQL_CHAR,0,(sal_Int8*)NULL,pData,&m_aLengthVector[columnIndex],**this,m_nTextEncoding,m_pStatement->getOwnConnection()->useOldDateFormat());
1025 }
1026 // -------------------------------------------------------------------------
1027 
1028 void SAL_CALL OResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) throw(SQLException, RuntimeException)
1029 {
1030 	updateValue(columnIndex,SQL_BIT,&x);
1031 }
1032 // -------------------------------------------------------------------------
1033 void SAL_CALL OResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
1034 {
1035 	updateValue(columnIndex,SQL_CHAR,&x);
1036 }
1037 // -------------------------------------------------------------------------
1038 
1039 void SAL_CALL OResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
1040 {
1041 	updateValue(columnIndex,SQL_TINYINT,&x);
1042 }
1043 // -------------------------------------------------------------------------
1044 void SAL_CALL OResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
1045 {
1046 	updateValue(columnIndex,SQL_INTEGER,&x);
1047 }
1048 // -------------------------------------------------------------------------
1049 void SAL_CALL OResultSet::updateLong( sal_Int32 /*columnIndex*/, sal_Int64 /*x*/ ) throw(SQLException, RuntimeException)
1050 {
1051     ::dbtools::throwFunctionNotSupportedException( "XRowUpdate::updateLong", *this );
1052 }
1053 // -----------------------------------------------------------------------
1054 void SAL_CALL OResultSet::updateFloat( sal_Int32 columnIndex, float x ) throw(SQLException, RuntimeException)
1055 {
1056 	updateValue(columnIndex,SQL_REAL,&x);
1057 }
1058 // -------------------------------------------------------------------------
1059 
1060 void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x ) throw(SQLException, RuntimeException)
1061 {
1062 	updateValue(columnIndex,SQL_DOUBLE,&x);
1063 }
1064 // -------------------------------------------------------------------------
1065 void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
1066 {
1067 	sal_Int32 nType = m_aRow[columnIndex].getTypeKind();
1068 	SQLSMALLINT nOdbcType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(nType));
1069 	m_aRow[columnIndex] = x;
1070 	m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarchar will be recognized by fillNeededData
1071 	updateValue(columnIndex,nOdbcType,(void*)&x);
1072 }
1073 // -------------------------------------------------------------------------
1074 void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
1075 {
1076 	sal_Int32 nType = m_aRow[columnIndex].getTypeKind();
1077 	SQLSMALLINT nOdbcType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(nType));
1078 	m_aRow[columnIndex] = x;
1079 	m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarbinary will be recognized by fillNeededData
1080 	updateValue(columnIndex,nOdbcType,(void*)&x);
1081 }
1082 // -------------------------------------------------------------------------
1083 void SAL_CALL OResultSet::updateDate( sal_Int32 columnIndex, const Date& x ) throw(SQLException, RuntimeException)
1084 {
1085 	DATE_STRUCT aVal = OTools::DateToOdbcDate(x);
1086 	updateValue(columnIndex,SQL_DATE,&aVal);
1087 }
1088 // -------------------------------------------------------------------------
1089 
1090 void SAL_CALL OResultSet::updateTime( sal_Int32 columnIndex, const Time& x ) throw(SQLException, RuntimeException)
1091 {
1092 	TIME_STRUCT aVal = OTools::TimeToOdbcTime(x);
1093 	updateValue(columnIndex,SQL_TIME,&aVal);
1094 }
1095 // -------------------------------------------------------------------------
1096 
1097 void SAL_CALL OResultSet::updateTimestamp( sal_Int32 columnIndex, const DateTime& x ) throw(SQLException, RuntimeException)
1098 {
1099 	TIMESTAMP_STRUCT aVal = OTools::DateTimeToTimestamp(x);
1100 	updateValue(columnIndex,SQL_TIMESTAMP,&aVal);
1101 }
1102 // -------------------------------------------------------------------------
1103 
1104 void SAL_CALL OResultSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
1105 {
1106 	if(!x.is())
1107 		::dbtools::throwFunctionSequenceException(*this);
1108 
1109 	Sequence<sal_Int8> aSeq;
1110 	x->readBytes(aSeq,length);
1111 	updateBytes(columnIndex,aSeq);
1112 }
1113 // -------------------------------------------------------------------------
1114 void SAL_CALL OResultSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
1115 {
1116 	updateBinaryStream(columnIndex,x,length);
1117 }
1118 // -------------------------------------------------------------------------
1119 void SAL_CALL OResultSet::refreshRow(  ) throw(SQLException, RuntimeException)
1120 {
1121     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::refreshRow" );
1122 	::osl::MutexGuard aGuard( m_aMutex );
1123 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1124 
1125 
1126 	//	SQLRETURN nRet = N3SQLSetPos(m_aStatementHandle,1,SQL_REFRESH,SQL_LOCK_NO_CHANGE);
1127 	m_nCurrentFetchState = N3SQLFetchScroll(m_aStatementHandle,SQL_FETCH_RELATIVE,0);
1128 	OTools::ThrowException(m_pStatement->getOwnConnection(),m_nCurrentFetchState,m_aStatementHandle,SQL_HANDLE_STMT,*this);
1129 }
1130 // -------------------------------------------------------------------------
1131 void SAL_CALL OResultSet::updateObject( sal_Int32 columnIndex, const Any& x ) throw(SQLException, RuntimeException)
1132 {
1133 	if (!::dbtools::implUpdateObject(this, columnIndex, x))
1134 		throw SQLException();
1135 }
1136 // -------------------------------------------------------------------------
1137 
1138 void SAL_CALL OResultSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ ) throw(SQLException, RuntimeException)
1139 {
1140 	if (!::dbtools::implUpdateObject(this, columnIndex, x))
1141 		throw SQLException();
1142 }
1143 // -------------------------------------------------------------------------
1144 // XRowLocate
1145 Any SAL_CALL OResultSet::getBookmark(  ) throw( SQLException,  RuntimeException)
1146 {
1147     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::getBookmark" );
1148 	 ::osl::MutexGuard aGuard( m_aMutex );
1149 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1150 
1151 	TBookmarkPosMap::iterator aFind = ::std::find_if(m_aPosToBookmarks.begin(),m_aPosToBookmarks.end(),
1152 		::std::compose1(::std::bind2nd(::std::equal_to<sal_Int32>(),m_nRowPos),::std::select2nd<TBookmarkPosMap::value_type>()));
1153 
1154 	if ( aFind == m_aPosToBookmarks.end() )
1155 	{
1156         if ( m_nUseBookmarks == ODBC_SQL_NOT_DEFINED )
1157         {
1158             RTL_LOGFILE_CONTEXT_TRACE( aLogger, "SQLGetStmtAttr" );
1159             m_nUseBookmarks = SQL_UB_OFF;
1160 		    SQLRETURN nRet = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_USE_BOOKMARKS,&m_nUseBookmarks,SQL_IS_UINTEGER,NULL);
1161             OSL_UNUSED( nRet );
1162         }
1163 		if(m_nUseBookmarks == SQL_UB_OFF)
1164 			throw SQLException();
1165 
1166 		m_aBookmark = OTools::getBytesValue(m_pStatement->getOwnConnection(),m_aStatementHandle,0,SQL_C_VARBOOKMARK,m_bWasNull,**this);
1167 		m_aPosToBookmarks[m_aBookmark] = m_nRowPos;
1168 		OSL_ENSURE(m_aBookmark.getLength(),"Invalid bookmark from length 0!");
1169 	}
1170 	else
1171 		m_aBookmark = aFind->first;
1172 	return makeAny(m_aBookmark);
1173 }
1174 // -------------------------------------------------------------------------
1175 sal_Bool SAL_CALL OResultSet::moveToBookmark( const  Any& bookmark ) throw( SQLException,  RuntimeException)
1176 {
1177     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::moveToBookmark" );
1178 	::osl::MutexGuard aGuard( m_aMutex );
1179 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1180 
1181 	m_nLastColumnPos = 0;
1182 	bookmark >>= m_aBookmark;
1183 	OSL_ENSURE(m_aBookmark.getLength(),"Invalid bookmark from length 0!");
1184 	if(m_aBookmark.getLength())
1185 	{
1186 		SQLRETURN nReturn = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_FETCH_BOOKMARK_PTR,m_aBookmark.getArray(),SQL_IS_POINTER); // SQL_LEN_BINARY_ATTR(aBookmark.getLength())
1187         OSL_UNUSED( nReturn );
1188 
1189         if ( SQL_INVALID_HANDLE != nReturn && SQL_ERROR != nReturn )
1190         {
1191 		    m_nCurrentFetchState = N3SQLFetchScroll(m_aStatementHandle,SQL_FETCH_BOOKMARK,0);
1192 		    OTools::ThrowException(m_pStatement->getOwnConnection(),m_nCurrentFetchState,m_aStatementHandle,SQL_HANDLE_STMT,*this);
1193 		    TBookmarkPosMap::iterator aFind = m_aPosToBookmarks.find(m_aBookmark);
1194 		    if(aFind != m_aPosToBookmarks.end())
1195 			    m_nRowPos = aFind->second;
1196 		    else
1197 			    m_nRowPos = -1;
1198 		    return m_nCurrentFetchState == SQL_SUCCESS || m_nCurrentFetchState == SQL_SUCCESS_WITH_INFO;
1199         }
1200 	}
1201 	return sal_False;
1202 }
1203 // -------------------------------------------------------------------------
1204 sal_Bool SAL_CALL OResultSet::moveRelativeToBookmark( const  Any& bookmark, sal_Int32 rows ) throw( SQLException,  RuntimeException)
1205 {
1206     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::moveRelativeToBookmark" );
1207 	::osl::MutexGuard aGuard( m_aMutex );
1208 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1209 
1210 
1211 	m_nLastColumnPos = 0;
1212 	bookmark >>= m_aBookmark;
1213 	SQLRETURN nReturn = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_FETCH_BOOKMARK_PTR,m_aBookmark.getArray(),SQL_IS_POINTER);
1214     OSL_UNUSED( nReturn );
1215 
1216 	m_nCurrentFetchState = N3SQLFetchScroll(m_aStatementHandle,SQL_FETCH_BOOKMARK,rows);
1217 	OTools::ThrowException(m_pStatement->getOwnConnection(),m_nCurrentFetchState,m_aStatementHandle,SQL_HANDLE_STMT,*this);
1218 	return m_nCurrentFetchState == SQL_SUCCESS || m_nCurrentFetchState == SQL_SUCCESS_WITH_INFO;
1219 }
1220 // -------------------------------------------------------------------------
1221 sal_Int32 SAL_CALL OResultSet::compareBookmarks( const Any& lhs, const  Any& rhs ) throw( SQLException,  RuntimeException)
1222 {
1223     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::compareBookmarks" );
1224 	::osl::MutexGuard aGuard( m_aMutex );
1225 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1226 
1227 	return (lhs == rhs) ? CompareBookmark::EQUAL : CompareBookmark::NOT_EQUAL;
1228 }
1229 // -------------------------------------------------------------------------
1230 sal_Bool SAL_CALL OResultSet::hasOrderedBookmarks(  ) throw( SQLException,  RuntimeException)
1231 {
1232 	return sal_False;
1233 }
1234 // -------------------------------------------------------------------------
1235 sal_Int32 SAL_CALL OResultSet::hashBookmark( const  Any& /*bookmark*/ ) throw( SQLException,  RuntimeException)
1236 {
1237     ::dbtools::throwFunctionNotSupportedException( "XRowLocate::hashBookmark", *this );
1238     return 0;
1239 }
1240 // -------------------------------------------------------------------------
1241 // XDeleteRows
1242 Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows( const  Sequence<  Any >& rows ) throw( SQLException,  RuntimeException)
1243 {
1244 	Sequence< sal_Int32 > aRet(rows.getLength());
1245 	sal_Int32 *pRet	= aRet.getArray();
1246 
1247 	const Any *pBegin	= rows.getConstArray();
1248 	const Any *pEnd		= pBegin + rows.getLength();
1249 
1250 	for(;pBegin != pEnd;++pBegin,++pRet)
1251 	{
1252 		try
1253 		{
1254 			if(moveToBookmark(*pBegin))
1255 			{
1256 				deleteRow();
1257 				*pRet = 1;
1258 			}
1259 		}
1260 		catch(SQLException&)
1261 		{
1262 			*pRet = 0;
1263 		}
1264 	}
1265 	return aRet;
1266 }
1267 //------------------------------------------------------------------------------
1268 sal_Int32 OResultSet::getResultSetConcurrency() const
1269 {
1270 	sal_uInt32 nValue = 0;
1271 	SQLRETURN nReturn = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CONCURRENCY,&nValue,SQL_IS_UINTEGER,0);
1272     OSL_UNUSED( nReturn );
1273 	if(SQL_CONCUR_READ_ONLY == nValue)
1274 		nValue = ResultSetConcurrency::READ_ONLY;
1275 	else
1276 		nValue = ResultSetConcurrency::UPDATABLE;
1277 
1278 	return nValue;
1279 }
1280 //------------------------------------------------------------------------------
1281 sal_Int32 OResultSet::getResultSetType() const
1282 {
1283 	sal_uInt32 nValue = 0;
1284 	N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_SENSITIVITY,&nValue,SQL_IS_UINTEGER,0);
1285 	if(SQL_SENSITIVE == nValue)
1286 		nValue = ResultSetType::SCROLL_SENSITIVE;
1287 	else if(SQL_INSENSITIVE == nValue)
1288 		nValue = ResultSetType::SCROLL_INSENSITIVE;
1289 	else
1290 	{
1291 		SQLINTEGER nCurType = 0;
1292 		N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_TYPE,&nCurType,SQL_IS_UINTEGER,0);
1293 		if(SQL_CURSOR_KEYSET_DRIVEN == nCurType)
1294 			nValue = ResultSetType::SCROLL_SENSITIVE;
1295 		else if(SQL_CURSOR_STATIC  == nCurType)
1296 			nValue = ResultSetType::SCROLL_INSENSITIVE;
1297 		else if(SQL_CURSOR_FORWARD_ONLY == nCurType)
1298 			nValue = ResultSetType::FORWARD_ONLY;
1299 		else if(SQL_CURSOR_DYNAMIC == nCurType)
1300 			nValue = ResultSetType::SCROLL_SENSITIVE;
1301 	}
1302 	return nValue;
1303 }
1304 //------------------------------------------------------------------------------
1305 sal_Int32 OResultSet::getFetchDirection() const
1306 {
1307 	return FetchDirection::FORWARD;
1308 }
1309 //------------------------------------------------------------------------------
1310 sal_Int32 OResultSet::getFetchSize() const
1311 {
1312 	sal_uInt32 nValue = 0;
1313 	N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE,&nValue,SQL_IS_UINTEGER,0);
1314 	return nValue;
1315 }
1316 //------------------------------------------------------------------------------
1317 ::rtl::OUString OResultSet::getCursorName() const
1318 {
1319 	SQLCHAR pName[258];
1320 	SQLSMALLINT nRealLen = 0;
1321 	N3SQLGetCursorName(m_aStatementHandle,(SQLCHAR*)pName,256,&nRealLen);
1322 	return ::rtl::OUString::createFromAscii((const char*)pName);
1323 }
1324 // -------------------------------------------------------------------------
1325 sal_Bool  OResultSet::isBookmarkable() const
1326 {
1327 	if(!m_aConnectionHandle)
1328 		return sal_False;
1329 
1330 	sal_uInt32 nValue = 0;
1331 	N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_TYPE,&nValue,SQL_IS_UINTEGER,0);
1332 
1333 	sal_Int32 nAttr = 0;
1334 	try
1335 	{
1336 		switch(nValue)
1337 		{
1338 		case SQL_CURSOR_FORWARD_ONLY:
1339 			return sal_False;
1340 		case SQL_CURSOR_STATIC:
1341 			OTools::GetInfo(m_pStatement->getOwnConnection(),m_aConnectionHandle,SQL_STATIC_CURSOR_ATTRIBUTES1,nAttr,NULL);
1342 			break;
1343 		case SQL_CURSOR_KEYSET_DRIVEN:
1344 			OTools::GetInfo(m_pStatement->getOwnConnection(),m_aConnectionHandle,SQL_KEYSET_CURSOR_ATTRIBUTES1,nAttr,NULL);
1345 			break;
1346 		case SQL_CURSOR_DYNAMIC:
1347 			OTools::GetInfo(m_pStatement->getOwnConnection(),m_aConnectionHandle,SQL_DYNAMIC_CURSOR_ATTRIBUTES1,nAttr,NULL);
1348 			break;
1349 		}
1350 	}
1351 	catch(Exception&)
1352 	{
1353 		return sal_False;
1354 	}
1355 
1356     if ( m_nUseBookmarks == ODBC_SQL_NOT_DEFINED )
1357     {
1358         m_nUseBookmarks = SQL_UB_OFF;
1359 	    SQLRETURN nRet = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_USE_BOOKMARKS,&m_nUseBookmarks,SQL_IS_UINTEGER,NULL);
1360         OSL_UNUSED( nRet );
1361     }
1362 
1363 	return (m_nUseBookmarks != SQL_UB_OFF) && (nAttr & SQL_CA1_BOOKMARK) == SQL_CA1_BOOKMARK;
1364 }
1365 //------------------------------------------------------------------------------
1366 void OResultSet::setFetchDirection(sal_Int32 _par0)
1367 {
1368 	OSL_ENSURE(_par0>0,"Illegal fetch direction!");
1369 	if ( _par0 > 0 )
1370 	{
1371 		N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_TYPE,(SQLPOINTER)_par0,SQL_IS_UINTEGER);
1372 	}
1373 }
1374 //------------------------------------------------------------------------------
1375 void OResultSet::setFetchSize(sal_Int32 _par0)
1376 {
1377 	OSL_ENSURE(_par0>0,"Illegal fetch size!");
1378 	if ( _par0 > 0 )
1379 	{
1380 		N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE,(SQLPOINTER)_par0,SQL_IS_UINTEGER);
1381 		delete m_pRowStatusArray;
1382 
1383 		m_pRowStatusArray = new SQLUSMALLINT[_par0];
1384 		N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_STATUS_PTR,m_pRowStatusArray,SQL_IS_POINTER);
1385 	}
1386 }
1387 // -------------------------------------------------------------------------
1388 IPropertyArrayHelper* OResultSet::createArrayHelper( ) const
1389 {
1390 	Sequence< Property > aProps(6);
1391 	Property* pProperties = aProps.getArray();
1392 	sal_Int32 nPos = 0;
1393 	DECL_PROP1IMPL(CURSORNAME,			::rtl::OUString) PropertyAttribute::READONLY);
1394 	DECL_PROP0(FETCHDIRECTION,			sal_Int32);
1395 	DECL_PROP0(FETCHSIZE,				sal_Int32);
1396 	DECL_BOOL_PROP1IMPL(ISBOOKMARKABLE) PropertyAttribute::READONLY);
1397 	DECL_PROP1IMPL(RESULTSETCONCURRENCY,sal_Int32) PropertyAttribute::READONLY);
1398 	DECL_PROP1IMPL(RESULTSETTYPE,		sal_Int32) PropertyAttribute::READONLY);
1399 
1400 	return new OPropertyArrayHelper(aProps);
1401 }
1402 // -------------------------------------------------------------------------
1403 IPropertyArrayHelper & OResultSet::getInfoHelper()
1404 {
1405 	return *const_cast<OResultSet*>(this)->getArrayHelper();
1406 }
1407 // -------------------------------------------------------------------------
1408 sal_Bool OResultSet::convertFastPropertyValue(
1409 							Any & rConvertedValue,
1410 							Any & rOldValue,
1411 							sal_Int32 nHandle,
1412 							const Any& rValue )
1413 								throw (::com::sun::star::lang::IllegalArgumentException)
1414 {
1415 	switch(nHandle)
1416 	{
1417 		case PROPERTY_ID_ISBOOKMARKABLE:
1418 		case PROPERTY_ID_CURSORNAME:
1419 		case PROPERTY_ID_RESULTSETCONCURRENCY:
1420 		case PROPERTY_ID_RESULTSETTYPE:
1421 			throw ::com::sun::star::lang::IllegalArgumentException();
1422 		case PROPERTY_ID_FETCHDIRECTION:
1423 			return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
1424 		case PROPERTY_ID_FETCHSIZE:
1425 			return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
1426 		default:
1427 			;
1428 	}
1429 	return sal_False;
1430 }
1431 // -------------------------------------------------------------------------
1432 void OResultSet::setFastPropertyValue_NoBroadcast(
1433 								sal_Int32 nHandle,
1434 								const Any& rValue
1435 												 )
1436 												 throw (Exception)
1437 {
1438 	switch(nHandle)
1439 	{
1440 		case PROPERTY_ID_ISBOOKMARKABLE:
1441 		case PROPERTY_ID_CURSORNAME:
1442 		case PROPERTY_ID_RESULTSETCONCURRENCY:
1443 		case PROPERTY_ID_RESULTSETTYPE:
1444 			throw Exception();
1445 		case PROPERTY_ID_FETCHDIRECTION:
1446 			setFetchDirection(getINT32(rValue));
1447 			break;
1448 		case PROPERTY_ID_FETCHSIZE:
1449 			setFetchSize(getINT32(rValue));
1450 			break;
1451 		default:
1452 			;
1453 	}
1454 }
1455 // -------------------------------------------------------------------------
1456 void OResultSet::getFastPropertyValue(
1457 								Any& rValue,
1458 								sal_Int32 nHandle
1459 									 ) const
1460 {
1461 	switch(nHandle)
1462 	{
1463 		case PROPERTY_ID_ISBOOKMARKABLE:
1464 			rValue = bool2any(isBookmarkable());
1465 			break;
1466 		case PROPERTY_ID_CURSORNAME:
1467 			rValue <<= getCursorName();
1468 			break;
1469 		case PROPERTY_ID_RESULTSETCONCURRENCY:
1470 			rValue <<= getResultSetConcurrency();
1471 			break;
1472 		case PROPERTY_ID_RESULTSETTYPE:
1473 			rValue <<= getResultSetType();
1474 			break;
1475 		case PROPERTY_ID_FETCHDIRECTION:
1476 			rValue <<= getFetchDirection();
1477 			break;
1478 		case PROPERTY_ID_FETCHSIZE:
1479 			rValue <<= getFetchSize();
1480 			break;
1481 	}
1482 }
1483 // -------------------------------------------------------------------------
1484 void OResultSet::fillRow(sal_Int32 _nToColumn)
1485 {
1486     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::fillRow" );
1487 	if((sal_Int32)m_aRow.size() <= _nToColumn)
1488 	{
1489 		m_aRow.resize(_nToColumn+1);
1490 		m_aRow[_nToColumn].setBound(sal_True);
1491 	}
1492 	m_bFetchData = sal_False;
1493 
1494 	sal_Int32			nColumn		= m_nLastColumnPos + 1;
1495 	TDataRow::iterator pColumn		= m_aRow.begin() + nColumn;
1496 	TDataRow::iterator pColumnEnd	= m_aRow.begin() + _nToColumn + 1;
1497 
1498 	for (; pColumn < pColumnEnd; ++nColumn, ++pColumn)
1499 	{
1500 		const sal_Int32 nType = pColumn->getTypeKind();
1501 		switch (nType)
1502 		{
1503 			case DataType::CHAR:
1504 			case DataType::VARCHAR:
1505             case DataType::DECIMAL:
1506 			case DataType::NUMERIC:
1507             case DataType::LONGVARCHAR:
1508 			case DataType::CLOB:
1509                 {
1510                     const SWORD nColumnType = impl_getColumnType_nothrow(nColumn);
1511 		            *pColumn = OTools::getStringValue(m_pStatement->getOwnConnection(),m_aStatementHandle,nColumn,nColumnType,m_bWasNull,**this,m_nTextEncoding);
1512                 }
1513 				break;
1514 			case DataType::BIGINT:
1515 				*pColumn = getLong(nColumn);
1516 				break;
1517 			case DataType::REAL:
1518 			case DataType::DOUBLE:
1519 				*pColumn = getDouble(nColumn);
1520 				break;
1521 			case DataType::LONGVARBINARY:
1522 			case DataType::BLOB:
1523 				*pColumn = getBytes(nColumn);
1524 				break;
1525 			case DataType::DATE:
1526 				*pColumn = getDate(nColumn);
1527 				break;
1528 			case DataType::TIME:
1529 				*pColumn = getTime(nColumn);
1530 				break;
1531 			case DataType::TIMESTAMP:
1532 				*pColumn = getTimestamp(nColumn);
1533 				break;
1534 			case DataType::BIT:
1535 				*pColumn = getBoolean(nColumn);
1536 				break;
1537 			case DataType::TINYINT:
1538 				*pColumn = getByte(nColumn);
1539 				break;
1540 			case DataType::SMALLINT:
1541 				*pColumn = getShort(nColumn);
1542 				break;
1543 			case DataType::INTEGER:
1544 				*pColumn = getInt(nColumn);
1545 				break;
1546 			case DataType::FLOAT:
1547 				*pColumn = getFloat(nColumn);
1548 				break;
1549 			case DataType::BINARY:
1550 			case DataType::VARBINARY:
1551 				*pColumn = getBytes(nColumn);
1552 				break;
1553 		}
1554 
1555 		if ( m_bWasNull )
1556 			pColumn->setNull();
1557 		if(nType != pColumn->getTypeKind())
1558 		{
1559 			pColumn->setTypeKind(nType);
1560 		}
1561 	}
1562 	m_nLastColumnPos = _nToColumn;
1563 	m_bFetchData = sal_True;
1564 }
1565 // -----------------------------------------------------------------------------
1566 void SAL_CALL OResultSet::acquire() throw()
1567 {
1568 	OResultSet_BASE::acquire();
1569 }
1570 // -----------------------------------------------------------------------------
1571 void SAL_CALL OResultSet::release() throw()
1572 {
1573 	OResultSet_BASE::release();
1574 }
1575 // -----------------------------------------------------------------------------
1576 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException)
1577 {
1578 	return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1579 }
1580 // -----------------------------------------------------------------------------
1581 sal_Bool OResultSet::move(IResultSetHelper::Movement _eCursorPosition, sal_Int32 _nOffset, sal_Bool /*_bRetrieveData*/)
1582 {
1583     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::move" );
1584 	SQLSMALLINT nFetchOrientation = SQL_FETCH_NEXT;
1585 	switch(_eCursorPosition)
1586 	{
1587 		case IResultSetHelper::NEXT:
1588 			nFetchOrientation = SQL_FETCH_NEXT;
1589 			break;
1590 		case IResultSetHelper::PRIOR:
1591 			nFetchOrientation = SQL_FETCH_PRIOR;
1592 			break;
1593 		case IResultSetHelper::FIRST:
1594 			nFetchOrientation = SQL_FETCH_FIRST;
1595 			break;
1596 		case IResultSetHelper::LAST:
1597 			nFetchOrientation = SQL_FETCH_LAST;
1598 			break;
1599 		case IResultSetHelper::RELATIVE:
1600 			nFetchOrientation = SQL_FETCH_RELATIVE;
1601 			break;
1602 		case IResultSetHelper::ABSOLUTE:
1603 			nFetchOrientation = SQL_FETCH_ABSOLUTE;
1604 			break;
1605 		case IResultSetHelper::BOOKMARK: // special case here because we are only called with position numbers
1606 		{
1607 			TBookmarkPosMap::iterator aIter = m_aPosToBookmarks.begin();
1608 			TBookmarkPosMap::iterator aEnd = m_aPosToBookmarks.end();
1609 			for (; aIter != aEnd; ++aIter)
1610 			{
1611 				if ( aIter->second == _nOffset )
1612 					return moveToBookmark(makeAny(aIter->first));
1613 			}
1614 			OSL_ENSURE(0,"Bookmark not found!");
1615 		}
1616 		return sal_False;
1617 	}
1618 
1619 	m_bEOF = sal_False;
1620 	m_nLastColumnPos = 0;
1621 
1622 	SQLRETURN nOldFetchStatus = m_nCurrentFetchState;
1623 	if ( !m_bUseFetchScroll && _eCursorPosition == IResultSetHelper::NEXT )
1624 		m_nCurrentFetchState = N3SQLFetch(m_aStatementHandle);
1625 	else
1626 		m_nCurrentFetchState = N3SQLFetchScroll(m_aStatementHandle,nFetchOrientation,_nOffset);
1627 
1628 	OSL_TRACE( __FILE__": OSkipDeletedSet::OResultSet::move(%d,%d), FetchState = %d",nFetchOrientation,_nOffset,m_nCurrentFetchState);
1629 	OTools::ThrowException(m_pStatement->getOwnConnection(),m_nCurrentFetchState,m_aStatementHandle,SQL_HANDLE_STMT,*this);
1630 
1631     const bool bSuccess = m_nCurrentFetchState == SQL_SUCCESS || m_nCurrentFetchState == SQL_SUCCESS_WITH_INFO;
1632 	if ( bSuccess )
1633 	{
1634 		switch(_eCursorPosition)
1635 		{
1636 			case IResultSetHelper::NEXT:
1637 				++m_nRowPos;
1638 				break;
1639 			case IResultSetHelper::PRIOR:
1640 				--m_nRowPos;
1641 				break;
1642 			case IResultSetHelper::FIRST:
1643 				m_nRowPos = 1;
1644 				break;
1645 			case IResultSetHelper::LAST:
1646 				m_bEOF = sal_True;
1647 				break;
1648 			case IResultSetHelper::RELATIVE:
1649 				m_nRowPos += _nOffset;
1650 				break;
1651 			case IResultSetHelper::ABSOLUTE:
1652 			case IResultSetHelper::BOOKMARK: // special case here because we are only called with position numbers
1653 				m_nRowPos = _nOffset;
1654 				break;
1655 		} // switch(_eCursorPosition)
1656         if ( m_nUseBookmarks == ODBC_SQL_NOT_DEFINED )
1657         {
1658             RTL_LOGFILE_CONTEXT_TRACE( aLogger, "SQLGetStmtAttr" );
1659             m_nUseBookmarks = SQL_UB_OFF;
1660 		    SQLRETURN nRet = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_USE_BOOKMARKS,&m_nUseBookmarks,SQL_IS_UINTEGER,NULL);
1661             OSL_UNUSED( nRet );
1662         }
1663 		if ( m_nUseBookmarks != SQL_UB_OFF )
1664 		{
1665             RTL_LOGFILE_CONTEXT_TRACE( aLogger, "OTools::getBytesValue" );
1666 			m_aBookmark = OTools::getBytesValue(m_pStatement->getOwnConnection(),m_aStatementHandle,0,SQL_C_VARBOOKMARK,m_bWasNull,**this);
1667 			m_aPosToBookmarks[m_aBookmark] = m_nRowPos;
1668 			OSL_ENSURE(m_aBookmark.getLength(),"Invalid bookmark from length 0!");
1669 		}
1670 	}
1671 	else if ( IResultSetHelper::PRIOR == _eCursorPosition && m_nCurrentFetchState == SQL_NO_DATA )
1672 		m_nRowPos = 0;
1673 	else if(IResultSetHelper::NEXT == _eCursorPosition && m_nCurrentFetchState == SQL_NO_DATA && nOldFetchStatus != SQL_NO_DATA)
1674 		++m_nRowPos;
1675 
1676 	return bSuccess;
1677 }
1678 // -----------------------------------------------------------------------------
1679 sal_Int32 OResultSet::getDriverPos() const
1680 {
1681 	sal_Int32 nValue = 0;
1682 	SQLRETURN nRet = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_NUMBER,&nValue,SQL_IS_UINTEGER,0);
1683     OSL_UNUSED( nRet );
1684 	OSL_TRACE( __FILE__": OResultSet::getDriverPos() = Ret = %d, RowNum = %d, RowPos = %d",nRet,nValue , m_nRowPos);
1685 	return nValue ? nValue : m_nRowPos;
1686 }
1687 // -----------------------------------------------------------------------------
1688 sal_Bool OResultSet::deletedVisible() const
1689 {
1690 	return sal_False;
1691 }
1692 // -----------------------------------------------------------------------------
1693 sal_Bool OResultSet::isRowDeleted() const
1694 {
1695 	return m_pRowStatusArray[0] == SQL_ROW_DELETED;
1696 }
1697 // -----------------------------------------------------------------------------
1698 sal_Bool OResultSet::moveImpl(IResultSetHelper::Movement _eCursorPosition, sal_Int32 _nOffset, sal_Bool _bRetrieveData)
1699 {
1700 	::osl::MutexGuard aGuard( m_aMutex );
1701 	checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
1702 	return (m_pSkipDeletedSet != NULL)
1703 				?   m_pSkipDeletedSet->skipDeleted(_eCursorPosition,_nOffset,_bRetrieveData)
1704 				:   move(_eCursorPosition,_nOffset,_bRetrieveData);
1705 }
1706 // -----------------------------------------------------------------------------
1707 void OResultSet::fillNeededData(SQLRETURN _nRet)
1708 {
1709     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OResultSet::fillNeededData" );
1710 	SQLRETURN nRet = _nRet;
1711 	if( nRet == SQL_NEED_DATA)
1712 	{
1713 		void* pColumnIndex = 0;
1714 		nRet = N3SQLParamData(m_aStatementHandle,&pColumnIndex);
1715 
1716 		do
1717 		{
1718 			if (nRet != SQL_SUCCESS && nRet != SQL_SUCCESS_WITH_INFO && nRet != SQL_NEED_DATA)
1719 				break;
1720 
1721 			sal_IntPtr nColumnIndex ( reinterpret_cast<sal_IntPtr>(pColumnIndex));
1722 			Sequence< sal_Int8 > aSeq;
1723 			switch(m_aRow[nColumnIndex].getTypeKind())
1724 			{
1725 				case DataType::BINARY:
1726 				case DataType::VARBINARY:
1727 				case DataType::LONGVARBINARY:
1728 				case DataType::BLOB:
1729 					aSeq = m_aRow[nColumnIndex];
1730 					N3SQLPutData (m_aStatementHandle, aSeq.getArray(), aSeq.getLength());
1731 					break;
1732 				case SQL_WLONGVARCHAR:
1733 				{
1734 					::rtl::OUString sRet;
1735 					sRet = m_aRow[nColumnIndex].getString();
1736 					nRet = N3SQLPutData (m_aStatementHandle, (SQLPOINTER)sRet.getStr(), sizeof(sal_Unicode)*sRet.getLength());
1737 					break;
1738 				}
1739 				case DataType::LONGVARCHAR:
1740 				case DataType::CLOB:
1741 				{
1742 					::rtl::OUString sRet;
1743 					sRet = m_aRow[nColumnIndex].getString();
1744 					::rtl::OString aString(::rtl::OUStringToOString(sRet,m_nTextEncoding));
1745 					nRet = N3SQLPutData (m_aStatementHandle, (SQLPOINTER)aString.getStr(), aString.getLength());
1746 					break;
1747 				}
1748 				default:
1749 					OSL_ENSURE(0,"Not supported at the moment!");
1750 			}
1751 			nRet = N3SQLParamData(m_aStatementHandle,&pColumnIndex);
1752 		}
1753 		while (nRet == SQL_NEED_DATA);
1754 	}
1755 }
1756 // -----------------------------------------------------------------------------
1757 SWORD OResultSet::impl_getColumnType_nothrow(sal_Int32 columnIndex)
1758 {
1759     ::std::map<sal_Int32,SWORD>::iterator aFind = m_aODBCColumnTypes.find(columnIndex);
1760     if ( aFind == m_aODBCColumnTypes.end() )
1761         aFind = m_aODBCColumnTypes.insert(::std::map<sal_Int32,SWORD>::value_type(columnIndex,OResultSetMetaData::getColumnODBCType(m_pStatement->getOwnConnection(),m_aStatementHandle,*this,columnIndex))).first;
1762     return aFind->second;
1763 }
1764 
1765