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