1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "sortresult.hxx"
22 #include <com/sun/star/sdbc/DataType.hpp>
23 #include <com/sun/star/sdbc/SQLException.hpp>
24 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
25 #include <com/sun/star/ucb/ListActionType.hpp>
26 #include <com/sun/star/ucb/XAnyCompare.hpp>
27 #include <cppuhelper/implbase.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <comphelper/diagnose_ex.hxx>
32 using namespace com::sun::star::beans
;
33 using namespace com::sun::star::container
;
34 using namespace com::sun::star::io
;
35 using namespace com::sun::star::lang
;
36 using namespace com::sun::star::sdbc
;
37 using namespace com::sun::star::ucb
;
38 using namespace com::sun::star::uno
;
39 using namespace com::sun::star::util
;
40 using namespace comphelper
;
52 Reference
< XAnyCompare
> mxCompareFunction
;
62 explicit SortListData( sal_IntPtr nPos
);
68 class SRSPropertySetInfo
: public cppu::WeakImplHelper
<
79 virtual Sequence
< Property
> SAL_CALL
getProperties() override
;
80 virtual Property SAL_CALL
getPropertyByName( const OUString
& aName
) override
;
81 virtual sal_Bool SAL_CALL
hasPropertyByName( const OUString
& Name
) override
;
85 SortedResultSet::SortedResultSet( Reference
< XResultSet
> const & aResult
)
96 SortedResultSet::~SortedResultSet()
103 SortInfo
*pInfo
= mpSortInfo
;
106 mpSortInfo
= pInfo
->mpNext
;
112 mpSortInfo
= nullptr;
114 mpPropSetInfo
.clear();
118 // XServiceInfo methods.
120 OUString SAL_CALL
SortedResultSet::getImplementationName()
122 return "com.sun.star.comp.ucb.SortedResultSet";
125 sal_Bool SAL_CALL
SortedResultSet::supportsService( const OUString
& ServiceName
)
127 return cppu::supportsService( this, ServiceName
);
130 css::uno::Sequence
< OUString
> SAL_CALL
SortedResultSet::getSupportedServiceNames()
132 return { RESULTSET_SERVICE_NAME
};
136 // XComponent methods.
138 void SAL_CALL
SortedResultSet::dispose()
140 std::unique_lock
aGuard( maMutex
);
142 if ( maDisposeEventListeners
.getLength(aGuard
) )
145 aEvt
.Source
= static_cast< XComponent
* >( this );
146 maDisposeEventListeners
.disposeAndClear( aGuard
, aEvt
);
149 if ( maPropChangeListeners
.hasContainedTypes(aGuard
) )
152 aEvt
.Source
= static_cast< XPropertySet
* >( this );
153 maPropChangeListeners
.disposeAndClear( aGuard
, aEvt
);
156 if ( maVetoChangeListeners
.hasContainedTypes(aGuard
) )
159 aEvt
.Source
= static_cast< XPropertySet
* >( this );
160 maVetoChangeListeners
.disposeAndClear( aGuard
, aEvt
);
168 void SAL_CALL
SortedResultSet::addEventListener(
169 const Reference
< XEventListener
>& Listener
)
171 std::unique_lock
aGuard( maMutex
);
173 maDisposeEventListeners
.addInterface( aGuard
, Listener
);
177 void SAL_CALL
SortedResultSet::removeEventListener(
178 const Reference
< XEventListener
>& Listener
)
180 std::unique_lock
aGuard( maMutex
);
182 maDisposeEventListeners
.removeInterface( aGuard
, Listener
);
186 // XContentAccess methods.
190 SortedResultSet::queryContentIdentifierString()
192 std::unique_lock
aGuard( maMutex
);
193 return Reference
< XContentAccess
>::query(mxOriginal
)->queryContentIdentifierString();
197 Reference
< XContentIdentifier
> SAL_CALL
198 SortedResultSet::queryContentIdentifier()
200 std::unique_lock
aGuard( maMutex
);
201 return Reference
< XContentAccess
>::query(mxOriginal
)->queryContentIdentifier();
205 Reference
< XContent
> SAL_CALL
206 SortedResultSet::queryContent()
208 std::unique_lock
aGuard( maMutex
);
209 return Reference
< XContentAccess
>::query(mxOriginal
)->queryContent();
213 // XResultSet methods.
215 sal_Bool SAL_CALL
SortedResultSet::next()
217 std::unique_lock
aGuard( maMutex
);
221 if ( mnCurEntry
> 0 )
223 if ( mnCurEntry
<= mnCount
)
225 sal_Int32 nIndex
= maS2O
[ mnCurEntry
];
226 return mxOriginal
->absolute( nIndex
);
230 mnCurEntry
= mnCount
+ 1;
237 sal_Bool SAL_CALL
SortedResultSet::isBeforeFirst()
246 sal_Bool SAL_CALL
SortedResultSet::isAfterLast()
248 if ( mnCurEntry
> mnCount
)
255 sal_Bool SAL_CALL
SortedResultSet::isFirst()
257 if ( mnCurEntry
== 1 )
264 sal_Bool SAL_CALL
SortedResultSet::isLast()
266 if ( mnCurEntry
== mnCount
)
273 void SAL_CALL
SortedResultSet::beforeFirst()
275 std::unique_lock
aGuard( maMutex
);
277 mxOriginal
->beforeFirst();
281 void SAL_CALL
SortedResultSet::afterLast()
283 std::unique_lock
aGuard( maMutex
);
284 mnCurEntry
= mnCount
+1;
285 mxOriginal
->afterLast();
289 sal_Bool SAL_CALL
SortedResultSet::first()
291 std::unique_lock
aGuard( maMutex
);
296 sal_Int32 nIndex
= maS2O
[ mnCurEntry
];
297 return mxOriginal
->absolute( nIndex
);
307 sal_Bool SAL_CALL
SortedResultSet::last()
309 std::unique_lock
aGuard( maMutex
);
313 mnCurEntry
= mnCount
;
314 sal_Int32 nIndex
= maS2O
[ mnCurEntry
];
315 return mxOriginal
->absolute( nIndex
);
325 sal_Int32 SAL_CALL
SortedResultSet::getRow()
332 moves the cursor to the given row number in the result set.
333 <p>If the row number is positive, the cursor moves to the given row
334 number with respect to the beginning of the result set. The first
335 row is row 1, the second is row 2, and so on.
336 <p>If the given row number is negative, the cursor moves to an
337 absolute row position with respect to the end of the result set.
338 For example, calling <code>moveToPosition(-1)</code> positions the
339 cursor on the last row, <code>moveToPosition(-2)</code> indicates the
340 next-to-last row, and so on.
341 <p>An attempt to position the cursor beyond the first/last row in the
342 result set leaves the cursor before/after the first/last row,
344 <p>Note: Calling <code>moveToPosition(1)</code> is the same
345 as calling <code>moveToFirst()</code>. Calling
346 <code>moveToPosition(-1)</code> is the same as calling
347 <code>moveToLast()</code>.
349 is the number of rows to move. Could be negative.
351 <TRUE/> if the cursor is on a row; <FALSE/> otherwise
353 if a database access error occurs or if row is 0, or the result set
354 type is FORWARD_ONLY.
356 sal_Bool SAL_CALL
SortedResultSet::absolute( sal_Int32 row
)
358 std::unique_lock
aGuard( maMutex
);
364 if ( row
<= mnCount
)
367 nIndex
= maS2O
[ mnCurEntry
];
368 return mxOriginal
->absolute( nIndex
);
372 mnCurEntry
= mnCount
+ 1;
378 throw SQLException();
382 if ( mnCount
+ row
+ 1 > 0 )
384 mnCurEntry
= mnCount
+ row
+ 1;
385 nIndex
= maS2O
[ mnCurEntry
];
386 return mxOriginal
->absolute( nIndex
);
398 moves the cursor a relative number of rows, either positive or negative.
400 Attempting to move beyond the first/last row in the result set positions
401 the cursor before/after the first/last row. Calling
402 <code>moveRelative(0)</code> is valid, but does not change the cursor
404 <p>Note: Calling <code>moveRelative(1)</code> is different from calling
405 <code>moveNext()</code> because is makes sense to call
406 <code>moveNext()</code> when there is no current row, for example,
407 when the cursor is positioned before the first row or after the last
408 row of the result set.
410 is the number of rows to move. Could be negative.
412 <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
415 if a database access error occurs or if there is no
416 current row, or the result set type is FORWARD_ONLY.
418 sal_Bool SAL_CALL
SortedResultSet::relative( sal_Int32 rows
)
420 std::unique_lock
aGuard( maMutex
);
422 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
424 throw SQLException();
430 sal_Int32 nTmp
= mnCurEntry
+ rows
;
437 else if ( nTmp
> mnCount
)
439 mnCurEntry
= mnCount
+ 1;
445 nTmp
= maS2O
[ mnCurEntry
];
446 return mxOriginal
->absolute( nTmp
);
452 moves the cursor to the previous row in the result set.
453 <p>Note: <code>previous()</code> is not the same as
454 <code>relative(-1)</code> because it makes sense to call
455 <code>previous()</code> when there is no current row.
456 @returns <TRUE/> if the cursor is on a valid row; <FALSE/> if it is off
459 if a database access error occurs or the result set type
462 sal_Bool SAL_CALL
SortedResultSet::previous()
464 std::unique_lock
aGuard( maMutex
);
468 if ( mnCurEntry
> 0 )
470 if ( mnCurEntry
<= mnCount
)
472 sal_Int32 nIndex
= maS2O
[ mnCurEntry
];
473 return mxOriginal
->absolute( nIndex
);
483 void SAL_CALL
SortedResultSet::refreshRow()
485 std::unique_lock
aGuard( maMutex
);
487 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
489 throw SQLException();
492 mxOriginal
->refreshRow();
496 sal_Bool SAL_CALL
SortedResultSet::rowUpdated()
498 std::unique_lock
aGuard( maMutex
);
500 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
502 throw SQLException();
505 return mxOriginal
->rowUpdated();
509 sal_Bool SAL_CALL
SortedResultSet::rowInserted()
511 std::unique_lock
aGuard( maMutex
);
513 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
515 throw SQLException();
518 return mxOriginal
->rowInserted();
522 sal_Bool SAL_CALL
SortedResultSet::rowDeleted()
524 std::unique_lock
aGuard( maMutex
);
526 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
528 throw SQLException();
531 return mxOriginal
->rowDeleted();
535 Reference
< XInterface
> SAL_CALL
SortedResultSet::getStatement()
537 std::unique_lock
aGuard( maMutex
);
539 if ( ( mnCurEntry
<= 0 ) || ( mnCurEntry
> mnCount
) )
541 throw SQLException();
544 return mxOriginal
->getStatement();
551 sal_Bool SAL_CALL
SortedResultSet::wasNull()
553 std::unique_lock
aGuard( maMutex
);
554 return Reference
< XRow
>::query(mxOriginal
)->wasNull();
558 OUString SAL_CALL
SortedResultSet::getString( sal_Int32 columnIndex
)
560 std::unique_lock
aGuard( maMutex
);
561 return Reference
< XRow
>::query(mxOriginal
)->getString( columnIndex
);
565 sal_Bool SAL_CALL
SortedResultSet::getBoolean( sal_Int32 columnIndex
)
567 std::unique_lock
aGuard( maMutex
);
568 return Reference
< XRow
>::query(mxOriginal
)->getBoolean( columnIndex
);
572 sal_Int8 SAL_CALL
SortedResultSet::getByte( sal_Int32 columnIndex
)
574 std::unique_lock
aGuard( maMutex
);
575 return Reference
< XRow
>::query(mxOriginal
)->getByte( columnIndex
);
579 sal_Int16 SAL_CALL
SortedResultSet::getShort( sal_Int32 columnIndex
)
581 std::unique_lock
aGuard( maMutex
);
582 return Reference
< XRow
>::query(mxOriginal
)->getShort( columnIndex
);
586 sal_Int32 SAL_CALL
SortedResultSet::getInt( sal_Int32 columnIndex
)
588 std::unique_lock
aGuard( maMutex
);
589 return Reference
< XRow
>::query(mxOriginal
)->getInt( columnIndex
);
592 sal_Int64 SAL_CALL
SortedResultSet::getLong( sal_Int32 columnIndex
)
594 std::unique_lock
aGuard( maMutex
);
595 return Reference
< XRow
>::query(mxOriginal
)->getLong( columnIndex
);
599 float SAL_CALL
SortedResultSet::getFloat( sal_Int32 columnIndex
)
601 std::unique_lock
aGuard( maMutex
);
602 return Reference
< XRow
>::query(mxOriginal
)->getFloat( columnIndex
);
606 double SAL_CALL
SortedResultSet::getDouble( sal_Int32 columnIndex
)
608 std::unique_lock
aGuard( maMutex
);
609 return Reference
< XRow
>::query(mxOriginal
)->getDouble( columnIndex
);
613 Sequence
< sal_Int8
> SAL_CALL
SortedResultSet::getBytes( sal_Int32 columnIndex
)
615 std::unique_lock
aGuard( maMutex
);
616 return Reference
< XRow
>::query(mxOriginal
)->getBytes( columnIndex
);
620 Date SAL_CALL
SortedResultSet::getDate( sal_Int32 columnIndex
)
622 std::unique_lock
aGuard( maMutex
);
623 return Reference
< XRow
>::query(mxOriginal
)->getDate( columnIndex
);
627 Time SAL_CALL
SortedResultSet::getTime( sal_Int32 columnIndex
)
629 std::unique_lock
aGuard( maMutex
);
630 return Reference
< XRow
>::query(mxOriginal
)->getTime( columnIndex
);
634 DateTime SAL_CALL
SortedResultSet::getTimestamp( sal_Int32 columnIndex
)
636 std::unique_lock
aGuard( maMutex
);
637 return Reference
< XRow
>::query(mxOriginal
)->getTimestamp( columnIndex
);
641 Reference
< XInputStream
> SAL_CALL
642 SortedResultSet::getBinaryStream( sal_Int32 columnIndex
)
644 std::unique_lock
aGuard( maMutex
);
645 return Reference
< XRow
>::query(mxOriginal
)->getBinaryStream( columnIndex
);
649 Reference
< XInputStream
> SAL_CALL
650 SortedResultSet::getCharacterStream( sal_Int32 columnIndex
)
652 std::unique_lock
aGuard( maMutex
);
653 return Reference
< XRow
>::query(mxOriginal
)->getCharacterStream( columnIndex
);
657 Any SAL_CALL
SortedResultSet::getObject( sal_Int32 columnIndex
,
658 const Reference
< XNameAccess
>& typeMap
)
660 std::unique_lock
aGuard( maMutex
);
661 return Reference
< XRow
>::query(mxOriginal
)->getObject( columnIndex
,
666 Reference
< XRef
> SAL_CALL
SortedResultSet::getRef( sal_Int32 columnIndex
)
668 std::unique_lock
aGuard( maMutex
);
669 return Reference
< XRow
>::query(mxOriginal
)->getRef( columnIndex
);
673 Reference
< XBlob
> SAL_CALL
SortedResultSet::getBlob( sal_Int32 columnIndex
)
675 std::unique_lock
aGuard( maMutex
);
676 return Reference
< XRow
>::query(mxOriginal
)->getBlob( columnIndex
);
680 Reference
< XClob
> SAL_CALL
SortedResultSet::getClob( sal_Int32 columnIndex
)
682 std::unique_lock
aGuard( maMutex
);
683 return Reference
< XRow
>::query(mxOriginal
)->getClob( columnIndex
);
687 Reference
< XArray
> SAL_CALL
SortedResultSet::getArray( sal_Int32 columnIndex
)
689 std::unique_lock
aGuard( maMutex
);
690 return Reference
< XRow
>::query(mxOriginal
)->getArray( columnIndex
);
694 // XCloseable methods.
697 void SAL_CALL
SortedResultSet::close()
699 std::unique_lock
aGuard( maMutex
);
700 Reference
< XCloseable
>::query(mxOriginal
)->close();
704 // XResultSetMetaDataSupplier methods.
707 Reference
< XResultSetMetaData
> SAL_CALL
SortedResultSet::getMetaData()
709 std::unique_lock
aGuard( maMutex
);
710 return Reference
< XResultSetMetaDataSupplier
>::query(mxOriginal
)->getMetaData();
714 // XPropertySet methods.
717 Reference
< XPropertySetInfo
> SAL_CALL
718 SortedResultSet::getPropertySetInfo()
720 std::unique_lock
aGuard( maMutex
);
722 if ( !mpPropSetInfo
.is() )
724 mpPropSetInfo
= new SRSPropertySetInfo();
727 return mpPropSetInfo
;
731 void SAL_CALL
SortedResultSet::setPropertyValue(
732 const OUString
& PropertyName
,
735 if ( PropertyName
== "RowCount" || PropertyName
== "IsRowCountFinal" )
736 throw IllegalArgumentException();
738 throw UnknownPropertyException(PropertyName
);
742 Any SAL_CALL
SortedResultSet::getPropertyValue( const OUString
& PropertyName
)
744 std::unique_lock
aGuard( maMutex
);
748 if ( PropertyName
== "RowCount" )
750 aRet
<<= maS2O
.Count();
752 else if ( PropertyName
== "IsRowCountFinal" )
754 bool bOrgFinal
= false;
759 aOrgRet
= Reference
< XPropertySet
>::query(mxOriginal
)->
760 getPropertyValue( PropertyName
);
761 aOrgRet
>>= bOrgFinal
;
765 aOrgRet
= Reference
< XPropertySet
>::query(mxOriginal
)->
766 getPropertyValue("RowCount");
767 sal_uInt32 nOrgCount
= 0;
768 aOrgRet
>>= nOrgCount
;
769 if ( nOrgCount
== maS2O
.Count() )
774 throw UnknownPropertyException(PropertyName
);
780 void SAL_CALL
SortedResultSet::addPropertyChangeListener(
781 const OUString
& PropertyName
,
782 const Reference
< XPropertyChangeListener
>& Listener
)
784 std::unique_lock
aGuard( maMutex
);
786 maPropChangeListeners
.addInterface( aGuard
, PropertyName
, Listener
);
790 void SAL_CALL
SortedResultSet::removePropertyChangeListener(
791 const OUString
& PropertyName
,
792 const Reference
< XPropertyChangeListener
>& Listener
)
794 std::unique_lock
aGuard( maMutex
);
796 maPropChangeListeners
.removeInterface( aGuard
, PropertyName
, Listener
);
800 void SAL_CALL
SortedResultSet::addVetoableChangeListener(
801 const OUString
& PropertyName
,
802 const Reference
< XVetoableChangeListener
>& Listener
)
804 std::unique_lock
aGuard( maMutex
);
806 maVetoChangeListeners
.addInterface( aGuard
, PropertyName
, Listener
);
810 void SAL_CALL
SortedResultSet::removeVetoableChangeListener(
811 const OUString
& PropertyName
,
812 const Reference
< XVetoableChangeListener
>& Listener
)
814 std::unique_lock
aGuard( maMutex
);
816 maVetoChangeListeners
.removeInterface( aGuard
, PropertyName
, Listener
);
822 sal_Int32
SortedResultSet::CompareImpl( const Reference
< XResultSet
>& xResultOne
,
823 const Reference
< XResultSet
>& xResultTwo
,
824 sal_Int32 nIndexOne
, sal_Int32 nIndexTwo
,
825 SortInfo
const * pSortInfo
)
827 Reference
< XRow
> xRowOne( xResultOne
, UNO_QUERY
);
828 Reference
< XRow
> xRowTwo( xResultTwo
, UNO_QUERY
);
830 sal_IntPtr nCompare
= 0;
831 sal_Int32 nColumn
= pSortInfo
->mnColumn
;
833 switch ( pSortInfo
->mnType
)
836 case DataType::TINYINT
:
837 case DataType::SMALLINT
:
838 case DataType::INTEGER
:
843 if ( xResultOne
->absolute( nIndexOne
) )
844 aOne
= xRowOne
->getInt( nColumn
);
845 if ( xResultTwo
->absolute( nIndexTwo
) )
846 aTwo
= xRowTwo
->getInt( nColumn
);
850 else if ( aOne
== aTwo
)
857 case DataType::BIGINT
:
862 if ( xResultOne
->absolute( nIndexOne
) )
863 aOne
= xRowOne
->getLong( nColumn
);
864 if ( xResultTwo
->absolute( nIndexTwo
) )
865 aTwo
= xRowTwo
->getLong( nColumn
);
869 else if ( aOne
== aTwo
)
876 case DataType::CHAR
:
877 case DataType::VARCHAR
:
878 case DataType::LONGVARCHAR
:
882 if ( xResultOne
->absolute( nIndexOne
) )
883 aOne
= xRowOne
->getString( nColumn
);
884 if ( xResultTwo
->absolute( nIndexTwo
) )
885 aTwo
= xRowTwo
->getString( nColumn
);
887 if ( ! pSortInfo
->mbCaseSensitive
)
889 aOne
= aOne
.toAsciiLowerCase();
890 aTwo
= aTwo
.toAsciiLowerCase();
893 nCompare
= aOne
.compareTo( aTwo
);
896 case DataType::DATE
:
901 if ( xResultOne
->absolute( nIndexOne
) )
902 aOne
= xRowOne
->getDate( nColumn
);
903 if ( xResultTwo
->absolute( nIndexTwo
) )
904 aTwo
= xRowTwo
->getDate( nColumn
);
906 nTmp
= static_cast<sal_Int32
>(aTwo
.Year
) - static_cast<sal_Int32
>(aOne
.Year
);
908 nTmp
= static_cast<sal_Int32
>(aTwo
.Month
) - static_cast<sal_Int32
>(aOne
.Month
);
910 nTmp
= static_cast<sal_Int32
>(aTwo
.Day
) - static_cast<sal_Int32
>(aOne
.Day
);
915 else if ( nTmp
== 0 )
922 case DataType::TIME
:
927 if ( xResultOne
->absolute( nIndexOne
) )
928 aOne
= xRowOne
->getTime( nColumn
);
929 if ( xResultTwo
->absolute( nIndexTwo
) )
930 aTwo
= xRowTwo
->getTime( nColumn
);
932 nTmp
= static_cast<sal_Int32
>(aTwo
.Hours
) - static_cast<sal_Int32
>(aOne
.Hours
);
934 nTmp
= static_cast<sal_Int32
>(aTwo
.Minutes
) - static_cast<sal_Int32
>(aOne
.Minutes
);
936 nTmp
= static_cast<sal_Int32
>(aTwo
.Seconds
) - static_cast<sal_Int32
>(aOne
.Seconds
);
938 nTmp
= static_cast<sal_Int32
>(aTwo
.NanoSeconds
)
939 - static_cast<sal_Int32
>(aOne
.NanoSeconds
);
943 else if ( nTmp
== 0 )
950 case DataType::TIMESTAMP
:
955 if ( xResultOne
->absolute( nIndexOne
) )
956 aOne
= xRowOne
->getTimestamp( nColumn
);
957 if ( xResultTwo
->absolute( nIndexTwo
) )
958 aTwo
= xRowTwo
->getTimestamp( nColumn
);
960 nTmp
= static_cast<sal_Int32
>(aTwo
.Year
) - static_cast<sal_Int32
>(aOne
.Year
);
962 nTmp
= static_cast<sal_Int32
>(aTwo
.Month
) - static_cast<sal_Int32
>(aOne
.Month
);
964 nTmp
= static_cast<sal_Int32
>(aTwo
.Day
) - static_cast<sal_Int32
>(aOne
.Day
);
966 nTmp
= static_cast<sal_Int32
>(aTwo
.Hours
) - static_cast<sal_Int32
>(aOne
.Hours
);
968 nTmp
= static_cast<sal_Int32
>(aTwo
.Minutes
) - static_cast<sal_Int32
>(aOne
.Minutes
);
970 nTmp
= static_cast<sal_Int32
>(aTwo
.Seconds
) - static_cast<sal_Int32
>(aOne
.Seconds
);
972 nTmp
= static_cast<sal_Int32
>(aTwo
.NanoSeconds
)
973 - static_cast<sal_Int32
>(aOne
.NanoSeconds
);
977 else if ( nTmp
== 0 )
984 case DataType::REAL
:
989 if ( xResultOne
->absolute( nIndexOne
) )
990 aOne
= xRowOne
->getFloat( nColumn
);
991 if ( xResultTwo
->absolute( nIndexTwo
) )
992 aTwo
= xRowTwo
->getFloat( nColumn
);
996 else if ( aOne
== aTwo
)
1003 case DataType::FLOAT
:
1004 case DataType::DOUBLE
:
1009 if ( xResultOne
->absolute( nIndexOne
) )
1010 aOne
= xRowOne
->getDouble( nColumn
);
1011 if ( xResultTwo
->absolute( nIndexTwo
) )
1012 aTwo
= xRowTwo
->getDouble( nColumn
);
1016 else if ( aOne
== aTwo
)
1025 OSL_FAIL( "DataType not supported for compare!" );
1033 sal_Int32
SortedResultSet::CompareImpl( const Reference
< XResultSet
>& xResultOne
,
1034 const Reference
< XResultSet
>& xResultTwo
,
1035 sal_Int32 nIndexOne
, sal_Int32 nIndexTwo
)
1037 sal_IntPtr nCompare
= 0;
1038 SortInfo
* pInfo
= mpSortInfo
;
1040 while ( !nCompare
&& pInfo
)
1042 if ( pInfo
->mbUseOwnCompare
)
1044 nCompare
= CompareImpl( xResultOne
, xResultTwo
,
1045 nIndexOne
, nIndexTwo
, pInfo
);
1051 Reference
< XRow
> xRowOne
=
1052 Reference
< XRow
>::query( xResultOne
);
1053 Reference
< XRow
> xRowTwo
=
1054 Reference
< XRow
>::query( xResultTwo
);
1056 if ( xResultOne
->absolute( nIndexOne
) )
1057 aOne
= xRowOne
->getObject( pInfo
->mnColumn
, nullptr );
1058 if ( xResultTwo
->absolute( nIndexTwo
) )
1059 aTwo
= xRowTwo
->getObject( pInfo
->mnColumn
, nullptr );
1061 nCompare
= pInfo
->mxCompareFunction
->compare( aOne
, aTwo
);
1064 if ( ! pInfo
->mbAscending
)
1065 nCompare
= - nCompare
;
1067 pInfo
= pInfo
->mpNext
;
1074 sal_Int32
SortedResultSet::Compare( SortListData
const *pOne
,
1075 SortListData
const *pTwo
)
1077 sal_IntPtr nIndexOne
;
1078 sal_IntPtr nIndexTwo
;
1080 Reference
< XResultSet
> xResultOne
;
1081 Reference
< XResultSet
> xResultTwo
;
1083 if ( pOne
->mbModified
)
1085 xResultOne
= mxOther
;
1086 nIndexOne
= pOne
->mnOldPos
;
1090 xResultOne
= mxOriginal
;
1091 nIndexOne
= pOne
->mnCurPos
;
1094 if ( pTwo
->mbModified
)
1096 xResultTwo
= mxOther
;
1097 nIndexTwo
= pTwo
->mnOldPos
;
1101 xResultTwo
= mxOriginal
;
1102 nIndexTwo
= pTwo
->mnCurPos
;
1105 sal_IntPtr nCompare
;
1106 nCompare
= CompareImpl( xResultOne
, xResultTwo
,
1107 nIndexOne
, nIndexTwo
);
1112 sal_Int32
SortedResultSet::FindPos( SortListData
const *pEntry
,
1113 sal_IntPtr _nStart
, sal_IntPtr _nEnd
)
1115 if ( _nStart
> _nEnd
)
1118 sal_IntPtr nStart
= _nStart
;
1119 sal_IntPtr nEnd
= _nEnd
;
1120 sal_IntPtr nMid
= 0, nCompare
= 0;
1123 while ( nStart
<= nEnd
)
1125 nMid
= ( nEnd
- nStart
) / 2 + nStart
;
1126 SortListData
*pMid
= maS2O
.GetData( nMid
);
1127 nCompare
= Compare( pEntry
, pMid
);
1130 nCompare
= (pEntry
!= pMid
) ? ((pEntry
< pMid
) ? -1 : 1) : 0;
1132 if ( nCompare
< 0 ) // pEntry < pMid
1138 if ( nCompare
< 0 ) // pEntry < pMid
1145 void SortedResultSet::PropertyChanged( const PropertyChangeEvent
& rEvt
)
1147 std::unique_lock
aGuard( maMutex
);
1149 if ( !maPropChangeListeners
.hasContainedTypes(aGuard
) )
1152 // Notify listeners interested especially in the changed property.
1153 OInterfaceContainerHelper4
<XPropertyChangeListener
>* pPropsContainer
=
1154 maPropChangeListeners
.getContainer( aGuard
, rEvt
.PropertyName
);
1155 if ( pPropsContainer
)
1156 pPropsContainer
->notifyEach( aGuard
, &XPropertyChangeListener::propertyChange
, rEvt
);
1158 // Notify listeners interested in all properties.
1159 pPropsContainer
= maPropChangeListeners
.getContainer( aGuard
, OUString() );
1160 if ( pPropsContainer
)
1161 pPropsContainer
->notifyEach( aGuard
, &XPropertyChangeListener::propertyChange
, rEvt
);
1168 void SortedResultSet::CopyData( SortedResultSet
*pSource
)
1170 const SortedEntryList
& rSrcS2O
= pSource
->maS2O
;
1172 sal_IntPtr i
, nCount
;
1178 maS2O
.Insert( nullptr, 0 );
1181 nCount
= rSrcS2O
.Count();
1183 for ( i
=1; i
<nCount
; i
++ )
1185 maS2O
.Insert( std::unique_ptr
<SortListData
>(new SortListData( rSrcS2O
[ i
] )), i
);
1186 m_O2S
.push_back(pSource
->m_O2S
[i
]);
1189 mnLastSort
= maS2O
.Count();
1190 mxOther
= pSource
->mxOriginal
;
1194 mpSortInfo
= pSource
->mpSortInfo
;
1200 void SortedResultSet::Initialize(
1201 const Sequence
< NumberedSortingInfo
> &xSortInfo
,
1202 const Reference
< XAnyCompareFactory
> &xCompFactory
)
1204 BuildSortInfo( mxOriginal
, xSortInfo
, xCompFactory
);
1205 // Insert dummy at pos 0
1206 maS2O
.Insert( std::unique_ptr
<SortListData
>(new SortListData( 0 )), 0 );
1208 sal_IntPtr nIndex
= 1;
1210 // now fetch all the elements from the original result set,
1211 // get there new position in the sorted result set and insert
1212 // an entry in the sorted to original mapping list
1214 while ( mxOriginal
->absolute( nIndex
) )
1216 std::unique_ptr
<SortListData
> pData(new SortListData( nIndex
));
1217 sal_IntPtr nPos
= FindPos( pData
.get(), 1, nIndex
-1 );
1219 maS2O
.Insert( std::move(pData
), nPos
);
1224 catch (const SQLException
&)
1226 TOOLS_WARN_EXCEPTION("ucb", "");
1229 // when we have fetched all the elements, we can create the
1230 // original to sorted mapping list from the s2o list
1234 // insert some dummy entries first and replace then
1235 // the entries with the right ones
1238 for ( i
=1; i
<maS2O
.Count(); i
++ )
1240 for ( i
=1; i
<maS2O
.Count(); i
++ )
1241 m_O2S
[maS2O
[i
]] = i
;
1243 mnCount
= maS2O
.Count() - 1;
1247 void SortedResultSet::CheckProperties( sal_Int32 nOldCount
, bool bWasFinal
)
1249 std::unique_lock
aGuard( maMutex
);
1251 if ( !maPropChangeListeners
.hasContainedTypes(aGuard
) )
1255 // check for propertyChangeEvents
1256 if ( nOldCount
!= GetCount() )
1258 bool bIsFinal
= false;
1259 PropertyChangeEvent aEvt
;
1261 aEvt
.PropertyName
= "RowCount";
1262 aEvt
.Further
= false;
1263 aEvt
.PropertyHandle
= -1;
1264 aEvt
.OldValue
<<= nOldCount
;
1265 aEvt
.NewValue
<<= GetCount();
1267 PropertyChanged( aEvt
);
1269 OUString aName
= "IsRowCountFinal";
1270 Any aRet
= getPropertyValue( aName
);
1271 if ( (aRet
>>= bIsFinal
) && bIsFinal
!= bWasFinal
)
1273 aEvt
.PropertyName
= aName
;
1274 aEvt
.Further
= false;
1275 aEvt
.PropertyHandle
= -1;
1276 aEvt
.OldValue
<<= bWasFinal
;
1277 aEvt
.NewValue
<<= bIsFinal
;
1278 PropertyChanged( aEvt
);
1282 catch (const UnknownPropertyException
&) {}
1283 catch (const WrappedTargetException
&) {}
1287 void SortedResultSet::InsertNew( sal_Int32 nPos
, sal_Int32 nCount
)
1289 // for all entries in the msS20-list, which are >= nPos, increase by nCount
1292 nEnd
= maS2O
.Count();
1293 for ( i
=1; i
<=nEnd
; i
++ )
1295 SortListData
*pData
= maS2O
.GetData( i
);
1296 if ( pData
->mnCurPos
>= nPos
)
1298 pData
->mnCurPos
+= nCount
;
1302 // and append the new entries at the end of the maS2O-list or insert at the
1303 // position nPos in the maS2O-list
1304 for ( i
=0; i
<nCount
; i
++ )
1307 std::unique_ptr
<SortListData
> pData(new SortListData( nEnd
));
1309 maS2O
.Insert( std::move(pData
), nEnd
); // Insert( Value, Position )
1310 m_O2S
.insert(m_O2S
.begin() + nPos
+ i
, nEnd
);
1317 void SortedResultSet::Remove( sal_Int32 nPos
, sal_Int32 nCount
, EventList
*pEvents
)
1319 sal_IntPtr nOldLastSort
;
1321 // correct mnLastSort first
1322 nOldLastSort
= mnLastSort
;
1323 if ( nPos
<= mnLastSort
)
1325 if ( nPos
+ nCount
- 1 <= mnLastSort
)
1326 mnLastSort
-= nCount
;
1328 mnLastSort
= nPos
- 1;
1331 // remove the entries from the lists and correct the positions
1332 // in the original2sorted list
1333 for ( sal_IntPtr i
=0; i
< nCount
; i
++ )
1335 sal_IntPtr nSortPos
= m_O2S
[nPos
];
1336 m_O2S
.erase(m_O2S
.begin() + nPos
);
1338 for (size_t j
=1; j
< m_O2S
.size(); ++j
)
1340 sal_IntPtr nVal
= m_O2S
[j
];
1341 if ( nVal
> nSortPos
)
1348 std::unique_ptr
<SortListData
> pData
= maS2O
.Remove( nSortPos
);
1349 if ( pData
->mbModified
)
1350 m_ModList
.erase(std::find(m_ModList
.begin(), m_ModList
.end(), pData
.get()));
1352 // generate remove Event, but not for new entries
1353 if ( nSortPos
<= nOldLastSort
)
1354 pEvents
->AddEvent( ListActionType::REMOVED
, nSortPos
);
1357 // correct the positions in the sorted list
1358 for ( sal_uInt32 i
=1; i
<= maS2O
.Count(); i
++ )
1360 SortListData
*pData
= maS2O
.GetData( i
);
1361 if ( pData
->mnCurPos
> nPos
)
1362 pData
->mnCurPos
-= nCount
;
1369 void SortedResultSet::Move( sal_Int32 nPos
, sal_Int32 nCount
, sal_Int32 nOffset
)
1374 sal_IntPtr i
, nSortPos
, nTo
;
1375 SortListData
*pData
;
1377 for ( i
=0; i
<nCount
; i
++ )
1379 nSortPos
= m_O2S
[nPos
+ i
];
1380 pData
= maS2O
.GetData( nSortPos
);
1381 pData
->mnCurPos
+= nOffset
;
1386 for ( i
=nPos
+nOffset
; i
<nPos
; i
++ )
1388 nSortPos
= m_O2S
[i
];
1389 pData
= maS2O
.GetData( nSortPos
);
1390 pData
->mnCurPos
+= nCount
;
1395 sal_IntPtr nStart
= nPos
+ nCount
;
1396 sal_IntPtr nEnd
= nStart
+ nOffset
;
1397 for ( i
=nStart
; i
<nEnd
; i
++ )
1399 nSortPos
= m_O2S
[i
];
1400 pData
= maS2O
.GetData( nSortPos
);
1401 pData
->mnCurPos
-= nCount
;
1405 // remember the to be moved entries
1406 std::unique_ptr
<sal_IntPtr
[]> pTmpArr(new sal_IntPtr
[ nCount
]);
1407 for ( i
=0; i
<nCount
; i
++ )
1408 pTmpArr
[i
] = m_O2S
[nPos
+ i
];
1410 // now move the entries, which are in the way
1413 // be carefully here, because nOffset is negative here, so an
1414 // addition is a subtraction
1415 sal_IntPtr nFrom
= nPos
- 1;
1416 nTo
= nPos
+ nCount
- 1;
1419 for ( i
=0; i
>nOffset
; i
-- )
1421 sal_IntPtr
const nVal
= m_O2S
[nFrom
+ i
];
1422 m_O2S
[nTo
+ i
] = nVal
;
1428 sal_IntPtr nStart
= nPos
+ nCount
;
1429 for ( i
=0; i
<nOffset
; i
++ )
1431 sal_IntPtr
const nVal
= m_O2S
[nStart
+ i
];
1432 m_O2S
[nPos
+ i
] = nVal
;
1436 // finally put the remembered entries at their new location
1437 nTo
= nPos
+ nOffset
;
1438 for ( i
=0; i
<nCount
; i
++ )
1440 m_O2S
[nTo
+ i
] = pTmpArr
[i
];
1445 void SortedResultSet::BuildSortInfo(
1446 const Reference
< XResultSet
>& aResult
,
1447 const Sequence
< NumberedSortingInfo
> &xSortInfo
,
1448 const Reference
< XAnyCompareFactory
> &xCompFactory
)
1450 Reference
< XResultSetMetaDataSupplier
> xMeta ( aResult
, UNO_QUERY
);
1454 OSL_FAIL( "No MetaData, No Sorting!" );
1458 Reference
< XResultSetMetaData
> xData
= xMeta
->getMetaData();
1459 const NumberedSortingInfo
*pSortInfo
= xSortInfo
.getConstArray();
1465 for ( sal_Int32 i
=xSortInfo
.getLength(); i
> 0; )
1468 nColumn
= pSortInfo
[ i
].ColumnIndex
;
1469 aPropName
= xData
->getColumnName( nColumn
);
1470 pInfo
= new SortInfo
;
1472 if ( xCompFactory
.is() )
1473 pInfo
->mxCompareFunction
= xCompFactory
->createAnyCompareByName(
1476 if ( pInfo
->mxCompareFunction
.is() )
1478 pInfo
->mbUseOwnCompare
= false;
1483 pInfo
->mbUseOwnCompare
= true;
1484 pInfo
->mnType
= xData
->getColumnType( nColumn
);
1487 pInfo
->mnColumn
= nColumn
;
1488 pInfo
->mbAscending
= pSortInfo
[ i
].Ascending
;
1489 pInfo
->mbCaseSensitive
= xData
->isCaseSensitive( nColumn
);
1490 pInfo
->mpNext
= mpSortInfo
;
1496 void SortedResultSet::SetChanged( sal_Int32 nPos
, sal_Int32 nCount
)
1498 for ( sal_IntPtr i
=0; i
<nCount
; i
++ )
1500 sal_IntPtr
const nSortPos
= m_O2S
[nPos
];
1501 if ( nSortPos
< mnLastSort
)
1503 SortListData
*pData
= maS2O
.GetData( nSortPos
);
1504 if ( ! pData
->mbModified
)
1506 pData
->mbModified
= true;
1507 m_ModList
.push_back(pData
);
1515 void SortedResultSet::ResortModified( EventList
* pList
)
1517 sal_IntPtr nCompare
, nCurPos
, nNewPos
;
1518 sal_IntPtr nStart
, nEnd
, nOffset
, nVal
;
1521 for (size_t i
= 0; i
< m_ModList
.size(); ++i
)
1523 SortListData
*const pData
= m_ModList
[i
];
1524 nCompare
= CompareImpl( mxOther
, mxOriginal
,
1525 pData
->mnOldPos
, pData
->mnCurPos
);
1526 pData
->mbModified
= false;
1527 if ( nCompare
!= 0 )
1529 nCurPos
= m_O2S
[pData
->mnCurPos
];
1532 nNewPos
= FindPos( pData
, 1, nCurPos
-1 );
1539 nNewPos
= FindPos( pData
, nCurPos
+1, mnLastSort
);
1545 if ( nNewPos
!= nCurPos
)
1547 // correct the lists!
1548 maS2O
.Move( static_cast<sal_uInt32
>(nCurPos
), nNewPos
);
1549 for (size_t j
= 1; j
< m_O2S
.size(); ++j
)
1552 if ( ( nStart
<= nVal
) && ( nVal
<= nEnd
) )
1559 m_O2S
[pData
->mnCurPos
] = nNewPos
;
1562 aAction
.Position
= nCurPos
;
1564 aAction
.ListActionType
= ListActionType::MOVED
;
1565 aAction
.ActionInfo
<<= nNewPos
-nCurPos
;
1566 pList
->Insert( aAction
);
1568 pList
->AddEvent( ListActionType::PROPERTIES_CHANGED
, nNewPos
);
1572 catch (const SQLException
&)
1574 TOOLS_WARN_EXCEPTION("ucb", "");
1581 void SortedResultSet::ResortNew( EventList
* pList
)
1583 sal_IntPtr i
, nNewPos
, nVal
;
1586 for ( i
= mnLastSort
; i
<static_cast<sal_IntPtr
>(maS2O
.Count()); i
++ )
1588 SortListData
*const pData
= m_ModList
[i
];
1589 nNewPos
= FindPos( pData
, 1, mnLastSort
);
1592 maS2O
.Move( static_cast<sal_uInt32
>(i
), nNewPos
);
1593 for (size_t j
=1; j
< m_O2S
.size(); ++j
)
1596 if ( nVal
>= nNewPos
)
1597 m_O2S
[j
] = nVal
+ 1;
1599 m_O2S
[pData
->mnCurPos
] = nNewPos
;
1602 pList
->AddEvent( ListActionType::INSERTED
, nNewPos
);
1605 catch (const SQLException
&)
1607 TOOLS_WARN_EXCEPTION("ucb", "");
1615 SortListData::SortListData( sal_IntPtr nPos
)
1622 SortedEntryList::SortedEntryList()
1626 SortedEntryList::~SortedEntryList()
1630 void SortedEntryList::Clear()
1636 void SortedEntryList::Insert( std::unique_ptr
<SortListData
> pEntry
, sal_Int32 nPos
)
1638 if ( nPos
< static_cast<sal_IntPtr
>(maData
.size()) )
1639 maData
.insert( maData
.begin() + nPos
, std::move(pEntry
) );
1641 maData
.push_back( std::move(pEntry
) );
1644 void SortedEntryList::Move( sal_Int32 nOldPos
, sal_Int32 nNewPos
)
1646 auto p
= std::move(maData
[nOldPos
]);
1647 maData
.erase( maData
.begin() + nOldPos
);
1648 maData
.insert(maData
.begin() + nNewPos
, std::move(p
));
1651 std::unique_ptr
<SortListData
> SortedEntryList::Remove( sal_Int32 nPos
)
1653 std::unique_ptr
<SortListData
> pData
;
1655 if ( nPos
< static_cast<sal_IntPtr
>(maData
.size()) )
1657 pData
= std::move(maData
[ nPos
]);
1658 maData
.erase( maData
.begin() + nPos
);
1665 SortListData
* SortedEntryList::GetData( sal_Int32 nPos
)
1667 SortListData
*pData
;
1669 if ( nPos
< static_cast<sal_IntPtr
>(maData
.size()) )
1670 pData
= maData
[ nPos
].get();
1678 sal_Int32
SortedEntryList::operator [] ( sal_Int32 nPos
) const
1680 SortListData
*pData
;
1682 if ( nPos
< static_cast<sal_IntPtr
>(maData
.size()) )
1683 pData
= maData
[ nPos
].get();
1688 if ( ! pData
->mbModified
)
1689 return pData
->mnCurPos
;
1692 OSL_FAIL( "SortedEntryList: Can't get value for modified entry!");
1697 OSL_FAIL( "SortedEntryList: invalid pos!");
1703 SRSPropertySetInfo::SRSPropertySetInfo()
1705 maProps
[0].Name
= "RowCount";
1706 maProps
[0].Handle
= -1;
1707 maProps
[0].Type
= cppu::UnoType
<OUString
>::get();
1708 maProps
[0].Attributes
= -1;
1710 maProps
[1].Name
= "IsRowCountFinal";
1711 maProps
[1].Handle
= -1;
1712 maProps
[1].Type
= cppu::UnoType
<bool>::get();
1713 maProps
[1].Attributes
= -1;
1716 // XPropertySetInfo methods.
1718 Sequence
< Property
> SAL_CALL
1719 SRSPropertySetInfo::getProperties()
1721 return Sequence
< Property
> ( maProps
, 2 );
1726 SRSPropertySetInfo::getPropertyByName( const OUString
& Name
)
1728 if ( Name
== "RowCount" )
1730 else if ( Name
== "IsRowCountFinal" )
1733 throw UnknownPropertyException(Name
);
1738 SRSPropertySetInfo::hasPropertyByName( const OUString
& Name
)
1740 if ( Name
== "RowCount" )
1742 else if ( Name
== "IsRowCountFinal" )
1748 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */