fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dbaccess / source / ui / relationdesign / RTableConnectionData.cxx
blob546b4c9053d81afa0dd5dbb8adc4361a839d9c7c
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 "RTableConnectionData.hxx"
21 #include <tools/debug.hxx>
22 #include <com/sun/star/sdbc/KeyRule.hpp>
23 #include <com/sun/star/sdbcx/KeyType.hpp>
24 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
25 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
26 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
27 #include <com/sun/star/sdbcx/XAppend.hpp>
28 #include <com/sun/star/sdbcx/XDrop.hpp>
29 #include <com/sun/star/container/XIndexAccess.hpp>
30 #include "dbustrings.hrc"
31 #include "dbu_rel.hrc"
32 #include "UITools.hxx"
33 #include "moduledbu.hxx"
34 #include <connectivity/dbexception.hxx>
35 #include <connectivity/dbtools.hxx>
37 using namespace dbaui;
38 using namespace ::com::sun::star::sdbc;
39 using namespace ::com::sun::star::sdbcx;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::beans;
42 using namespace ::com::sun::star::container;
43 using namespace ::com::sun::star::lang;
45 // class ORelationTableConnectionData
46 ORelationTableConnectionData::ORelationTableConnectionData()
47 :OTableConnectionData()
48 ,m_nUpdateRules(KeyRule::NO_ACTION)
49 ,m_nDeleteRules(KeyRule::NO_ACTION)
50 ,m_nCardinality(CARDINAL_UNDEFINED)
54 ORelationTableConnectionData::ORelationTableConnectionData( const TTableWindowData::value_type& _pReferencingTable,
55 const TTableWindowData::value_type& _pReferencedTable,
56 const OUString& rConnName )
57 :OTableConnectionData( _pReferencingTable, _pReferencedTable )
58 ,m_nUpdateRules(KeyRule::NO_ACTION)
59 ,m_nDeleteRules(KeyRule::NO_ACTION)
60 ,m_nCardinality(CARDINAL_UNDEFINED)
62 m_aConnName = rConnName;
64 if ( !m_aConnName.isEmpty() )
65 SetCardinality();
68 ORelationTableConnectionData::ORelationTableConnectionData( const ORelationTableConnectionData& rConnData )
69 :OTableConnectionData( rConnData )
71 *this = rConnData;
74 ORelationTableConnectionData::~ORelationTableConnectionData()
78 bool ORelationTableConnectionData::DropRelation()
80 ::osl::MutexGuard aGuard( m_aMutex );
81 // delete relation
82 Reference< XIndexAccess> xKeys = getReferencingTable()->getKeys();
83 if( !m_aConnName.isEmpty() && xKeys.is() )
85 const sal_Int32 nCount = xKeys->getCount();
86 for(sal_Int32 i = 0;i < nCount;++i)
88 Reference< XPropertySet> xKey(xKeys->getByIndex(i),UNO_QUERY);
89 OSL_ENSURE(xKey.is(),"Key is not valid!");
90 if(xKey.is())
92 OUString sName;
93 xKey->getPropertyValue(PROPERTY_NAME) >>= sName;
94 if(sName == m_aConnName)
96 Reference< XDrop> xDrop(xKeys,UNO_QUERY);
97 OSL_ENSURE(xDrop.is(),"can't drop key because we haven't a drop interface!");
98 if(xDrop.is())
99 xDrop->dropByIndex(i);
100 break;
105 return true;
108 void ORelationTableConnectionData::ChangeOrientation()
110 // exchange Source- and DestFieldName of the lines
111 OUString sTempString;
112 OConnectionLineDataVec::iterator aIter = m_vConnLineData.begin();
113 OConnectionLineDataVec::iterator aEnd = m_vConnLineData.end();
114 for(;aIter != aEnd;++aIter)
116 sTempString = (*aIter)->GetSourceFieldName();
117 (*aIter)->SetSourceFieldName( (*aIter)->GetDestFieldName() );
118 (*aIter)->SetDestFieldName( sTempString );
121 // adapt member
122 TTableWindowData::value_type pTemp = m_pReferencingTable;
123 m_pReferencingTable = m_pReferencedTable;
124 m_pReferencedTable = pTemp;
127 void ORelationTableConnectionData::SetCardinality()
129 ::osl::MutexGuard aGuard( m_aMutex );
130 m_nCardinality = CARDINAL_UNDEFINED;
132 if( IsSourcePrimKey() )
134 if( IsDestPrimKey() )
135 m_nCardinality = CARDINAL_ONE_ONE;
136 else
137 m_nCardinality = CARDINAL_ONE_MANY;
140 if( IsDestPrimKey() )
142 if( !IsSourcePrimKey() )
143 m_nCardinality = CARDINAL_MANY_ONE;
148 bool ORelationTableConnectionData::checkPrimaryKey(const Reference< XPropertySet>& i_xTable,EConnectionSide _eEConnectionSide) const
150 // check if Table has the primary key column dependig on _eEConnectionSide
151 sal_uInt16 nPrimKeysCount = 0,
152 nValidLinesCount = 0;
153 const Reference< XNameAccess> xKeyColumns = dbtools::getPrimaryKeyColumns_throw(i_xTable);
154 if ( xKeyColumns.is() )
156 Sequence< OUString> aKeyColumns = xKeyColumns->getElementNames();
157 const OUString* pKeyIter = aKeyColumns.getConstArray();
158 const OUString* pKeyEnd = pKeyIter + aKeyColumns.getLength();
160 for(;pKeyIter != pKeyEnd;++pKeyIter)
162 OConnectionLineDataVec::const_iterator aIter = m_vConnLineData.begin();
163 OConnectionLineDataVec::const_iterator aEnd = m_vConnLineData.end();
164 for(;aIter != aEnd;++aIter)
166 ++nValidLinesCount;
167 if ( (*aIter)->GetFieldName(_eEConnectionSide) == *pKeyIter )
169 ++nPrimKeysCount;
170 break;
174 if ( nPrimKeysCount != aKeyColumns.getLength() )
175 return false;
177 if ( !nPrimKeysCount || nPrimKeysCount != nValidLinesCount )
178 return false;
180 return true;
183 bool ORelationTableConnectionData::IsConnectionPossible()
185 ::osl::MutexGuard aGuard( m_aMutex );
187 // if the SourceFields are a PrimKey, it's only the orientation which is wrong
188 if ( IsSourcePrimKey() && !IsDestPrimKey() )
189 ChangeOrientation();
191 return true;
194 OConnectionLineDataRef ORelationTableConnectionData::CreateLineDataObj()
196 return new OConnectionLineData();
199 OConnectionLineDataRef ORelationTableConnectionData::CreateLineDataObj( const OConnectionLineData& rConnLineData )
201 return new OConnectionLineData( rConnLineData );
204 void ORelationTableConnectionData::CopyFrom(const OTableConnectionData& rSource)
206 // retract to the (non-virtual) operator= like in the base class
207 *this = *static_cast<const ORelationTableConnectionData*>(&rSource);
210 ORelationTableConnectionData& ORelationTableConnectionData::operator=( const ORelationTableConnectionData& rConnData )
212 if (&rConnData == this)
213 return *this;
215 OTableConnectionData::operator=( rConnData );
216 m_nUpdateRules = rConnData.GetUpdateRules();
217 m_nDeleteRules = rConnData.GetDeleteRules();
218 m_nCardinality = rConnData.GetCardinality();
220 return *this;
223 namespace dbaui
225 bool operator==(const ORelationTableConnectionData& lhs, const ORelationTableConnectionData& rhs)
227 bool bEqual = (lhs.m_nUpdateRules == rhs.m_nUpdateRules)
228 && (lhs.m_nDeleteRules == rhs.m_nDeleteRules)
229 && (lhs.m_nCardinality == rhs.m_nCardinality)
230 && (lhs.getReferencingTable() == rhs.getReferencingTable())
231 && (lhs.getReferencedTable() == rhs.getReferencedTable())
232 && (lhs.m_aConnName == rhs.m_aConnName)
233 && (lhs.m_vConnLineData.size() == rhs.m_vConnLineData.size());
235 if ( bEqual )
237 std::vector< OConnectionLineDataRef >::const_iterator aIter = lhs.m_vConnLineData.begin();
238 std::vector< OConnectionLineDataRef >::const_iterator aEnd = lhs.m_vConnLineData.end();
239 for (sal_Int32 i = 0; aIter != aEnd; ++aIter,++i)
241 if ( *(rhs.m_vConnLineData[i]) != **aIter )
242 break;
244 bEqual = aIter == aEnd;
246 return bEqual;
251 bool ORelationTableConnectionData::Update()
253 ::osl::MutexGuard aGuard( m_aMutex );
254 // delete old relation
256 DropRelation();
257 if( !IsConnectionPossible() )
258 return false;
261 // reassign the keys because the orientaion could be changed
262 Reference<XPropertySet> xTableProp(getReferencingTable()->getTable());
263 Reference< XIndexAccess> xKeys ( getReferencingTable()->getKeys());
265 if ( !xKeys.is() )
266 return false;
267 // create new relation
268 Reference<XDataDescriptorFactory> xKeyFactory(xKeys,UNO_QUERY);
269 OSL_ENSURE(xKeyFactory.is(),"No XDataDescriptorFactory Interface!");
270 Reference<XAppend> xAppend(xKeyFactory,UNO_QUERY);
271 OSL_ENSURE(xAppend.is(),"No XAppend Interface!");
273 Reference<XPropertySet> xKey = xKeyFactory->createDataDescriptor();
274 OSL_ENSURE(xKey.is(),"Key is null!");
275 if ( xKey.is() && xTableProp.is() )
277 // build a foreign key name
278 OUString sSourceName;
279 xTableProp->getPropertyValue(PROPERTY_NAME) >>= sSourceName;
280 OUString sKeyName = sSourceName;
281 sKeyName += getReferencedTable()->GetTableName();
283 xKey->setPropertyValue(PROPERTY_NAME,makeAny(sKeyName));
284 xKey->setPropertyValue(PROPERTY_TYPE,makeAny(KeyType::FOREIGN));
285 xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,makeAny(OUString(getReferencedTable()->GetTableName())));
286 xKey->setPropertyValue(PROPERTY_UPDATERULE, makeAny(GetUpdateRules()));
287 xKey->setPropertyValue(PROPERTY_DELETERULE, makeAny(GetDeleteRules()));
290 Reference<XColumnsSupplier> xColSup(xKey,UNO_QUERY);
291 if ( xColSup.is() )
293 Reference<XNameAccess> xColumns = xColSup->getColumns();
294 Reference<XDataDescriptorFactory> xColumnFactory(xColumns,UNO_QUERY);
295 Reference<XAppend> xColumnAppend(xColumns,UNO_QUERY);
296 if ( xColumnFactory.is() )
298 OConnectionLineDataVec::iterator aIter = m_vConnLineData.begin();
299 OConnectionLineDataVec::iterator aEnd = m_vConnLineData.end();
300 for(;aIter != aEnd;++aIter)
302 if(!((*aIter)->GetSourceFieldName().isEmpty() || (*aIter)->GetDestFieldName().isEmpty()))
304 Reference<XPropertySet> xColumn;
305 xColumn = xColumnFactory->createDataDescriptor();
306 if ( xColumn.is() )
308 xColumn->setPropertyValue(PROPERTY_NAME,makeAny((*aIter)->GetSourceFieldName()));
309 xColumn->setPropertyValue(PROPERTY_RELATEDCOLUMN,makeAny((*aIter)->GetDestFieldName()));
310 xColumnAppend->appendByDescriptor(xColumn);
315 if ( xColumns->hasElements() )
316 xAppend->appendByDescriptor(xKey);
318 // to get the key we have to reget it because after append it is no longer valid
321 // get the name of foreign key; search for columns
322 m_aConnName.clear();
323 xKey.clear();
324 bool bDropRelation = false;
325 for(sal_Int32 i=0;i<xKeys->getCount();++i)
327 xKeys->getByIndex(i) >>= xKey;
328 OSL_ENSURE(xKey.is(),"Key is not valid!");
329 if ( xKey.is() )
331 sal_Int32 nType = 0;
332 xKey->getPropertyValue(PROPERTY_TYPE) >>= nType;
333 OUString sReferencedTable;
334 xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable;
335 if ( sReferencedTable == getReferencedTable()->GetTableName() )
337 xColSup.set(xKey,UNO_QUERY_THROW);
340 Reference<XNameAccess> xColumns = xColSup->getColumns();
341 Sequence< OUString> aNames = xColumns->getElementNames();
342 const OUString* pIter = aNames.getConstArray();
343 const OUString* pEnd = pIter + aNames.getLength();
345 Reference<XPropertySet> xColumn;
346 OUString sName,sRelatedColumn;
347 for ( ; pIter != pEnd ; ++pIter )
349 xColumn.set(xColumns->getByName(*pIter),UNO_QUERY_THROW);
350 xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
351 xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
353 OConnectionLineDataVec::iterator aIter = m_vConnLineData.begin();
354 OConnectionLineDataVec::iterator aEnd = m_vConnLineData.end();
355 for(;aIter != aEnd;++aIter)
357 if( (*aIter)->GetSourceFieldName() == sName
358 && (*aIter)->GetDestFieldName() == sRelatedColumn )
360 break;
363 if ( aIter == m_vConnLineData.end() )
364 break;
366 if ( pIter == pEnd )
368 xKey->getPropertyValue(PROPERTY_NAME) >>= sName;
369 m_aConnName = sName;
370 bDropRelation = aNames.getLength() == 0; // the key contains no column, so it isn't valid and we have to drop it
371 //here we already know our column structure so we don't have to recreate the table connection data
372 xColSup.clear();
373 break;
376 catch(Exception&)
381 xKey.clear();
383 if ( bDropRelation )
385 DropRelation();
386 OUString sError(ModuleRes(STR_QUERY_REL_COULD_NOT_CREATE));
387 ::dbtools::throwGenericSQLException(sError,NULL);
390 // The fields the relation marks may not be the same as our LineDatas mark after the relation has been updated
391 if ( xColSup.is() )
393 OConnectionLineDataVec().swap(m_vConnLineData);
394 Reference<XNameAccess> xColumns = xColSup->getColumns();
395 Sequence< OUString> aNames = xColumns->getElementNames();
396 const OUString* pIter = aNames.getConstArray();
397 const OUString* pEnd = pIter + aNames.getLength();
399 m_vConnLineData.reserve( aNames.getLength() );
400 Reference<XPropertySet> xColumn;
401 OUString sName,sRelatedColumn;
403 for(;pIter != pEnd;++pIter)
405 xColumns->getByName(*pIter) >>= xColumn;
406 if ( xColumn.is() )
408 OConnectionLineDataRef pNewData = CreateLineDataObj();
410 xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
411 xColumn->getPropertyValue(PROPERTY_RELATEDCOLUMN) >>= sRelatedColumn;
413 pNewData->SetSourceFieldName(sName);
414 pNewData->SetDestFieldName(sRelatedColumn);
415 m_vConnLineData.push_back(pNewData);
419 // NOTE : the caller is responsible for updating any other objects referencing the old LineDatas (for instance a ConnLine)
421 // determine cardinality
422 SetCardinality();
424 return true;
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */