1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: RTableConnectionData.cxx,v $
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"
33 #include "RTableConnectionData.hxx"
34 #include <tools/debug.hxx>
35 #include <com/sun/star/sdbc/KeyRule.hpp>
36 #include <com/sun/star/sdbcx/KeyType.hpp>
37 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
38 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
39 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
40 #include <com/sun/star/sdbcx/XAppend.hpp>
41 #include <com/sun/star/sdbcx/XDrop.hpp>
42 #include <com/sun/star/container/XIndexAccess.hpp>
43 #include "dbustrings.hrc"
44 #include "dbu_rel.hrc"
45 #include "UITools.hxx"
46 #include "moduledbu.hxx"
47 #include <connectivity/dbexception.hxx>
49 using namespace dbaui
;
50 using namespace ::com::sun::star::sdbc
;
51 using namespace ::com::sun::star::sdbcx
;
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::beans
;
54 using namespace ::com::sun::star::container
;
55 using namespace ::com::sun::star::lang
;
57 DBG_NAME(ORelationTableConnectionData
)
58 //========================================================================
59 // class ORelationTableConnectionData
60 //========================================================================
61 //------------------------------------------------------------------------
62 ORelationTableConnectionData::ORelationTableConnectionData()
63 :OTableConnectionData()
64 ,m_nUpdateRules(KeyRule::NO_ACTION
)
65 ,m_nDeleteRules(KeyRule::NO_ACTION
)
66 ,m_nCardinality(CARDINAL_UNDEFINED
)
68 DBG_CTOR(ORelationTableConnectionData
,NULL
);
70 //------------------------------------------------------------------------
71 ORelationTableConnectionData::ORelationTableConnectionData( const TTableWindowData::value_type
& _pReferencingTable
,
72 const TTableWindowData::value_type
& _pReferencedTable
,
73 const ::rtl::OUString
& rConnName
)
74 :OTableConnectionData( _pReferencingTable
, _pReferencedTable
)
75 ,m_nUpdateRules(KeyRule::NO_ACTION
)
76 ,m_nDeleteRules(KeyRule::NO_ACTION
)
77 ,m_nCardinality(CARDINAL_UNDEFINED
)
79 DBG_CTOR(ORelationTableConnectionData
,NULL
);
80 m_aConnName
= rConnName
;
82 if ( m_aConnName
.Len() )
86 //------------------------------------------------------------------------
87 ORelationTableConnectionData::ORelationTableConnectionData( const ORelationTableConnectionData
& rConnData
)
88 :OTableConnectionData( rConnData
)
90 DBG_CTOR(ORelationTableConnectionData
,NULL
);
94 //------------------------------------------------------------------------
95 ORelationTableConnectionData::~ORelationTableConnectionData()
97 DBG_DTOR(ORelationTableConnectionData
,NULL
);
100 //------------------------------------------------------------------------
101 BOOL
ORelationTableConnectionData::DropRelation()
103 DBG_CHKTHIS(ORelationTableConnectionData
,NULL
);
104 ::osl::MutexGuard
aGuard( m_aMutex
);
105 ////////////////////////////////////////////////////////////
107 Reference
< XIndexAccess
> xKeys
= getReferencingTable()->getKeys();
108 if( m_aConnName
.Len() && xKeys
.is() )
110 const sal_Int32 nCount
= xKeys
->getCount();
111 for(sal_Int32 i
= 0;i
< nCount
;++i
)
113 Reference
< XPropertySet
> xKey(xKeys
->getByIndex(i
),UNO_QUERY
);
114 OSL_ENSURE(xKey
.is(),"Key is not valid!");
117 ::rtl::OUString sName
;
118 xKey
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
119 if(String(sName
) == m_aConnName
)
121 Reference
< XDrop
> xDrop(xKeys
,UNO_QUERY
);
122 OSL_ENSURE(xDrop
.is(),"can't drop key because we haven't a drop interface!");
124 xDrop
->dropByIndex(i
);
133 //------------------------------------------------------------------------
134 void ORelationTableConnectionData::ChangeOrientation()
136 DBG_CHKTHIS(ORelationTableConnectionData
,NULL
);
137 //////////////////////////////////////////////////////////////////////
138 // Source- und DestFieldName der Linien austauschen
139 ::rtl::OUString sTempString
;
140 OConnectionLineDataVec::iterator aIter
= m_vConnLineData
.begin();
141 OConnectionLineDataVec::iterator aEnd
= m_vConnLineData
.end();
142 for(;aIter
!= aEnd
;++aIter
)
144 sTempString
= (*aIter
)->GetSourceFieldName();
145 (*aIter
)->SetSourceFieldName( (*aIter
)->GetDestFieldName() );
146 (*aIter
)->SetDestFieldName( sTempString
);
149 //////////////////////////////////////////////////////////////////////
151 TTableWindowData::value_type pTemp
= m_pReferencingTable
;
152 m_pReferencingTable
= m_pReferencedTable
;
153 m_pReferencedTable
= pTemp
;
156 //------------------------------------------------------------------------
157 void ORelationTableConnectionData::SetCardinality()
159 DBG_CHKTHIS(ORelationTableConnectionData
,NULL
);
160 ::osl::MutexGuard
aGuard( m_aMutex
);
161 m_nCardinality
= CARDINAL_UNDEFINED
;
163 if( IsSourcePrimKey() )
165 if( IsDestPrimKey() )
166 m_nCardinality
= CARDINAL_ONE_ONE
;
168 m_nCardinality
= CARDINAL_ONE_MANY
;
171 if( IsDestPrimKey() )
173 if( !IsSourcePrimKey() )
174 m_nCardinality
= CARDINAL_MANY_ONE
;
178 // -----------------------------------------------------------------------------
179 BOOL
ORelationTableConnectionData::checkPrimaryKey(const Reference
< XIndexAccess
>& _xKeys
,EConnectionSide _eEConnectionSide
) const
181 // check if Table has the primary key column dependig on _eEConnectionSide
182 USHORT nPrimKeysCount
= 0,
183 nValidLinesCount
= 0;
184 ::std::vector
<Reference
<XNameAccess
> > vKeyColumns
= ::dbaui::getKeyColumns(_xKeys
,KeyType::PRIMARY
);
185 if ( vKeyColumns
.size() == 1 )
187 // OSL_ENSURE(vKeyColumns.size()==1,"There can be only one primary key in a table!");
188 Sequence
< ::rtl::OUString
> aKeyColumns
;
189 Reference
<XNameAccess
> xKeyColumns
= *vKeyColumns
.begin();
190 if ( xKeyColumns
.is() )
192 aKeyColumns
= xKeyColumns
->getElementNames();
193 const ::rtl::OUString
* pKeyIter
= aKeyColumns
.getConstArray();
194 const ::rtl::OUString
* pKeyEnd
= pKeyIter
+ aKeyColumns
.getLength();
196 for(;pKeyIter
!= pKeyEnd
;++pKeyIter
)
198 OConnectionLineDataVec::const_iterator aIter
= m_vConnLineData
.begin();
199 OConnectionLineDataVec::const_iterator aEnd
= m_vConnLineData
.end();
200 for(;aIter
!= aEnd
;++aIter
)
203 if ( (*aIter
)->GetFieldName(_eEConnectionSide
) == *pKeyIter
)
211 if ( nPrimKeysCount
!= aKeyColumns
.getLength() )
214 if ( !nPrimKeysCount
|| nPrimKeysCount
!= nValidLinesCount
)
219 //------------------------------------------------------------------------
220 BOOL
ORelationTableConnectionData::IsConnectionPossible()
222 DBG_CHKTHIS(ORelationTableConnectionData
,NULL
);
223 ::osl::MutexGuard
aGuard( m_aMutex
);
225 //////////////////////////////////////////////////////////////////////
226 // Wenn die SourceFelder ein PrimKey sind, ist nur die Orientierung falsch
227 if ( IsSourcePrimKey() && !IsDestPrimKey() )
233 //------------------------------------------------------------------------
234 OConnectionLineDataRef
ORelationTableConnectionData::CreateLineDataObj()
236 return new OConnectionLineData();
239 //------------------------------------------------------------------------
240 OConnectionLineDataRef
ORelationTableConnectionData::CreateLineDataObj( const OConnectionLineData
& rConnLineData
)
242 return new OConnectionLineData( rConnLineData
);
245 //------------------------------------------------------------------------
246 void ORelationTableConnectionData::CopyFrom(const OTableConnectionData
& rSource
)
248 // wie in der Basisklasse zurueckziehen auf das (nicht-virtuelle) operator=
249 *this = *static_cast<const ORelationTableConnectionData
*>(&rSource
);
252 //------------------------------------------------------------------------
253 ORelationTableConnectionData
& ORelationTableConnectionData::operator=( const ORelationTableConnectionData
& rConnData
)
255 if (&rConnData
== this)
258 OTableConnectionData::operator=( rConnData
);
259 m_nUpdateRules
= rConnData
.GetUpdateRules();
260 m_nDeleteRules
= rConnData
.GetDeleteRules();
261 m_nCardinality
= rConnData
.GetCardinality();
267 //-------------------------------------------------------------------------
268 bool operator==(const ORelationTableConnectionData
& lhs
, const ORelationTableConnectionData
& rhs
)
270 bool bEqual
= (lhs
.m_nUpdateRules
== rhs
.m_nUpdateRules
)
271 && (lhs
.m_nDeleteRules
== rhs
.m_nDeleteRules
)
272 && (lhs
.m_nCardinality
== rhs
.m_nCardinality
)
273 && (lhs
.getReferencingTable() == rhs
.getReferencingTable())
274 && (lhs
.getReferencedTable() == rhs
.getReferencedTable())
275 && (lhs
.m_aConnName
== rhs
.m_aConnName
)
276 && (lhs
.m_vConnLineData
.size() == rhs
.m_vConnLineData
.size());
280 std::vector
< OConnectionLineDataRef
>::const_iterator aIter
= lhs
.m_vConnLineData
.begin();
281 std::vector
< OConnectionLineDataRef
>::const_iterator aEnd
= lhs
.m_vConnLineData
.end();
282 for (sal_Int32 i
= 0; aIter
!= aEnd
; ++aIter
,++i
)
284 if ( *(rhs
.m_vConnLineData
[i
]) != **aIter
)
287 bEqual
= aIter
== aEnd
;
292 //------------------------------------------------------------------------
293 BOOL
ORelationTableConnectionData::Update()
295 ::osl::MutexGuard
aGuard( m_aMutex
);
296 ////////////////////////////////////////////////////////////
297 // Alte Relation loeschen
300 if( !IsConnectionPossible() )
304 // reassign the keys because the orientaion could be changed
305 Reference
<XPropertySet
> xTableProp(getReferencingTable()->getTable());
306 Reference
< XIndexAccess
> xKeys ( getReferencingTable()->getKeys());
310 ////////////////////////////////////////////////////////////
311 // Neue Relation erzeugen
312 Reference
<XDataDescriptorFactory
> xKeyFactory(xKeys
,UNO_QUERY
);
313 OSL_ENSURE(xKeyFactory
.is(),"No XDataDescriptorFactory Interface!");
314 Reference
<XAppend
> xAppend(xKeyFactory
,UNO_QUERY
);
315 OSL_ENSURE(xAppend
.is(),"No XAppend Interface!");
317 Reference
<XPropertySet
> xKey
= xKeyFactory
->createDataDescriptor();
318 OSL_ENSURE(xKey
.is(),"Key is null!");
319 if ( xKey
.is() && xTableProp
.is() )
321 // build a foreign key name
322 ::rtl::OUString sSourceName
;
323 xTableProp
->getPropertyValue(PROPERTY_NAME
) >>= sSourceName
;
324 ::rtl::OUString sKeyName
= sSourceName
;
325 sKeyName
+= getReferencedTable()->GetTableName();
327 xKey
->setPropertyValue(PROPERTY_NAME
,makeAny(sKeyName
));
328 xKey
->setPropertyValue(PROPERTY_TYPE
,makeAny(KeyType::FOREIGN
));
329 xKey
->setPropertyValue(PROPERTY_REFERENCEDTABLE
,makeAny(::rtl::OUString(getReferencedTable()->GetTableName())));
330 xKey
->setPropertyValue(PROPERTY_UPDATERULE
, makeAny(GetUpdateRules()));
331 xKey
->setPropertyValue(PROPERTY_DELETERULE
, makeAny(GetDeleteRules()));
334 Reference
<XColumnsSupplier
> xColSup(xKey
,UNO_QUERY
);
337 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
338 Reference
<XDataDescriptorFactory
> xColumnFactory(xColumns
,UNO_QUERY
);
339 Reference
<XAppend
> xColumnAppend(xColumns
,UNO_QUERY
);
340 if ( xColumnFactory
.is() )
342 OConnectionLineDataVec::iterator aIter
= m_vConnLineData
.begin();
343 OConnectionLineDataVec::iterator aEnd
= m_vConnLineData
.end();
344 for(;aIter
!= aEnd
;++aIter
)
346 if((*aIter
)->GetSourceFieldName().getLength() && (*aIter
)->GetDestFieldName().getLength())
348 Reference
<XPropertySet
> xColumn
;
349 xColumn
= xColumnFactory
->createDataDescriptor();
352 xColumn
->setPropertyValue(PROPERTY_NAME
,makeAny((*aIter
)->GetSourceFieldName()));
353 xColumn
->setPropertyValue(PROPERTY_RELATEDCOLUMN
,makeAny((*aIter
)->GetDestFieldName()));
354 xColumnAppend
->appendByDescriptor(xColumn
);
359 if ( xColumns
->hasElements() )
360 xAppend
->appendByDescriptor(xKey
);
362 // to get the key we have to reget it because after append it is no longer valid
365 // get the name of foreign key // search for columns
366 m_aConnName
= ::rtl::OUString();
368 bool bDropRelation
= false;
369 for(sal_Int32 i
=0;i
<xKeys
->getCount();++i
)
371 xKeys
->getByIndex(i
) >>= xKey
;
372 OSL_ENSURE(xKey
.is(),"Key is not valid!");
376 xKey
->getPropertyValue(PROPERTY_TYPE
) >>= nType
;
377 ::rtl::OUString sReferencedTable
;
378 xKey
->getPropertyValue(PROPERTY_REFERENCEDTABLE
) >>= sReferencedTable
;
379 if ( sReferencedTable
== ::rtl::OUString(getReferencedTable()->GetTableName()) )
381 xColSup
.set(xKey
,UNO_QUERY_THROW
);
384 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
385 Sequence
< ::rtl::OUString
> aNames
= xColumns
->getElementNames();
386 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
387 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
389 Reference
<XPropertySet
> xColumn
;
390 ::rtl::OUString sName
,sRelatedColumn
;
391 for ( ; pIter
!= pEnd
; ++pIter
)
393 xColumn
.set(xColumns
->getByName(*pIter
),UNO_QUERY_THROW
);
394 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
395 xColumn
->getPropertyValue(PROPERTY_RELATEDCOLUMN
) >>= sRelatedColumn
;
397 OConnectionLineDataVec::iterator aIter
= m_vConnLineData
.begin();
398 OConnectionLineDataVec::iterator aEnd
= m_vConnLineData
.end();
399 for(;aIter
!= aEnd
;++aIter
)
401 if( (*aIter
)->GetSourceFieldName() == sName
402 && (*aIter
)->GetDestFieldName() == sRelatedColumn
)
407 if ( aIter
== m_vConnLineData
.end() )
412 xKey
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
414 bDropRelation
= aNames
.getLength() == 0; // the key contains no column, so it isn't valid and we have to drop it
415 //here we already know our column structure so we don't have to recreate the table connection data
426 } // for(sal_Int32 i=0;i<xKeys->getCount();++i)
430 String
sError(ModuleRes(STR_QUERY_REL_COULD_NOT_CREATE
));
431 ::dbtools::throwGenericSQLException(sError
,NULL
);
434 // OSL_ENSURE(xKey.is(),"No key found have insertion!");
436 // The fields the relation marks may not be the same as our LineDatas mark after the relation has been updated
439 OConnectionLineDataVec().swap(m_vConnLineData
);
440 Reference
<XNameAccess
> xColumns
= xColSup
->getColumns();
441 Sequence
< ::rtl::OUString
> aNames
= xColumns
->getElementNames();
442 const ::rtl::OUString
* pIter
= aNames
.getConstArray();
443 const ::rtl::OUString
* pEnd
= pIter
+ aNames
.getLength();
445 m_vConnLineData
.reserve( aNames
.getLength() );
446 Reference
<XPropertySet
> xColumn
;
447 ::rtl::OUString sName
,sRelatedColumn
;
449 for(;pIter
!= pEnd
;++pIter
)
451 xColumns
->getByName(*pIter
) >>= xColumn
;
454 OConnectionLineDataRef pNewData
= CreateLineDataObj();
456 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
457 xColumn
->getPropertyValue(PROPERTY_RELATEDCOLUMN
) >>= sRelatedColumn
;
459 pNewData
->SetSourceFieldName(sName
);
460 pNewData
->SetDestFieldName(sRelatedColumn
);
461 m_vConnLineData
.push_back(pNewData
);
464 } // if ( xColSup.is() )
465 // NOTE : the caller is resposible for updating any other objects referencing the old LineDatas (for instance a ConnLine)
467 ////////////////////////////////////////////////////////////
468 // Kardinalitaet bestimmen
473 // -----------------------------------------------------------------------------