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         sal_Int32 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() noexcept
1140 {
1141     OResultSet_BASE::acquire();
1142 }
1143 
release()1144 void SAL_CALL OResultSet::release() noexcept
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