LibreOffice Module connectivity (master) 1
TKeys.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21#include <TKey.hxx>
23#include <com/sun/star/sdb/tools/XKeyAlteration.hpp>
24#include <com/sun/star/sdbc/XRow.hpp>
25#include <com/sun/star/sdbc/XResultSet.hpp>
26#include <com/sun/star/sdbcx/KeyType.hpp>
27#include <com/sun/star/sdbc/KeyRule.hpp>
28#include <com/sun/star/sdbc/SQLException.hpp>
30#include <comphelper/types.hxx>
31#include <TConnection.hxx>
32
33namespace connectivity
34{
35using namespace comphelper;
36using namespace connectivity::sdbcx;
37using namespace dbtools;
38using namespace ::com::sun::star::uno;
39using namespace ::com::sun::star::beans;
40using namespace ::com::sun::star::sdbcx;
41using namespace ::com::sun::star::sdbc;
42using namespace ::com::sun::star::container;
43using namespace ::com::sun::star::lang;
44
45
47 ::osl::Mutex& _rMutex,
48 const ::std::vector< OUString>& _rVector
49 ) : OKeys_BASE(*_pTable,true,_rMutex,_rVector,true)
50 ,m_pTable(_pTable)
51{
52}
53
55{
57
58 if(!_rName.isEmpty())
59 {
60 xRet = new OTableKeyHelper(m_pTable,_rName,m_pTable->getKeyProperties(_rName));
61 }
62
63 if(!xRet.is()) // we have a primary key with a system name
64 {
65 xRet = new OTableKeyHelper(m_pTable,_rName,m_pTable->getKeyProperties(_rName));
66 }
67
68 return xRet;
69}
70
72{
74}
75
76Reference< XPropertySet > OKeysHelper::createDescriptor()
77{
78 return new OTableKeyHelper(m_pTable);
79}
80
83static OUString getKeyRuleString(bool _bUpdate,sal_Int32 _nKeyRule)
84{
85 const char* pKeyRule = nullptr;
86 switch ( _nKeyRule )
87 {
88 case KeyRule::CASCADE:
89 pKeyRule = _bUpdate ? " ON UPDATE CASCADE " : " ON DELETE CASCADE ";
90 break;
91 case KeyRule::RESTRICT:
92 pKeyRule = _bUpdate ? " ON UPDATE RESTRICT " : " ON DELETE RESTRICT ";
93 break;
94 case KeyRule::SET_NULL:
95 pKeyRule = _bUpdate ? " ON UPDATE SET NULL " : " ON DELETE SET NULL ";
96 break;
97 case KeyRule::SET_DEFAULT:
98 pKeyRule = _bUpdate ? " ON UPDATE SET DEFAULT " : " ON DELETE SET DEFAULT ";
99 break;
100 default:
101 ;
102 }
103 OUString sRet;
104 if ( pKeyRule )
105 sRet = OUString::createFromAscii(pKeyRule);
106 return sRet;
107}
108
109void OKeysHelper::cloneDescriptorColumns( const sdbcx::ObjectType& _rSourceDescriptor, const sdbcx::ObjectType& _rDestDescriptor )
110{
111 Reference< XColumnsSupplier > xColSupp( _rSourceDescriptor, UNO_QUERY_THROW );
112 Reference< XIndexAccess > xSourceCols( xColSupp->getColumns(), UNO_QUERY_THROW );
113
114 xColSupp.set( _rDestDescriptor, UNO_QUERY_THROW );
115 Reference< XAppend > xDestAppend( xColSupp->getColumns(), UNO_QUERY_THROW );
116
117 sal_Int32 nCount = xSourceCols->getCount();
118 for ( sal_Int32 i=0; i< nCount; ++i )
119 {
120 Reference< XPropertySet > xColProp( xSourceCols->getByIndex(i), UNO_QUERY );
121 xDestAppend->appendByDescriptor( xColProp );
122 }
123}
124
125// XAppend
126sdbcx::ObjectType OKeysHelper::appendObject( const OUString& _rForName, const Reference< XPropertySet >& descriptor )
127{
128 Reference< XConnection> xConnection = m_pTable->getConnection();
129 if ( !xConnection.is() )
130 return nullptr;
131 if ( m_pTable->isNew() )
132 {
133 Reference< XPropertySet > xNewDescriptor( cloneDescriptor( descriptor ) );
134 cloneDescriptorColumns( descriptor, xNewDescriptor );
135 return xNewDescriptor;
136 }
137
138 const ::dbtools::OPropertyMap& rPropMap = OMetaConnection::getPropMap();
139 sal_Int32 nKeyType = getINT32(descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)));
140 sal_Int32 nUpdateRule = 0, nDeleteRule = 0;
141 OUString sReferencedName;
142
143 if ( nKeyType == KeyType::FOREIGN )
144 {
145 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_REFERENCEDTABLE)) >>= sReferencedName;
146 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_UPDATERULE)) >>= nUpdateRule;
147 descriptor->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_DELETERULE)) >>= nDeleteRule;
148 }
149
150 if ( m_pTable->getKeyService().is() )
151 {
152 m_pTable->getKeyService()->addKey(m_pTable,descriptor);
153 }
154 else
155 {
156 // if we're here, we belong to a table which is not new, i.e. already exists in the database.
157 // In this case, really append the new index.
158 OUStringBuffer aSql("ALTER TABLE ");
159 OUString aQuote = m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString( );
160
161 aSql.append(composeTableName( m_pTable->getConnection()->getMetaData(), m_pTable, ::dbtools::EComposeRule::InTableDefinitions, true )
162 + " ADD ");
163
164 if ( nKeyType == KeyType::PRIMARY )
165 {
166 aSql.append(" PRIMARY KEY (");
167 }
168 else if ( nKeyType == KeyType::FOREIGN )
169 {
170 aSql.append(" FOREIGN KEY (");
171 }
172 else
173 throw SQLException();
174
175 Reference<XColumnsSupplier> xColumnSup(descriptor,UNO_QUERY);
176 Reference<XIndexAccess> xColumns(xColumnSup->getColumns(),UNO_QUERY);
177 Reference< XPropertySet > xColProp;
178 for(sal_Int32 i = 0 ; i < xColumns->getCount() ; ++i)
179 {
180 if ( i > 0 )
181 aSql.append(",");
182 xColProp.set(xColumns->getByIndex(i), css::uno::UNO_QUERY);
183 aSql.append( ::dbtools::quoteName( aQuote,getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)))) );
184
185 }
186 aSql.append(")");
187
188 if ( nKeyType == KeyType::FOREIGN )
189 {
190 aSql.append(" REFERENCES "
191 + ::dbtools::quoteTableName(m_pTable->getConnection()->getMetaData(),sReferencedName,::dbtools::EComposeRule::InTableDefinitions)
192 + " (");
193
194 for(sal_Int32 i=0;i<xColumns->getCount();++i)
195 {
196 if ( i > 0 )
197 aSql.append(",");
198 xColumns->getByIndex(i) >>= xColProp;
199 aSql.append(::dbtools::quoteName( aQuote,getString(xColProp->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_RELATEDCOLUMN)))));
200
201 }
202 aSql.append(")"
203 + getKeyRuleString(true ,nUpdateRule)
204 + getKeyRuleString(false ,nDeleteRule));
205 }
206
207 Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( );
208 xStmt->execute(aSql.makeStringAndClear());
209 }
210 // find the name which the database gave the new key
211 OUString sNewName( _rForName );
212 try
213 {
214 OUString aSchema,aTable;
215 m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_SCHEMANAME)) >>= aSchema;
216 m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_NAME)) >>= aTable;
217 Reference< XResultSet > xResult;
218 sal_Int32 nColumn = 12;
219 if ( nKeyType == KeyType::FOREIGN )
220 xResult = m_pTable->getMetaData()->getImportedKeys( m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
221 ,aSchema
222 ,aTable);
223 else
224 {
225 xResult = m_pTable->getMetaData()->getPrimaryKeys( m_pTable->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_CATALOGNAME))
226 ,aSchema
227 ,aTable);
228 nColumn = 6;
229 }
230 if ( xResult.is() )
231 {
232 Reference< XRow > xRow(xResult,UNO_QUERY);
233 while( xResult->next() )
234 {
235 OUString sName = xRow->getString(nColumn);
236 if ( !m_pElements->exists(sName) ) // this name wasn't inserted yet so it must be the new one
237 {
238 descriptor->setPropertyValue( rPropMap.getNameByIndex( PROPERTY_ID_NAME ), Any( sName ) );
239 sNewName = sName;
240 break;
241 }
242 }
243 ::comphelper::disposeComponent(xResult);
244 }
245 }
246 catch(const SQLException&)
247 {
248 }
249
250 m_pTable->addKey(sNewName,std::make_shared<sdbcx::KeyProperties>(sReferencedName,nKeyType,nUpdateRule,nDeleteRule));
251
252 return createObject( sNewName );
253}
254
256{
257 return " DROP CONSTRAINT ";
258}
259
260// XDrop
261void OKeysHelper::dropObject(sal_Int32 _nPos, const OUString& _sElementName)
262{
263 Reference< XConnection> xConnection = m_pTable->getConnection();
264 if ( !xConnection.is() || m_pTable->isNew() )
265 return;
266
267 Reference<XPropertySet> xKey(getObject(_nPos),UNO_QUERY);
268 if ( m_pTable->getKeyService().is() )
269 {
270 m_pTable->getKeyService()->dropKey(m_pTable,xKey);
271 }
272 else
273 {
274 OUStringBuffer aSql(
275 "ALTER TABLE "
276 + composeTableName( m_pTable->getConnection()->getMetaData(), m_pTable,::dbtools::EComposeRule::InTableDefinitions, true ));
277
278 sal_Int32 nKeyType = KeyType::PRIMARY;
279 if ( xKey.is() )
280 {
282 xKey->getPropertyValue(rPropMap.getNameByIndex(PROPERTY_ID_TYPE)) >>= nKeyType;
283 }
284 if ( KeyType::PRIMARY == nKeyType )
285 {
286 aSql.append(" DROP PRIMARY KEY");
287 }
288 else
289 {
290 aSql.append(getDropForeignKey());
291 const OUString aQuote = m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString();
292 aSql.append( ::dbtools::quoteName( aQuote,_sElementName) );
293 }
294
295 Reference< XStatement > xStmt = m_pTable->getConnection()->createStatement( );
296 if ( xStmt.is() )
297 {
298 xStmt->execute(aSql.makeStringAndClear());
299 ::comphelper::disposeComponent(xStmt);
300 }
301 }
302}
303
304} // namespace connectivity
305
306
307/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OTableHelper * m_pTable
Definition: TKeys.hxx:32
OKeysHelper(OTableHelper *_pTable, ::osl::Mutex &_rMutex, const ::std::vector< OUString > &_rVector)
Definition: TKeys.cxx:46
virtual sdbcx::ObjectType createObject(const OUString &_rName) override
Definition: TKeys.cxx:54
virtual OUString getDropForeignKey() const
Definition: TKeys.cxx:255
virtual void impl_refresh() override
Definition: TKeys.cxx:71
static void cloneDescriptorColumns(const sdbcx::ObjectType &_rSourceDescriptor, const sdbcx::ObjectType &_rDestDescriptor)
Definition: TKeys.cxx:109
virtual void dropObject(sal_Int32 _nPos, const OUString &_sElementName) override
Definition: TKeys.cxx:261
virtual css::uno::Reference< css::beans::XPropertySet > createDescriptor() override
Definition: TKeys.cxx:76
virtual sdbcx::ObjectType appendObject(const OUString &_rForName, const css::uno::Reference< css::beans::XPropertySet > &descriptor) override
appends an object described by a descriptor, under a given name
Definition: TKeys.cxx:126
::dbtools::OPropertyMap & getPropMap()
Definition: TConnection.cxx:68
css::uno::Reference< css::sdbc::XConnection > const & getConnection() const
void addKey(const OUString &_sName, const std::shared_ptr< sdbcx::KeyProperties > &_aKeyProperties)
virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > getMetaData() const override
std::shared_ptr< sdbcx::KeyProperties > getKeyProperties(const OUString &_sName) const
css::uno::Reference< css::sdb::tools::XKeyAlteration > const & getKeyService() const
virtual void refreshKeys() override
ObjectType getObject(sal_Int32 _nIndex)
return the object, if not existent it creates it.
::std::unique_ptr< IObjectCollection > m_pElements
Definition: VCollection.hxx:91
ObjectType cloneDescriptor(const ObjectType &_descriptor)
clones the given descriptor
const OUString & getNameByIndex(sal_Int32 _nIndex) const
Definition: propertyids.cxx:95
int nCount
OUString sName
sal_Int32 getINT32(const Any &_rAny)
OUString getString(const Any &_rAny)
css::uno::Reference< css::beans::XPropertySet > ObjectType
Definition: VCollection.hxx:59
static OUString getKeyRuleString(bool _bUpdate, sal_Int32 _nKeyRule)
returns the keyrule string for the primary key
Definition: TKeys.cxx:83
OUString composeTableName(const Reference< XDatabaseMetaData > &_rxMetaData, const OUString &_rCatalog, const OUString &_rSchema, const OUString &_rName, bool _bQuote, EComposeRule _eComposeRule)
Definition: dbtools.cxx:1286
OUString quoteTableName(const Reference< XDatabaseMetaData > &_rxMeta, const OUString &_rName, EComposeRule _eComposeRule)
Definition: dbtools.cxx:853
OUString quoteName(std::u16string_view _rQuote, const OUString &_rName)
quote the given name with the given quote string.
int i
#define PROPERTY_ID_NAME
Definition: propertyids.hxx:50
#define PROPERTY_ID_REFERENCEDTABLE
Definition: propertyids.hxx:61
#define PROPERTY_ID_TYPE
Definition: propertyids.hxx:51
#define PROPERTY_ID_CATALOGNAME
Definition: propertyids.hxx:70
#define PROPERTY_ID_RELATEDCOLUMN
Definition: propertyids.hxx:75
#define PROPERTY_ID_SCHEMANAME
Definition: propertyids.hxx:69
#define PROPERTY_ID_DELETERULE
Definition: propertyids.hxx:63
#define PROPERTY_ID_UPDATERULE
Definition: propertyids.hxx:62
sal_Int32 _nPos