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