1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "connectivity/TKeys.hxx"
21 #include "connectivity/TKey.hxx"
22 #include <com/sun/star/sdbc/XRow.hpp>
23 #include <com/sun/star/sdbc/XResultSet.hpp>
24 #include <com/sun/star/sdbcx/KeyType.hpp>
25 #include <com/sun/star/sdbc/KeyRule.hpp>
26 #include "connectivity/dbtools.hxx"
27 #include <comphelper/types.hxx>
28 #include <comphelper/property.hxx>
29 #include "TConnection.hxx"
31 namespace connectivity
33 using namespace comphelper
;
34 using namespace connectivity::sdbcx
;
35 using namespace dbtools
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::beans
;
38 using namespace ::com::sun::star::sdbcx
;
39 using namespace ::com::sun::star::sdbc
;
40 using namespace ::com::sun::star::container
;
41 using namespace ::com::sun::star::lang
;
45 OKeysHelper::OKeysHelper( OTableHelper
* _pTable
,
46 ::osl::Mutex
& _rMutex
,
47 const TStringVector
& _rVector
48 ) : OKeys_BASE(*_pTable
,true,_rMutex
,_rVector
,true)
53 sdbcx::ObjectType
OKeysHelper::createObject(const OUString
& _rName
)
55 sdbcx::ObjectType xRet
= NULL
;
59 OTableKeyHelper
* pRet
= new OTableKeyHelper(m_pTable
,_rName
,m_pTable
->getKeyProperties(_rName
));
63 if(!xRet
.is()) // we have a primary key with a system name
65 OTableKeyHelper
* pRet
= new OTableKeyHelper(m_pTable
,_rName
,m_pTable
->getKeyProperties(_rName
));
72 void OKeysHelper::impl_refresh() throw(RuntimeException
)
74 m_pTable
->refreshKeys();
77 Reference
< XPropertySet
> OKeysHelper::createDescriptor()
79 return new OTableKeyHelper(m_pTable
);
82 /** returns the keyrule string for the primary key
84 OUString
getKeyRuleString(bool _bUpdate
,sal_Int32 _nKeyRule
)
86 const char* pKeyRule
= NULL
;
89 case KeyRule::CASCADE
:
90 pKeyRule
= _bUpdate
? " ON UPDATE CASCADE " : " ON DELETE CASCADE ";
92 case KeyRule::RESTRICT
:
93 pKeyRule
= _bUpdate
? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT ";
95 case KeyRule::SET_NULL
:
96 pKeyRule
= _bUpdate
? " ON UPDATE SET NULL " : " ON DELETE SET NULL ";
98 case KeyRule::SET_DEFAULT
:
99 pKeyRule
= _bUpdate
? " ON UPDATE SET DEFAULT " : " ON DELETE SET DEFAULT ";
106 sRet
= OUString::createFromAscii(pKeyRule
);
110 void OKeysHelper::cloneDescriptorColumns( const sdbcx::ObjectType
& _rSourceDescriptor
, const sdbcx::ObjectType
& _rDestDescriptor
)
112 Reference
< XColumnsSupplier
> xColSupp( _rSourceDescriptor
, UNO_QUERY_THROW
);
113 Reference
< XIndexAccess
> xSourceCols( xColSupp
->getColumns(), UNO_QUERY_THROW
);
115 xColSupp
.set( _rDestDescriptor
, UNO_QUERY_THROW
);
116 Reference
< XAppend
> xDestAppend( xColSupp
->getColumns(), UNO_QUERY_THROW
);
118 sal_Int32 nCount
= xSourceCols
->getCount();
119 for ( sal_Int32 i
=0; i
< nCount
; ++i
)
121 Reference
< XPropertySet
> xColProp( xSourceCols
->getByIndex(i
), UNO_QUERY
);
122 xDestAppend
->appendByDescriptor( xColProp
);
127 sdbcx::ObjectType
OKeysHelper::appendObject( const OUString
& _rForName
, const Reference
< XPropertySet
>& descriptor
)
129 Reference
< XConnection
> xConnection
= m_pTable
->getConnection();
130 if ( !xConnection
.is() )
132 if ( m_pTable
->isNew() )
134 Reference
< XPropertySet
> xNewDescriptor( cloneDescriptor( descriptor
) );
135 cloneDescriptorColumns( descriptor
, xNewDescriptor
);
136 return xNewDescriptor
;
139 const ::dbtools::OPropertyMap
& rPropMap
= OMetaConnection::getPropMap();
140 sal_Int32 nKeyType
= getINT32(descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_TYPE
)));
141 sal_Int32 nUpdateRule
= 0, nDeleteRule
= 0;
142 OUString sReferencedName
;
144 if ( nKeyType
== KeyType::FOREIGN
)
146 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE
)) >>= sReferencedName
;
147 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_UPDATERULE
)) >>= nUpdateRule
;
148 descriptor
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_DELETERULE
)) >>= nDeleteRule
;
151 if ( m_pTable
->getKeyService().is() )
153 m_pTable
->getKeyService()->addKey(m_pTable
,descriptor
);
157 // if we're here, we belong to a table which is not new, i.e. already exists in the database.
158 // In this case, really append the new index.
160 aSql
.appendAscii("ALTER TABLE ");
161 OUString aQuote
= m_pTable
->getConnection()->getMetaData()->getIdentifierQuoteString( );
163 aSql
.append(composeTableName( m_pTable
->getConnection()->getMetaData(), m_pTable
, ::dbtools::eInTableDefinitions
, false, false, true ));
164 aSql
.appendAscii(" ADD ");
166 if ( nKeyType
== KeyType::PRIMARY
)
168 aSql
.appendAscii(" PRIMARY KEY (");
170 else if ( nKeyType
== KeyType::FOREIGN
)
172 aSql
.appendAscii(" 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
)
183 aSql
.appendAscii(",");
184 xColProp
.set(xColumns
->getByIndex(i
), css::uno::UNO_QUERY
);
185 aSql
.append( ::dbtools::quoteName( aQuote
,getString(xColProp
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_NAME
)))) );
188 aSql
.appendAscii(")");
190 if ( nKeyType
== KeyType::FOREIGN
)
192 aSql
.appendAscii(" REFERENCES ");
193 aSql
.append(::dbtools::quoteTableName(m_pTable
->getConnection()->getMetaData(),sReferencedName
,::dbtools::eInTableDefinitions
));
194 aSql
.appendAscii(" (");
196 for(sal_Int32 i
=0;i
<xColumns
->getCount();++i
)
199 aSql
.appendAscii(",");
200 xColumns
->getByIndex(i
) >>= xColProp
;
201 aSql
.append(::dbtools::quoteName( aQuote
,getString(xColProp
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_RELATEDCOLUMN
)))));
204 aSql
.appendAscii(")");
205 aSql
.append(getKeyRuleString(true ,nUpdateRule
));
206 aSql
.append(getKeyRuleString(false ,nDeleteRule
));
209 Reference
< XStatement
> xStmt
= m_pTable
->getConnection()->createStatement( );
210 xStmt
->execute(aSql
.makeStringAndClear());
212 // find the name which the database gave the new key
213 OUString
sNewName( _rForName
);
216 OUString aSchema
,aTable
;
217 m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_SCHEMANAME
)) >>= aSchema
;
218 m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_NAME
)) >>= aTable
;
219 Reference
< XResultSet
> xResult
;
220 sal_Int32 nColumn
= 12;
221 if ( nKeyType
== KeyType::FOREIGN
)
222 xResult
= m_pTable
->getMetaData()->getImportedKeys( m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_CATALOGNAME
))
227 xResult
= m_pTable
->getMetaData()->getPrimaryKeys( m_pTable
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_CATALOGNAME
))
234 Reference
< XRow
> xRow(xResult
,UNO_QUERY
);
235 while( xResult
->next() )
237 OUString sName
= xRow
->getString(nColumn
);
238 if ( !m_pElements
->exists(sName
) ) // this name wasn't inserted yet so it must be the new one
240 descriptor
->setPropertyValue( rPropMap
.getNameByIndex( PROPERTY_ID_NAME
), makeAny( sName
) );
245 ::comphelper::disposeComponent(xResult
);
248 catch(const SQLException
&)
252 m_pTable
->addKey(sNewName
,sdbcx::TKeyProperties(new sdbcx::KeyProperties(sReferencedName
,nKeyType
,nUpdateRule
,nDeleteRule
)));
254 return createObject( sNewName
);
257 OUString
OKeysHelper::getDropForeignKey() const
259 return OUString(" DROP CONSTRAINT ");
263 void OKeysHelper::dropObject(sal_Int32 _nPos
, const OUString
& _sElementName
)
265 Reference
< XConnection
> xConnection
= m_pTable
->getConnection();
266 if ( xConnection
.is() && !m_pTable
->isNew() )
268 Reference
<XPropertySet
> xKey(getObject(_nPos
),UNO_QUERY
);
269 if ( m_pTable
->getKeyService().is() )
271 m_pTable
->getKeyService()->dropKey(m_pTable
,xKey
);
276 aSql
.appendAscii("ALTER TABLE ");
278 aSql
.append( composeTableName( m_pTable
->getConnection()->getMetaData(), m_pTable
,::dbtools::eInTableDefinitions
, false, false, true ));
280 sal_Int32 nKeyType
= KeyType::PRIMARY
;
283 ::dbtools::OPropertyMap
& rPropMap
= OMetaConnection::getPropMap();
284 xKey
->getPropertyValue(rPropMap
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nKeyType
;
286 if ( KeyType::PRIMARY
== nKeyType
)
288 aSql
.appendAscii(" DROP PRIMARY KEY");
292 aSql
.append(getDropForeignKey());
293 const OUString aQuote
= m_pTable
->getConnection()->getMetaData()->getIdentifierQuoteString();
294 aSql
.append( ::dbtools::quoteName( aQuote
,_sElementName
) );
297 Reference
< XStatement
> xStmt
= m_pTable
->getConnection()->createStatement( );
300 xStmt
->execute(aSql
.makeStringAndClear());
301 ::comphelper::disposeComponent(xStmt
);
307 } // namespace connectivity
310 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */