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: TKeys.cxx,v $
10 * $Revision: 1.13.30.1 $
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_connectivity.hxx"
33 #include "connectivity/TKeys.hxx"
34 #include "connectivity/TKey.hxx"
35 #include <com/sun/star/sdbc/XRow.hpp>
36 #include <com/sun/star/sdbc/XResultSet.hpp>
37 #include <com/sun/star/sdbcx/KeyType.hpp>
38 #include <com/sun/star/sdbc/KeyRule.hpp>
39 #include "connectivity/dbtools.hxx"
40 #include <comphelper/extract.hxx>
41 #include <comphelper/types.hxx>
42 #include <comphelper/property.hxx>
43 #include "TConnection.hxx"
45 namespace connectivity
47 using namespace comphelper
;
48 using namespace connectivity::sdbcx
;
49 using namespace dbtools
;
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::beans
;
52 using namespace ::com::sun::star::sdbcx
;
53 using namespace ::com::sun::star::sdbc
;
54 using namespace ::com::sun::star::container
;
55 using namespace ::com::sun::star::lang
;
59 OKeysHelper::OKeysHelper( OTableHelper
* _pTable
,
60 ::osl::Mutex
& _rMutex
,
61 const TStringVector
& _rVector
62 ) : OKeys_BASE(*_pTable
,sal_True
,_rMutex
,_rVector
,sal_True
)
66 // -------------------------------------------------------------------------
67 sdbcx::ObjectType
OKeysHelper::createObject(const ::rtl::OUString
& _rName
)
69 sdbcx::ObjectType xRet
= NULL
;
71 if(_rName
.getLength())
73 OTableKeyHelper
* pRet
= new OTableKeyHelper(m_pTable
,_rName
,m_pTable
->getKeyProperties(_rName
));
77 if(!xRet
.is()) // we have a primary key with a system name
79 OTableKeyHelper
* pRet
= new OTableKeyHelper(m_pTable
,_rName
,m_pTable
->getKeyProperties(_rName
));
85 // -------------------------------------------------------------------------
86 void OKeysHelper::impl_refresh() throw(RuntimeException
)
88 m_pTable
->refreshKeys();
90 // -------------------------------------------------------------------------
91 Reference
< XPropertySet
> OKeysHelper::createDescriptor()
93 return new OTableKeyHelper(m_pTable
);
95 // -----------------------------------------------------------------------------
96 /** returns the keyrule string for the primary key
98 ::rtl::OUString
getKeyRuleString(sal_Bool _bUpdate
,sal_Int32 _nKeyRule
)
100 const char* pKeyRule
= NULL
;
103 case KeyRule::CASCADE
:
104 pKeyRule
= _bUpdate
? " ON UPDATE CASCADE " : " ON DELETE CASCADE ";
106 case KeyRule::RESTRICT
:
107 pKeyRule
= _bUpdate
? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT ";
109 case KeyRule::SET_NULL
:
110 pKeyRule
= _bUpdate
? " ON UPDATE SET NULL " : " ON DELETE SET NULL ";
112 case KeyRule::SET_DEFAULT
:
113 pKeyRule
= _bUpdate
? " ON UPDATE SET DEFAULT " : " ON DELETE SET DEFAULT ";
118 ::rtl::OUString sRet
;
120 sRet
= ::rtl::OUString::createFromAscii(pKeyRule
);
123 // -------------------------------------------------------------------------
124 void OKeysHelper::cloneDescriptorColumns( const sdbcx::ObjectType
& _rSourceDescriptor
, const sdbcx::ObjectType
& _rDestDescriptor
)
126 Reference
< XColumnsSupplier
> xColSupp( _rSourceDescriptor
, UNO_QUERY_THROW
);
127 Reference
< XIndexAccess
> xSourceCols( xColSupp
->getColumns(), UNO_QUERY_THROW
);
129 xColSupp
.set( _rDestDescriptor
, UNO_QUERY_THROW
);
130 Reference
< XAppend
> xDestAppend( xColSupp
->getColumns(), UNO_QUERY_THROW
);
132 sal_Int32 nCount
= xSourceCols
->getCount();
133 for ( sal_Int32 i
=0; i
< nCount
; ++i
)
135 Reference
< XPropertySet
> xColProp( xSourceCols
->getByIndex(i
), UNO_QUERY
);
136 xDestAppend
->appendByDescriptor( xColProp
);
139 // -------------------------------------------------------------------------
141 sdbcx::ObjectType
OKeysHelper::appendObject( const ::rtl::OUString
& _rForName
, const Reference
< XPropertySet
>& descriptor
)
143 Reference
< XConnection
> xConnection
= m_pTable
->getConnection();
144 if ( !xConnection
.is() )
146 if ( m_pTable
->isNew() )
148 Reference
< XPropertySet
> xNewDescriptor( cloneDescriptor( descriptor
) );
149 cloneDescriptorColumns( descriptor
, xNewDescriptor
);
150 return xNewDescriptor
;
153 // if we're here, we belong to a table which is not new, i.e. already exists in the database.
154 // In this case, really append the new index.
156 const ::dbtools::OPropertyMap
& rPropMap
= OMetaConnection::getPropMap();
157 sal_Int32 nKeyType
= getINT32(descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_TYPE
)));
159 ::rtl::OUString aSql
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ALTER TABLE "));
160 ::rtl::OUString aQuote
= m_pTable
->getConnection()->getMetaData()->getIdentifierQuoteString( );
161 ::rtl::OUString aDot
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
163 aSql
+= composeTableName( m_pTable
->getConnection()->getMetaData(), m_pTable
, ::dbtools::eInTableDefinitions
, false, false, true );
164 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ADD "));
166 if ( nKeyType
== KeyType::PRIMARY
)
168 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" PRIMARY KEY ("));
170 else if ( nKeyType
== KeyType::FOREIGN
)
172 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FOREIGN KEY ("));
175 throw SQLException();
177 Reference
<XColumnsSupplier
> xColumnSup(descriptor
,UNO_QUERY
);
178 Reference
<XIndexAccess
> xColumns(xColumnSup
->getColumns(),UNO_QUERY
);
179 Reference
< XPropertySet
> xColProp
;
180 for(sal_Int32 i
=0;i
<xColumns
->getCount();++i
)
182 ::cppu::extractInterface(xColProp
,xColumns
->getByIndex(i
));
183 aSql
+= ::dbtools::quoteName( aQuote
,getString(xColProp
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_NAME
))))
184 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
186 aSql
= aSql
.replaceAt(aSql
.getLength()-1,1,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")));
188 sal_Int32 nUpdateRule
= 0, nDeleteRule
= 0;
189 ::rtl::OUString sReferencedName
;
191 if ( nKeyType
== KeyType::FOREIGN
)
193 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE
)) >>= sReferencedName
;
195 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" REFERENCES "))
196 + ::dbtools::quoteTableName(m_pTable
->getConnection()->getMetaData(),sReferencedName
,::dbtools::eInTableDefinitions
);
197 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ("));
199 for(sal_Int32 i
=0;i
<xColumns
->getCount();++i
)
201 xColumns
->getByIndex(i
) >>= xColProp
;
202 aSql
+= ::dbtools::quoteName( aQuote
,getString(xColProp
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_RELATEDCOLUMN
))))
203 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
205 aSql
= aSql
.replaceAt(aSql
.getLength()-1,1,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")")));
207 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_UPDATERULE
)) >>= nUpdateRule
;
208 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_DELETERULE
)) >>= nDeleteRule
;
210 aSql
+= getKeyRuleString(sal_True
,nUpdateRule
);
211 aSql
+= getKeyRuleString(sal_False
,nDeleteRule
);
214 Reference
< XStatement
> xStmt
= m_pTable
->getConnection()->createStatement( );
215 xStmt
->execute(aSql
);
216 // find the name which the database gave the new key
217 ::rtl::OUString
sNewName( _rForName
);
220 ::rtl::OUString aSchema
,aTable
;
221 m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_SCHEMANAME
)) >>= aSchema
;
222 m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_NAME
)) >>= aTable
;
223 Reference
< XResultSet
> xResult
;
224 sal_Int32 nColumn
= 12;
225 if ( nKeyType
== KeyType::FOREIGN
)
226 xResult
= m_pTable
->getMetaData()->getImportedKeys( m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_CATALOGNAME
))
231 xResult
= m_pTable
->getMetaData()->getPrimaryKeys( m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_CATALOGNAME
))
238 Reference
< XRow
> xRow(xResult
,UNO_QUERY
);
239 while( xResult
->next() )
241 ::rtl::OUString sName
= xRow
->getString(nColumn
);
242 if ( !m_pElements
->exists(sName
) ) // this name wasn't inserted yet so it must be te new one
244 descriptor
->setPropertyValue( rPropMap
.getNameByIndex( PROPERTY_ID_NAME
), makeAny( sName
) );
249 ::comphelper::disposeComponent(xResult
);
252 catch(const SQLException
&)
256 m_pTable
->addKey(sNewName
,sdbcx::TKeyProperties(new sdbcx::KeyProperties(sReferencedName
,nKeyType
,nUpdateRule
,nDeleteRule
)));
258 return createObject( sNewName
);
260 // -----------------------------------------------------------------------------
261 ::rtl::OUString
OKeysHelper::getDropForeignKey() const
263 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP CONSTRAINT "));
265 // -------------------------------------------------------------------------
267 void OKeysHelper::dropObject(sal_Int32 _nPos
,const ::rtl::OUString _sElementName
)
269 Reference
< XConnection
> xConnection
= m_pTable
->getConnection();
270 if ( xConnection
.is() && !m_pTable
->isNew() )
272 ::rtl::OUString aSql
= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ALTER TABLE "));
274 aSql
+= composeTableName( m_pTable
->getConnection()->getMetaData(), m_pTable
,::dbtools::eInTableDefinitions
, false, false, true );
276 Reference
<XPropertySet
> xKey(getObject(_nPos
),UNO_QUERY
);
278 sal_Int32 nKeyType
= KeyType::PRIMARY
;
281 ::dbtools::OPropertyMap
& rPropMap
= OMetaConnection::getPropMap();
282 xKey
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nKeyType
;
284 if ( KeyType::PRIMARY
== nKeyType
)
286 aSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP PRIMARY KEY"));
290 aSql
+= getDropForeignKey();
291 const ::rtl::OUString aQuote
= m_pTable
->getConnection()->getMetaData()->getIdentifierQuoteString();
292 aSql
+= ::dbtools::quoteName( aQuote
,_sElementName
);
295 Reference
< XStatement
> xStmt
= m_pTable
->getConnection()->createStatement( );
298 xStmt
->execute(aSql
);
299 ::comphelper::disposeComponent(xStmt
);
303 // -----------------------------------------------------------------------------
304 } // namespace connectivity
305 // -----------------------------------------------------------------------------