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