1*96de5490SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*96de5490SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*96de5490SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*96de5490SAndrew Rist  * distributed with this work for additional information
6*96de5490SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*96de5490SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*96de5490SAndrew Rist  * "License"); you may not use this file except in compliance
9*96de5490SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*96de5490SAndrew Rist  *
11*96de5490SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*96de5490SAndrew Rist  *
13*96de5490SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*96de5490SAndrew Rist  * software distributed under the License is distributed on an
15*96de5490SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*96de5490SAndrew Rist  * KIND, either express or implied.  See the License for the
17*96de5490SAndrew Rist  * specific language governing permissions and limitations
18*96de5490SAndrew Rist  * under the License.
19*96de5490SAndrew Rist  *
20*96de5490SAndrew Rist  *************************************************************/
21*96de5490SAndrew Rist 
22*96de5490SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_dbaccess.hxx"
26cdf0e10cSrcweir #include "dbu_reghelper.hxx"
27cdf0e10cSrcweir #include <sfx2/sfxsids.hrc>
28cdf0e10cSrcweir #include "dbu_rel.hrc"
29cdf0e10cSrcweir #include <vcl/svapp.hxx>
30cdf0e10cSrcweir #include "browserids.hxx"
31cdf0e10cSrcweir #include <comphelper/types.hxx>
32cdf0e10cSrcweir #include "dbustrings.hrc"
33cdf0e10cSrcweir #include <connectivity/dbtools.hxx>
34cdf0e10cSrcweir #include <com/sun/star/frame/FrameSearchFlag.hpp>
35cdf0e10cSrcweir #include <comphelper/extract.hxx>
36cdf0e10cSrcweir #include <com/sun/star/container/XChild.hpp>
37cdf0e10cSrcweir #include <com/sun/star/container/XNameContainer.hpp>
38cdf0e10cSrcweir #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
39cdf0e10cSrcweir #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
40cdf0e10cSrcweir #include <com/sun/star/sdbcx/KeyType.hpp>
41cdf0e10cSrcweir #include <com/sun/star/sdbcx/XDrop.hpp>
42cdf0e10cSrcweir #include <com/sun/star/sdbcx/XAlterTable.hpp>
43cdf0e10cSrcweir #include <com/sun/star/sdbcx/XAppend.hpp>
44cdf0e10cSrcweir #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
45cdf0e10cSrcweir #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
46cdf0e10cSrcweir #include <com/sun/star/sdb/SQLContext.hpp>
47cdf0e10cSrcweir #include <com/sun/star/sdbc/SQLWarning.hpp>
48cdf0e10cSrcweir #include <com/sun/star/sdbc/ColumnValue.hpp>
49cdf0e10cSrcweir #include <com/sun/star/sdbc/XRow.hpp>
50cdf0e10cSrcweir #include <connectivity/dbexception.hxx>
51cdf0e10cSrcweir #include <connectivity/dbmetadata.hxx>
52cdf0e10cSrcweir #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
53cdf0e10cSrcweir #include <comphelper/streamsection.hxx>
54cdf0e10cSrcweir #include <comphelper/basicio.hxx>
55cdf0e10cSrcweir #include <comphelper/seqstream.hxx>
56cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSource.hpp>
57cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSink.hpp>
58cdf0e10cSrcweir #include "sqlmessage.hxx"
59cdf0e10cSrcweir #include "RelationController.hxx"
60cdf0e10cSrcweir #include <vcl/msgbox.hxx>
61cdf0e10cSrcweir #include "TableWindowData.hxx"
62cdf0e10cSrcweir #include "dbustrings.hrc"
63cdf0e10cSrcweir #include "UITools.hxx"
64cdf0e10cSrcweir #include "RTableConnectionData.hxx"
65cdf0e10cSrcweir #include "RelationTableView.hxx"
66cdf0e10cSrcweir #include "RelationDesignView.hxx"
67cdf0e10cSrcweir #include <tools/debug.hxx>
68cdf0e10cSrcweir #include <tools/diagnose_ex.h>
69cdf0e10cSrcweir #include <vcl/waitobj.hxx>
70cdf0e10cSrcweir #include <osl/thread.hxx>
71cdf0e10cSrcweir #include <vos/mutex.hxx>
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
74cdf0e10cSrcweir #define MAX_THREADS 10
75cdf0e10cSrcweir 
createRegistryInfo_ORelationControl()76cdf0e10cSrcweir extern "C" void SAL_CALL createRegistryInfo_ORelationControl()
77cdf0e10cSrcweir {
78cdf0e10cSrcweir 	static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::ORelationController > aAutoRegistration;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir 
82cdf0e10cSrcweir using namespace ::com::sun::star::uno;
83cdf0e10cSrcweir using namespace ::com::sun::star::io;
84cdf0e10cSrcweir using namespace ::com::sun::star::beans;
85cdf0e10cSrcweir using namespace ::com::sun::star::frame;
86cdf0e10cSrcweir using namespace ::com::sun::star::util;
87cdf0e10cSrcweir using namespace ::com::sun::star::lang;
88cdf0e10cSrcweir using namespace ::com::sun::star::container;
89cdf0e10cSrcweir using namespace ::com::sun::star::sdbcx;
90cdf0e10cSrcweir using namespace ::com::sun::star::sdbc;
91cdf0e10cSrcweir using namespace ::com::sun::star::sdb;
92cdf0e10cSrcweir using namespace ::com::sun::star::ui::dialogs;
93cdf0e10cSrcweir using namespace ::com::sun::star::util;
94cdf0e10cSrcweir //	using namespace ::com::sun::star::sdbcx;
95cdf0e10cSrcweir //	using namespace ::connectivity;
96cdf0e10cSrcweir using namespace ::dbtools;
97cdf0e10cSrcweir using namespace ::dbaui;
98cdf0e10cSrcweir using namespace ::comphelper;
99cdf0e10cSrcweir using namespace ::osl;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir //------------------------------------------------------------------------------
getImplementationName()102cdf0e10cSrcweir ::rtl::OUString SAL_CALL ORelationController::getImplementationName() throw( RuntimeException )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir 	return getImplementationName_Static();
105cdf0e10cSrcweir }
106cdf0e10cSrcweir 
107cdf0e10cSrcweir //------------------------------------------------------------------------------
getImplementationName_Static()108cdf0e10cSrcweir ::rtl::OUString ORelationController::getImplementationName_Static() throw( RuntimeException )
109cdf0e10cSrcweir {
110cdf0e10cSrcweir 	return ::rtl::OUString::createFromAscii("org.openoffice.comp.dbu.ORelationDesign");
111cdf0e10cSrcweir }
112cdf0e10cSrcweir //------------------------------------------------------------------------------
getSupportedServiceNames_Static(void)113cdf0e10cSrcweir Sequence< ::rtl::OUString> ORelationController::getSupportedServiceNames_Static(void) throw( RuntimeException )
114cdf0e10cSrcweir {
115cdf0e10cSrcweir 	Sequence< ::rtl::OUString> aSupported(1);
116cdf0e10cSrcweir 	aSupported.getArray()[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.RelationDesign");
117cdf0e10cSrcweir 	return aSupported;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir //-------------------------------------------------------------------------
getSupportedServiceNames()120cdf0e10cSrcweir Sequence< ::rtl::OUString> SAL_CALL ORelationController::getSupportedServiceNames() throw(RuntimeException)
121cdf0e10cSrcweir {
122cdf0e10cSrcweir 	return getSupportedServiceNames_Static();
123cdf0e10cSrcweir }
124cdf0e10cSrcweir // -------------------------------------------------------------------------
Create(const Reference<XMultiServiceFactory> & _rxFactory)125cdf0e10cSrcweir Reference< XInterface > SAL_CALL ORelationController::Create(const Reference<XMultiServiceFactory >& _rxFactory)
126cdf0e10cSrcweir {
127cdf0e10cSrcweir 	return *(new ORelationController(_rxFactory));
128cdf0e10cSrcweir }
129cdf0e10cSrcweir DBG_NAME(ORelationController);
130cdf0e10cSrcweir // -----------------------------------------------------------------------------
ORelationController(const Reference<XMultiServiceFactory> & _rM)131cdf0e10cSrcweir ORelationController::ORelationController(const Reference< XMultiServiceFactory >& _rM)
132cdf0e10cSrcweir 	: OJoinController(_rM)
133cdf0e10cSrcweir     ,m_nThreadEvent(0)
134cdf0e10cSrcweir 	,m_bRelationsPossible(sal_True)
135cdf0e10cSrcweir {
136cdf0e10cSrcweir 	DBG_CTOR(ORelationController,NULL);
137cdf0e10cSrcweir 	InvalidateAll();
138cdf0e10cSrcweir }
139cdf0e10cSrcweir // -----------------------------------------------------------------------------
~ORelationController()140cdf0e10cSrcweir ORelationController::~ORelationController()
141cdf0e10cSrcweir {
142cdf0e10cSrcweir 	DBG_DTOR(ORelationController,NULL);
143cdf0e10cSrcweir }
144cdf0e10cSrcweir // -----------------------------------------------------------------------------
GetState(sal_uInt16 _nId) const145cdf0e10cSrcweir FeatureState ORelationController::GetState(sal_uInt16 _nId) const
146cdf0e10cSrcweir {
147cdf0e10cSrcweir 	FeatureState aReturn;
148cdf0e10cSrcweir 	aReturn.bEnabled = m_bRelationsPossible;
149cdf0e10cSrcweir 	switch (_nId)
150cdf0e10cSrcweir 	{
151cdf0e10cSrcweir 		case SID_RELATION_ADD_RELATION:
152cdf0e10cSrcweir 			aReturn.bEnabled = !m_vTableData.empty() && isConnected() && isEditable();
153cdf0e10cSrcweir 			aReturn.bChecked = false;
154cdf0e10cSrcweir 			break;
155cdf0e10cSrcweir 		case ID_BROWSER_SAVEDOC:
156cdf0e10cSrcweir 			aReturn.bEnabled = haveDataSource() && impl_isModified();
157cdf0e10cSrcweir 			break;
158cdf0e10cSrcweir 		default:
159cdf0e10cSrcweir 			aReturn = OJoinController::GetState(_nId);
160cdf0e10cSrcweir 			break;
161cdf0e10cSrcweir 	}
162cdf0e10cSrcweir 	return aReturn;
163cdf0e10cSrcweir }
164cdf0e10cSrcweir // -----------------------------------------------------------------------------
Execute(sal_uInt16 _nId,const Sequence<PropertyValue> & aArgs)165cdf0e10cSrcweir void ORelationController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
166cdf0e10cSrcweir {
167cdf0e10cSrcweir 	switch(_nId)
168cdf0e10cSrcweir 	{
169cdf0e10cSrcweir 		case ID_BROWSER_SAVEDOC:
170cdf0e10cSrcweir 			{
171cdf0e10cSrcweir 				OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
172cdf0e10cSrcweir 				if(!::dbaui::checkDataSourceAvailable(::comphelper::getString(getDataSource()->getPropertyValue(PROPERTY_NAME)),getORB()))
173cdf0e10cSrcweir 				{
174cdf0e10cSrcweir 					String aMessage(ModuleRes(STR_DATASOURCE_DELETED));
175cdf0e10cSrcweir 					OSQLWarningBox( getView(), aMessage ).Execute();
176cdf0e10cSrcweir 				}
177cdf0e10cSrcweir 				else
178cdf0e10cSrcweir 				{
179cdf0e10cSrcweir 					// now we save the layout information
180cdf0e10cSrcweir 					//  create the output stream
181cdf0e10cSrcweir 					try
182cdf0e10cSrcweir 					{
183cdf0e10cSrcweir 						if ( haveDataSource() && getDataSource()->getPropertySetInfo()->hasPropertyByName(PROPERTY_LAYOUTINFORMATION) )
184cdf0e10cSrcweir 						{
185cdf0e10cSrcweir                             ::comphelper::NamedValueCollection aWindowsData;
186cdf0e10cSrcweir 							saveTableWindows( aWindowsData );
187cdf0e10cSrcweir 							getDataSource()->setPropertyValue( PROPERTY_LAYOUTINFORMATION, makeAny( aWindowsData.getPropertyValues() ) );
188cdf0e10cSrcweir 							setModified(sal_False);
189cdf0e10cSrcweir 						}
190cdf0e10cSrcweir 					}
191cdf0e10cSrcweir 					catch ( const Exception& )
192cdf0e10cSrcweir 					{
193cdf0e10cSrcweir                         DBG_UNHANDLED_EXCEPTION();
194cdf0e10cSrcweir 					}
195cdf0e10cSrcweir 				}
196cdf0e10cSrcweir 			}
197cdf0e10cSrcweir 			break;
198cdf0e10cSrcweir 		case SID_RELATION_ADD_RELATION:
199cdf0e10cSrcweir 			static_cast<ORelationTableView*>(static_cast<ORelationDesignView*>( getView() )->getTableView())->AddNewRelation();
200cdf0e10cSrcweir 			break;
201cdf0e10cSrcweir 		default:
202cdf0e10cSrcweir 			OJoinController::Execute(_nId,aArgs);
203cdf0e10cSrcweir 			return;
204cdf0e10cSrcweir 	}
205cdf0e10cSrcweir 	InvalidateFeature(_nId);
206cdf0e10cSrcweir }
207cdf0e10cSrcweir // -----------------------------------------------------------------------------
impl_initialize()208cdf0e10cSrcweir void ORelationController::impl_initialize()
209cdf0e10cSrcweir {
210cdf0e10cSrcweir 	OJoinController::impl_initialize();
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     if( !getSdbMetaData().supportsRelations() )
213cdf0e10cSrcweir 	{// check if this database supports relations
214cdf0e10cSrcweir 
215cdf0e10cSrcweir 		setEditable(sal_False);
216cdf0e10cSrcweir 		m_bRelationsPossible	= sal_False;
217cdf0e10cSrcweir 		{
218cdf0e10cSrcweir 			String sTitle(ModuleRes(STR_RELATIONDESIGN));
219cdf0e10cSrcweir 			sTitle.Erase(0,3);
220cdf0e10cSrcweir 			OSQLMessageBox aDlg(NULL,sTitle,ModuleRes(STR_RELATIONDESIGN_NOT_AVAILABLE));
221cdf0e10cSrcweir 			aDlg.Execute();
222cdf0e10cSrcweir 		}
223cdf0e10cSrcweir 		disconnect();
224cdf0e10cSrcweir 		throw SQLException();
225cdf0e10cSrcweir 	}
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 	if(!m_bRelationsPossible)
228cdf0e10cSrcweir 		InvalidateAll();
229cdf0e10cSrcweir 
230cdf0e10cSrcweir 	// we need a datasource
231cdf0e10cSrcweir 	OSL_ENSURE(haveDataSource(),"ORelationController::initialize: need a datasource!");
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 	Reference<XTablesSupplier> xSup(getConnection(),UNO_QUERY);
234cdf0e10cSrcweir 	OSL_ENSURE(xSup.is(),"Connection isn't a XTablesSupplier!");
235cdf0e10cSrcweir 	if(xSup.is())
236cdf0e10cSrcweir 		m_xTables = xSup->getTables();
237cdf0e10cSrcweir 	// load the layoutInformation
238cdf0e10cSrcweir 	loadLayoutInformation();
239cdf0e10cSrcweir 	try
240cdf0e10cSrcweir 	{
241cdf0e10cSrcweir 		loadData();
242cdf0e10cSrcweir         if ( !m_nThreadEvent )
243cdf0e10cSrcweir             Application::PostUserEvent(LINK(this, ORelationController, OnThreadFinished));
244cdf0e10cSrcweir 	}
245cdf0e10cSrcweir     catch( const Exception& )
246cdf0e10cSrcweir     {
247cdf0e10cSrcweir         DBG_UNHANDLED_EXCEPTION();
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir }
251cdf0e10cSrcweir // -----------------------------------------------------------------------------
getPrivateTitle() const252cdf0e10cSrcweir ::rtl::OUString ORelationController::getPrivateTitle( ) const
253cdf0e10cSrcweir {
254cdf0e10cSrcweir     ::rtl::OUString sName = getDataSourceName();
255cdf0e10cSrcweir 	return ::dbaui::getStrippedDatabaseName(getDataSource(),sName);
256cdf0e10cSrcweir }
257cdf0e10cSrcweir // -----------------------------------------------------------------------------
Construct(Window * pParent)258cdf0e10cSrcweir sal_Bool ORelationController::Construct(Window* pParent)
259cdf0e10cSrcweir {
260cdf0e10cSrcweir 	setView( * new ORelationDesignView( pParent, *this, getORB() ) );
261cdf0e10cSrcweir 	OJoinController::Construct(pParent);
262cdf0e10cSrcweir 	return sal_True;
263cdf0e10cSrcweir }
264cdf0e10cSrcweir // -----------------------------------------------------------------------------
saveModified()265cdf0e10cSrcweir short ORelationController::saveModified()
266cdf0e10cSrcweir {
267cdf0e10cSrcweir 	short nSaved = RET_YES;
268cdf0e10cSrcweir 	if(haveDataSource() && isModified())
269cdf0e10cSrcweir 	{
270cdf0e10cSrcweir 		QueryBox aQry(getView(), ModuleRes(RELATION_DESIGN_SAVEMODIFIED));
271cdf0e10cSrcweir 		nSaved = aQry.Execute();
272cdf0e10cSrcweir 		if(nSaved == RET_YES)
273cdf0e10cSrcweir 			Execute(ID_BROWSER_SAVEDOC,Sequence<PropertyValue>());
274cdf0e10cSrcweir 	}
275cdf0e10cSrcweir 	return nSaved;
276cdf0e10cSrcweir }
277cdf0e10cSrcweir // -----------------------------------------------------------------------------
describeSupportedFeatures()278cdf0e10cSrcweir void ORelationController::describeSupportedFeatures()
279cdf0e10cSrcweir {
280cdf0e10cSrcweir 	OJoinController::describeSupportedFeatures();
281cdf0e10cSrcweir     implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT );
282cdf0e10cSrcweir }
283cdf0e10cSrcweir namespace
284cdf0e10cSrcweir {
285cdf0e10cSrcweir     class RelationLoader : public ::osl::Thread
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         DECLARE_STL_MAP(::rtl::OUString,::boost::shared_ptr<OTableWindowData>,::comphelper::UStringMixLess,TTableDataHelper);
288cdf0e10cSrcweir         TTableDataHelper                    m_aTableData;
289cdf0e10cSrcweir         TTableConnectionData                m_vTableConnectionData;
290cdf0e10cSrcweir         const Sequence< ::rtl::OUString>    m_aTableList;
291cdf0e10cSrcweir         ORelationController*                m_pParent;
292cdf0e10cSrcweir         const Reference< XDatabaseMetaData> m_xMetaData;
293cdf0e10cSrcweir         const Reference< XNameAccess >	    m_xTables;
294cdf0e10cSrcweir         const sal_Int32                     m_nStartIndex;
295cdf0e10cSrcweir         const sal_Int32                     m_nEndIndex;
296cdf0e10cSrcweir 
297cdf0e10cSrcweir     public:
RelationLoader(ORelationController * _pParent,const Reference<XDatabaseMetaData> & _xMetaData,const Reference<XNameAccess> & _xTables,const Sequence<::rtl::OUString> & _aTableList,const sal_Int32 _nStartIndex,const sal_Int32 _nEndIndex)298cdf0e10cSrcweir 	    RelationLoader(ORelationController* _pParent
299cdf0e10cSrcweir                         ,const Reference< XDatabaseMetaData>& _xMetaData
300cdf0e10cSrcweir                         ,const Reference< XNameAccess >& _xTables
301cdf0e10cSrcweir                         ,const Sequence< ::rtl::OUString>& _aTableList
302cdf0e10cSrcweir                         ,const sal_Int32 _nStartIndex
303cdf0e10cSrcweir                         ,const sal_Int32 _nEndIndex)
304cdf0e10cSrcweir             :m_aTableData(_xMetaData.is() && _xMetaData->supportsMixedCaseQuotedIdentifiers())
305cdf0e10cSrcweir             ,m_aTableList(_aTableList)
306cdf0e10cSrcweir             ,m_pParent(_pParent)
307cdf0e10cSrcweir             ,m_xMetaData(_xMetaData)
308cdf0e10cSrcweir             ,m_xTables(_xTables)
309cdf0e10cSrcweir             ,m_nStartIndex(_nStartIndex)
310cdf0e10cSrcweir             ,m_nEndIndex(_nEndIndex)
311cdf0e10cSrcweir 	    {
312cdf0e10cSrcweir         }
313cdf0e10cSrcweir 
314cdf0e10cSrcweir         /// Working method which should be overridden.
315cdf0e10cSrcweir 	    virtual void SAL_CALL run();
316cdf0e10cSrcweir         virtual void SAL_CALL onTerminated();
317cdf0e10cSrcweir     protected:
~RelationLoader()318cdf0e10cSrcweir         virtual ~RelationLoader(){}
319cdf0e10cSrcweir 
320cdf0e10cSrcweir         void loadTableData(const Any& _aTable);
321cdf0e10cSrcweir     };
322cdf0e10cSrcweir 
run()323cdf0e10cSrcweir     void SAL_CALL RelationLoader::run()
324cdf0e10cSrcweir     {
325cdf0e10cSrcweir         const ::rtl::OUString* pIter = m_aTableList.getConstArray() + m_nStartIndex;
326cdf0e10cSrcweir         for(sal_Int32 i = m_nStartIndex; i < m_nEndIndex;++i,++pIter)
327cdf0e10cSrcweir         {
328cdf0e10cSrcweir             ::rtl::OUString sCatalog,sSchema,sTable;
329cdf0e10cSrcweir 		    ::dbtools::qualifiedNameComponents(m_xMetaData,
330cdf0e10cSrcweir 											    *pIter,
331cdf0e10cSrcweir 											    sCatalog,
332cdf0e10cSrcweir 											    sSchema,
333cdf0e10cSrcweir 											    sTable,
334cdf0e10cSrcweir 											    ::dbtools::eInDataManipulation);
335cdf0e10cSrcweir 		    Any aCatalog;
336cdf0e10cSrcweir 		    if ( sCatalog.getLength() )
337cdf0e10cSrcweir 			    aCatalog <<= sCatalog;
338cdf0e10cSrcweir 
339cdf0e10cSrcweir             try
340cdf0e10cSrcweir             {
341cdf0e10cSrcweir 		        Reference< XResultSet > xResult = m_xMetaData->getImportedKeys(aCatalog, sSchema,sTable);
342cdf0e10cSrcweir 		        if ( xResult.is() && xResult->next() )
343cdf0e10cSrcweir                 {
344cdf0e10cSrcweir                     ::comphelper::disposeComponent(xResult);
345cdf0e10cSrcweir 			        loadTableData(m_xTables->getByName(*pIter));
346cdf0e10cSrcweir                 } // if ( xResult.is() && xResult->next() )
347cdf0e10cSrcweir             }
348cdf0e10cSrcweir             catch( const Exception& )
349cdf0e10cSrcweir             {
350cdf0e10cSrcweir                 DBG_UNHANDLED_EXCEPTION();
351cdf0e10cSrcweir             }
352cdf0e10cSrcweir         }
353cdf0e10cSrcweir     }
onTerminated()354cdf0e10cSrcweir     void SAL_CALL RelationLoader::onTerminated()
355cdf0e10cSrcweir     {
356cdf0e10cSrcweir         m_pParent->mergeData(m_vTableConnectionData);
357cdf0e10cSrcweir         delete this;
358cdf0e10cSrcweir     }
359cdf0e10cSrcweir 
loadTableData(const Any & _aTable)360cdf0e10cSrcweir     void RelationLoader::loadTableData(const Any& _aTable)
361cdf0e10cSrcweir     {
362cdf0e10cSrcweir         Reference<XPropertySet> xTableProp(_aTable,UNO_QUERY);
363cdf0e10cSrcweir         const ::rtl::OUString sSourceName = ::dbtools::composeTableName( m_xMetaData, xTableProp, ::dbtools::eInTableDefinitions, false, false, false );
364cdf0e10cSrcweir         TTableDataHelper::iterator aFind = m_aTableData.find(sSourceName);
365cdf0e10cSrcweir         bool bNotFound = true, bAdded = false;
366cdf0e10cSrcweir         if ( aFind == m_aTableData.end() )
367cdf0e10cSrcweir         {
368cdf0e10cSrcweir             aFind = m_aTableData.insert(TTableDataHelper::value_type(sSourceName,::boost::shared_ptr<OTableWindowData>(new OTableWindowData(xTableProp,sSourceName, sSourceName)))).first;
369cdf0e10cSrcweir 		    aFind->second->ShowAll(sal_False);
370cdf0e10cSrcweir             bAdded = true;
371cdf0e10cSrcweir         }
372cdf0e10cSrcweir         TTableWindowData::value_type pReferencingTable = aFind->second;
373cdf0e10cSrcweir 	    Reference<XIndexAccess> xKeys = pReferencingTable->getKeys();
374cdf0e10cSrcweir         const Reference<XKeysSupplier> xKeySup(xTableProp,UNO_QUERY);
375cdf0e10cSrcweir 
376cdf0e10cSrcweir 	    if ( !xKeys.is() && xKeySup.is() )
377cdf0e10cSrcweir 	    {
378cdf0e10cSrcweir 		    xKeys = xKeySup->getKeys();
379cdf0e10cSrcweir         }
380cdf0e10cSrcweir 
381cdf0e10cSrcweir 	    if ( xKeys.is() )
382cdf0e10cSrcweir 	    {
383cdf0e10cSrcweir 		    Reference<XPropertySet> xKey;
384cdf0e10cSrcweir             const sal_Int32 nCount = xKeys->getCount();
385cdf0e10cSrcweir 		    for(sal_Int32 i = 0 ; i < nCount ; ++i)
386cdf0e10cSrcweir 		    {
387cdf0e10cSrcweir 			    xKeys->getByIndex(i) >>= xKey;
388cdf0e10cSrcweir 			    sal_Int32 nKeyType = 0;
389cdf0e10cSrcweir 			    xKey->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
390cdf0e10cSrcweir 			    if ( KeyType::FOREIGN == nKeyType )
391cdf0e10cSrcweir 			    {
392cdf0e10cSrcweir                     bNotFound = false;
393cdf0e10cSrcweir 				    ::rtl::OUString sReferencedTable;
394cdf0e10cSrcweir 				    xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
395cdf0e10cSrcweir 				    //////////////////////////////////////////////////////////////////////
396cdf0e10cSrcweir 				    // insert windows
397cdf0e10cSrcweir                     TTableDataHelper::iterator aRefFind = m_aTableData.find(sReferencedTable);
398cdf0e10cSrcweir                     if ( aRefFind == m_aTableData.end() )
399cdf0e10cSrcweir                     {
400cdf0e10cSrcweir                         if ( m_xTables->hasByName(sReferencedTable) )
401cdf0e10cSrcweir                         {
402cdf0e10cSrcweir                             Reference<XPropertySet>  xReferencedTable(m_xTables->getByName(sReferencedTable),UNO_QUERY);
403cdf0e10cSrcweir 					        aRefFind = m_aTableData.insert(TTableDataHelper::value_type(sReferencedTable,::boost::shared_ptr<OTableWindowData>(new OTableWindowData(xReferencedTable,sReferencedTable, sReferencedTable)))).first;
404cdf0e10cSrcweir 		                    aRefFind->second->ShowAll(sal_False);
405cdf0e10cSrcweir                         }
406cdf0e10cSrcweir                         else
407cdf0e10cSrcweir                             continue; // table name could not be found so we do not show this table releation
408cdf0e10cSrcweir                     } // if ( aFind == m_aTableData.end() )
409cdf0e10cSrcweir                     TTableWindowData::value_type pReferencedTable = aRefFind->second;
410cdf0e10cSrcweir 
411cdf0e10cSrcweir 				    ::rtl::OUString sKeyName;
412cdf0e10cSrcweir 				    xKey->getPropertyValue(PROPERTY_NAME) >>= sKeyName;
413cdf0e10cSrcweir 				    //////////////////////////////////////////////////////////////////////
414cdf0e10cSrcweir 				    // insert connection
415cdf0e10cSrcweir                     ORelationTableConnectionData* pTabConnData = new ORelationTableConnectionData( pReferencingTable, pReferencedTable, sKeyName );
416cdf0e10cSrcweir                     m_vTableConnectionData.push_back(TTableConnectionData::value_type(pTabConnData));
417cdf0e10cSrcweir 				    //////////////////////////////////////////////////////////////////////
418cdf0e10cSrcweir 				    // insert columns
419cdf0e10cSrcweir 				    const Reference<XColumnsSupplier> xColsSup(xKey,UNO_QUERY);
420cdf0e10cSrcweir 				    OSL_ENSURE(xColsSup.is(),"Key is no XColumnsSupplier!");
421cdf0e10cSrcweir 				    const Reference<XNameAccess> xColumns		= xColsSup->getColumns();
422cdf0e10cSrcweir 				    const Sequence< ::rtl::OUString> aNames	= xColumns->getElementNames();
423cdf0e10cSrcweir 				    const ::rtl::OUString* pIter	= aNames.getConstArray();
424cdf0e10cSrcweir 				    const ::rtl::OUString* pEnd		= pIter + aNames.getLength();
425cdf0e10cSrcweir 				    ::rtl::OUString sColumnName,sRelatedName;
426cdf0e10cSrcweir 				    for(sal_uInt16 j=0;pIter != pEnd;++pIter,++j)
427cdf0e10cSrcweir 				    {
428cdf0e10cSrcweir 					    const Reference<XPropertySet> xPropSet(xColumns->getByName(*pIter),UNO_QUERY);
429cdf0e10cSrcweir 					    OSL_ENSURE(xPropSet.is(),"Invalid column found in KeyColumns!");
430cdf0e10cSrcweir                         if ( xPropSet.is() )
431cdf0e10cSrcweir                         {
432cdf0e10cSrcweir 					        xPropSet->getPropertyValue(PROPERTY_NAME)			>>= sColumnName;
433cdf0e10cSrcweir 					        xPropSet->getPropertyValue(PROPERTY_RELATEDCOLUMN)	>>= sRelatedName;
434cdf0e10cSrcweir                         }
435cdf0e10cSrcweir 					    pTabConnData->SetConnLine( j, sColumnName, sRelatedName );
436cdf0e10cSrcweir 				    }
437cdf0e10cSrcweir 				    //////////////////////////////////////////////////////////////////////
438cdf0e10cSrcweir 				    // Update/Del-Flags setzen
439cdf0e10cSrcweir 				    sal_Int32	nUpdateRule = 0;
440cdf0e10cSrcweir 				    sal_Int32	nDeleteRule = 0;
441cdf0e10cSrcweir 				    xKey->getPropertyValue(PROPERTY_UPDATERULE) >>= nUpdateRule;
442cdf0e10cSrcweir 				    xKey->getPropertyValue(PROPERTY_DELETERULE) >>= nDeleteRule;
443cdf0e10cSrcweir 
444cdf0e10cSrcweir 				    pTabConnData->SetUpdateRules( nUpdateRule );
445cdf0e10cSrcweir 				    pTabConnData->SetDeleteRules( nDeleteRule );
446cdf0e10cSrcweir 
447cdf0e10cSrcweir 				    //////////////////////////////////////////////////////////////////////
448cdf0e10cSrcweir 				    // Kardinalitaet setzen
449cdf0e10cSrcweir 				    pTabConnData->SetCardinality();
450cdf0e10cSrcweir 			    }
451cdf0e10cSrcweir 		    }
452cdf0e10cSrcweir 	    } // if ( xKeys.is() )
453cdf0e10cSrcweir     }
454cdf0e10cSrcweir }
455cdf0e10cSrcweir 
mergeData(const TTableConnectionData & _aConnectionData)456cdf0e10cSrcweir void ORelationController::mergeData(const TTableConnectionData& _aConnectionData)
457cdf0e10cSrcweir {
458cdf0e10cSrcweir     ::osl::MutexGuard aGuard( getMutex() );
459cdf0e10cSrcweir 
460cdf0e10cSrcweir     ::std::copy( _aConnectionData.begin(), _aConnectionData.end(), ::std::back_inserter( m_vTableConnectionData ));
461cdf0e10cSrcweir     //const Reference< XDatabaseMetaData> xMetaData = getConnection()->getMetaData();
462cdf0e10cSrcweir     const sal_Bool bCase = sal_True;//xMetaData.is() && xMetaData->supportsMixedCaseQuotedIdentifiers();
463cdf0e10cSrcweir     // here we are finished, so we can collect the table from connection data
464cdf0e10cSrcweir     TTableConnectionData::iterator aConnDataIter = m_vTableConnectionData.begin();
465cdf0e10cSrcweir     TTableConnectionData::iterator aConnDataEnd = m_vTableConnectionData.end();
466cdf0e10cSrcweir     for(;aConnDataIter != aConnDataEnd;++aConnDataIter)
467cdf0e10cSrcweir     {
468cdf0e10cSrcweir         if ( !existsTable((*aConnDataIter)->getReferencingTable()->GetComposedName(),bCase) )
469cdf0e10cSrcweir         {
470cdf0e10cSrcweir             m_vTableData.push_back((*aConnDataIter)->getReferencingTable());
471cdf0e10cSrcweir         }
472cdf0e10cSrcweir         if ( !existsTable((*aConnDataIter)->getReferencedTable()->GetComposedName(),bCase) )
473cdf0e10cSrcweir         {
474cdf0e10cSrcweir             m_vTableData.push_back((*aConnDataIter)->getReferencedTable());
475cdf0e10cSrcweir         }
476cdf0e10cSrcweir     } // for(;aConnDataIter != aConnDataEnd;++aConnDataIter)
477cdf0e10cSrcweir     if ( m_nThreadEvent )
478cdf0e10cSrcweir     {
479cdf0e10cSrcweir         --m_nThreadEvent;
480cdf0e10cSrcweir         if ( !m_nThreadEvent )
481cdf0e10cSrcweir             Application::PostUserEvent(LINK(this, ORelationController, OnThreadFinished));
482cdf0e10cSrcweir     }
483cdf0e10cSrcweir }
484cdf0e10cSrcweir // -----------------------------------------------------------------------------
485cdf0e10cSrcweir IMPL_LINK( ORelationController, OnThreadFinished, void*, /*NOTINTERESTEDIN*/ )
486cdf0e10cSrcweir {
487cdf0e10cSrcweir     vos::OGuard aSolarGuard( Application::GetSolarMutex() );
488cdf0e10cSrcweir     ::osl::MutexGuard aGuard( getMutex() );
489cdf0e10cSrcweir     try
490cdf0e10cSrcweir 	{
491cdf0e10cSrcweir         getView()->initialize();	// show the windows and fill with our informations
492cdf0e10cSrcweir 	    getView()->Invalidate(INVALIDATE_NOERASE);
493cdf0e10cSrcweir         ClearUndoManager();
494cdf0e10cSrcweir 	    setModified(sal_False);		// and we are not modified yet
495cdf0e10cSrcweir 
496cdf0e10cSrcweir 	    if(m_vTableData.empty())
497cdf0e10cSrcweir 		    Execute(ID_BROWSER_ADDTABLE,Sequence<PropertyValue>());
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir     catch( const Exception& )
500cdf0e10cSrcweir     {
501cdf0e10cSrcweir         DBG_UNHANDLED_EXCEPTION();
502cdf0e10cSrcweir     }
503cdf0e10cSrcweir     m_pWaitObject.reset();
504cdf0e10cSrcweir     return 0L;
505cdf0e10cSrcweir }
506cdf0e10cSrcweir // -----------------------------------------------------------------------------
loadData()507cdf0e10cSrcweir void ORelationController::loadData()
508cdf0e10cSrcweir {
509cdf0e10cSrcweir 	m_pWaitObject.reset( new WaitObject(getView()) );
510cdf0e10cSrcweir 	try
511cdf0e10cSrcweir 	{
512cdf0e10cSrcweir 		if ( !m_xTables.is() )
513cdf0e10cSrcweir 			return;
514cdf0e10cSrcweir         DatabaseMetaData aMeta(getConnection());
515cdf0e10cSrcweir 	    // this may take some time
516cdf0e10cSrcweir 	    const Reference< XDatabaseMetaData> xMetaData = getConnection()->getMetaData();
517cdf0e10cSrcweir 	    const Sequence< ::rtl::OUString> aNames = m_xTables->getElementNames();
518cdf0e10cSrcweir         const sal_Int32 nCount = aNames.getLength();
519cdf0e10cSrcweir         if ( aMeta.supportsThreads() )
520cdf0e10cSrcweir         {
521cdf0e10cSrcweir 		    const sal_Int32 nMaxElements = (nCount / MAX_THREADS) +1;
522cdf0e10cSrcweir             sal_Int32 nStart = 0,nEnd = ::std::min(nMaxElements,nCount);
523cdf0e10cSrcweir 		    while(nStart != nEnd)
524cdf0e10cSrcweir 		    {
525cdf0e10cSrcweir                 ++m_nThreadEvent;
526cdf0e10cSrcweir                 RelationLoader* pThread = new RelationLoader(this,xMetaData,m_xTables,aNames,nStart,nEnd);
527cdf0e10cSrcweir                 pThread->createSuspended();
528cdf0e10cSrcweir                 pThread->setPriority(osl_Thread_PriorityBelowNormal);
529cdf0e10cSrcweir                 pThread->resume();
530cdf0e10cSrcweir                 nStart = nEnd;
531cdf0e10cSrcweir                 nEnd += nMaxElements;
532cdf0e10cSrcweir                 nEnd = ::std::min(nEnd,nCount);
533cdf0e10cSrcweir             } // for(;pIter != pEnd;++pIter)
534cdf0e10cSrcweir         } // if ( aMeta.supportsThreads() )
535cdf0e10cSrcweir         else
536cdf0e10cSrcweir         {
537cdf0e10cSrcweir             RelationLoader* pThread = new RelationLoader(this,xMetaData,m_xTables,aNames,0,nCount);
538cdf0e10cSrcweir             pThread->run();
539cdf0e10cSrcweir             pThread->onTerminated();
540cdf0e10cSrcweir         }
541cdf0e10cSrcweir 	}
542cdf0e10cSrcweir 	catch(SQLException& e)
543cdf0e10cSrcweir 	{
544cdf0e10cSrcweir 		showError(SQLExceptionInfo(e));
545cdf0e10cSrcweir 	}
546cdf0e10cSrcweir 	catch(const Exception&)
547cdf0e10cSrcweir 	{
548cdf0e10cSrcweir         DBG_UNHANDLED_EXCEPTION();
549cdf0e10cSrcweir 	}
550cdf0e10cSrcweir }
551cdf0e10cSrcweir // -----------------------------------------------------------------------------
existsTable(const::rtl::OUString & _rComposedTableName,sal_Bool _bCase) const552cdf0e10cSrcweir TTableWindowData::value_type ORelationController::existsTable(const ::rtl::OUString& _rComposedTableName,sal_Bool _bCase)  const
553cdf0e10cSrcweir {
554cdf0e10cSrcweir 	::comphelper::UStringMixEqual bCase(_bCase);
555cdf0e10cSrcweir 	TTableWindowData::const_iterator aIter = m_vTableData.begin();
556cdf0e10cSrcweir     TTableWindowData::const_iterator aEnd = m_vTableData.end();
557cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
558cdf0e10cSrcweir 	{
559cdf0e10cSrcweir 		if(bCase((*aIter)->GetComposedName(),_rComposedTableName))
560cdf0e10cSrcweir 			break;
561cdf0e10cSrcweir 	}
562cdf0e10cSrcweir     return ( aIter != aEnd) ? *aIter : TTableWindowData::value_type();
563cdf0e10cSrcweir }
564cdf0e10cSrcweir // -----------------------------------------------------------------------------
loadLayoutInformation()565cdf0e10cSrcweir void ORelationController::loadLayoutInformation()
566cdf0e10cSrcweir {
567cdf0e10cSrcweir 	try
568cdf0e10cSrcweir 	{
569cdf0e10cSrcweir 		OSL_ENSURE(haveDataSource(),"We need a datasource from our connection!");
570cdf0e10cSrcweir 		if ( haveDataSource() )
571cdf0e10cSrcweir 		{
572cdf0e10cSrcweir 			if ( getDataSource()->getPropertySetInfo()->hasPropertyByName(PROPERTY_LAYOUTINFORMATION) )
573cdf0e10cSrcweir 			{
574cdf0e10cSrcweir 				Sequence<PropertyValue> aWindows;
575cdf0e10cSrcweir 				getDataSource()->getPropertyValue(PROPERTY_LAYOUTINFORMATION) >>= aWindows;
576cdf0e10cSrcweir 				loadTableWindows(aWindows);
577cdf0e10cSrcweir 			}
578cdf0e10cSrcweir 		}
579cdf0e10cSrcweir 	}
580cdf0e10cSrcweir 	catch(Exception&)
581cdf0e10cSrcweir 	{
582cdf0e10cSrcweir 	}
583cdf0e10cSrcweir }
584cdf0e10cSrcweir // -----------------------------------------------------------------------------
reset()585cdf0e10cSrcweir void ORelationController::reset()
586cdf0e10cSrcweir {
587cdf0e10cSrcweir 	loadLayoutInformation();
588cdf0e10cSrcweir 	ODataView* pView = getView();
589cdf0e10cSrcweir 	OSL_ENSURE(pView,"No current view!");
590cdf0e10cSrcweir 	if(pView)
591cdf0e10cSrcweir 	{
592cdf0e10cSrcweir 		pView->initialize();
593cdf0e10cSrcweir 		pView->Invalidate(INVALIDATE_NOERASE);
594cdf0e10cSrcweir 	}
595cdf0e10cSrcweir }
596cdf0e10cSrcweir 
597cdf0e10cSrcweir // -----------------------------------------------------------------------------
allowViews() const598cdf0e10cSrcweir bool ORelationController::allowViews() const
599cdf0e10cSrcweir {
600cdf0e10cSrcweir     return false;
601cdf0e10cSrcweir }
602cdf0e10cSrcweir 
603cdf0e10cSrcweir // -----------------------------------------------------------------------------
allowQueries() const604cdf0e10cSrcweir bool ORelationController::allowQueries() const
605cdf0e10cSrcweir {
606cdf0e10cSrcweir     return false;
607cdf0e10cSrcweir }
608cdf0e10cSrcweir 
609cdf0e10cSrcweir // -----------------------------------------------------------------------------
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 
612