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 <ado/AResultSet.hxx>
21 #include <ado/AResultSetMetaData.hxx>
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <com/sun/star/sdbc/KeyRule.hpp>
24 #include <com/sun/star/sdbc/IndexType.hpp>
25 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
26 #include <comphelper/property.hxx>
27 #include <com/sun/star/lang/DisposedException.hpp>
28 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
29 #include <com/sun/star/sdbc/ResultSetType.hpp>
30 #include <com/sun/star/sdbc/FetchDirection.hpp>
31 #include <cppuhelper/typeprovider.hxx>
32 #include <cppuhelper/supportsservice.hxx>
33 #include <comphelper/sequence.hxx>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <comphelper/seqstream.hxx>
36 #include <connectivity/dbexception.hxx>
37 #include <connectivity/dbtools.hxx>
38 #include <comphelper/types.hxx>
39
40 using namespace ::comphelper;
41
42
43 #include <oledb.h>
44
45 #define CHECK_RETURN(x) \
46 if(!SUCCEEDED(x)) \
47 ADOS::ThrowException(*m_pStmt->m_pConnection->getConnection(),*this);
48
49 using namespace connectivity::ado;
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::lang;
52 using namespace com::sun::star::beans;
53 using namespace com::sun::star::sdbc;
54
55
56 // IMPLEMENT_SERVICE_INFO(OResultSet,"com.sun.star.sdbcx.AResultSet","com.sun.star.sdbc.ResultSet");
getImplementationName()57 OUString SAL_CALL OResultSet::getImplementationName( )
58 {
59 return "com.sun.star.sdbcx.ado.ResultSet";
60 }
61
getSupportedServiceNames()62 css::uno::Sequence< OUString > SAL_CALL OResultSet::getSupportedServiceNames( )
63 {
64 return {"com.sun.star.sdbc.ResultSet","com.sun.star.sdbcx.ResultSet"};
65 }
66
supportsService(const OUString & _rServiceName)67 sal_Bool SAL_CALL OResultSet::supportsService( const OUString& _rServiceName )
68 {
69 return cppu::supportsService(this, _rServiceName);
70 }
71
OResultSet(ADORecordset * _pRecordSet,OStatement_Base * pStmt)72 OResultSet::OResultSet(ADORecordset* _pRecordSet,OStatement_Base* pStmt) : OResultSet_BASE(m_aMutex)
73 ,OPropertySetHelper(OResultSet_BASE::rBHelper)
74 ,m_pRecordSet(_pRecordSet)
75 ,m_pStmt(pStmt)
76 ,m_xStatement(*pStmt)
77 ,m_nRowPos(0)
78 ,m_bEOF(false)
79 ,m_bOnFirstAfterOpen(false)
80 {
81 }
82
OResultSet(ADORecordset * _pRecordSet)83 OResultSet::OResultSet(ADORecordset* _pRecordSet) : OResultSet_BASE(m_aMutex)
84 ,OPropertySetHelper(OResultSet_BASE::rBHelper)
85 ,m_pRecordSet(_pRecordSet)
86 ,m_pStmt(nullptr)
87 ,m_nRowPos(0)
88 ,m_bEOF(false)
89 ,m_bOnFirstAfterOpen(false)
90 {
91 }
92
construct()93 void OResultSet::construct()
94 {
95 osl_atomic_increment( &m_refCount );
96 if (!m_pRecordSet)
97 {
98 OSL_FAIL( "OResultSet::construct: no RecordSet!" );
99 Reference< XInterface > xInt( *this );
100 osl_atomic_decrement( &m_refCount );
101 ::dbtools::throwFunctionSequenceException( xInt );
102 }
103 m_pRecordSet->AddRef();
104 VARIANT_BOOL bIsAtBOF;
105 CHECK_RETURN(m_pRecordSet->get_BOF(&bIsAtBOF))
106 m_bOnFirstAfterOpen = bIsAtBOF != VARIANT_TRUE;
107 osl_atomic_decrement( &m_refCount );
108 }
109
~OResultSet()110 OResultSet::~OResultSet()
111 {
112 if(m_pRecordSet)
113 m_pRecordSet->Release();
114 }
115
disposing()116 void OResultSet::disposing()
117 {
118 OPropertySetHelper::disposing();
119
120 ::osl::MutexGuard aGuard(m_aMutex);
121 if(m_pRecordSet)
122 m_pRecordSet->Close();
123 m_xStatement.clear();
124 m_xMetaData.clear();
125 }
126
queryInterface(const Type & rType)127 Any SAL_CALL OResultSet::queryInterface( const Type & rType )
128 {
129 Any aRet = OPropertySetHelper::queryInterface(rType);
130 return aRet.hasValue() ? aRet : OResultSet_BASE::queryInterface(rType);
131 }
132
getTypes()133 css::uno::Sequence< css::uno::Type > SAL_CALL OResultSet::getTypes( )
134 {
135 ::cppu::OTypeCollection aTypes( cppu::UnoType<css::beans::XMultiPropertySet>::get(),
136 cppu::UnoType<css::beans::XFastPropertySet>::get(),
137 cppu::UnoType<css::beans::XPropertySet>::get());
138
139 return ::comphelper::concatSequences(aTypes.getTypes(),OResultSet_BASE::getTypes());
140 }
141
142
findColumn(const OUString & columnName)143 sal_Int32 SAL_CALL OResultSet::findColumn( const OUString& columnName )
144 {
145 ::osl::MutexGuard aGuard( m_aMutex );
146 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
147
148
149 Reference< XResultSetMetaData > xMeta = getMetaData();
150 sal_Int32 nLen = xMeta->getColumnCount();
151 sal_Int32 i = 1;
152 for(;i<=nLen;++i)
153 {
154 if(xMeta->isCaseSensitive(i) ? columnName == xMeta->getColumnName(i) :
155 columnName.equalsIgnoreAsciiCase(xMeta->getColumnName(i)))
156 return i;
157 }
158
159 ::dbtools::throwInvalidColumnException( columnName, *this );
160 assert(false);
161 return 0; // Never reached
162 }
163 #define BLOCK_SIZE 256
164
getBinaryStream(sal_Int32 columnIndex)165 Reference< css::io::XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 columnIndex )
166 {
167 ::osl::MutexGuard aGuard( m_aMutex );
168 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
169
170 WpADOField aField = ADOS::getField(m_pRecordSet,columnIndex);
171
172 if((aField.GetAttributes() & adFldLong) == adFldLong)
173 {
174 //Copy the data only up to the Actual Size of Field.
175 sal_Int32 nSize = aField.GetActualSize();
176 Sequence<sal_Int8> aData(nSize);
177 long index = 0;
178 while(index < nSize)
179 {
180 m_aValue = aField.GetChunk(BLOCK_SIZE);
181 if(m_aValue.isNull())
182 break;
183 UCHAR chData;
184 for(long index2 = 0;index2 < BLOCK_SIZE;++index2)
185 {
186 HRESULT hr = ::SafeArrayGetElement(m_aValue.parray,&index2,&chData);
187 if(SUCCEEDED(hr))
188 {
189 //Take BYTE by BYTE and advance Memory Location
190 aData.getArray()[index++] = chData;
191 }
192 else
193 break;
194 }
195 }
196
197 return new ::comphelper::SequenceInputStream(aData);
198 }
199 // else we ask for a bytesequence
200 aField.get_Value(m_aValue);
201
202 return m_aValue.isNull() ? nullptr : new ::comphelper::SequenceInputStream(m_aValue.getByteSequence());
203 }
204
getCharacterStream(sal_Int32)205 Reference< css::io::XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 /*columnIndex*/ )
206 {
207 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getCharacterStream", *this );
208 return nullptr;
209 }
210
getValue(sal_Int32 columnIndex)211 OLEVariant OResultSet::getValue(sal_Int32 columnIndex )
212 {
213 ::osl::MutexGuard aGuard( m_aMutex );
214 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
215
216 WpADOField aField = ADOS::getField(m_pRecordSet,columnIndex);
217 aField.get_Value(m_aValue);
218 return m_aValue;
219 }
220
getBoolean(sal_Int32 columnIndex)221 sal_Bool SAL_CALL OResultSet::getBoolean( sal_Int32 columnIndex )
222 {
223 return getValue(columnIndex).getBool();
224 }
225
226
getByte(sal_Int32 columnIndex)227 sal_Int8 SAL_CALL OResultSet::getByte( sal_Int32 columnIndex )
228 {
229 return getValue(columnIndex).getInt8();
230 }
231
232
getBytes(sal_Int32 columnIndex)233 Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes( sal_Int32 columnIndex )
234 {
235 return getValue(columnIndex).getByteSequence();
236 }
237
238
getDate(sal_Int32 columnIndex)239 css::util::Date SAL_CALL OResultSet::getDate( sal_Int32 columnIndex )
240 {
241 return getValue(columnIndex).getDate();
242 }
243
244
getDouble(sal_Int32 columnIndex)245 double SAL_CALL OResultSet::getDouble( sal_Int32 columnIndex )
246 {
247 return getValue(columnIndex).getDouble();
248 }
249
250
getFloat(sal_Int32 columnIndex)251 float SAL_CALL OResultSet::getFloat( sal_Int32 columnIndex )
252 {
253 return getValue(columnIndex).getFloat();
254 }
255
256
getInt(sal_Int32 columnIndex)257 sal_Int32 SAL_CALL OResultSet::getInt( sal_Int32 columnIndex )
258 {
259 return getValue(columnIndex).getInt32();
260 }
261
262
getRow()263 sal_Int32 SAL_CALL OResultSet::getRow( )
264 {
265 ::osl::MutexGuard aGuard( m_aMutex );
266 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
267
268
269 PositionEnum_Param aPos;
270 m_pRecordSet->get_AbsolutePosition(&aPos);
271 return (aPos > 0) ? static_cast<sal_Int32>(aPos) : m_nRowPos;
272 // return the rowcount from driver if the driver doesn't support this return our count
273 }
274
275
getLong(sal_Int32)276 sal_Int64 SAL_CALL OResultSet::getLong( sal_Int32 /*columnIndex*/ )
277 {
278 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getLong", *this );
279 return sal_Int64(0);
280 }
281
282
getMetaData()283 Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData( )
284 {
285 ::osl::MutexGuard aGuard( m_aMutex );
286 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
287
288
289 if(!m_xMetaData.is())
290 m_xMetaData = new OResultSetMetaData(m_pRecordSet);
291 return m_xMetaData;
292 }
293
getArray(sal_Int32)294 Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 /*columnIndex*/ )
295 {
296 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getArray", *this );
297 return nullptr;
298 }
299
300
getClob(sal_Int32)301 Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 /*columnIndex*/ )
302 {
303 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getClob", *this );
304 return nullptr;
305 }
306
getBlob(sal_Int32)307 Reference< XBlob > SAL_CALL OResultSet::getBlob( sal_Int32 /*columnIndex*/ )
308 {
309 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getBlob", *this );
310 return nullptr;
311 }
312
313
getRef(sal_Int32)314 Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 /*columnIndex*/ )
315 {
316 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *this );
317 return nullptr;
318 }
319
320
getObject(sal_Int32 columnIndex,const Reference<css::container::XNameAccess> &)321 Any SAL_CALL OResultSet::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& /*typeMap*/ )
322 {
323 return getValue(columnIndex).makeAny();
324 }
325
326
getShort(sal_Int32 columnIndex)327 sal_Int16 SAL_CALL OResultSet::getShort( sal_Int32 columnIndex )
328 {
329 return getValue(columnIndex).getInt16();
330 }
331
332
getString(sal_Int32 columnIndex)333 OUString SAL_CALL OResultSet::getString( sal_Int32 columnIndex )
334 {
335 return getValue(columnIndex).getString();
336 }
337
338
getTime(sal_Int32 columnIndex)339 css::util::Time SAL_CALL OResultSet::getTime( sal_Int32 columnIndex )
340 {
341 return getValue(columnIndex).getTime();
342 }
343
344
getTimestamp(sal_Int32 columnIndex)345 css::util::DateTime SAL_CALL OResultSet::getTimestamp( sal_Int32 columnIndex )
346 {
347 return getValue(columnIndex).getDateTime();
348 }
349
350
isAfterLast()351 sal_Bool SAL_CALL OResultSet::isAfterLast( )
352 {
353 ::osl::MutexGuard aGuard( m_aMutex );
354 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
355
356
357 VARIANT_BOOL bIsAtEOF;
358 CHECK_RETURN(m_pRecordSet->get_EOF(&bIsAtEOF))
359 return bIsAtEOF == VARIANT_TRUE;
360 }
361
isFirst()362 sal_Bool SAL_CALL OResultSet::isFirst( )
363 {
364 ::osl::MutexGuard aGuard( m_aMutex );
365 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
366
367
368 return m_nRowPos == 1;
369 }
370
isLast()371 sal_Bool SAL_CALL OResultSet::isLast( )
372 {
373 ::osl::MutexGuard aGuard( m_aMutex );
374 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
375
376
377 return true;
378 }
379
beforeFirst()380 void SAL_CALL OResultSet::beforeFirst( )
381 {
382 ::osl::MutexGuard aGuard( m_aMutex );
383 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
384
385
386 if(first())
387 m_bOnFirstAfterOpen = !previous();
388 }
389
afterLast()390 void SAL_CALL OResultSet::afterLast( )
391 {
392 ::osl::MutexGuard aGuard( m_aMutex );
393 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
394
395
396 if(last())
397 next();
398 m_bEOF = true;
399 }
400
401
close()402 void SAL_CALL OResultSet::close( )
403 {
404 {
405 ::osl::MutexGuard aGuard( m_aMutex );
406 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
407
408 }
409 dispose();
410 }
411
412
first()413 sal_Bool SAL_CALL OResultSet::first( )
414 {
415 ::osl::MutexGuard aGuard( m_aMutex );
416 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
417
418
419 if(SUCCEEDED(m_pRecordSet->MoveFirst()))
420 {
421 m_nRowPos = 1;
422 m_bOnFirstAfterOpen = false;
423 return true;
424 }
425 return false;
426 }
427
428
last()429 sal_Bool SAL_CALL OResultSet::last( )
430 {
431 ::osl::MutexGuard aGuard( m_aMutex );
432 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
433
434
435 bool bRet = SUCCEEDED(m_pRecordSet->MoveLast());
436 if(bRet)
437 {
438 m_pRecordSet->get_RecordCount(&m_nRowPos);
439 m_bOnFirstAfterOpen = false;
440 }
441 return bRet;
442 }
443
absolute(sal_Int32 row)444 sal_Bool SAL_CALL OResultSet::absolute( sal_Int32 row )
445 {
446 ::osl::MutexGuard aGuard( m_aMutex );
447 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
448
449
450 if(!row) // absolute with zero not allowed
451 ::dbtools::throwFunctionSequenceException(*this);
452
453 bool bCheck = true;
454 if(row < 0)
455 {
456 bCheck = SUCCEEDED(m_pRecordSet->MoveLast());
457 if ( bCheck )
458 {
459 while(++row < 0 && bCheck)
460 bCheck = SUCCEEDED(m_pRecordSet->MovePrevious());
461 }
462 }
463 else
464 {
465 first();
466 OLEVariant aEmpty;
467 aEmpty.setNoArg();
468 bCheck = SUCCEEDED(m_pRecordSet->Move(row-1,aEmpty)); // move to row -1 because we stand already on the first
469 if(bCheck)
470 m_nRowPos = row;
471 }
472 if(bCheck)
473 m_bOnFirstAfterOpen = false;
474 return bCheck;
475 }
476
relative(sal_Int32 row)477 sal_Bool SAL_CALL OResultSet::relative( sal_Int32 row )
478 {
479 ::osl::MutexGuard aGuard( m_aMutex );
480 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
481
482
483 OLEVariant aEmpty;
484 aEmpty.setNoArg();
485 sal_Int32 nNewPos = row;
486 if ( m_bOnFirstAfterOpen && nNewPos > 0 )
487 --nNewPos;
488 bool bRet = SUCCEEDED(m_pRecordSet->Move(row,aEmpty));
489 if(bRet)
490 {
491 m_nRowPos += row;
492 m_bOnFirstAfterOpen = false;
493 }
494 return bRet;
495 }
496
previous()497 sal_Bool SAL_CALL OResultSet::previous( )
498 {
499 ::osl::MutexGuard aGuard( m_aMutex );
500 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
501
502 bool bRet = SUCCEEDED(m_pRecordSet->MovePrevious());
503 if(bRet)
504 {
505 --m_nRowPos;
506 m_bOnFirstAfterOpen = false;
507 }
508 return bRet;
509 }
510
getStatement()511 Reference< XInterface > SAL_CALL OResultSet::getStatement( )
512 {
513 ::osl::MutexGuard aGuard( m_aMutex );
514 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
515 return m_xStatement;
516 }
517
518
rowDeleted()519 sal_Bool SAL_CALL OResultSet::rowDeleted( )
520 {
521 ::osl::MutexGuard aGuard( m_aMutex );
522 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
523
524
525 sal_Int32 eRec;
526 m_pRecordSet->get_Status(&eRec);
527 bool bRet = (RecordStatusEnum(eRec) & adRecDeleted) == adRecDeleted;
528 if(bRet)
529 --m_nRowPos;
530 return bRet;
531 }
532
rowInserted()533 sal_Bool SAL_CALL OResultSet::rowInserted( )
534 { ::osl::MutexGuard aGuard( m_aMutex );
535 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
536
537
538 sal_Int32 eRec;
539 m_pRecordSet->get_Status(&eRec);
540 bool bRet = (RecordStatusEnum(eRec) & adRecNew) == adRecNew;
541 if(bRet)
542 ++m_nRowPos;
543 return bRet;
544 }
545
rowUpdated()546 sal_Bool SAL_CALL OResultSet::rowUpdated( )
547 {
548 ::osl::MutexGuard aGuard( m_aMutex );
549 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
550
551
552 sal_Int32 eRec;
553 m_pRecordSet->get_Status(&eRec);
554 return (RecordStatusEnum(eRec) & adRecModified) == adRecModified;
555 }
556
557
isBeforeFirst()558 sal_Bool SAL_CALL OResultSet::isBeforeFirst( )
559 {
560 ::osl::MutexGuard aGuard( m_aMutex );
561 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
562
563
564 OSL_ENSURE(!m_nRowPos,"OResultSet::isBeforeFirst: Error in setting m_nRowPos!");
565 VARIANT_BOOL bIsAtBOF = VARIANT_TRUE;
566 if(!m_bOnFirstAfterOpen)
567 {
568 OSL_ENSURE(!m_nRowPos,"OResultSet::isBeforeFirst: Error in setting m_nRowPos!");
569 m_pRecordSet->get_BOF(&bIsAtBOF);
570 }
571 return bIsAtBOF == VARIANT_TRUE;
572 }
573
574
next()575 sal_Bool SAL_CALL OResultSet::next( )
576 {
577 ::osl::MutexGuard aGuard( m_aMutex );
578 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
579
580
581 bool bRet = true;
582 if(m_bOnFirstAfterOpen)
583 {
584 m_bOnFirstAfterOpen = false;
585 ++m_nRowPos;
586 }
587 else
588 {
589 bRet = SUCCEEDED(m_pRecordSet->MoveNext());
590
591 if(bRet)
592 {
593 VARIANT_BOOL bIsAtEOF;
594 CHECK_RETURN(m_pRecordSet->get_EOF(&bIsAtEOF))
595 bRet = bIsAtEOF != VARIANT_TRUE;
596 ++m_nRowPos;
597 }
598 else
599 ADOS::ThrowException(*m_pStmt->m_pConnection->getConnection(),*this);
600 }
601
602 return bRet;
603 }
604
605
wasNull()606 sal_Bool SAL_CALL OResultSet::wasNull( )
607 {
608 ::osl::MutexGuard aGuard( m_aMutex );
609 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
610
611
612 return m_aValue.isNull();
613 }
614
615
cancel()616 void SAL_CALL OResultSet::cancel( )
617 {
618 ::osl::MutexGuard aGuard( m_aMutex );
619 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
620
621
622 m_pRecordSet->Cancel();
623 }
624
clearWarnings()625 void SAL_CALL OResultSet::clearWarnings( )
626 {
627 }
628
getWarnings()629 Any SAL_CALL OResultSet::getWarnings( )
630 {
631 return Any();
632 }
633
insertRow()634 void SAL_CALL OResultSet::insertRow( )
635 {
636 ::osl::MutexGuard aGuard( m_aMutex );
637 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
638
639
640 OLEVariant aEmpty;
641 aEmpty.setNoArg();
642 m_pRecordSet->AddNew(aEmpty,aEmpty);
643 }
644
updateRow()645 void SAL_CALL OResultSet::updateRow( )
646 {
647 ::osl::MutexGuard aGuard( m_aMutex );
648 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
649
650
651 OLEVariant aEmpty;
652 aEmpty.setNoArg();
653 m_pRecordSet->Update(aEmpty,aEmpty);
654 }
655
deleteRow()656 void SAL_CALL OResultSet::deleteRow( )
657 {
658 ::osl::MutexGuard aGuard( m_aMutex );
659 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
660
661
662 m_pRecordSet->Delete();
663 m_pRecordSet->UpdateBatch(adAffectCurrent);
664 }
665
666
cancelRowUpdates()667 void SAL_CALL OResultSet::cancelRowUpdates( )
668 {
669 ::osl::MutexGuard aGuard( m_aMutex );
670 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
671
672
673 m_pRecordSet->CancelUpdate();
674 }
675
676
moveToInsertRow()677 void SAL_CALL OResultSet::moveToInsertRow( )
678 {
679 // ::osl::MutexGuard aGuard( m_aMutex );
680 //checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
681 // if ( getResultSetConcurrency() == ResultSetConcurrency::READ_ONLY )
682 // throw SQLException();
683 }
684
685
moveToCurrentRow()686 void SAL_CALL OResultSet::moveToCurrentRow( )
687 {
688 }
689
updateValue(sal_Int32 columnIndex,const OLEVariant & x)690 void OResultSet::updateValue(sal_Int32 columnIndex,const OLEVariant& x)
691 {
692 ::osl::MutexGuard aGuard( m_aMutex );
693 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
694
695 WpADOField aField = ADOS::getField(m_pRecordSet,columnIndex);
696 aField.PutValue(x);
697 }
698
updateNull(sal_Int32 columnIndex)699 void SAL_CALL OResultSet::updateNull( sal_Int32 columnIndex )
700 {
701 OLEVariant x;
702 x.setNull();
703 updateValue(columnIndex,x);
704 }
705
706
updateBoolean(sal_Int32 columnIndex,sal_Bool x)707 void SAL_CALL OResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x )
708 {
709 updateValue(columnIndex,bool(x));
710 }
711
updateByte(sal_Int32 columnIndex,sal_Int8 x)712 void SAL_CALL OResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x )
713 {
714 updateValue(columnIndex,x);
715 }
716
717
updateShort(sal_Int32 columnIndex,sal_Int16 x)718 void SAL_CALL OResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x )
719 {
720 updateValue(columnIndex,x);
721 }
722
updateInt(sal_Int32 columnIndex,sal_Int32 x)723 void SAL_CALL OResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x )
724 {
725 updateValue(columnIndex,x);
726 }
727
updateLong(sal_Int32 columnIndex,sal_Int64 x)728 void SAL_CALL OResultSet::updateLong( sal_Int32 columnIndex, sal_Int64 x )
729 {
730 updateValue(columnIndex,x);
731 }
732
updateFloat(sal_Int32 columnIndex,float x)733 void SAL_CALL OResultSet::updateFloat( sal_Int32 columnIndex, float x )
734 {
735 updateValue(columnIndex,x);
736 }
737
738
updateDouble(sal_Int32 columnIndex,double x)739 void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x )
740 {
741 updateValue(columnIndex,x);
742 }
743
updateString(sal_Int32 columnIndex,const OUString & x)744 void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const OUString& x )
745 {
746 updateValue(columnIndex,x);
747 }
748
updateBytes(sal_Int32 columnIndex,const Sequence<sal_Int8> & x)749 void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x )
750 {
751 updateValue(columnIndex,x);
752 }
753
updateDate(sal_Int32 columnIndex,const css::util::Date & x)754 void SAL_CALL OResultSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x )
755 {
756 updateValue(columnIndex,x);
757 }
758
759
updateTime(sal_Int32 columnIndex,const css::util::Time & x)760 void SAL_CALL OResultSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x )
761 {
762 updateValue(columnIndex,x);
763 }
764
765
updateTimestamp(sal_Int32 columnIndex,const css::util::DateTime & x)766 void SAL_CALL OResultSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x )
767 {
768 updateValue(columnIndex,x);
769 }
770
771
updateBinaryStream(sal_Int32 columnIndex,const Reference<css::io::XInputStream> & x,sal_Int32 length)772 void SAL_CALL OResultSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
773 {
774 if(!x.is())
775 ::dbtools::throwFunctionSequenceException(*this);
776
777 Sequence<sal_Int8> aSeq;
778 x->readBytes(aSeq,length);
779 updateBytes(columnIndex,aSeq);
780 }
781
updateCharacterStream(sal_Int32 columnIndex,const Reference<css::io::XInputStream> & x,sal_Int32 length)782 void SAL_CALL OResultSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length )
783 {
784 if(!x.is())
785 ::dbtools::throwFunctionSequenceException(*this);
786
787 Sequence<sal_Int8> aSeq;
788 x->readBytes(aSeq,length);
789 updateBytes(columnIndex,aSeq);
790 }
791
refreshRow()792 void SAL_CALL OResultSet::refreshRow( )
793 {
794 ::osl::MutexGuard aGuard( m_aMutex );
795 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
796
797
798 m_pRecordSet->Resync(adAffectCurrent);
799 }
800
updateObject(sal_Int32 columnIndex,const Any & x)801 void SAL_CALL OResultSet::updateObject( sal_Int32 columnIndex, const Any& x )
802 {
803 if (!::dbtools::implUpdateObject(this, columnIndex, x))
804 throw SQLException();
805 }
806
807
updateNumericObject(sal_Int32 columnIndex,const Any & x,sal_Int32)808 void SAL_CALL OResultSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ )
809 {
810 if (!::dbtools::implUpdateObject(this, columnIndex, x))
811 throw SQLException();
812 }
813
814 // XRowLocate
getBookmark()815 Any SAL_CALL OResultSet::getBookmark( )
816 {
817 ::osl::MutexGuard aGuard( m_aMutex );
818 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
819
820 if(m_nRowPos < static_cast<sal_Int32>(m_aBookmarks.size())) // this bookmark was already fetched
821 return makeAny(sal_Int32(m_nRowPos-1));
822
823 OLEVariant aVar;
824 m_pRecordSet->get_Bookmark(&aVar);
825 m_aBookmarks.push_back(aVar);
826 return makeAny(static_cast<sal_Int32>(m_aBookmarks.size()-1));
827
828 }
829
moveToBookmark(const Any & bookmark)830 sal_Bool SAL_CALL OResultSet::moveToBookmark( const Any& bookmark )
831 {
832 ::osl::MutexGuard aGuard( m_aMutex );
833 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
834
835
836 sal_Int32 nPos = 0;
837 bookmark >>= nPos;
838 OSL_ENSURE(nPos >= 0 && nPos < static_cast<sal_Int32>(m_aBookmarks.size()),"Invalid Index for vector");
839 if(nPos < 0 || nPos >= static_cast<sal_Int32>(m_aBookmarks.size()))
840 ::dbtools::throwFunctionSequenceException(*this);
841
842 return SUCCEEDED(m_pRecordSet->Move(0,m_aBookmarks[nPos]));
843 }
844
moveRelativeToBookmark(const Any & bookmark,sal_Int32 rows)845 sal_Bool SAL_CALL OResultSet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
846 {
847 ::osl::MutexGuard aGuard( m_aMutex );
848 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
849
850
851 sal_Int32 nPos = 0;
852 bookmark >>= nPos;
853 nPos += rows;
854 OSL_ENSURE(nPos >= 0 && nPos < static_cast<sal_Int32>(m_aBookmarks.size()),"Invalid Index for vector");
855 if(nPos < 0 || nPos >= static_cast<sal_Int32>(m_aBookmarks.size()))
856 ::dbtools::throwFunctionSequenceException(*this);
857 return SUCCEEDED(m_pRecordSet->Move(rows,m_aBookmarks[nPos]));
858 }
859
compareBookmarks(const Any & bookmark1,const Any & bookmark2)860 sal_Int32 SAL_CALL OResultSet::compareBookmarks( const Any& bookmark1, const Any& bookmark2 )
861 {
862 ::osl::MutexGuard aGuard( m_aMutex );
863 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
864
865 sal_Int32 nPos1 = 0;
866 bookmark1 >>= nPos1;
867 sal_Int32 nPos2 = 0;
868 bookmark2 >>= nPos2;
869 if(nPos1 == nPos2) // they should be equal
870 return css::sdbcx::CompareBookmark::EQUAL;
871
872 OSL_ENSURE((nPos1 >= 0 && nPos1 < static_cast<sal_Int32>(m_aBookmarks.size())) || (nPos1 >= 0 && nPos2 < static_cast<sal_Int32>(m_aBookmarks.size())),"Invalid Index for vector");
873
874 CompareEnum eNum;
875 m_pRecordSet->CompareBookmarks(m_aBookmarks[nPos1],m_aBookmarks[nPos2],&eNum);
876 return static_cast<sal_Int32>(eNum) - 1;
877 }
878
hasOrderedBookmarks()879 sal_Bool SAL_CALL OResultSet::hasOrderedBookmarks( )
880 {
881 ::osl::MutexGuard aGuard( m_aMutex );
882 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
883
884
885 ADOProperties* pProps = nullptr;
886 m_pRecordSet->get_Properties(&pProps);
887 WpADOProperties aProps;
888 aProps.setWithOutAddRef(pProps);
889 ADOS::ThrowException(*static_cast<OConnection*>(m_pStmt->getConnection().get())->getConnection(),*this);
890 OSL_ENSURE(aProps.IsValid(),"There are no properties at the connection");
891
892 WpADOProperty aProp(aProps.GetItem(OUString("Bookmarks Ordered")));
893 OLEVariant aVar;
894 if(aProp.IsValid())
895 aVar = aProp.GetValue();
896 else
897 ADOS::ThrowException(*static_cast<OConnection*>(m_pStmt->getConnection().get())->getConnection(),*this);
898
899 bool bValue(false);
900 if(!aVar.isNull() && !aVar.isEmpty())
901 bValue = aVar.getBool();
902 return bValue;
903 }
904
hashBookmark(const Any & bookmark)905 sal_Int32 SAL_CALL OResultSet::hashBookmark( const Any& bookmark )
906 {
907 ::osl::MutexGuard aGuard( m_aMutex );
908 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
909
910
911 sal_Int32 nPos = 0;
912 bookmark >>= nPos;
913 return nPos;
914 }
915
916 // XDeleteRows
deleteRows(const Sequence<Any> & rows)917 Sequence< sal_Int32 > SAL_CALL OResultSet::deleteRows( const Sequence< Any >& rows )
918 {
919 ::osl::MutexGuard aGuard( m_aMutex );
920 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
921
922
923 OLEVariant aVar;
924 sal_Int32 nPos = 0;
925
926 // Create SafeArray Bounds and initialize the array
927 SAFEARRAYBOUND rgsabound[1];
928 rgsabound[0].lLbound = 0;
929 rgsabound[0].cElements = rows.getLength();
930 SAFEARRAY *psa = SafeArrayCreate( VT_VARIANT, 1, rgsabound );
931
932 const Any* pBegin = rows.getConstArray();
933 const Any* pEnd = pBegin + rows.getLength();
934 for(sal_Int32 i=0;pBegin != pEnd ;++pBegin,++i)
935 {
936 *pBegin >>= nPos;
937 SafeArrayPutElement(psa,&i,&m_aBookmarks[nPos]);
938 }
939
940 // Initialize and fill the SafeArray
941 OLEVariant vsa;
942 vsa.setArray(psa,VT_VARIANT);
943
944 m_pRecordSet->put_Filter(vsa);
945 m_pRecordSet->Delete(adAffectGroup);
946 m_pRecordSet->UpdateBatch(adAffectGroup);
947
948 Sequence< sal_Int32 > aSeq(rows.getLength());
949 if(first())
950 {
951 sal_Int32* pSeq = aSeq.getArray();
952 sal_Int32 i=0;
953 do
954 {
955 OSL_ENSURE(i<aSeq.getLength(),"Index greater than length of sequence");
956 m_pRecordSet->get_Status(&pSeq[i]);
957 if(pSeq[i++] == adRecDeleted)
958 --m_nRowPos;
959 }
960 while(next());
961 }
962 return aSeq;
963 }
964
getResultSetConcurrency() const965 sal_Int32 OResultSet::getResultSetConcurrency() const
966 {
967 sal_Int32 nValue=ResultSetConcurrency::READ_ONLY;
968 LockTypeEnum eRet;
969 if(!SUCCEEDED(m_pRecordSet->get_LockType(&eRet)))
970 {
971 switch(eRet)
972 {
973 case adLockReadOnly:
974 nValue = ResultSetConcurrency::READ_ONLY;
975 break;
976 default:
977 nValue = ResultSetConcurrency::UPDATABLE;
978 break;
979 }
980 }
981 return nValue;
982 }
983
getResultSetType() const984 sal_Int32 OResultSet::getResultSetType() const
985 {
986 sal_Int32 nValue=0;
987 CursorTypeEnum eRet;
988 if(!SUCCEEDED(m_pRecordSet->get_CursorType(&eRet)))
989 {
990 switch(eRet)
991 {
992 case adOpenUnspecified:
993 case adOpenForwardOnly:
994 nValue = ResultSetType::FORWARD_ONLY;
995 break;
996 case adOpenStatic:
997 case adOpenKeyset:
998 nValue = ResultSetType::SCROLL_INSENSITIVE;
999 break;
1000 case adOpenDynamic:
1001 nValue = ResultSetType::SCROLL_SENSITIVE;
1002 break;
1003 }
1004 }
1005 return nValue;
1006 }
1007
getFetchDirection()1008 sal_Int32 OResultSet::getFetchDirection()
1009 {
1010 return FetchDirection::FORWARD;
1011 }
1012
getFetchSize() const1013 sal_Int32 OResultSet::getFetchSize() const
1014 {
1015 sal_Int32 nValue=-1;
1016 m_pRecordSet->get_CacheSize(&nValue);
1017 return nValue;
1018 }
1019
getCursorName()1020 OUString OResultSet::getCursorName()
1021 {
1022 return OUString();
1023 }
1024
1025
setFetchDirection(sal_Int32)1026 void OResultSet::setFetchDirection(sal_Int32 /*_par0*/)
1027 {
1028 ::dbtools::throwFeatureNotImplementedSQLException( "ResultSet::FetchDirection", *this );
1029 }
1030
setFetchSize(sal_Int32 _par0)1031 void OResultSet::setFetchSize(sal_Int32 _par0)
1032 {
1033 m_pRecordSet->put_CacheSize(_par0);
1034 }
1035
createArrayHelper() const1036 ::cppu::IPropertyArrayHelper* OResultSet::createArrayHelper( ) const
1037 {
1038 Sequence< css::beans::Property > aProps(5);
1039 css::beans::Property* pProperties = aProps.getArray();
1040 sal_Int32 nPos = 0;
1041
1042 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
1043 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
1044
1045 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
1046 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
1047
1048 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE),
1049 PROPERTY_ID_ISBOOKMARKABLE, cppu::UnoType<bool>::get(), PropertyAttribute::READONLY);
1050
1051 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
1052 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
1053
1054 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
1055 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY);
1056
1057 return new ::cppu::OPropertyArrayHelper(aProps);
1058 }
1059
getInfoHelper()1060 ::cppu::IPropertyArrayHelper & OResultSet::getInfoHelper()
1061 {
1062 return *getArrayHelper();
1063 }
1064
convertFastPropertyValue(Any & rConvertedValue,Any & rOldValue,sal_Int32 nHandle,const Any & rValue)1065 sal_Bool OResultSet::convertFastPropertyValue(
1066 Any & rConvertedValue,
1067 Any & rOldValue,
1068 sal_Int32 nHandle,
1069 const Any& rValue )
1070 {
1071 switch(nHandle)
1072 {
1073 case PROPERTY_ID_ISBOOKMARKABLE:
1074 case PROPERTY_ID_CURSORNAME:
1075 case PROPERTY_ID_RESULTSETCONCURRENCY:
1076 case PROPERTY_ID_RESULTSETTYPE:
1077 throw css::lang::IllegalArgumentException();
1078 break;
1079 case PROPERTY_ID_FETCHDIRECTION:
1080 return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
1081 case PROPERTY_ID_FETCHSIZE:
1082 return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
1083 default:
1084 ;
1085 }
1086 return false;
1087 }
1088
setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any & rValue)1089 void OResultSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
1090 {
1091 switch(nHandle)
1092 {
1093 case PROPERTY_ID_ISBOOKMARKABLE:
1094 case PROPERTY_ID_CURSORNAME:
1095 case PROPERTY_ID_RESULTSETCONCURRENCY:
1096 case PROPERTY_ID_RESULTSETTYPE:
1097 throw Exception("cannot set prop " + OUString::number(nHandle), nullptr);
1098 break;
1099 case PROPERTY_ID_FETCHDIRECTION:
1100 setFetchDirection(getINT32(rValue));
1101 break;
1102 case PROPERTY_ID_FETCHSIZE:
1103 setFetchSize(getINT32(rValue));
1104 break;
1105 default:
1106 ;
1107 }
1108 }
1109
getFastPropertyValue(Any & rValue,sal_Int32 nHandle) const1110 void OResultSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
1111 {
1112 switch(nHandle)
1113 {
1114 case PROPERTY_ID_ISBOOKMARKABLE:
1115 {
1116 VARIANT_BOOL bBool;
1117 m_pRecordSet->Supports(adBookmark,&bBool);
1118 rValue <<= (bBool == VARIANT_TRUE);
1119 }
1120 break;
1121 case PROPERTY_ID_CURSORNAME:
1122 rValue <<= getCursorName();
1123 break;
1124 case PROPERTY_ID_RESULTSETCONCURRENCY:
1125 rValue <<= getResultSetConcurrency();
1126 break;
1127 case PROPERTY_ID_RESULTSETTYPE:
1128 rValue <<= getResultSetType();
1129 break;
1130 case PROPERTY_ID_FETCHDIRECTION:
1131 rValue <<= getFetchDirection();
1132 break;
1133 case PROPERTY_ID_FETCHSIZE:
1134 rValue <<= getFetchSize();
1135 break;
1136 }
1137 }
1138
acquire()1139 void SAL_CALL OResultSet::acquire() throw()
1140 {
1141 OResultSet_BASE::acquire();
1142 }
1143
release()1144 void SAL_CALL OResultSet::release() throw()
1145 {
1146 OResultSet_BASE::release();
1147 }
1148
getPropertySetInfo()1149 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo( )
1150 {
1151 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1152 }
1153
1154
1155 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1156