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