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 .
20 #include <DatabaseDataProvider.hxx>
21 #include <strings.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <comphelper/types.hxx>
24 #include <comphelper/namedvaluecollection.hxx>
25 #include <connectivity/FValue.hxx>
26 #include <sal/macros.h>
27 #include <comphelper/diagnose_ex.hxx>
29 #include <com/sun/star/task/XInteractionHandler.hpp>
30 #include <com/sun/star/sdb/CommandType.hpp>
31 #include <com/sun/star/sdbc/DataType.hpp>
32 #include <com/sun/star/sdbc/XRow.hpp>
33 #include <com/sun/star/sdbc/XResultSet.hpp>
34 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
35 #include <com/sun/star/sdbc/XColumnLocate.hpp>
36 #include <com/sun/star/beans/NamedValue.hpp>
37 #include <com/sun/star/chart/ChartDataRowSource.hpp>
38 #include <com/sun/star/chart/XChartDataArray.hpp>
43 // TODO: update for new HavingClause-aware FilterManager
47 using namespace ::com::sun::star
;
48 using ::com::sun::star::uno::Reference
;
50 DatabaseDataProvider::DatabaseDataProvider(uno::Reference
< uno::XComponentContext
> const & context
) :
51 TDatabaseDataProvider(m_aMutex
),
52 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>(
53 context
, IMPLEMENTS_PROPERTY_SET
, uno::Sequence
< OUString
>()),
54 m_aParameterManager( m_aMutex
, context
),
56 m_CommandType(sdb::CommandType::COMMAND
), // #i94114
58 m_EscapeProcessing(true),
61 m_xInternal
.set( m_xContext
->getServiceManager()->createInstanceWithContext(u
"com.sun.star.comp.chart.InternalDataProvider"_ustr
,m_xContext
), uno::UNO_QUERY
);
62 m_xRangeConversion
.set(m_xInternal
,uno::UNO_QUERY
);
63 m_xComplexDescriptionAccess
.set(m_xInternal
,uno::UNO_QUERY
);
65 osl_atomic_increment( &m_refCount
);
67 m_xRowSet
.set( m_xContext
->getServiceManager()->createInstanceWithContext(SERVICE_SDB_ROWSET
,m_xContext
), uno::UNO_QUERY
);
68 m_xAggregate
.set(m_xRowSet
,uno::UNO_QUERY
);
69 m_xAggregateSet
.set(m_xRowSet
,uno::UNO_QUERY
);
70 uno::Reference
<beans::XPropertySet
> xProp(static_cast< ::cppu::OWeakObject
* >( this ),uno::UNO_QUERY
);
71 m_aFilterManager
.initialize( m_xAggregateSet
);
72 m_aParameterManager
.initialize( xProp
, m_xAggregate
);
73 m_xAggregateSet
->setPropertyValue(PROPERTY_COMMAND_TYPE
,uno::Any(m_CommandType
));
74 m_xAggregateSet
->setPropertyValue(PROPERTY_ESCAPE_PROCESSING
,uno::Any(m_EscapeProcessing
));
76 osl_atomic_decrement( &m_refCount
);
79 void SAL_CALL
DatabaseDataProvider::disposing()
81 m_aParameterManager
.dispose(); // (to free any references it may have to me)
82 m_aFilterManager
.dispose(); // (ditto)
85 m_xAggregateSet
.clear();
87 m_xRangeConversion
.clear();
88 ::comphelper::disposeComponent(m_xRowSet
);
89 ::comphelper::disposeComponent(m_xInternal
);
90 m_xActiveConnection
.clear();
93 uno::Any
DatabaseDataProvider::queryInterface(uno::Type
const & type
)
95 return TDatabaseDataProvider::queryInterface(type
);
99 OUString SAL_CALL
DatabaseDataProvider::getImplementationName( )
101 return u
"com.sun.star.comp.dbaccess.DatabaseDataProvider"_ustr
;
104 sal_Bool SAL_CALL
DatabaseDataProvider::supportsService( const OUString
& _rServiceName
)
106 return cppu::supportsService(this, _rServiceName
);
109 uno::Sequence
< OUString
> SAL_CALL
DatabaseDataProvider::getSupportedServiceNames( )
111 return { u
"com.sun.star.chart2.data.DatabaseDataProvider"_ustr
};
114 // lang::XInitialization:
115 void SAL_CALL
DatabaseDataProvider::initialize(const uno::Sequence
< uno::Any
> & aArguments
)
117 osl::MutexGuard
g(m_aMutex
);
118 for (auto& arg
: aArguments
)
120 if ( !m_xActiveConnection
.is() )
121 arg
>>= m_xActiveConnection
;
122 else if ( !m_xHandler
.is() )
125 m_xAggregateSet
->setPropertyValue( PROPERTY_ACTIVE_CONNECTION
, uno::Any( m_xActiveConnection
) );
128 // chart2::data::XDataProvider:
129 sal_Bool SAL_CALL
DatabaseDataProvider::createDataSourcePossible(const uno::Sequence
< beans::PropertyValue
> & _aArguments
)
131 for (auto& arg
: _aArguments
)
133 if (arg
.Name
== "DataRowSource")
135 css::chart::ChartDataRowSource eRowSource
= css::chart::ChartDataRowSource_COLUMNS
;
136 arg
.Value
>>= eRowSource
;
137 if ( eRowSource
!= css::chart::ChartDataRowSource_COLUMNS
)
140 else if (arg
.Name
== "CellRangeRepresentation")
143 arg
.Value
>>= sRange
;
144 if ( sRange
!= "all" )
147 else if (arg
.Name
== "FirstCellAsLabel")
149 bool bFirstCellAsLabel
= true;
150 arg
.Value
>>= bFirstCellAsLabel
;
151 if ( !bFirstCellAsLabel
)
158 uno::Reference
< chart2::data::XDataSource
> SAL_CALL
DatabaseDataProvider::createDataSource(const uno::Sequence
< beans::PropertyValue
> & _aArguments
)
160 osl::ResettableMutexGuard
aClearForNotifies(m_aMutex
);
161 if ( createDataSourcePossible(_aArguments
) )
165 uno::Reference
< chart::XChartDataArray
> xChartData( m_xInternal
, uno::UNO_QUERY_THROW
);
166 xChartData
->setData( uno::Sequence
< uno::Sequence
< double > >() );
167 xChartData
->setColumnDescriptions( uno::Sequence
< OUString
>() );
168 if ( m_xInternal
->hasDataByRangeRepresentation( OUString::number( 0 ) ) )
169 m_xInternal
->deleteSequence(0);
171 catch( const uno::Exception
& )
173 DBG_UNHANDLED_EXCEPTION("dbaccess");
176 ::comphelper::NamedValueCollection
aArgs( _aArguments
);
177 const bool bHasCategories
= aArgs
.getOrDefault( u
"HasCategories"_ustr
, true );
178 uno::Sequence
< OUString
> aColumnNames
=
179 aArgs
.getOrDefault( u
"ColumnDescriptions"_ustr
, uno::Sequence
< OUString
>() );
182 if ( !m_Command
.isEmpty() && m_xActiveConnection
.is() )
186 impl_fillRowSet_throw();
187 if ( impl_fillParameters_nothrow(aClearForNotifies
) )
188 m_xRowSet
->execute();
189 impl_fillInternalDataProvider_throw(bHasCategories
,aColumnNames
);
192 catch(const uno::Exception
& /*e*/)
196 if ( !bRet
) // no command set or an error occurred, use Internal data handler
198 uno::Reference
< lang::XInitialization
> xIni(m_xInternal
,uno::UNO_QUERY
);
201 beans::NamedValue
aParam(u
"CreateDefaultData"_ustr
,uno::Any(true));
202 uno::Sequence
< uno::Any
> aInitArgs
{ uno::Any(aParam
) };
203 xIni
->initialize(aInitArgs
);
208 return m_xInternal
->createDataSource(_aArguments
);
211 uno::Sequence
< beans::PropertyValue
> SAL_CALL
DatabaseDataProvider::detectArguments(const uno::Reference
< chart2::data::XDataSource
> & _xDataSource
)
213 ::comphelper::NamedValueCollection aArguments
;
214 aArguments
.put( u
"CellRangeRepresentation"_ustr
, uno::Any( u
"all"_ustr
) );
215 aArguments
.put( u
"DataRowSource"_ustr
, uno::Any( chart::ChartDataRowSource_COLUMNS
) );
216 // internal data always contains labels
217 aArguments
.put( u
"FirstCellAsLabel"_ustr
, uno::Any( true ) );
219 bool bHasCategories
= false;
220 if( _xDataSource
.is())
222 uno::Sequence
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aSequences(_xDataSource
->getDataSequences());
223 const sal_Int32
nCount( aSequences
.getLength());
224 for( sal_Int32 nIdx
=0; nIdx
<nCount
; ++nIdx
)
226 if( aSequences
[nIdx
].is() )
228 uno::Reference
< beans::XPropertySet
> xSeqProp( aSequences
[nIdx
]->getValues(), uno::UNO_QUERY
);
231 && ( xSeqProp
->getPropertyValue( u
"Role"_ustr
) >>= aRole
)
232 && aRole
== "categories"
235 bHasCategories
= true;
241 aArguments
.put( u
"HasCategories"_ustr
, uno::Any( bHasCategories
) );
242 return aArguments
.getPropertyValues();
245 sal_Bool SAL_CALL
DatabaseDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString
& /*aRangeRepresentation*/)
250 uno::Any
DatabaseDataProvider::impl_getNumberFormatKey_nothrow(const OUString
& _sRangeRepresentation
) const
252 std::map
< OUString
,css::uno::Any
>::const_iterator aFind
= m_aNumberFormats
.find(_sRangeRepresentation
);
253 if ( aFind
!= m_aNumberFormats
.end() )
254 return aFind
->second
;
255 return uno::Any(sal_Int32(0));
258 uno::Reference
< chart2::data::XDataSequence
> SAL_CALL
DatabaseDataProvider::createDataSequenceByRangeRepresentation(const OUString
& _sRangeRepresentation
)
260 osl::MutexGuard
g(m_aMutex
);
261 uno::Reference
< chart2::data::XDataSequence
> xData
= m_xInternal
->createDataSequenceByRangeRepresentation(_sRangeRepresentation
);
262 uno::Reference
<beans::XPropertySet
> xProp(xData
,uno::UNO_QUERY
);
263 static constexpr OUString s_sNumberFormatKey
= u
"NumberFormatKey"_ustr
;
264 if ( xProp
.is() && xProp
->getPropertySetInfo()->hasPropertyByName(s_sNumberFormatKey
) )
266 xProp
->setPropertyValue(s_sNumberFormatKey
,impl_getNumberFormatKey_nothrow(_sRangeRepresentation
));
271 uno::Reference
<chart2::data::XDataSequence
>
272 SAL_CALL
DatabaseDataProvider::createDataSequenceByValueArray(
273 const OUString
& /*aRole*/, const OUString
& /*aRangeRepresentation*/, const OUString
& /*aRoleQualifier*/ )
275 return uno::Reference
<chart2::data::XDataSequence
>();
278 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
DatabaseDataProvider::getComplexRowDescriptions()
280 return m_xComplexDescriptionAccess
->getComplexRowDescriptions();
283 void SAL_CALL
DatabaseDataProvider::setComplexRowDescriptions( const uno::Sequence
< uno::Sequence
< OUString
> >& aRowDescriptions
)
285 m_xComplexDescriptionAccess
->setComplexRowDescriptions(aRowDescriptions
);
288 uno::Sequence
< uno::Sequence
< OUString
> > SAL_CALL
DatabaseDataProvider::getComplexColumnDescriptions()
290 return m_xComplexDescriptionAccess
->getComplexColumnDescriptions();
293 void SAL_CALL
DatabaseDataProvider::setComplexColumnDescriptions( const uno::Sequence
< uno::Sequence
< OUString
> >& aColumnDescriptions
)
295 m_xComplexDescriptionAccess
->setComplexColumnDescriptions(aColumnDescriptions
);
298 // ____ XChartDataArray ____
299 uno::Sequence
< uno::Sequence
< double > > SAL_CALL
DatabaseDataProvider::getData()
301 return m_xComplexDescriptionAccess
->getData();
304 void SAL_CALL
DatabaseDataProvider::setData( const uno::Sequence
< uno::Sequence
< double > >& rDataInRows
)
306 m_xComplexDescriptionAccess
->setData(rDataInRows
);
309 void SAL_CALL
DatabaseDataProvider::setRowDescriptions( const uno::Sequence
< OUString
>& aRowDescriptions
)
311 m_xComplexDescriptionAccess
->setRowDescriptions(aRowDescriptions
);
314 void SAL_CALL
DatabaseDataProvider::setColumnDescriptions( const uno::Sequence
< OUString
>& aColumnDescriptions
)
316 m_xComplexDescriptionAccess
->setColumnDescriptions(aColumnDescriptions
);
319 uno::Sequence
< OUString
> SAL_CALL
DatabaseDataProvider::getRowDescriptions()
321 return m_xComplexDescriptionAccess
->getRowDescriptions();
324 uno::Sequence
< OUString
> SAL_CALL
DatabaseDataProvider::getColumnDescriptions()
326 return m_xComplexDescriptionAccess
->getColumnDescriptions();
329 // ____ XChartData (base of XChartDataArray) ____
330 void SAL_CALL
DatabaseDataProvider::addChartDataChangeEventListener(const uno::Reference
< css::chart::XChartDataChangeEventListener
>& x
)
332 m_xComplexDescriptionAccess
->addChartDataChangeEventListener(x
);
335 void SAL_CALL
DatabaseDataProvider::removeChartDataChangeEventListener(const uno::Reference
< css::chart::XChartDataChangeEventListener
>& x
)
337 m_xComplexDescriptionAccess
->removeChartDataChangeEventListener(x
);
340 double SAL_CALL
DatabaseDataProvider::getNotANumber()
342 return m_xComplexDescriptionAccess
->getNotANumber();
345 sal_Bool SAL_CALL
DatabaseDataProvider::isNotANumber( double nNumber
)
347 return m_xComplexDescriptionAccess
->isNotANumber(nNumber
);
350 uno::Reference
< sheet::XRangeSelection
> SAL_CALL
DatabaseDataProvider::getRangeSelection()
352 // TODO: Exchange the default return implementation for "getRangeSelection" !!!
353 // Exchange the default return implementation.
354 // NOTE: Default initialized polymorphic structs can cause problems because of
355 // missing default initialization of primitive types of some C++ compilers or
356 // different Any initialization in Java and C++ polymorphic structs.
357 return uno::Reference
< sheet::XRangeSelection
>();
360 // chart2::data::XRangeXMLConversion:
361 OUString SAL_CALL
DatabaseDataProvider::convertRangeToXML(const OUString
& _sRangeRepresentation
)
363 osl::MutexGuard
g(m_aMutex
);
364 return m_xRangeConversion
->convertRangeToXML(_sRangeRepresentation
);
367 OUString SAL_CALL
DatabaseDataProvider::convertRangeFromXML(const OUString
& _sXMLRange
)
369 osl::MutexGuard
g(m_aMutex
);
370 return m_xRangeConversion
->convertRangeFromXML(_sXMLRange
);
373 // com.sun.star.beans.XPropertySet:
374 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
DatabaseDataProvider::getPropertySetInfo()
376 return ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::getPropertySetInfo();
379 void SAL_CALL
DatabaseDataProvider::setPropertyValue(const OUString
& aPropertyName
, const uno::Any
& aValue
)
381 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::setPropertyValue(aPropertyName
, aValue
);
384 uno::Any SAL_CALL
DatabaseDataProvider::getPropertyValue(const OUString
& aPropertyName
)
386 return ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::getPropertyValue(aPropertyName
);
389 void SAL_CALL
DatabaseDataProvider::addPropertyChangeListener(const OUString
& aPropertyName
, const uno::Reference
< beans::XPropertyChangeListener
> & xListener
)
391 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::addPropertyChangeListener(aPropertyName
, xListener
);
394 void SAL_CALL
DatabaseDataProvider::removePropertyChangeListener(const OUString
& aPropertyName
, const uno::Reference
< beans::XPropertyChangeListener
> & xListener
)
396 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::removePropertyChangeListener(aPropertyName
, xListener
);
399 void SAL_CALL
DatabaseDataProvider::addVetoableChangeListener(const OUString
& aPropertyName
, const uno::Reference
< beans::XVetoableChangeListener
> & xListener
)
401 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::addVetoableChangeListener(aPropertyName
, xListener
);
404 void SAL_CALL
DatabaseDataProvider::removeVetoableChangeListener(const OUString
& aPropertyName
, const uno::Reference
< beans::XVetoableChangeListener
> & xListener
)
406 ::cppu::PropertySetMixin
< chart2::data::XDatabaseDataProvider
>::removeVetoableChangeListener(aPropertyName
, xListener
);
409 // chart2::data::XDatabaseDataProvider:
410 uno::Sequence
< OUString
> SAL_CALL
DatabaseDataProvider::getMasterFields()
412 osl::MutexGuard
g(m_aMutex
);
413 return m_MasterFields
;
416 void SAL_CALL
DatabaseDataProvider::setMasterFields(const uno::Sequence
< OUString
> & the_value
)
418 impl_invalidateParameter_nothrow();
419 set(u
"MasterFields"_ustr
,the_value
,m_MasterFields
);
422 uno::Sequence
< OUString
> SAL_CALL
DatabaseDataProvider::getDetailFields()
424 osl::MutexGuard
g(m_aMutex
);
425 return m_DetailFields
;
428 void SAL_CALL
DatabaseDataProvider::setDetailFields(const uno::Sequence
< OUString
> & the_value
)
430 set(u
"DetailFields"_ustr
,the_value
,m_DetailFields
);
433 OUString SAL_CALL
DatabaseDataProvider::getCommand()
435 osl::MutexGuard
g(m_aMutex
);
439 void SAL_CALL
DatabaseDataProvider::setCommand(const OUString
& the_value
)
442 osl::MutexGuard
g(m_aMutex
);
443 impl_invalidateParameter_nothrow();
444 m_xAggregateSet
->setPropertyValue( PROPERTY_COMMAND
, uno::Any( the_value
) );
446 set(PROPERTY_COMMAND
,the_value
,m_Command
);
449 ::sal_Int32 SAL_CALL
DatabaseDataProvider::getCommandType()
451 osl::MutexGuard
g(m_aMutex
);
452 return m_CommandType
;
455 void SAL_CALL
DatabaseDataProvider::setCommandType(::sal_Int32 the_value
)
458 osl::MutexGuard
g(m_aMutex
);
459 m_xAggregateSet
->setPropertyValue( PROPERTY_COMMAND_TYPE
, uno::Any( the_value
) );
461 set(PROPERTY_COMMAND_TYPE
,the_value
,m_CommandType
);
464 OUString SAL_CALL
DatabaseDataProvider::getFilter()
466 osl::MutexGuard
g(m_aMutex
);
467 return m_aFilterManager
.getFilterComponent( dbtools::FilterManager::FilterComponent::PublicFilter
);
470 void SAL_CALL
DatabaseDataProvider::setFilter(const OUString
& the_value
)
473 osl::MutexGuard
g(m_aMutex
);
474 m_aFilterManager
.setFilterComponent( dbtools::FilterManager::FilterComponent::PublicFilter
, the_value
);
476 set(PROPERTY_FILTER
,the_value
,m_Filter
);
479 sal_Bool SAL_CALL
DatabaseDataProvider::getApplyFilter()
481 osl::MutexGuard
g(m_aMutex
);
482 return m_ApplyFilter
;
485 void SAL_CALL
DatabaseDataProvider::setApplyFilter( sal_Bool the_value
)
488 osl::MutexGuard
g(m_aMutex
);
489 m_xAggregateSet
->setPropertyValue( PROPERTY_APPLYFILTER
, uno::Any( the_value
) );
491 set(PROPERTY_APPLYFILTER
,static_cast<bool>(the_value
),m_ApplyFilter
);
494 OUString SAL_CALL
DatabaseDataProvider::getHavingClause()
496 osl::MutexGuard
g(m_aMutex
);
497 return m_HavingClause
;
500 void SAL_CALL
DatabaseDataProvider::setHavingClause( const OUString
& the_value
)
503 osl::MutexGuard
g(m_aMutex
);
504 m_xAggregateSet
->setPropertyValue( PROPERTY_HAVING_CLAUSE
, uno::Any( the_value
) );
506 set(PROPERTY_HAVING_CLAUSE
,the_value
,m_HavingClause
);
509 OUString SAL_CALL
DatabaseDataProvider::getGroupBy()
511 osl::MutexGuard
g(m_aMutex
);
515 void SAL_CALL
DatabaseDataProvider::setGroupBy( const OUString
& the_value
)
518 osl::MutexGuard
g(m_aMutex
);
519 m_xAggregateSet
->setPropertyValue( PROPERTY_GROUP_BY
, uno::Any( the_value
) );
521 set(PROPERTY_GROUP_BY
,the_value
,m_GroupBy
);
524 OUString SAL_CALL
DatabaseDataProvider::getOrder()
526 osl::MutexGuard
g(m_aMutex
);
530 void SAL_CALL
DatabaseDataProvider::setOrder( const OUString
& the_value
)
533 osl::MutexGuard
g(m_aMutex
);
534 m_xAggregateSet
->setPropertyValue( PROPERTY_ORDER
, uno::Any( the_value
) );
536 set(PROPERTY_ORDER
,the_value
,m_Order
);
539 sal_Bool SAL_CALL
DatabaseDataProvider::getEscapeProcessing()
541 osl::MutexGuard
g(m_aMutex
);
542 return m_EscapeProcessing
;
545 void SAL_CALL
DatabaseDataProvider::setEscapeProcessing(sal_Bool the_value
)
547 set(PROPERTY_ESCAPE_PROCESSING
,static_cast<bool>(the_value
),m_EscapeProcessing
);
550 ::sal_Int32 SAL_CALL
DatabaseDataProvider::getRowLimit()
552 osl::MutexGuard
g(m_aMutex
);
556 void SAL_CALL
DatabaseDataProvider::setRowLimit(::sal_Int32 the_value
)
558 set(u
"RowLimit"_ustr
,the_value
,m_RowLimit
);
561 uno::Reference
< sdbc::XConnection
> SAL_CALL
DatabaseDataProvider::getActiveConnection()
563 osl::MutexGuard
g(m_aMutex
);
564 return m_xActiveConnection
;
567 void SAL_CALL
DatabaseDataProvider::setActiveConnection(const uno::Reference
< sdbc::XConnection
> & the_value
)
569 if ( !the_value
.is() )
570 throw lang::IllegalArgumentException();
571 set(PROPERTY_ACTIVE_CONNECTION
,the_value
,m_xActiveConnection
);
574 OUString SAL_CALL
DatabaseDataProvider::getDataSourceName()
576 osl::MutexGuard
g(m_aMutex
);
577 return m_DataSourceName
;
580 void SAL_CALL
DatabaseDataProvider::setDataSourceName(const OUString
& the_value
)
582 set(PROPERTY_DATASOURCENAME
,the_value
,m_DataSourceName
);
587 struct ColumnDescription
590 sal_Int32 nResultSetPosition
;
594 :nResultSetPosition( 0 )
595 ,nDataType( sdbc::DataType::VARCHAR
)
598 explicit ColumnDescription( OUString i_sName
)
599 :sName(std::move( i_sName
))
600 ,nResultSetPosition( 0 )
601 ,nDataType( sdbc::DataType::VARCHAR
)
606 struct CreateColumnDescription
608 ColumnDescription
operator()( const OUString
& i_rName
)
610 return ColumnDescription( i_rName
);
614 struct SelectColumnName
616 const OUString
& operator()( const ColumnDescription
& i_rColumn
)
618 return i_rColumn
.sName
;
623 void DatabaseDataProvider::impl_fillInternalDataProvider_throw(bool _bHasCategories
,const uno::Sequence
< OUString
>& i_aColumnNames
)
625 // clear the data before fill the new one
626 uno::Reference
< sdbcx::XColumnsSupplier
> xColSup(m_xRowSet
,uno::UNO_QUERY_THROW
);
627 uno::Reference
< container::XNameAccess
> xColumns( xColSup
->getColumns(), uno::UNO_SET_THROW
);
628 const uno::Sequence
< OUString
> aRowSetColumnNames( xColumns
->getElementNames() );
630 typedef std::vector
< ColumnDescription
> ColumnDescriptions
;
631 ColumnDescriptions aColumns
;
632 bool bFirstColumnIsCategory
= _bHasCategories
;
633 if ( i_aColumnNames
.hasElements() )
635 // some normalizations ...
636 uno::Sequence
< OUString
> aImposedColumnNames( i_aColumnNames
);
638 // strangely, there exist documents where the ColumnDescriptions end with a number of empty strings. /me
639 // thinks they're generated when you have a chart based on a result set with n columns, but remove some
640 // of those columns from the chart - it looks like a bug in the report XML export to me.
641 // So, get rid of the "trailing" empty columns
642 sal_Int32 nLastNonEmptyColName
= aImposedColumnNames
.getLength() - 1;
643 for ( ; nLastNonEmptyColName
>= 0; --nLastNonEmptyColName
)
645 if ( !aImposedColumnNames
[ nLastNonEmptyColName
].isEmpty() )
648 aImposedColumnNames
.realloc( nLastNonEmptyColName
+ 1 );
650 // second, for X-Y-charts the ColumnDescriptions exported by chart miss the name of the first (non-category)
651 // column. This, this results in a ColumnDescriptions array like <"", "col2", "col3">, where you'd expect
652 // <"col1", "col2", "col3">.
653 // Fix this with some heuristics:
654 if ( aImposedColumnNames
.hasElements() && ( !aImposedColumnNames
[0].isEmpty() ) )
656 const sal_Int32 nAssumedRowSetColumnIndex
= _bHasCategories
? 1 : 0;
657 if ( nAssumedRowSetColumnIndex
< aRowSetColumnNames
.getLength() )
658 aImposedColumnNames
.getArray()[0] = aRowSetColumnNames
[ nAssumedRowSetColumnIndex
];
661 const sal_Int32 nCount
= aImposedColumnNames
.getLength();
662 for ( sal_Int32 i
= 0 ; i
< nCount
; ++i
)
664 const OUString
& sColumnName( aImposedColumnNames
[i
] );
665 if ( !xColumns
->hasByName( sColumnName
) )
668 if ( _bHasCategories
&& aColumns
.empty() )
670 if ( aRowSetColumnNames
.hasElements() )
671 aColumns
.emplace_back( aRowSetColumnNames
[0] );
673 aColumns
.emplace_back( sColumnName
);
674 bFirstColumnIsCategory
= true;
676 aColumns
.emplace_back( sColumnName
);
679 if ( aColumns
.empty() )
681 aColumns
.resize( aRowSetColumnNames
.getLength() );
683 aRowSetColumnNames
.begin(),
684 aRowSetColumnNames
.end(),
686 CreateColumnDescription()
691 uno::Reference
< sdbc::XResultSet
> xRes( m_xRowSet
, uno::UNO_QUERY_THROW
);
692 uno::Reference
< sdbc::XRow
> xRow( m_xRowSet
,uno::UNO_QUERY_THROW
);
693 uno::Reference
< sdbc::XResultSetMetaDataSupplier
> xSuppMeta( m_xRowSet
,uno::UNO_QUERY_THROW
);
694 uno::Reference
< sdbc::XColumnLocate
> xColumnLocate( m_xRowSet
, uno::UNO_QUERY_THROW
);
696 sal_Int32 columnIndex
= 0;
697 for (auto & column
: aColumns
)
699 column
.nResultSetPosition
= xColumnLocate
->findColumn( column
.sName
);
701 const uno::Reference
< beans::XPropertySet
> xColumn( xColumns
->getByName( column
.sName
), uno::UNO_QUERY_THROW
);
702 const uno::Any
aNumberFormat( xColumn
->getPropertyValue( PROPERTY_NUMBERFORMAT
) );
703 OSL_VERIFY( xColumn
->getPropertyValue( PROPERTY_TYPE
) >>= column
.nDataType
);
705 const OUString sRangeName
= OUString::number( columnIndex
);
706 m_aNumberFormats
.emplace( sRangeName
, aNumberFormat
);
710 std::vector
< OUString
> aRowLabels
;
711 std::vector
< std::vector
< double > > aDataValues
;
712 sal_Int32 nRowCount
= 0;
713 ::connectivity::ORowSetValue aValue
;
714 while( xRes
->next() && (!m_RowLimit
|| nRowCount
< m_RowLimit
) )
718 aValue
.fill( aColumns
[0].nResultSetPosition
, aColumns
[0].nDataType
, xRow
);
719 aRowLabels
.push_back( aValue
.getString() );
721 std::vector
< double > aRow
;
722 bool bFirstLoop
= true;
723 for (auto const& column
: aColumns
)
728 if (bFirstColumnIsCategory
)
732 aValue
.fill( column
.nResultSetPosition
, column
.nDataType
, xRow
);
733 if ( aValue
.isNull() )
734 aRow
.push_back( std::numeric_limits
<double>::quiet_NaN() );
736 aRow
.push_back( aValue
.getDouble() );
739 aDataValues
.push_back( aRow
);
742 // insert default data when no rows exist
746 static const double fDefaultData
[ ] =
751 for(sal_Int32 h
= 0,k
= 0; h
< nRowCount
; ++h
,++k
)
753 aRowLabels
.push_back(OUString::number(h
+1));
754 std::vector
< double > aRow
;
755 const sal_Int32 nSize
= std::size(fDefaultData
);
756 for (size_t j
= 0; j
< (aColumns
.size()-1); ++j
,++k
)
760 aRow
.push_back(fDefaultData
[k
]);
762 aDataValues
.push_back(aRow
);
766 uno::Reference
< chart::XChartDataArray
> xData(m_xInternal
,uno::UNO_QUERY
);
767 xData
->setRowDescriptions(comphelper::containerToSequence(aRowLabels
));
769 const size_t nOffset
= bFirstColumnIsCategory
? 1 : 0;
770 uno::Sequence
< OUString
> aColumnDescriptions( aColumns
.size() - nOffset
);
772 aColumns
.begin() + nOffset
,
774 aColumnDescriptions
.getArray(),
777 xData
->setColumnDescriptions( aColumnDescriptions
);
779 uno::Sequence
< uno::Sequence
< double > > aData(aDataValues
.size());
780 uno::Sequence
< double >* pDataIter
= aData
.getArray();
781 uno::Sequence
< double >* pDataEnd
= pDataIter
+ aData
.getLength();
782 for(sal_Int32 i
= 0;pDataIter
!= pDataEnd
; ++pDataIter
,++i
)
784 if ( !aDataValues
[i
].empty() )
785 *pDataIter
= comphelper::containerToSequence(aDataValues
[i
]);
787 xData
->setData(aData
);
790 void DatabaseDataProvider::impl_fillRowSet_throw()
792 m_xAggregateSet
->setPropertyValue( PROPERTY_FILTER
, uno::Any( getFilter() ) );
793 uno::Reference
< sdbc::XParameters
> xParam(m_xRowSet
,uno::UNO_QUERY_THROW
);
794 xParam
->clearParameters( );
797 bool DatabaseDataProvider::impl_fillParameters_nothrow( ::osl::ResettableMutexGuard
& _rClearForNotifies
)
799 // do we have to fill the parameters again?
800 if ( !m_aParameterManager
.isUpToDate() )
801 m_aParameterManager
.updateParameterInfo( m_aFilterManager
);
803 if ( m_aParameterManager
.isUpToDate() )
804 return m_aParameterManager
.fillParameterValues( m_xHandler
, _rClearForNotifies
);
809 // css::sdbc::XParameters
810 void SAL_CALL
DatabaseDataProvider::setNull(sal_Int32 parameterIndex
, sal_Int32 sqlType
)
812 m_aParameterManager
.setNull(parameterIndex
, sqlType
);
815 void SAL_CALL
DatabaseDataProvider::setObjectNull(sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& typeName
)
817 m_aParameterManager
.setObjectNull(parameterIndex
, sqlType
, typeName
);
820 void SAL_CALL
DatabaseDataProvider::setBoolean(sal_Int32 parameterIndex
, sal_Bool x
)
822 m_aParameterManager
.setBoolean(parameterIndex
, x
);
825 void SAL_CALL
DatabaseDataProvider::setByte(sal_Int32 parameterIndex
, sal_Int8 x
)
827 m_aParameterManager
.setByte(parameterIndex
, x
);
830 void SAL_CALL
DatabaseDataProvider::setShort(sal_Int32 parameterIndex
, sal_Int16 x
)
832 m_aParameterManager
.setShort(parameterIndex
, x
);
835 void SAL_CALL
DatabaseDataProvider::setInt(sal_Int32 parameterIndex
, sal_Int32 x
)
837 m_aParameterManager
.setInt(parameterIndex
, x
);
840 void SAL_CALL
DatabaseDataProvider::setLong(sal_Int32 parameterIndex
, sal_Int64 x
)
842 m_aParameterManager
.setLong(parameterIndex
, x
);
845 void SAL_CALL
DatabaseDataProvider::setFloat(sal_Int32 parameterIndex
, float x
)
847 m_aParameterManager
.setFloat(parameterIndex
, x
);
850 void SAL_CALL
DatabaseDataProvider::setDouble(sal_Int32 parameterIndex
, double x
)
852 m_aParameterManager
.setDouble(parameterIndex
, x
);
855 void SAL_CALL
DatabaseDataProvider::setString(sal_Int32 parameterIndex
, const OUString
& x
)
857 m_aParameterManager
.setString(parameterIndex
, x
);
860 void SAL_CALL
DatabaseDataProvider::setBytes(sal_Int32 parameterIndex
, const uno::Sequence
< sal_Int8
>& x
)
862 m_aParameterManager
.setBytes(parameterIndex
, x
);
865 void SAL_CALL
DatabaseDataProvider::setDate(sal_Int32 parameterIndex
, const util::Date
& x
)
867 m_aParameterManager
.setDate(parameterIndex
, x
);
870 void SAL_CALL
DatabaseDataProvider::setTime(sal_Int32 parameterIndex
, const util::Time
& x
)
872 m_aParameterManager
.setTime(parameterIndex
, x
);
875 void SAL_CALL
DatabaseDataProvider::setTimestamp(sal_Int32 parameterIndex
, const util::DateTime
& x
)
877 m_aParameterManager
.setTimestamp(parameterIndex
, x
);
880 void SAL_CALL
DatabaseDataProvider::setBinaryStream(sal_Int32 parameterIndex
, const uno::Reference
<io::XInputStream
>& x
, sal_Int32 length
)
882 m_aParameterManager
.setBinaryStream(parameterIndex
, x
, length
);
885 void SAL_CALL
DatabaseDataProvider::setCharacterStream(sal_Int32 parameterIndex
, const uno::Reference
<io::XInputStream
>& x
, sal_Int32 length
)
887 m_aParameterManager
.setCharacterStream(parameterIndex
, x
, length
);
890 void SAL_CALL
DatabaseDataProvider::setObjectWithInfo(sal_Int32 parameterIndex
, const uno::Any
& x
, sal_Int32 targetSqlType
, sal_Int32 scale
)
892 m_aParameterManager
.setObjectWithInfo(parameterIndex
, x
, targetSqlType
, scale
);
895 void SAL_CALL
DatabaseDataProvider::setObject(sal_Int32 parameterIndex
, const uno::Any
& x
)
897 m_aParameterManager
.setObject(parameterIndex
, x
);
900 void SAL_CALL
DatabaseDataProvider::setRef(sal_Int32 parameterIndex
, const uno::Reference
<sdbc::XRef
>& x
)
902 m_aParameterManager
.setRef(parameterIndex
, x
);
905 void SAL_CALL
DatabaseDataProvider::setBlob(sal_Int32 parameterIndex
, const uno::Reference
<sdbc::XBlob
>& x
)
907 m_aParameterManager
.setBlob(parameterIndex
, x
);
910 void SAL_CALL
DatabaseDataProvider::setClob(sal_Int32 parameterIndex
, const uno::Reference
<sdbc::XClob
>& x
)
912 m_aParameterManager
.setClob(parameterIndex
, x
);
915 void SAL_CALL
DatabaseDataProvider::setArray(sal_Int32 parameterIndex
, const Reference
<sdbc::XArray
>& x
)
917 m_aParameterManager
.setArray(parameterIndex
, x
);
920 void SAL_CALL
DatabaseDataProvider::clearParameters()
922 m_aParameterManager
.clearParameters();
925 // css::sdbc::XRowSet
926 void SAL_CALL
DatabaseDataProvider::execute()
928 uno::Sequence
< beans::PropertyValue
> aEmpty
;
929 createDataSource(aEmpty
);
932 void SAL_CALL
DatabaseDataProvider::addRowSetListener(const uno::Reference
<sdbc::XRowSetListener
>& _rListener
)
935 m_xRowSet
->addRowSetListener(_rListener
);
938 void SAL_CALL
DatabaseDataProvider::removeRowSetListener(const uno::Reference
<sdbc::XRowSetListener
>& _rListener
)
941 m_xRowSet
->removeRowSetListener(_rListener
);
944 // css::sdbc::XResultSet
945 sal_Bool SAL_CALL
DatabaseDataProvider::next()
947 return m_xRowSet
->next();
950 sal_Bool SAL_CALL
DatabaseDataProvider::isBeforeFirst()
952 return m_xRowSet
->isBeforeFirst();
955 sal_Bool SAL_CALL
DatabaseDataProvider::isAfterLast()
957 return m_xRowSet
->isAfterLast();
960 sal_Bool SAL_CALL
DatabaseDataProvider::isFirst()
962 return m_xRowSet
->isFirst();
965 sal_Bool SAL_CALL
DatabaseDataProvider::isLast()
967 return m_xRowSet
->isLast();
970 void SAL_CALL
DatabaseDataProvider::beforeFirst()
972 m_xRowSet
->beforeFirst();
975 void SAL_CALL
DatabaseDataProvider::afterLast()
977 m_xRowSet
->afterLast();
980 sal_Bool SAL_CALL
DatabaseDataProvider::first()
982 return m_xRowSet
->first();
985 sal_Bool SAL_CALL
DatabaseDataProvider::last()
987 return m_xRowSet
->last();
990 sal_Int32 SAL_CALL
DatabaseDataProvider::getRow()
992 return m_xRowSet
->getRow();
995 sal_Bool SAL_CALL
DatabaseDataProvider::absolute(sal_Int32 row
)
997 return m_xRowSet
->absolute(row
);
1000 sal_Bool SAL_CALL
DatabaseDataProvider::relative(sal_Int32 rows
)
1002 return m_xRowSet
->relative(rows
);
1005 sal_Bool SAL_CALL
DatabaseDataProvider::previous()
1007 return m_xRowSet
->previous();
1010 void SAL_CALL
DatabaseDataProvider::refreshRow()
1012 m_xRowSet
->refreshRow();
1015 sal_Bool SAL_CALL
DatabaseDataProvider::rowUpdated()
1017 return m_xRowSet
->rowUpdated();
1020 sal_Bool SAL_CALL
DatabaseDataProvider::rowInserted()
1022 return m_xRowSet
->rowInserted();
1025 sal_Bool SAL_CALL
DatabaseDataProvider::rowDeleted()
1027 return m_xRowSet
->rowDeleted();
1030 uno::Reference
< uno::XInterface
> SAL_CALL
DatabaseDataProvider::getStatement()
1032 return m_xRowSet
->getStatement();
1035 uno::Reference
< uno::XInterface
> SAL_CALL
DatabaseDataProvider::getParent( )
1040 void SAL_CALL
DatabaseDataProvider::setParent( const uno::Reference
< uno::XInterface
>& _xParent
)
1042 osl::MutexGuard
g(m_aMutex
);
1043 m_xParent
= _xParent
;
1046 void DatabaseDataProvider::impl_invalidateParameter_nothrow()
1048 osl::MutexGuard
g(m_aMutex
);
1049 m_aParameterManager
.clearAllParameterInformation();
1052 } // namespace dbaccess
1055 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1056 com_sun_star_comp_dbaccess_DatabaseDataProvider_get_implementation(
1057 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
1059 return cppu::acquire(new dbaccess::DatabaseDataProvider(context
));
1063 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */