Fix GNU C++ version check
[LibreOffice.git] / dbaccess / source / core / misc / DatabaseDataProvider.cxx
blob8bf661362cd437125e6ac63f8f729d2220e43032
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
40 #include <utility>
41 #include <vector>
43 // TODO: update for new HavingClause-aware FilterManager
45 namespace dbaccess
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 ),
55 m_xContext(context),
56 m_CommandType(sdb::CommandType::COMMAND), // #i94114
57 m_RowLimit(0),
58 m_EscapeProcessing(true),
59 m_ApplyFilter(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)
84 m_xParent.clear();
85 m_xAggregateSet.clear();
86 m_xAggregate.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);
98 // XServiceInfo
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() )
123 arg >>= m_xHandler;
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 )
138 return false;
140 else if (arg.Name == "CellRangeRepresentation")
142 OUString sRange;
143 arg.Value >>= sRange;
144 if ( sRange != "all" )
145 return false;
147 else if (arg.Name == "FirstCellAsLabel")
149 bool bFirstCellAsLabel = true;
150 arg.Value >>= bFirstCellAsLabel;
151 if ( !bFirstCellAsLabel )
152 return false;
155 return true;
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 >() );
181 bool bRet = false;
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);
190 bRet = true;
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);
199 if ( xIni.is() )
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 );
229 OUString aRole;
230 if ( xSeqProp.is()
231 && ( xSeqProp->getPropertyValue( u"Role"_ustr ) >>= aRole )
232 && aRole == "categories"
235 bHasCategories = true;
236 break;
241 aArguments.put( u"HasCategories"_ustr, uno::Any( bHasCategories ) );
242 return aArguments.getPropertyValues();
245 sal_Bool SAL_CALL DatabaseDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString & /*aRangeRepresentation*/)
247 return true;
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));
268 return xData;
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);
436 return m_Command;
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);
512 return m_GroupBy;
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);
527 return m_Order;
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);
553 return m_RowLimit;
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);
585 namespace
587 struct ColumnDescription
589 OUString sName;
590 sal_Int32 nResultSetPosition;
591 sal_Int32 nDataType;
593 ColumnDescription()
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() )
646 break;
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 ) )
666 continue;
668 if ( _bHasCategories && aColumns.empty() )
670 if ( aRowSetColumnNames.hasElements() )
671 aColumns.emplace_back( aRowSetColumnNames[0] );
672 else
673 aColumns.emplace_back( sColumnName );
674 bFirstColumnIsCategory = true;
676 aColumns.emplace_back( sColumnName );
679 if ( aColumns.empty() )
681 aColumns.resize( aRowSetColumnNames.getLength() );
682 std::transform(
683 aRowSetColumnNames.begin(),
684 aRowSetColumnNames.end(),
685 aColumns.begin(),
686 CreateColumnDescription()
690 // fill the data
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 );
707 ++columnIndex;
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) )
716 ++nRowCount;
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)
725 if (bFirstLoop)
727 bFirstLoop = false;
728 if (bFirstColumnIsCategory)
729 continue;
732 aValue.fill( column.nResultSetPosition, column.nDataType, xRow );
733 if ( aValue.isNull() )
734 aRow.push_back( std::numeric_limits<double>::quiet_NaN() );
735 else
736 aRow.push_back( aValue.getDouble() );
739 aDataValues.push_back( aRow );
742 // insert default data when no rows exist
743 if ( !nRowCount )
745 nRowCount = 3;
746 static const double fDefaultData[ ] =
747 { 9.10, 3.20, 4.54,
748 2.40, 8.80, 9.65,
749 3.10, 1.50, 3.70,
750 4.30, 9.02, 6.20 };
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)
758 if ( k >= nSize )
759 k = 0;
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 );
771 std::transform(
772 aColumns.begin() + nOffset,
773 aColumns.end(),
774 aColumnDescriptions.getArray(),
775 SelectColumnName()
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 );
806 return true;
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)
934 if (m_xRowSet.is())
935 m_xRowSet->addRowSetListener(_rListener);
938 void SAL_CALL DatabaseDataProvider::removeRowSetListener(const uno::Reference<sdbc::XRowSetListener>& _rListener)
940 if (m_xRowSet.is())
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( )
1037 return m_xParent;
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: */