1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "odbc/OResultSet.hxx"
21 #include "odbc/OTools.hxx"
22 #include "odbc/OResultSetMetaData.hxx"
23 #include <com/sun/star/sdbc/DataType.hpp>
24 #include <com/sun/star/beans/PropertyAttribute.hpp>
25 #include <com/sun/star/beans/PropertyVetoException.hpp>
26 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
27 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
28 #include <com/sun/star/sdbc/FetchDirection.hpp>
29 #include <com/sun/star/sdbc/ResultSetType.hpp>
30 #include <comphelper/property.hxx>
31 #include <comphelper/sequence.hxx>
32 #include <cppuhelper/typeprovider.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <comphelper/types.hxx>
36 #include "connectivity/dbtools.hxx"
37 #include "connectivity/dbexception.hxx"
38 #include "diagnose_ex.h"
39 #include <boost/static_assert.hpp>
41 #include <o3tl/compat_functional.hxx>
43 using namespace ::comphelper
;
44 using namespace connectivity
;
45 using namespace connectivity::odbc
;
47 using namespace com::sun::star::uno
;
48 using namespace com::sun::star::lang
;
49 using namespace com::sun::star::beans
;
50 using namespace com::sun::star::sdbc
;
51 using namespace com::sun::star::sdbcx
;
52 using namespace com::sun::star::container
;
53 using namespace com::sun::star::io
;
54 using namespace com::sun::star::util
;
56 #define ODBC_SQL_NOT_DEFINED 99UL
57 BOOST_STATIC_ASSERT( ODBC_SQL_NOT_DEFINED
!= SQL_UB_OFF
);
58 BOOST_STATIC_ASSERT( ODBC_SQL_NOT_DEFINED
!= SQL_UB_ON
);
59 BOOST_STATIC_ASSERT( ODBC_SQL_NOT_DEFINED
!= SQL_UB_FIXED
);
60 BOOST_STATIC_ASSERT( ODBC_SQL_NOT_DEFINED
!= SQL_UB_VARIABLE
);
64 const SQLLEN nMaxBookmarkLen
= 20;
68 // IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.OResultSet","com.sun.star.sdbc.ResultSet");
69 OUString SAL_CALL
OResultSet::getImplementationName( ) throw ( RuntimeException
, std::exception
)
71 return OUString("com.sun.star.sdbcx.odbc.ResultSet");
74 Sequence
< OUString
> SAL_CALL
OResultSet::getSupportedServiceNames( ) throw( RuntimeException
, std::exception
)
76 Sequence
< OUString
> aSupported(2);
77 aSupported
[0] = "com.sun.star.sdbc.ResultSet";
78 aSupported
[1] = "com.sun.star.sdbcx.ResultSet";
82 sal_Bool SAL_CALL
OResultSet::supportsService( const OUString
& _rServiceName
) throw( RuntimeException
, std::exception
)
84 return cppu::supportsService(this, _rServiceName
);
88 OResultSet::OResultSet(SQLHANDLE _pStatementHandle
,OStatement_Base
* pStmt
) : OResultSet_BASE(m_aMutex
)
89 ,OPropertySetHelper(OResultSet_BASE::rBHelper
)
90 ,m_bFetchDataInOrder(true)
91 ,m_aStatementHandle(_pStatementHandle
)
92 ,m_aConnectionHandle(pStmt
->getConnectionHandle())
94 ,m_pSkipDeletedSet(NULL
)
97 ,m_pRowStatusArray( NULL
)
98 ,m_nTextEncoding(pStmt
->getOwnConnection()->getTextEncoding())
100 ,m_nUseBookmarks(ODBC_SQL_NOT_DEFINED
)
101 ,m_nCurrentFetchState(0)
104 ,m_bLastRecord(false)
105 ,m_bFreeHandle(false)
107 ,m_bRowInserted(false)
108 ,m_bRowDeleted(false)
109 ,m_bUseFetchScroll(false)
111 osl_atomic_increment( &m_refCount
);
114 m_pRowStatusArray
= new SQLUSMALLINT
[1]; // the default value
115 setStmtOption
<SQLUSMALLINT
*, SQL_IS_POINTER
>(SQL_ATTR_ROW_STATUS_PTR
, m_pRowStatusArray
);
117 catch(const Exception
&)
118 { // we don't want our result destroy here
120 SQLULEN nCurType
= 0;
123 nCurType
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CURSOR_TYPE
);
124 SQLUINTEGER nValueLen
= m_pStatement
->getCursorProperties(nCurType
,false);
125 if( (nValueLen
& SQL_CA2_SENSITIVITY_DELETIONS
) != SQL_CA2_SENSITIVITY_DELETIONS
||
126 (nValueLen
& SQL_CA2_CRC_EXACT
) != SQL_CA2_CRC_EXACT
)
127 m_pSkipDeletedSet
= new OSkipDeletedSet(this);
129 catch(const Exception
&)
130 { // we don't want our result destroy here
134 SQLUINTEGER nValueLen
= 0;
135 // Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441%28v=vs.85%29.aspx
136 // LibreOffice ODBC binds columns only on update, so we don't care about SQL_GD_ANY_COLUMN / SQL_GD_BOUND
137 // TODO: maybe a problem if a column is updated, then an earlier column fetched?
138 // an updated column is bound...
139 // TODO: aren't we assuming SQL_GD_OUTPUT_PARAMS?
140 // If yes, we should at least OSL_ENSURE it,
141 // even better throw an exception any OUT parameter registration if !SQL_GD_OUTPUT_PARAMS.
142 // If !SQL_GD_ANY_ORDER, cache the whole row so that callers can access columns in any order.
143 // In other words, isolate them from ODBC restrictions.
144 // TODO: we assume SQL_GD_BLOCK, unless fetchSize is 1
145 OTools::GetInfo(m_pStatement
->getOwnConnection(),m_aConnectionHandle
,SQL_GETDATA_EXTENSIONS
,nValueLen
,NULL
);
146 m_bFetchDataInOrder
= !((SQL_GD_ANY_ORDER
& nValueLen
) == SQL_GD_ANY_ORDER
);
148 catch(const Exception
&)
150 m_bFetchDataInOrder
= true;
154 // TODO: this does *not* do what it appears.
155 // We use SQLFetchScroll unconditionally in several places
156 // the *only* difference this makes is whether ::next() uses SQLFetchScroll or SQLFetch
157 // so this test seems pointless
158 if ( getOdbcFunction(ODBC3SQLGetFunctions
) )
160 SQLUSMALLINT nSupported
= 0;
161 m_bUseFetchScroll
= ( N3SQLGetFunctions(m_aConnectionHandle
,SQL_API_SQLFETCHSCROLL
,&nSupported
) == SQL_SUCCESS
&& nSupported
== 1 );
164 catch(const Exception
&)
166 m_bUseFetchScroll
= false;
169 osl_atomic_decrement( &m_refCount
);
172 OResultSet::~OResultSet()
174 delete [] m_pRowStatusArray
;
175 delete m_pSkipDeletedSet
;
178 void OResultSet::construct()
180 osl_atomic_increment( &m_refCount
);
182 osl_atomic_decrement( &m_refCount
);
185 void OResultSet::disposing(void)
187 SQLRETURN nRet
= N3SQLCloseCursor(m_aStatementHandle
);
189 OPropertySetHelper::disposing();
191 ::osl::MutexGuard
aGuard(m_aMutex
);
194 m_pStatement
->getOwnConnection()->freeStatementHandle(m_aStatementHandle
);
196 m_xStatement
.clear();
200 SQLRETURN
OResultSet::unbind(bool _bUnbindHandle
)
203 if ( _bUnbindHandle
)
204 nRet
= N3SQLFreeStmt(m_aStatementHandle
,SQL_UNBIND
);
206 if ( m_aBindVector
.size() > 0 )
208 TVoidVector::iterator pValue
= m_aBindVector
.begin();
209 TVoidVector::iterator pEnd
= m_aBindVector
.end();
210 for(; pValue
!= pEnd
; ++pValue
)
212 switch (pValue
->second
)
215 case DataType::VARCHAR
:
216 delete static_cast< OString
* >(reinterpret_cast< void * >(pValue
->first
));
218 case DataType::BIGINT
:
219 delete static_cast< sal_Int64
* >(reinterpret_cast< void * >(pValue
->first
));
221 case DataType::DECIMAL
:
222 case DataType::NUMERIC
:
223 delete static_cast< OString
* >(reinterpret_cast< void * >(pValue
->first
));
226 case DataType::DOUBLE
:
227 delete static_cast< double* >(reinterpret_cast< void * >(pValue
->first
));
229 case DataType::LONGVARCHAR
:
231 delete [] static_cast< char* >(reinterpret_cast< void * >(pValue
->first
));
233 case DataType::LONGVARBINARY
:
235 delete [] static_cast< char* >(reinterpret_cast< void * >(pValue
->first
));
238 delete static_cast< DATE_STRUCT
* >(reinterpret_cast< void * >(pValue
->first
));
241 delete static_cast< TIME_STRUCT
* >(reinterpret_cast< void * >(pValue
->first
));
243 case DataType::TIMESTAMP
:
244 delete static_cast< TIMESTAMP_STRUCT
* >(reinterpret_cast< void * >(pValue
->first
));
247 case DataType::TINYINT
:
248 delete static_cast< sal_Int8
* >(reinterpret_cast< void * >(pValue
->first
));
250 case DataType::SMALLINT
:
251 delete static_cast< sal_Int16
* >(reinterpret_cast< void * >(pValue
->first
));
253 case DataType::INTEGER
:
254 delete static_cast< sal_Int32
* >(reinterpret_cast< void * >(pValue
->first
));
256 case DataType::FLOAT
:
257 delete static_cast< float* >(reinterpret_cast< void * >(pValue
->first
));
259 case DataType::BINARY
:
260 case DataType::VARBINARY
:
261 delete static_cast< sal_Int8
* >(reinterpret_cast< void * >(pValue
->first
));
265 m_aBindVector
.clear();
270 TVoidPtr
OResultSet::allocBindColumn(sal_Int32 _nType
,sal_Int32 _nColumnIndex
)
276 case DataType::VARCHAR
:
277 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new OString()),_nType
);
279 case DataType::BIGINT
:
280 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new sal_Int64(0)),_nType
);
282 case DataType::DECIMAL
:
283 case DataType::NUMERIC
:
284 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new OString()),_nType
);
287 case DataType::DOUBLE
:
288 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new double(0.0)),_nType
);
290 case DataType::LONGVARCHAR
:
292 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new char[2]),_nType
); // only for finding
294 case DataType::LONGVARBINARY
:
296 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new char[2]),_nType
); // only for finding
299 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new DATE_STRUCT
),_nType
);
302 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new TIME_STRUCT
),_nType
);
304 case DataType::TIMESTAMP
:
305 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new TIMESTAMP_STRUCT
),_nType
);
308 case DataType::TINYINT
:
309 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new sal_Int8(0)),_nType
);
311 case DataType::SMALLINT
:
312 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new sal_Int16(0)),_nType
);
314 case DataType::INTEGER
:
315 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new sal_Int32(0)),_nType
);
317 case DataType::FLOAT
:
318 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new float(0)),_nType
);
320 case DataType::BINARY
:
321 case DataType::VARBINARY
:
322 aPair
= TVoidPtr(reinterpret_cast< sal_Int64
>(new sal_Int8
[m_aRow
[_nColumnIndex
].getSequence().getLength()]),_nType
);
325 SAL_WARN( "connectivity.drivers", "Unknown type");
326 aPair
= TVoidPtr(0,_nType
);
331 void OResultSet::allocBuffer()
333 Reference
< XResultSetMetaData
> xMeta
= getMetaData();
334 sal_Int32 nLen
= xMeta
->getColumnCount();
336 m_aBindVector
.reserve(nLen
);
337 m_aRow
.resize(nLen
+1);
339 m_aRow
[0].setTypeKind(DataType::VARBINARY
);
340 m_aRow
[0].setBound( false );
342 for(sal_Int32 i
= 1;i
<=nLen
;++i
)
344 sal_Int32 nType
= xMeta
->getColumnType(i
);
345 m_aRow
[i
].setTypeKind( nType
);
346 m_aRow
[i
].setBound( false );
348 m_aLengthVector
.resize(nLen
+ 1);
351 void OResultSet::releaseBuffer()
354 m_aLengthVector
.clear();
357 Any SAL_CALL
OResultSet::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
359 Any aRet
= OPropertySetHelper::queryInterface(rType
);
360 return aRet
.hasValue() ? aRet
: OResultSet_BASE::queryInterface(rType
);
363 Sequence
< Type
> SAL_CALL
OResultSet::getTypes( ) throw( RuntimeException
, std::exception
)
365 OTypeCollection
aTypes( ::getCppuType( (const Reference
< ::com::sun::star::beans::XMultiPropertySet
> *)0 ),
366 ::getCppuType( (const Reference
< ::com::sun::star::beans::XFastPropertySet
> *)0 ),
367 ::getCppuType( (const Reference
< ::com::sun::star::beans::XPropertySet
> *)0 ));
369 return ::comphelper::concatSequences(aTypes
.getTypes(),OResultSet_BASE::getTypes());
373 sal_Int32 SAL_CALL
OResultSet::findColumn( const OUString
& columnName
) throw(SQLException
, RuntimeException
, std::exception
)
375 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
378 ::osl::MutexGuard
aGuard( m_aMutex
);
380 Reference
< XResultSetMetaData
> xMeta
= getMetaData();
381 sal_Int32 nLen
= xMeta
->getColumnCount();
385 if(xMeta
->isCaseSensitive(i
) ? columnName
== xMeta
->getColumnName(i
) :
386 columnName
.equalsIgnoreAsciiCase(xMeta
->getColumnName(i
)))
390 ::dbtools::throwInvalidColumnException( columnName
, *this );
392 return 0; // Never reached
395 void OResultSet::ensureCacheForColumn(sal_Int32 columnIndex
)
397 SAL_INFO( "connectivity.drivers", "odbc lionel@mamane.lu OResultSet::ensureCacheForColumn" );
399 assert(columnIndex
>= 0);
401 const TDataRow::size_type oldCacheSize
= m_aRow
.size();
402 const TDataRow::size_type uColumnIndex
= static_cast<TDataRow::size_type
>(columnIndex
);
404 if (oldCacheSize
> uColumnIndex
)
408 m_aRow
.resize(columnIndex
+ 1);
409 TDataRow::iterator
i (m_aRow
.begin() + oldCacheSize
);
410 const TDataRow::const_iterator
end(m_aRow
.end());
411 for (; i
!= end
; ++i
)
416 void OResultSet::invalidateCache()
418 const TDataRow::const_iterator end
= m_aRow
.end();
419 for(TDataRow::iterator i
=m_aRow
.begin(); i
!=end
; ++i
)
425 Reference
< XInputStream
> SAL_CALL
OResultSet::getBinaryStream( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
427 ::osl::MutexGuard
aGuard( m_aMutex
);
428 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
430 ::dbtools::throwFunctionNotSupportedException( "XRow::getBinaryStream", *this );
435 Reference
< XInputStream
> SAL_CALL
OResultSet::getCharacterStream( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
437 ::osl::MutexGuard
aGuard( m_aMutex
);
438 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
440 ::dbtools::throwFunctionNotSupportedException( "XRow::getBinaryStream", *this );
445 template < typename T
> T
OResultSet::impl_getValue( const sal_Int32 _nColumnIndex
, SQLSMALLINT nType
)
449 OTools::getValue(m_pStatement
->getOwnConnection(), m_aStatementHandle
, _nColumnIndex
, nType
, m_bWasNull
, **this, &val
, sizeof(val
));
454 // this function exists for the implicit conversion to sal_Bool (compared to a direct call to impl_getValue)
455 bool OResultSet::impl_getBoolean( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
457 return impl_getValue
<sal_Int8
>(columnIndex
, SQL_C_BIT
);
460 template < typename T
> T
OResultSet::getValue( sal_Int32 columnIndex
)
462 ::osl::MutexGuard
aGuard( m_aMutex
);
463 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
464 fillColumn(columnIndex
);
465 m_bWasNull
= m_aRow
[columnIndex
].isNull();
466 return m_aRow
[columnIndex
];
468 sal_Bool SAL_CALL
OResultSet::getBoolean( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
470 return getValue
<sal_Bool
>( columnIndex
);
473 sal_Int8 SAL_CALL
OResultSet::getByte( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
475 return getValue
<sal_Int8
>( columnIndex
);
479 Sequence
< sal_Int8
> SAL_CALL
OResultSet::getBytes( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
481 ::osl::MutexGuard
aGuard( m_aMutex
);
482 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
483 fillColumn(columnIndex
);
484 m_bWasNull
= m_aRow
[columnIndex
].isNull();
486 Sequence
< sal_Int8
> nRet
;
487 switch(m_aRow
[columnIndex
].getTypeKind())
489 case DataType::BINARY
:
490 case DataType::VARBINARY
:
491 case DataType::LONGVARBINARY
:
492 nRet
= m_aRow
[columnIndex
];
497 sRet
= m_aRow
[columnIndex
].getString();
498 nRet
= Sequence
<sal_Int8
>(reinterpret_cast<const sal_Int8
*>(sRet
.getStr()),sizeof(sal_Unicode
)*sRet
.getLength());
503 Sequence
< sal_Int8
> OResultSet::impl_getBytes( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
505 const SWORD nColumnType
= impl_getColumnType_nothrow(columnIndex
);
511 case SQL_WLONGVARCHAR
:
514 case SQL_LONGVARCHAR
:
516 OUString aRet
= OTools::getStringValue(m_pStatement
->getOwnConnection(),m_aStatementHandle
,columnIndex
,nColumnType
,m_bWasNull
,**this,m_nTextEncoding
);
517 return Sequence
<sal_Int8
>(reinterpret_cast<const sal_Int8
*>(aRet
.getStr()),sizeof(sal_Unicode
)*aRet
.getLength());
520 return OTools::getBytesValue(m_pStatement
->getOwnConnection(),m_aStatementHandle
,columnIndex
,SQL_C_BINARY
,m_bWasNull
,**this);
524 Date
OResultSet::impl_getDate( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
526 DATE_STRUCT aDate
= impl_getValue
< DATE_STRUCT
> ( columnIndex
,
527 m_pStatement
->getOwnConnection()->useOldDateFormat() ? SQL_C_DATE
: SQL_C_TYPE_DATE
);
529 return Date(aDate
.day
, aDate
.month
, aDate
.year
);
532 Date SAL_CALL
OResultSet::getDate( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
534 return getValue
<Date
>( columnIndex
);
538 double SAL_CALL
OResultSet::getDouble( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
540 return getValue
<double>( columnIndex
);
544 float SAL_CALL
OResultSet::getFloat( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
546 return getValue
<float>( columnIndex
);
549 sal_Int16 SAL_CALL
OResultSet::getShort( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
551 return getValue
<sal_Int16
>( columnIndex
);
554 sal_Int32 SAL_CALL
OResultSet::getInt( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
556 return getValue
<sal_Int32
>( columnIndex
);
559 sal_Int64 SAL_CALL
OResultSet::getLong( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
561 return getValue
<sal_Int64
>( columnIndex
);
563 sal_Int64
OResultSet::impl_getLong( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
567 return impl_getValue
<sal_Int64
>(columnIndex
, SQL_C_SBIGINT
);
569 catch(const SQLException
&)
571 return getString(columnIndex
).toInt64();
575 sal_Int32 SAL_CALL
OResultSet::getRow( ) throw(SQLException
, RuntimeException
, std::exception
)
577 ::osl::MutexGuard
aGuard( m_aMutex
);
578 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
580 return m_pSkipDeletedSet
? m_pSkipDeletedSet
->getMappedPosition(getDriverPos()) : getDriverPos();
583 Reference
< XResultSetMetaData
> SAL_CALL
OResultSet::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
585 ::osl::MutexGuard
aGuard( m_aMutex
);
586 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
589 if(!m_xMetaData
.is())
590 m_xMetaData
= new OResultSetMetaData(m_pStatement
->getOwnConnection(),m_aStatementHandle
);
594 Reference
< XArray
> SAL_CALL
OResultSet::getArray( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
596 ::dbtools::throwFunctionNotSupportedException( "XRow::getArray", *this );
602 Reference
< XClob
> SAL_CALL
OResultSet::getClob( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
604 ::dbtools::throwFunctionNotSupportedException( "XRow::getClob", *this );
608 Reference
< XBlob
> SAL_CALL
OResultSet::getBlob( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
610 ::dbtools::throwFunctionNotSupportedException( "XRow::getBlob", *this );
615 Reference
< XRef
> SAL_CALL
OResultSet::getRef( sal_Int32
/*columnIndex*/ ) throw(SQLException
, RuntimeException
, std::exception
)
617 ::dbtools::throwFunctionNotSupportedException( "XRow::getRef", *this );
622 Any SAL_CALL
OResultSet::getObject( sal_Int32 columnIndex
, const Reference
< ::com::sun::star::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
, std::exception
)
624 return getValue
<ORowSetValue
>( columnIndex
).makeAny();
627 OUString
OResultSet::impl_getString( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
629 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
630 const SWORD nColumnType
= impl_getColumnType_nothrow(columnIndex
);
631 return OTools::getStringValue(m_pStatement
->getOwnConnection(),m_aStatementHandle
,columnIndex
,nColumnType
,m_bWasNull
,**this,m_nTextEncoding
);
633 OUString
OResultSet::getString( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
635 return getValue
<OUString
>( columnIndex
);
638 Time
OResultSet::impl_getTime( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
640 TIME_STRUCT aTime
= impl_getValue
< TIME_STRUCT
> ( columnIndex
,
641 m_pStatement
->getOwnConnection()->useOldDateFormat() ? SQL_C_TIME
: SQL_C_TYPE_TIME
);
643 return Time(0, aTime
.second
,aTime
.minute
,aTime
.hour
, false);
645 Time SAL_CALL
OResultSet::getTime( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
647 return getValue
<Time
>( columnIndex
);
650 DateTime
OResultSet::impl_getTimestamp( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
)
652 TIMESTAMP_STRUCT aTime
= impl_getValue
< TIMESTAMP_STRUCT
> ( columnIndex
,
653 m_pStatement
->getOwnConnection()->useOldDateFormat() ? SQL_C_TIMESTAMP
: SQL_C_TYPE_TIMESTAMP
);
655 return DateTime(aTime
.fraction
,
664 DateTime SAL_CALL
OResultSet::getTimestamp( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
666 return getValue
<DateTime
>( columnIndex
);
669 sal_Bool SAL_CALL
OResultSet::isBeforeFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
671 ::osl::MutexGuard
aGuard( m_aMutex
);
672 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
673 return m_nRowPos
== 0;
676 sal_Bool SAL_CALL
OResultSet::isAfterLast( ) throw(SQLException
, RuntimeException
, std::exception
)
678 ::osl::MutexGuard
aGuard( m_aMutex
);
679 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
681 return m_nRowPos
!= 0 && m_nCurrentFetchState
== SQL_NO_DATA
;
684 sal_Bool SAL_CALL
OResultSet::isFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
686 ::osl::MutexGuard
aGuard( m_aMutex
);
687 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
689 return m_nRowPos
== 1;
692 sal_Bool SAL_CALL
OResultSet::isLast( ) throw(SQLException
, RuntimeException
, std::exception
)
694 ::osl::MutexGuard
aGuard( m_aMutex
);
695 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
698 return m_bEOF
&& m_nCurrentFetchState
!= SQL_NO_DATA
;
701 void SAL_CALL
OResultSet::beforeFirst( ) throw(SQLException
, RuntimeException
, std::exception
)
703 ::osl::MutexGuard
aGuard( m_aMutex
);
704 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
709 m_nCurrentFetchState
= SQL_SUCCESS
;
712 void SAL_CALL
OResultSet::afterLast( ) throw(SQLException
, RuntimeException
, std::exception
)
714 ::osl::MutexGuard
aGuard( m_aMutex
);
715 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
723 void SAL_CALL
OResultSet::close( ) throw(SQLException
, RuntimeException
, std::exception
)
726 ::osl::MutexGuard
aGuard( m_aMutex
);
727 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
734 sal_Bool SAL_CALL
OResultSet::first( ) throw(SQLException
, RuntimeException
, std::exception
)
736 return moveImpl(IResultSetHelper::FIRST
,0,true);
740 sal_Bool SAL_CALL
OResultSet::last( ) throw(SQLException
, RuntimeException
, std::exception
)
742 return moveImpl(IResultSetHelper::LAST
,0,true);
745 sal_Bool SAL_CALL
OResultSet::absolute( sal_Int32 row
) throw(SQLException
, RuntimeException
, std::exception
)
747 return moveImpl(IResultSetHelper::ABSOLUTE
,row
,true);
750 sal_Bool SAL_CALL
OResultSet::relative( sal_Int32 row
) throw(SQLException
, RuntimeException
, std::exception
)
752 return moveImpl(IResultSetHelper::RELATIVE
,row
,true);
755 sal_Bool SAL_CALL
OResultSet::previous( ) throw(SQLException
, RuntimeException
, std::exception
)
757 return moveImpl(IResultSetHelper::PRIOR
,0,true);
760 Reference
< XInterface
> SAL_CALL
OResultSet::getStatement( ) throw(SQLException
, RuntimeException
, std::exception
)
762 ::osl::MutexGuard
aGuard( m_aMutex
);
763 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
768 sal_Bool SAL_CALL
OResultSet::rowDeleted() throw(SQLException
, RuntimeException
, std::exception
)
770 ::osl::MutexGuard
aGuard( m_aMutex
);
771 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
773 bool bRet
= m_bRowDeleted
;
774 m_bRowDeleted
= false;
779 sal_Bool SAL_CALL
OResultSet::rowInserted( ) throw(SQLException
, RuntimeException
, std::exception
)
781 ::osl::MutexGuard
aGuard( m_aMutex
);
782 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
784 bool bInserted
= m_bRowInserted
;
785 m_bRowInserted
= false;
790 sal_Bool SAL_CALL
OResultSet::rowUpdated( ) throw(SQLException
, RuntimeException
, std::exception
)
792 ::osl::MutexGuard
aGuard( m_aMutex
);
793 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
796 return m_pRowStatusArray
[0] == SQL_ROW_UPDATED
;
800 sal_Bool SAL_CALL
OResultSet::next( ) throw(SQLException
, RuntimeException
, std::exception
)
802 return moveImpl(IResultSetHelper::NEXT
,1,true);
806 sal_Bool SAL_CALL
OResultSet::wasNull( ) throw(SQLException
, RuntimeException
, std::exception
)
808 ::osl::MutexGuard
aGuard( m_aMutex
);
809 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
815 void SAL_CALL
OResultSet::cancel( ) throw(RuntimeException
, std::exception
)
817 ::osl::MutexGuard
aGuard( m_aMutex
);
818 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
821 OTools::ThrowException(m_pStatement
->getOwnConnection(),N3SQLCancel(m_aStatementHandle
),m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
824 void SAL_CALL
OResultSet::clearWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
828 Any SAL_CALL
OResultSet::getWarnings( ) throw(SQLException
, RuntimeException
, std::exception
)
833 void SAL_CALL
OResultSet::insertRow( ) throw(SQLException
, RuntimeException
, std::exception
)
835 ::osl::MutexGuard
aGuard( m_aMutex
);
836 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
840 Sequence
<sal_Int8
> aBookmark(nMaxBookmarkLen
);
841 BOOST_STATIC_ASSERT(static_cast<size_t>(nMaxBookmarkLen
) >= sizeof(SQLLEN
));
843 SQLRETURN nRet
= N3SQLBindCol(m_aStatementHandle
,
846 aBookmark
.getArray(),
851 bool bPositionByBookmark
= ( NULL
!= getOdbcFunction( ODBC3SQLBulkOperations
) );
852 if ( bPositionByBookmark
)
854 nRet
= N3SQLBulkOperations( m_aStatementHandle
, SQL_ADD
);
855 fillNeededData( nRet
);
860 next(); // must be done
861 nRet
= N3SQLSetPos( m_aStatementHandle
, 1, SQL_ADD
, SQL_LOCK_NO_CHANGE
);
862 fillNeededData( nRet
);
864 aBookmark
.realloc(nRealLen
);
867 OTools::ThrowException(m_pStatement
->getOwnConnection(),nRet
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
869 catch(const SQLException
&)
876 OTools::ThrowException(m_pStatement
->getOwnConnection(),nRet
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
878 if ( bPositionByBookmark
)
880 setStmtOption
<SQLLEN
*, SQL_IS_POINTER
>(SQL_ATTR_FETCH_BOOKMARK_PTR
, reinterpret_cast<SQLLEN
*>(aBookmark
.getArray()));
882 nRet
= N3SQLFetchScroll(m_aStatementHandle
,SQL_FETCH_BOOKMARK
,0);
885 nRet
= N3SQLFetchScroll(m_aStatementHandle
,SQL_FETCH_RELATIVE
,0); // OJ 06.03.2004
886 // sometimes we got an error but we are not interested in anymore #106047# OJ
887 // OTools::ThrowException(m_pStatement->getOwnConnection(),nRet,m_aStatementHandle,SQL_HANDLE_STMT,*this);
889 if(m_pSkipDeletedSet
)
891 if(moveToBookmark(makeAny(aBookmark
)))
893 sal_Int32 nRowPos
= getDriverPos();
894 if ( -1 == m_nRowPos
)
896 nRowPos
= m_aPosToBookmarks
.size() + 1;
898 if ( nRowPos
== m_nRowPos
)
901 m_pSkipDeletedSet
->insertNewPosition(nRowPos
);
902 m_aPosToBookmarks
[aBookmark
] = nRowPos
;
905 m_bRowInserted
= true;
909 void SAL_CALL
OResultSet::updateRow( ) throw(SQLException
, RuntimeException
, std::exception
)
911 ::osl::MutexGuard
aGuard( m_aMutex
);
912 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
918 bool bPositionByBookmark
= ( NULL
!= getOdbcFunction( ODBC3SQLBulkOperations
) );
919 if ( bPositionByBookmark
)
922 assert(m_aRow
[0].isBound());
923 Sequence
<sal_Int8
> aBookmark(m_aRow
[0].getSequence());
924 SQLLEN nRealLen
= aBookmark
.getLength();
925 nRet
= N3SQLBindCol(m_aStatementHandle
,
928 aBookmark
.getArray(),
929 aBookmark
.getLength(),
932 OTools::ThrowException(m_pStatement
->getOwnConnection(),nRet
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
933 fillNeededData(nRet
= N3SQLBulkOperations(m_aStatementHandle
, SQL_UPDATE_BY_BOOKMARK
));
934 // the driver should not have touched this
935 // (neither the contents of aBookmark FWIW)
936 assert(nRealLen
== aBookmark
.getLength());
940 fillNeededData(nRet
= N3SQLSetPos(m_aStatementHandle
,1,SQL_UPDATE
,SQL_LOCK_NO_CHANGE
));
942 OTools::ThrowException(m_pStatement
->getOwnConnection(),nRet
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
943 // unbind all columns so we can fetch all columns again with SQLGetData
944 // (and also so that our buffers don't clobber anything, and
945 // so that a subsequent fetch does not overwrite m_aRow[0])
948 OSL_ENSURE(nRet
== SQL_SUCCESS
,"ODBC insert could not unbind the columns after success");
952 // unbind all columns so that a subsequent fetch does not overwrite m_aRow[0]
954 OSL_ENSURE(nRet
== SQL_SUCCESS
,"ODBC insert could not unbind the columns after failure");
959 void SAL_CALL
OResultSet::deleteRow( ) throw(SQLException
, RuntimeException
, std::exception
)
961 SQLRETURN nRet
= SQL_SUCCESS
;
962 sal_Int32 nPos
= getDriverPos();
963 nRet
= N3SQLSetPos(m_aStatementHandle
,1,SQL_DELETE
,SQL_LOCK_NO_CHANGE
);
964 OTools::ThrowException(m_pStatement
->getOwnConnection(),nRet
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
966 m_bRowDeleted
= ( m_pRowStatusArray
[0] == SQL_ROW_DELETED
);
969 TBookmarkPosMap::iterator aIter
= m_aPosToBookmarks
.begin();
970 TBookmarkPosMap::iterator aEnd
= m_aPosToBookmarks
.end();
971 for (; aIter
!= aEnd
; ++aIter
)
973 if ( aIter
->second
== nPos
)
975 m_aPosToBookmarks
.erase(aIter
);
980 if ( m_pSkipDeletedSet
)
981 m_pSkipDeletedSet
->deletePosition(nPos
);
985 void SAL_CALL
OResultSet::cancelRowUpdates( ) throw(SQLException
, RuntimeException
, std::exception
)
990 void SAL_CALL
OResultSet::moveToInsertRow( ) throw(SQLException
, RuntimeException
, std::exception
)
992 ::osl::MutexGuard
aGuard( m_aMutex
);
993 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
997 // first unbound all columns
998 OSL_VERIFY_EQUALS( unbind(), SQL_SUCCESS
, "Could not unbind columns!" );
999 // SQLRETURN nRet = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE ,(SQLPOINTER)1,SQL_IS_INTEGER);
1000 m_bInserting
= true;
1004 void SAL_CALL
OResultSet::moveToCurrentRow( ) throw(SQLException
, RuntimeException
, std::exception
)
1009 void OResultSet::updateValue(sal_Int32 columnIndex
,SQLSMALLINT _nType
,void* _pValue
) throw(SQLException
, RuntimeException
)
1011 ::osl::MutexGuard
aGuard( m_aMutex
);
1012 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1014 m_aBindVector
.push_back(allocBindColumn(OTools::MapOdbcType2Jdbc(_nType
),columnIndex
));
1015 void* pData
= reinterpret_cast<void*>(m_aBindVector
.rbegin()->first
);
1016 OSL_ENSURE(pData
!= NULL
,"Data for update is NULL!");
1017 OTools::bindValue( m_pStatement
->getOwnConnection(),
1024 &m_aLengthVector
[columnIndex
],
1027 m_pStatement
->getOwnConnection()->useOldDateFormat());
1030 void SAL_CALL
OResultSet::updateNull( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
1032 ::osl::MutexGuard
aGuard( m_aMutex
);
1033 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1035 m_aBindVector
.push_back(allocBindColumn(DataType::CHAR
,columnIndex
));
1036 void* pData
= reinterpret_cast<void*>(m_aBindVector
.rbegin()->first
);
1037 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());
1041 void SAL_CALL
OResultSet::updateBoolean( sal_Int32 columnIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
, std::exception
)
1043 updateValue(columnIndex
,SQL_BIT
,&x
);
1046 void SAL_CALL
OResultSet::updateByte( sal_Int32 columnIndex
, sal_Int8 x
) throw(SQLException
, RuntimeException
, std::exception
)
1048 updateValue(columnIndex
,SQL_CHAR
,&x
);
1052 void SAL_CALL
OResultSet::updateShort( sal_Int32 columnIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
, std::exception
)
1054 updateValue(columnIndex
,SQL_TINYINT
,&x
);
1057 void SAL_CALL
OResultSet::updateInt( sal_Int32 columnIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
, std::exception
)
1059 updateValue(columnIndex
,SQL_INTEGER
,&x
);
1062 void SAL_CALL
OResultSet::updateLong( sal_Int32
/*columnIndex*/, sal_Int64
/*x*/ ) throw(SQLException
, RuntimeException
, std::exception
)
1064 ::dbtools::throwFunctionNotSupportedException( "XRowUpdate::updateLong", *this );
1067 void SAL_CALL
OResultSet::updateFloat( sal_Int32 columnIndex
, float x
) throw(SQLException
, RuntimeException
, std::exception
)
1069 updateValue(columnIndex
,SQL_REAL
,&x
);
1073 void SAL_CALL
OResultSet::updateDouble( sal_Int32 columnIndex
, double x
) throw(SQLException
, RuntimeException
, std::exception
)
1075 updateValue(columnIndex
,SQL_DOUBLE
,&x
);
1078 void SAL_CALL
OResultSet::updateString( sal_Int32 columnIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1080 sal_Int32 nType
= m_aRow
[columnIndex
].getTypeKind();
1081 SQLSMALLINT nOdbcType
= OTools::jdbcTypeToOdbc(nType
);
1082 m_aRow
[columnIndex
] = x
;
1083 m_aRow
[columnIndex
].setTypeKind(nType
); // OJ: otherwise longvarchar will be recognized by fillNeededData
1084 m_aRow
[columnIndex
].setBound(true);
1085 updateValue(columnIndex
,nOdbcType
,(void*)&x
);
1088 void SAL_CALL
OResultSet::updateBytes( sal_Int32 columnIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
, std::exception
)
1090 sal_Int32 nType
= m_aRow
[columnIndex
].getTypeKind();
1091 SQLSMALLINT nOdbcType
= OTools::jdbcTypeToOdbc(nType
);
1092 m_aRow
[columnIndex
] = x
;
1093 m_aRow
[columnIndex
].setTypeKind(nType
); // OJ: otherwise longvarbinary will be recognized by fillNeededData
1094 m_aRow
[columnIndex
].setBound(true);
1095 updateValue(columnIndex
,nOdbcType
,(void*)&x
);
1098 void SAL_CALL
OResultSet::updateDate( sal_Int32 columnIndex
, const Date
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1100 DATE_STRUCT aVal
= OTools::DateToOdbcDate(x
);
1101 updateValue(columnIndex
,SQL_DATE
,&aVal
);
1105 void SAL_CALL
OResultSet::updateTime( sal_Int32 columnIndex
, const Time
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1107 TIME_STRUCT aVal
= OTools::TimeToOdbcTime(x
);
1108 updateValue(columnIndex
,SQL_TIME
,&aVal
);
1112 void SAL_CALL
OResultSet::updateTimestamp( sal_Int32 columnIndex
, const DateTime
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1114 TIMESTAMP_STRUCT aVal
= OTools::DateTimeToTimestamp(x
);
1115 updateValue(columnIndex
,SQL_TIMESTAMP
,&aVal
);
1119 void SAL_CALL
OResultSet::updateBinaryStream( sal_Int32 columnIndex
, const Reference
< XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
1122 ::dbtools::throwFunctionSequenceException(*this);
1124 Sequence
<sal_Int8
> aSeq
;
1125 x
->readBytes(aSeq
,length
);
1126 updateBytes(columnIndex
,aSeq
);
1129 void SAL_CALL
OResultSet::updateCharacterStream( sal_Int32 columnIndex
, const Reference
< XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
1131 updateBinaryStream(columnIndex
,x
,length
);
1134 void SAL_CALL
OResultSet::refreshRow( ) throw(SQLException
, RuntimeException
, std::exception
)
1136 ::osl::MutexGuard
aGuard( m_aMutex
);
1137 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1140 // SQLRETURN nRet = N3SQLSetPos(m_aStatementHandle,1,SQL_REFRESH,SQL_LOCK_NO_CHANGE);
1141 m_nCurrentFetchState
= N3SQLFetchScroll(m_aStatementHandle
,SQL_FETCH_RELATIVE
,0);
1142 OTools::ThrowException(m_pStatement
->getOwnConnection(),m_nCurrentFetchState
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
1145 void SAL_CALL
OResultSet::updateObject( sal_Int32 columnIndex
, const Any
& x
) throw(SQLException
, RuntimeException
, std::exception
)
1147 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1148 throw SQLException();
1152 void SAL_CALL
OResultSet::updateNumericObject( sal_Int32 columnIndex
, const Any
& x
, sal_Int32
/*scale*/ ) throw(SQLException
, RuntimeException
, std::exception
)
1154 if (!::dbtools::implUpdateObject(this, columnIndex
, x
))
1155 throw SQLException();
1159 Any SAL_CALL
OResultSet::getBookmark( ) throw( SQLException
, RuntimeException
, std::exception
)
1162 if(m_aRow
[0].isNull())
1163 throw SQLException();
1164 return m_aRow
[0].makeAny();
1166 Sequence
<sal_Int8
> OResultSet::impl_getBookmark( ) throw( SQLException
, RuntimeException
)
1168 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1170 TBookmarkPosMap::iterator aFind
= ::std::find_if(m_aPosToBookmarks
.begin(),m_aPosToBookmarks
.end(),
1171 ::o3tl::compose1(::std::bind2nd(::std::equal_to
<sal_Int32
>(),m_nRowPos
),::o3tl::select2nd
<TBookmarkPosMap::value_type
>()));
1173 if ( aFind
== m_aPosToBookmarks
.end() )
1175 if ( m_nUseBookmarks
== ODBC_SQL_NOT_DEFINED
)
1177 m_nUseBookmarks
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_USE_BOOKMARKS
, SQL_UB_OFF
);
1179 if(m_nUseBookmarks
== SQL_UB_OFF
)
1180 throw SQLException();
1182 Sequence
<sal_Int8
> bookmark
= OTools::getBytesValue(m_pStatement
->getOwnConnection(),m_aStatementHandle
,0,SQL_C_VARBOOKMARK
,m_bWasNull
,**this);
1183 m_aPosToBookmarks
[bookmark
] = m_nRowPos
;
1184 OSL_ENSURE(bookmark
.getLength(),"Invalid bookmark from length 0!");
1189 return aFind
->first
;
1193 sal_Bool SAL_CALL
OResultSet::moveToBookmark( const Any
& bookmark
) throw( SQLException
, RuntimeException
, std::exception
)
1195 ::osl::MutexGuard
aGuard( m_aMutex
);
1196 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1199 Sequence
<sal_Int8
> aBookmark
;
1200 bookmark
>>= aBookmark
;
1201 OSL_ENSURE(aBookmark
.getLength(),"Invalid bookmark from length 0!");
1202 if(aBookmark
.getLength())
1204 SQLRETURN nReturn
= setStmtOption
<SQLLEN
*, SQL_IS_POINTER
>(SQL_ATTR_FETCH_BOOKMARK_PTR
, reinterpret_cast<SQLLEN
*>(aBookmark
.getArray()));
1206 if ( SQL_INVALID_HANDLE
!= nReturn
&& SQL_ERROR
!= nReturn
)
1208 m_nCurrentFetchState
= N3SQLFetchScroll(m_aStatementHandle
,SQL_FETCH_BOOKMARK
,0);
1209 OTools::ThrowException(m_pStatement
->getOwnConnection(),m_nCurrentFetchState
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
1210 TBookmarkPosMap::iterator aFind
= m_aPosToBookmarks
.find(aBookmark
);
1211 if(aFind
!= m_aPosToBookmarks
.end())
1212 m_nRowPos
= aFind
->second
;
1215 return m_nCurrentFetchState
== SQL_SUCCESS
|| m_nCurrentFetchState
== SQL_SUCCESS_WITH_INFO
;
1221 sal_Bool SAL_CALL
OResultSet::moveRelativeToBookmark( const Any
& bookmark
, sal_Int32 rows
) throw( SQLException
, RuntimeException
, std::exception
)
1223 ::osl::MutexGuard
aGuard( m_aMutex
);
1224 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1228 Sequence
<sal_Int8
> aBookmark
;
1229 bookmark
>>= aBookmark
;
1230 SQLRETURN nReturn
= setStmtOption
<SQLLEN
*, SQL_IS_POINTER
>(SQL_ATTR_FETCH_BOOKMARK_PTR
, reinterpret_cast<SQLLEN
*>(aBookmark
.getArray()));
1231 OSL_UNUSED( nReturn
);
1233 m_nCurrentFetchState
= N3SQLFetchScroll(m_aStatementHandle
,SQL_FETCH_BOOKMARK
,rows
);
1234 OTools::ThrowException(m_pStatement
->getOwnConnection(),m_nCurrentFetchState
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
1235 return m_nCurrentFetchState
== SQL_SUCCESS
|| m_nCurrentFetchState
== SQL_SUCCESS_WITH_INFO
;
1238 sal_Int32 SAL_CALL
OResultSet::compareBookmarks( const Any
& lhs
, const Any
& rhs
) throw( SQLException
, RuntimeException
, std::exception
)
1240 ::osl::MutexGuard
aGuard( m_aMutex
);
1241 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1243 return (lhs
== rhs
) ? CompareBookmark::EQUAL
: CompareBookmark::NOT_EQUAL
;
1246 sal_Bool SAL_CALL
OResultSet::hasOrderedBookmarks( ) throw( SQLException
, RuntimeException
, std::exception
)
1251 sal_Int32 SAL_CALL
OResultSet::hashBookmark( const Any
& /*bookmark*/ ) throw( SQLException
, RuntimeException
, std::exception
)
1253 ::dbtools::throwFunctionNotSupportedException( "XRowLocate::hashBookmark", *this );
1258 Sequence
< sal_Int32
> SAL_CALL
OResultSet::deleteRows( const Sequence
< Any
>& rows
) throw( SQLException
, RuntimeException
, std::exception
)
1260 Sequence
< sal_Int32
> aRet(rows
.getLength());
1261 sal_Int32
*pRet
= aRet
.getArray();
1263 const Any
*pBegin
= rows
.getConstArray();
1264 const Any
*pEnd
= pBegin
+ rows
.getLength();
1266 for(;pBegin
!= pEnd
;++pBegin
,++pRet
)
1270 if(moveToBookmark(*pBegin
))
1276 catch(const SQLException
&)
1284 template < typename T
, SQLINTEGER BufferLength
> T
OResultSet::getStmtOption (SQLINTEGER fOption
, T dflt
) const
1287 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
1288 N3SQLGetStmtAttr(m_aStatementHandle
, fOption
, &result
, BufferLength
, NULL
);
1291 template < typename T
, SQLINTEGER BufferLength
> SQLRETURN
OResultSet::setStmtOption (SQLINTEGER fOption
, T value
) const
1293 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
1294 SQLPOINTER sv
= reinterpret_cast<SQLPOINTER
>(value
);
1295 return N3SQLSetStmtAttr(m_aStatementHandle
, fOption
, sv
, BufferLength
);
1298 sal_Int32
OResultSet::getResultSetConcurrency() const
1300 sal_uInt32 nValue
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CONCURRENCY
);
1301 if(SQL_CONCUR_READ_ONLY
== nValue
)
1302 nValue
= ResultSetConcurrency::READ_ONLY
;
1304 nValue
= ResultSetConcurrency::UPDATABLE
;
1309 sal_Int32
OResultSet::getResultSetType() const
1311 sal_uInt32 nValue
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CURSOR_SENSITIVITY
);
1312 if(SQL_SENSITIVE
== nValue
)
1313 nValue
= ResultSetType::SCROLL_SENSITIVE
;
1314 else if(SQL_INSENSITIVE
== nValue
)
1315 nValue
= ResultSetType::SCROLL_INSENSITIVE
;
1318 SQLULEN nCurType
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CURSOR_TYPE
);
1319 if(SQL_CURSOR_KEYSET_DRIVEN
== nCurType
)
1320 nValue
= ResultSetType::SCROLL_SENSITIVE
;
1321 else if(SQL_CURSOR_STATIC
== nCurType
)
1322 nValue
= ResultSetType::SCROLL_INSENSITIVE
;
1323 else if(SQL_CURSOR_FORWARD_ONLY
== nCurType
)
1324 nValue
= ResultSetType::FORWARD_ONLY
;
1325 else if(SQL_CURSOR_DYNAMIC
== nCurType
)
1326 nValue
= ResultSetType::SCROLL_SENSITIVE
;
1331 sal_Int32
OResultSet::getFetchDirection() const
1333 return FetchDirection::FORWARD
;
1336 sal_Int32
OResultSet::getFetchSize() const
1338 return getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_ROW_ARRAY_SIZE
);
1341 OUString
OResultSet::getCursorName() const
1344 SQLSMALLINT nRealLen
= 0;
1345 N3SQLGetCursorName(m_aStatementHandle
,(SQLCHAR
*)pName
,256,&nRealLen
);
1346 return OUString::createFromAscii((const char*)pName
);
1349 bool OResultSet::isBookmarkable() const
1351 if(!m_aConnectionHandle
)
1354 const SQLULEN nCursorType
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CURSOR_TYPE
);
1356 sal_Int32 nAttr
= 0;
1361 case SQL_CURSOR_FORWARD_ONLY
:
1363 case SQL_CURSOR_STATIC
:
1364 OTools::GetInfo(m_pStatement
->getOwnConnection(),m_aConnectionHandle
,SQL_STATIC_CURSOR_ATTRIBUTES1
,nAttr
,NULL
);
1366 case SQL_CURSOR_KEYSET_DRIVEN
:
1367 OTools::GetInfo(m_pStatement
->getOwnConnection(),m_aConnectionHandle
,SQL_KEYSET_CURSOR_ATTRIBUTES1
,nAttr
,NULL
);
1369 case SQL_CURSOR_DYNAMIC
:
1370 OTools::GetInfo(m_pStatement
->getOwnConnection(),m_aConnectionHandle
,SQL_DYNAMIC_CURSOR_ATTRIBUTES1
,nAttr
,NULL
);
1374 catch(const Exception
&)
1379 if ( m_nUseBookmarks
== ODBC_SQL_NOT_DEFINED
)
1381 m_nUseBookmarks
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_USE_BOOKMARKS
, SQL_UB_OFF
);
1384 return (m_nUseBookmarks
!= SQL_UB_OFF
) && (nAttr
& SQL_CA1_BOOKMARK
) == SQL_CA1_BOOKMARK
;
1387 void OResultSet::setFetchDirection(sal_Int32 _par0
)
1389 ::dbtools::throwFunctionNotSupportedException( "setFetchDirection", *this );
1391 OSL_ENSURE(_par0
>0,"Illegal fetch direction!");
1394 setStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_CURSOR_TYPE
, _par0
);
1398 void OResultSet::setFetchSize(sal_Int32 _par0
)
1400 OSL_ENSURE(_par0
>0,"Illegal fetch size!");
1403 throw ::com::sun::star::beans::PropertyVetoException("SDBC/ODBC layer not prepared for fetchSize > 1", *this);
1407 setStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_ROW_ARRAY_SIZE
, _par0
);
1408 delete [] m_pRowStatusArray
;
1410 m_pRowStatusArray
= new SQLUSMALLINT
[_par0
];
1411 setStmtOption
<SQLUSMALLINT
*, SQL_IS_POINTER
>(SQL_ATTR_ROW_STATUS_PTR
, m_pRowStatusArray
);
1415 IPropertyArrayHelper
* OResultSet::createArrayHelper( ) const
1417 Sequence
< Property
> aProps(6);
1418 Property
* pProperties
= aProps
.getArray();
1420 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME
),
1421 PROPERTY_ID_CURSORNAME
, cppu::UnoType
<OUString
>::get(), PropertyAttribute::READONLY
);
1423 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION
),
1424 PROPERTY_ID_FETCHDIRECTION
, cppu::UnoType
<sal_Int32
>::get(), 0);
1426 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE
),
1427 PROPERTY_ID_FETCHSIZE
, cppu::UnoType
<sal_Int32
>::get(), 0);
1429 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE
),
1430 PROPERTY_ID_ISBOOKMARKABLE
, ::getBooleanCppuType(), PropertyAttribute::READONLY
);
1432 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY
),
1433 PROPERTY_ID_RESULTSETCONCURRENCY
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
1435 pProperties
[nPos
++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE
),
1436 PROPERTY_ID_RESULTSETTYPE
, cppu::UnoType
<sal_Int32
>::get(), PropertyAttribute::READONLY
);
1438 return new OPropertyArrayHelper(aProps
);
1441 IPropertyArrayHelper
& OResultSet::getInfoHelper()
1443 return *const_cast<OResultSet
*>(this)->getArrayHelper();
1446 sal_Bool
OResultSet::convertFastPropertyValue(
1447 Any
& rConvertedValue
,
1451 throw (::com::sun::star::lang::IllegalArgumentException
)
1455 case PROPERTY_ID_ISBOOKMARKABLE
:
1456 case PROPERTY_ID_CURSORNAME
:
1457 case PROPERTY_ID_RESULTSETCONCURRENCY
:
1458 case PROPERTY_ID_RESULTSETTYPE
:
1459 throw ::com::sun::star::lang::IllegalArgumentException();
1460 case PROPERTY_ID_FETCHDIRECTION
:
1461 return ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getFetchDirection());
1462 case PROPERTY_ID_FETCHSIZE
:
1463 return ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getFetchSize());
1470 void OResultSet::setFastPropertyValue_NoBroadcast(
1474 throw (Exception
, std::exception
)
1478 case PROPERTY_ID_ISBOOKMARKABLE
:
1479 case PROPERTY_ID_CURSORNAME
:
1480 case PROPERTY_ID_RESULTSETCONCURRENCY
:
1481 case PROPERTY_ID_RESULTSETTYPE
:
1483 case PROPERTY_ID_FETCHDIRECTION
:
1484 setFetchDirection(getINT32(rValue
));
1486 case PROPERTY_ID_FETCHSIZE
:
1487 setFetchSize(getINT32(rValue
));
1494 void OResultSet::getFastPropertyValue(
1501 case PROPERTY_ID_ISBOOKMARKABLE
:
1502 rValue
= css::uno::makeAny(isBookmarkable());
1504 case PROPERTY_ID_CURSORNAME
:
1505 rValue
<<= getCursorName();
1507 case PROPERTY_ID_RESULTSETCONCURRENCY
:
1508 rValue
<<= getResultSetConcurrency();
1510 case PROPERTY_ID_RESULTSETTYPE
:
1511 rValue
<<= getResultSetType();
1513 case PROPERTY_ID_FETCHDIRECTION
:
1514 rValue
<<= getFetchDirection();
1516 case PROPERTY_ID_FETCHSIZE
:
1517 rValue
<<= getFetchSize();
1522 void OResultSet::fillColumn(const sal_Int32 _nColumn
)
1524 ensureCacheForColumn(_nColumn
);
1526 if (m_aRow
[_nColumn
].isBound())
1530 if(m_bFetchDataInOrder
)
1532 // m_aRow necessarily has a prefix of bound values, then all unbound values
1533 // EXCEPT for column 0
1534 // so use binary search to find the earliest unbound value before or at _nColumn
1536 sal_Int32 upper
=_nColumn
;
1538 while (lower
< upper
)
1540 const sal_Int32 middle
=(upper
-lower
)/2 + lower
;
1541 if(m_aRow
[middle
].isBound())
1558 TDataRow::iterator pColumn
= m_aRow
.begin() + curCol
;
1559 const TDataRow::const_iterator pColumnEnd
= m_aRow
.begin() + _nColumn
+ 1;
1565 *pColumn
=impl_getBookmark();
1567 catch (SQLException
&)
1571 pColumn
->setBound(true);
1576 for (; pColumn
!= pColumnEnd
; ++curCol
, ++pColumn
)
1578 const sal_Int32 nType
= pColumn
->getTypeKind();
1581 case DataType::CHAR
:
1582 case DataType::VARCHAR
:
1583 case DataType::DECIMAL
:
1584 case DataType::NUMERIC
:
1585 case DataType::LONGVARCHAR
:
1586 case DataType::CLOB
:
1587 *pColumn
=impl_getString(curCol
);
1589 case DataType::FLOAT
:
1590 *pColumn
= impl_getValue
<float>(curCol
, SQL_C_FLOAT
);
1592 case DataType::REAL
:
1593 case DataType::DOUBLE
:
1594 *pColumn
= impl_getValue
<double>(curCol
, SQL_C_DOUBLE
);
1596 case DataType::BINARY
:
1597 case DataType::VARBINARY
:
1598 case DataType::LONGVARBINARY
:
1599 case DataType::BLOB
:
1600 *pColumn
= impl_getBytes(curCol
);
1602 case DataType::DATE
:
1603 *pColumn
= impl_getDate(curCol
);
1605 case DataType::TIME
:
1606 *pColumn
= impl_getTime(curCol
);
1608 case DataType::TIMESTAMP
:
1609 *pColumn
= impl_getTimestamp(curCol
);
1612 *pColumn
= impl_getBoolean(curCol
);
1614 case DataType::TINYINT
:
1615 *pColumn
= impl_getValue
<sal_Int8
>(curCol
, SQL_C_TINYINT
);
1617 case DataType::SMALLINT
:
1618 *pColumn
= impl_getValue
<sal_Int16
>(curCol
, SQL_C_SHORT
);
1620 case DataType::INTEGER
:
1621 *pColumn
= impl_getValue
<sal_Int32
>(curCol
, SQL_C_LONG
);
1623 case DataType::BIGINT
:
1624 *pColumn
= impl_getLong(curCol
);
1627 SAL_WARN( "connectivity.drivers","Unknown DataType");
1632 pColumn
->setBound(true);
1633 if(nType
!= pColumn
->getTypeKind())
1635 pColumn
->setTypeKind(nType
);
1640 void SAL_CALL
OResultSet::acquire() throw()
1642 OResultSet_BASE::acquire();
1645 void SAL_CALL
OResultSet::release() throw()
1647 OResultSet_BASE::release();
1650 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
OResultSet::getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
1652 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1655 bool OResultSet::move(IResultSetHelper::Movement _eCursorPosition
, sal_Int32 _nOffset
, bool /*_bRetrieveData*/)
1657 SQLSMALLINT nFetchOrientation
= SQL_FETCH_NEXT
;
1658 switch(_eCursorPosition
)
1660 case IResultSetHelper::NEXT
:
1661 nFetchOrientation
= SQL_FETCH_NEXT
;
1663 case IResultSetHelper::PRIOR
:
1664 nFetchOrientation
= SQL_FETCH_PRIOR
;
1666 case IResultSetHelper::FIRST
:
1667 nFetchOrientation
= SQL_FETCH_FIRST
;
1669 case IResultSetHelper::LAST
:
1670 nFetchOrientation
= SQL_FETCH_LAST
;
1672 case IResultSetHelper::RELATIVE
:
1673 nFetchOrientation
= SQL_FETCH_RELATIVE
;
1675 case IResultSetHelper::ABSOLUTE
:
1676 nFetchOrientation
= SQL_FETCH_ABSOLUTE
;
1678 case IResultSetHelper::BOOKMARK
: // special case here because we are only called with position numbers
1680 TBookmarkPosMap::iterator aIter
= m_aPosToBookmarks
.begin();
1681 TBookmarkPosMap::iterator aEnd
= m_aPosToBookmarks
.end();
1682 for (; aIter
!= aEnd
; ++aIter
)
1684 if ( aIter
->second
== _nOffset
)
1685 return moveToBookmark(makeAny(aIter
->first
));
1687 SAL_WARN( "connectivity.drivers","Bookmark not found!");
1695 SQLRETURN nOldFetchStatus
= m_nCurrentFetchState
;
1696 // TODO FIXME: both of these will misbehave for
1697 // _eCursorPosition == IResultSetHelper::NEXT/PREVIOUS
1698 // when fetchSize > 1
1699 if ( !m_bUseFetchScroll
&& _eCursorPosition
== IResultSetHelper::NEXT
)
1700 m_nCurrentFetchState
= N3SQLFetch(m_aStatementHandle
);
1702 m_nCurrentFetchState
= N3SQLFetchScroll(m_aStatementHandle
,nFetchOrientation
,_nOffset
);
1704 OSL_TRACE( __FILE__
": OResultSet::move(%d,%d), FetchState = %d",nFetchOrientation
,_nOffset
,m_nCurrentFetchState
);
1705 OTools::ThrowException(m_pStatement
->getOwnConnection(),m_nCurrentFetchState
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
1707 const bool bSuccess
= m_nCurrentFetchState
== SQL_SUCCESS
|| m_nCurrentFetchState
== SQL_SUCCESS_WITH_INFO
;
1710 switch(_eCursorPosition
)
1712 case IResultSetHelper::NEXT
:
1715 case IResultSetHelper::PRIOR
:
1718 case IResultSetHelper::FIRST
:
1721 case IResultSetHelper::LAST
:
1724 case IResultSetHelper::RELATIVE
:
1725 m_nRowPos
+= _nOffset
;
1727 case IResultSetHelper::ABSOLUTE
:
1728 case IResultSetHelper::BOOKMARK
: // special case here because we are only called with position numbers
1729 m_nRowPos
= _nOffset
;
1731 } // switch(_eCursorPosition)
1732 if ( m_nUseBookmarks
== ODBC_SQL_NOT_DEFINED
)
1734 m_nUseBookmarks
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_USE_BOOKMARKS
, SQL_UB_OFF
);
1736 if ( m_nUseBookmarks
== SQL_UB_OFF
)
1738 m_aRow
[0].setNull();
1742 ensureCacheForColumn(0);
1743 Sequence
<sal_Int8
> bookmark
= OTools::getBytesValue(m_pStatement
->getOwnConnection(),m_aStatementHandle
,0,SQL_C_VARBOOKMARK
,m_bWasNull
,**this);
1744 m_aPosToBookmarks
[bookmark
] = m_nRowPos
;
1745 OSL_ENSURE(bookmark
.getLength(),"Invalid bookmark from length 0!");
1746 m_aRow
[0] = bookmark
;
1748 m_aRow
[0].setBound(true);
1750 else if ( IResultSetHelper::PRIOR
== _eCursorPosition
&& m_nCurrentFetchState
== SQL_NO_DATA
)
1751 // we went beforeFirst
1753 else if(IResultSetHelper::NEXT
== _eCursorPosition
&& m_nCurrentFetchState
== SQL_NO_DATA
&& nOldFetchStatus
!= SQL_NO_DATA
)
1754 // we went afterLast
1760 sal_Int32
OResultSet::getDriverPos() const
1762 sal_Int32 nValue
= getStmtOption
<SQLULEN
, SQL_IS_UINTEGER
>(SQL_ATTR_ROW_NUMBER
);
1763 OSL_TRACE( __FILE__
": OResultSet::getDriverPos() = RowNum = %d, RowPos = %d", nValue
, m_nRowPos
);
1764 return nValue
? nValue
: m_nRowPos
;
1767 bool OResultSet::deletedVisible() const
1772 bool OResultSet::isRowDeleted() const
1774 return m_pRowStatusArray
[0] == SQL_ROW_DELETED
;
1777 bool OResultSet::moveImpl(IResultSetHelper::Movement _eCursorPosition
, sal_Int32 _nOffset
, bool _bRetrieveData
)
1779 ::osl::MutexGuard
aGuard( m_aMutex
);
1780 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
1781 return (m_pSkipDeletedSet
!= NULL
)
1782 ? m_pSkipDeletedSet
->skipDeleted(_eCursorPosition
,_nOffset
,_bRetrieveData
)
1783 : move(_eCursorPosition
,_nOffset
,_bRetrieveData
);
1786 void OResultSet::fillNeededData(SQLRETURN _nRet
)
1788 SQLRETURN nRet
= _nRet
;
1789 if( nRet
== SQL_NEED_DATA
)
1791 void* pColumnIndex
= 0;
1792 nRet
= N3SQLParamData(m_aStatementHandle
,&pColumnIndex
);
1796 if (nRet
!= SQL_SUCCESS
&& nRet
!= SQL_SUCCESS_WITH_INFO
&& nRet
!= SQL_NEED_DATA
)
1799 sal_IntPtr
nColumnIndex ( reinterpret_cast<sal_IntPtr
>(pColumnIndex
));
1800 Sequence
< sal_Int8
> aSeq
;
1801 switch(m_aRow
[nColumnIndex
].getTypeKind())
1803 case DataType::BINARY
:
1804 case DataType::VARBINARY
:
1805 case DataType::LONGVARBINARY
:
1806 case DataType::BLOB
:
1807 aSeq
= m_aRow
[nColumnIndex
];
1808 N3SQLPutData (m_aStatementHandle
, aSeq
.getArray(), aSeq
.getLength());
1810 case SQL_WLONGVARCHAR
:
1813 sRet
= m_aRow
[nColumnIndex
].getString();
1814 nRet
= N3SQLPutData (m_aStatementHandle
, (SQLPOINTER
)sRet
.getStr(), sizeof(sal_Unicode
)*sRet
.getLength());
1817 case DataType::LONGVARCHAR
:
1818 case DataType::CLOB
:
1821 sRet
= m_aRow
[nColumnIndex
].getString();
1822 OString
aString(OUStringToOString(sRet
,m_nTextEncoding
));
1823 nRet
= N3SQLPutData (m_aStatementHandle
, (SQLPOINTER
)aString
.getStr(), aString
.getLength());
1827 SAL_WARN( "connectivity.drivers","Not supported at the moment!");
1829 nRet
= N3SQLParamData(m_aStatementHandle
,&pColumnIndex
);
1831 while (nRet
== SQL_NEED_DATA
);
1835 SWORD
OResultSet::impl_getColumnType_nothrow(sal_Int32 columnIndex
)
1837 ::std::map
<sal_Int32
,SWORD
>::iterator aFind
= m_aODBCColumnTypes
.find(columnIndex
);
1838 if ( aFind
== m_aODBCColumnTypes
.end() )
1839 aFind
= m_aODBCColumnTypes
.insert(::std::map
<sal_Int32
,SWORD
>::value_type(columnIndex
,OResultSetMetaData::getColumnODBCType(m_pStatement
->getOwnConnection(),m_aStatementHandle
,*this,columnIndex
))).first
;
1840 return aFind
->second
;
1843 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */