Update ooo320-m1
[ooovba.git] / dbaccess / source / core / api / query.cxx
blobcb4f568a4f5c633cab5510b60cc299d6fc328ba8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: query.cxx,v $
10 * $Revision: 1.35 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
34 #ifndef _DBA_COREAPI_QUERY_HXX_
35 #include "query.hxx"
36 #endif
37 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
38 #include "dbastrings.hrc"
39 #endif
40 #ifndef DBTOOLS_WARNINGSCONTAINER_HXX
41 #include <connectivity/warningscontainer.hxx>
42 #endif
43 #ifndef DBA_HELPERCOLLECTIONS_HXX
44 #include "HelperCollections.hxx"
45 #endif
46 #ifndef _DBA_CORE_RESOURCE_HXX_
47 #include "core_resource.hxx"
48 #endif
49 #ifndef _DBA_CORE_RESOURCE_HRC_
50 #include "core_resource.hrc"
51 #endif
53 #ifndef _CPPUHELPER_QUERYINTERFACE_HXX_
54 #include <cppuhelper/queryinterface.hxx>
55 #endif
56 #ifndef _TOOLS_DEBUG_HXX
57 #include <tools/debug.hxx>
58 #endif
59 #ifndef TOOLS_DIAGNOSE_EX_H
60 #include <tools/diagnose_ex.h>
61 #endif
62 #ifndef _COMPHELPER_PROPERTY_AGGREGATION_HXX_
63 #include <comphelper/propagg.hxx>
64 #endif
65 #ifndef _COMPHELPER_SEQUENCE_HXX_
66 #include <comphelper/sequence.hxx>
67 #endif
69 /** === begin UNO includes === **/
70 #ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
71 #include <com/sun/star/sdbc/XConnection.hpp>
72 #endif
73 #ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
74 #include <com/sun/star/lang/DisposedException.hpp>
75 #endif
76 #ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_
77 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
78 #endif
79 #ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_
80 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
81 #endif
82 /** === end UNO includes === **/
84 #ifndef _COMPHELPER_TYPES_HXX_
85 #include <comphelper/types.hxx>
86 #endif
87 #ifndef _COMPHELPER_PROPERTY_HXX_
88 #include <comphelper/property.hxx>
89 #endif
90 #ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
91 #include <unotools/sharedunocomponent.hxx>
92 #endif
93 #ifndef _DBACORE_DEFINITIONCOLUMN_HXX_
94 #include "definitioncolumn.hxx"
95 #endif
97 #include <functional>
99 #ifndef DBACORE_SDBCORETOOLS_HXX
100 #include "sdbcoretools.hxx"
101 #endif
102 #ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX
103 #include "querycomposer.hxx"
104 #endif
105 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
106 #include <com/sun/star/beans/PropertyAttribute.hpp>
107 #endif
108 #ifndef DBA_CONTAINERMEDIATOR_HXX
109 #include "ContainerMediator.hxx"
110 #endif
112 using namespace dbaccess;
113 using namespace ::com::sun::star::uno;
114 using namespace ::com::sun::star::sdbc;
115 using namespace ::com::sun::star::sdbcx;
116 using namespace ::com::sun::star::sdb;
117 using namespace ::com::sun::star::lang;
118 using namespace ::com::sun::star::util;
119 using namespace ::com::sun::star::beans;
120 using namespace ::com::sun::star::container;
121 using namespace ::comphelper;
122 using namespace ::osl;
123 using namespace ::cppu;
124 using namespace ::utl;
126 //........................................................................
127 namespace dbaccess
129 //........................................................................
131 //==========================================================================
132 //= OQuery
133 //==========================================================================
134 DBG_NAME(OQuery)
135 //--------------------------------------------------------------------------
136 OQuery::OQuery( const Reference< XPropertySet >& _rxCommandDefinition
137 ,const Reference< XConnection >& _rxConn
138 ,const Reference< XMultiServiceFactory >& _xORB)
139 :OContentHelper(_xORB,NULL,TContentPtr(new OContentHelper_Impl))
140 ,OQueryDescriptor_Base(m_aMutex,*this)
141 ,ODataSettings(OContentHelper::rBHelper,sal_True)
142 ,m_xCommandDefinition(_rxCommandDefinition)
143 ,m_xConnection(_rxConn)
144 ,m_pColumnMediator( NULL )
145 ,m_pWarnings( NULL )
146 ,m_bCaseSensitiv(sal_True)
147 ,m_eDoingCurrently(NONE)
149 DBG_CTOR(OQuery, NULL);
150 registerProperties();
151 ODataSettings::registerPropertiesFor(this);
153 osl_incrementInterlockedCount(&m_refCount);
154 DBG_ASSERT(m_xCommandDefinition.is(), "OQuery::OQuery : invalid CommandDefinition object !");
155 if ( m_xCommandDefinition.is() )
159 ::comphelper::copyProperties(_rxCommandDefinition,this);
161 catch(Exception&)
163 OSL_ENSURE(sal_False, "OQueryDescriptor_Base::OQueryDescriptor_Base: caught an exception!");
166 m_xCommandDefinition->addPropertyChangeListener(::rtl::OUString(), this);
167 // m_xCommandDefinition->addPropertyChangeListener(PROPERTY_NAME, this);
168 m_xCommandPropInfo = m_xCommandDefinition->getPropertySetInfo();
170 DBG_ASSERT(m_xConnection.is(), "OQuery::OQuery : invalid connection !");
171 osl_decrementInterlockedCount(&m_refCount);
174 //--------------------------------------------------------------------------
175 OQuery::~OQuery()
177 DBG_DTOR(OQuery, NULL);
179 // -----------------------------------------------------------------------------
180 IMPLEMENT_IMPLEMENTATION_ID(OQuery);
181 IMPLEMENT_GETTYPES3(OQuery,OQueryDescriptor_Base,ODataSettings,OContentHelper);
182 IMPLEMENT_FORWARD_XINTERFACE3( OQuery,OContentHelper,OQueryDescriptor_Base,ODataSettings)
183 //--------------------------------------------------------------------------
184 void OQuery::rebuildColumns()
186 OSL_PRECOND( getColumnCount() == 0, "OQuery::rebuildColumns: column container should be empty!" );
187 // the base class' definition of rebuildColumns promised that clearColumns is called before rebuildColumns
191 m_pColumnMediator = NULL;
193 Reference<XColumnsSupplier> xColSup(m_xCommandDefinition,UNO_QUERY);
194 if ( xColSup.is() )
196 Reference< XNameAccess > xColumnDefinitions = xColSup->getColumns();
197 if ( xColumnDefinitions.is() )
198 m_pColumnMediator = new OContainerMediator( m_pColumns, xColumnDefinitions, m_xConnection, OContainerMediator::eColumns );
201 // fill the columns with columns from the statement
202 Reference< XMultiServiceFactory > xFactory( m_xConnection, UNO_QUERY_THROW );
203 SharedUNOComponent< XSingleSelectQueryComposer, DisposableComponent > xComposer(
204 Reference< XSingleSelectQueryComposer >( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ) );
206 Reference< XNameAccess > xColumns;
207 Reference< XIndexAccess > xColumnsIndexed;
210 xComposer->setQuery( m_sCommand );
211 Reference< XColumnsSupplier > xCols( xComposer, UNO_QUERY_THROW );
212 xColumns.set( xCols->getColumns(), UNO_QUERY_THROW );
213 xColumnsIndexed.set( xColumns, UNO_QUERY_THROW );
215 catch( const SQLException& ) { }
217 SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
218 if ( !xColumns.is() || ( xColumnsIndexed->getCount() == 0 ) )
219 { // the QueryComposer could not parse it. Try a lean version.
220 xPreparedStatement.set( m_xConnection->prepareStatement( m_sCommand ), UNO_QUERY_THROW );
221 Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xPreparedStatement, UNO_QUERY_THROW );
222 Reference< XResultSetMetaData > xResultSetMeta( xResMetaDataSup->getMetaData() );
223 if ( !xResultSetMeta.is() )
225 ::rtl::OUString sError( DBA_RES( RID_STR_STATEMENT_WITHOUT_RESULT_SET ) );
226 ::dbtools::throwSQLException( sError, SQL_GENERAL_ERROR, *this );
229 Reference< XDatabaseMetaData > xDBMeta( m_xConnection->getMetaData(), UNO_QUERY_THROW );
230 ::vos::ORef< OSQLColumns > aParseColumns(
231 ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, xDBMeta ) );
232 xColumns = OPrivateColumns::createWithIntrinsicNames(
233 aParseColumns, xDBMeta->storesMixedCaseQuotedIdentifiers(), *this, m_aMutex );
234 if ( !xColumns.is() )
235 throw RuntimeException();
238 Sequence< ::rtl::OUString> aNames = xColumns->getElementNames();
239 const ::rtl::OUString* pBegin = aNames.getConstArray();
240 const ::rtl::OUString* pEnd = pBegin + aNames.getLength();
241 for ( ;pBegin != pEnd; ++pBegin)
243 Reference<XPropertySet> xSource(xColumns->getByName( *pBegin ),UNO_QUERY);
244 OTableColumn* pColumn = new OTableColumn( xSource );
245 Reference<XChild> xChild(*pColumn,UNO_QUERY);
246 if ( xChild.is() )
247 xChild->setParent(*this);
249 implAppendColumn( *pBegin, pColumn );
250 Reference<XPropertySet> xDest(*pColumn,UNO_QUERY);
251 if ( m_pColumnMediator.is() )
252 m_pColumnMediator->notifyElementCreated( *pBegin, xDest );
255 catch( const SQLContext& e )
257 if ( m_pWarnings )
258 m_pWarnings->appendWarning( e );
260 catch( const SQLWarning& e )
262 if ( m_pWarnings )
263 m_pWarnings->appendWarning( e );
265 catch( const SQLException& e )
267 if ( m_pWarnings )
268 m_pWarnings->appendWarning( e );
270 catch( const Exception& )
272 DBG_UNHANDLED_EXCEPTION();
276 // XServiceInfo
277 //--------------------------------------------------------------------------
278 IMPLEMENT_SERVICE_INFO3(OQuery, "com.sun.star.sdb.dbaccess.OQuery", SERVICE_SDB_DATASETTINGS, SERVICE_SDB_QUERY, SERVICE_SDB_QUERYDEFINITION)
280 // ::com::sun::star::beans::XPropertyChangeListener
281 //--------------------------------------------------------------------------
282 void SAL_CALL OQuery::propertyChange( const PropertyChangeEvent& _rSource ) throw(RuntimeException)
284 sal_Int32 nOwnHandle = -1;
286 MutexGuard aGuard(m_aMutex);
288 DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(),
289 "OQuery::propertyChange : where did this call come from ?");
291 if (m_eDoingCurrently == SETTING_PROPERTIES)
292 // we're setting the property ourself, so we will do the neccessary notifications later
293 return;
295 // forward this to our own member holding a copy of the property value
296 if (getArrayHelper()->hasPropertyByName(_rSource.PropertyName))
298 Property aOwnProp = getArrayHelper()->getPropertyByName(_rSource.PropertyName);
299 nOwnHandle = aOwnProp.Handle;
300 ODataSettings::setFastPropertyValue_NoBroadcast(nOwnHandle, _rSource.NewValue);
301 // don't use our own setFastPropertyValue_NoBroadcast, this would forward it to the CommandSettings,
302 // again
303 // and don't use the "real" setPropertyValue, this is to expensive and not sure to succeed
305 else
307 DBG_ERROR("OQuery::propertyChange : my CommandDefinition has more properties than I do !");
311 fire(&nOwnHandle, &_rSource.NewValue, &_rSource.OldValue, 1, sal_False);
314 //--------------------------------------------------------------------------
315 void SAL_CALL OQuery::disposing( const EventObject& _rSource ) throw (RuntimeException)
317 MutexGuard aGuard(m_aMutex);
319 (void)_rSource;
320 DBG_ASSERT(_rSource.Source.get() == Reference< XInterface >(m_xCommandDefinition, UNO_QUERY).get(),
321 "OQuery::disposing : where did this call come from ?");
323 m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this);
324 m_xCommandDefinition = NULL;
327 // XDataDescriptorFactory
328 //--------------------------------------------------------------------------
329 Reference< XPropertySet > SAL_CALL OQuery::createDataDescriptor( ) throw(RuntimeException)
331 return new OQueryDescriptor(*this);
334 // pseudo-XComponent
335 //--------------------------------------------------------------------------
336 void SAL_CALL OQuery::disposing()
338 MutexGuard aGuard(m_aMutex);
339 if (m_xCommandDefinition.is())
341 m_xCommandDefinition->removePropertyChangeListener(::rtl::OUString(), this);
342 m_xCommandDefinition = NULL;
344 disposeColumns();
346 m_pWarnings = NULL;
349 //--------------------------------------------------------------------------
350 void OQuery::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue ) throw (Exception)
352 ODataSettings::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
353 ::rtl::OUString sAggPropName;
354 sal_Int16 nAttr = 0;
355 if (getInfoHelper().fillPropertyMembersByHandle(&sAggPropName,&nAttr,_nHandle) &&
356 m_xCommandPropInfo.is() &&
357 m_xCommandPropInfo->hasPropertyByName(sAggPropName))
358 { // the base class holds the property values itself, but we have to forward this to our CommandDefinition
360 m_eDoingCurrently = SETTING_PROPERTIES;
361 OAutoActionReset(this);
362 m_xCommandDefinition->setPropertyValue(sAggPropName, _rValue);
364 if ( PROPERTY_ID_COMMAND == _nHandle )
365 // the columns are out of date if we are based on a new statement ....
366 // 90573 - 16.08.2001 - frank.schoenheit@sun.com
367 setColumnsOutOfDate();
371 //--------------------------------------------------------------------------
372 Reference< XPropertySetInfo > SAL_CALL OQuery::getPropertySetInfo( ) throw(RuntimeException)
374 return createPropertySetInfo( getInfoHelper() ) ;
377 //------------------------------------------------------------------------------
378 ::cppu::IPropertyArrayHelper& OQuery::getInfoHelper()
380 return *getArrayHelper();
383 //--------------------------------------------------------------------------
384 ::cppu::IPropertyArrayHelper* OQuery::createArrayHelper( ) const
386 Sequence< Property > aProps;
387 // our own props
388 describeProperties(aProps);
389 return new ::cppu::OPropertyArrayHelper(aProps);
391 // -----------------------------------------------------------------------------
392 OColumn* OQuery::createColumn(const ::rtl::OUString& /*_rName*/) const
394 return NULL;
396 // -----------------------------------------------------------------------------
397 void SAL_CALL OQuery::rename( const ::rtl::OUString& newName ) throw (SQLException, ElementExistException, RuntimeException)
399 MutexGuard aGuard(m_aMutex);
400 Reference<XRename> xRename(m_xCommandDefinition,UNO_QUERY);
401 OSL_ENSURE(xRename.is(),"No XRename interface!");
402 if(xRename.is())
403 xRename->rename(newName);
405 // -----------------------------------------------------------------------------
406 void OQuery::registerProperties()
408 // the properties which OCommandBase supplies (it has no own registration, as it's not derived from
409 // a OPropertyStateContainer)
410 registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND|PropertyAttribute::CONSTRAINED,
411 &m_sElementName, ::getCppuType(&m_sElementName));
413 registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND,
414 &m_sCommand, ::getCppuType(&m_sCommand));
416 registerProperty(PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND,
417 &m_bEscapeProcessing, ::getBooleanCppuType());
419 registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND,
420 &m_sUpdateTableName, ::getCppuType(&m_sUpdateTableName));
422 registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND,
423 &m_sUpdateSchemaName, ::getCppuType(&m_sUpdateSchemaName));
425 registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND,
426 &m_sUpdateCatalogName, ::getCppuType(&m_sUpdateCatalogName));
428 registerProperty(PROPERTY_LAYOUTINFORMATION, PROPERTY_ID_LAYOUTINFORMATION, PropertyAttribute::BOUND,
429 &m_aLayoutInformation, ::getCppuType(&m_aLayoutInformation));
432 // -----------------------------------------------------------------------------
433 ::rtl::OUString OQuery::determineContentType() const
435 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseQuery" ) );
438 // -----------------------------------------------------------------------------
439 //........................................................................
440 } // namespace dbaccess
441 //........................................................................