xref: /trunk/main/connectivity/source/drivers/adabas/BTable.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include "adabas/BTable.hxx"
31 #include "adabas/BTables.hxx"
32 #include "adabas/BIndexes.hxx"
33 #include "adabas/BColumns.hxx"
34 #include "adabas/BKeys.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 <cppuhelper/typeprovider.hxx>
40 #include <com/sun/star/lang/DisposedException.hpp>
41 #include <com/sun/star/sdbc/ColumnValue.hpp>
42 #include <comphelper/sequence.hxx>
43 #include <comphelper/extract.hxx>
44 #include <comphelper/types.hxx>
45 #include "connectivity/dbtools.hxx"
46 #include "adabas/BCatalog.hxx"
47 
48 
49 using namespace ::comphelper;
50 using namespace connectivity::adabas;
51 using namespace connectivity;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::sdbcx;
55 using namespace ::com::sun::star::sdbc;
56 using namespace ::com::sun::star::container;
57 using namespace ::com::sun::star::lang;
58 
59 OAdabasTable::OAdabasTable( sdbcx::OCollection* _pTables,
60                            OAdabasConnection* _pConnection)
61     :OTable_TYPEDEF(_pTables,_pConnection,sal_True)
62     ,m_pConnection(_pConnection)
63 {
64     construct();
65 }
66 // -------------------------------------------------------------------------
67 OAdabasTable::OAdabasTable( sdbcx::OCollection* _pTables,
68                            OAdabasConnection* _pConnection,
69                     const ::rtl::OUString& _Name,
70                     const ::rtl::OUString& _Type,
71                     const ::rtl::OUString& _Description ,
72                     const ::rtl::OUString& _SchemaName,
73                     const ::rtl::OUString& _CatalogName
74                 ) : OTableHelper(   _pTables,
75                                     _pConnection,
76                                     sal_True,
77                                     _Name,
78                                     _Type,
79                                     _Description,
80                                     _SchemaName,
81                                     _CatalogName)
82                 ,m_pConnection(_pConnection)
83 {
84     construct();
85 }
86 // -----------------------------------------------------------------------------
87 sdbcx::OCollection* OAdabasTable::createColumns(const TStringVector& _rNames)
88 {
89     return new OColumns(this,m_aMutex,_rNames);
90 }
91 // -----------------------------------------------------------------------------
92 sdbcx::OCollection* OAdabasTable::createKeys(const TStringVector& _rNames)
93 {
94     return new OKeys(this,m_aMutex,_rNames);
95 }
96 // -----------------------------------------------------------------------------
97 sdbcx::OCollection* OAdabasTable::createIndexes(const TStringVector& _rNames)
98 {
99     return new OIndexes(this,m_aMutex,_rNames);
100 }
101 //--------------------------------------------------------------------------
102 Sequence< sal_Int8 > OAdabasTable::getUnoTunnelImplementationId()
103 {
104     static ::cppu::OImplementationId * pId = 0;
105     if (! pId)
106     {
107         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
108         if (! pId)
109         {
110             static ::cppu::OImplementationId aId;
111             pId = &aId;
112         }
113     }
114     return pId->getImplementationId();
115 }
116 
117 // com::sun::star::lang::XUnoTunnel
118 //------------------------------------------------------------------
119 sal_Int64 OAdabasTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
120 {
121     return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
122                 ? reinterpret_cast< sal_Int64 >( this )
123                 : OTable_TYPEDEF::getSomething(rId);
124 }
125 // -------------------------------------------------------------------------
126 // XAlterTable
127 void SAL_CALL OAdabasTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException)
128 {
129     ::osl::MutexGuard aGuard(m_aMutex);
130     checkDisposed(
131 #ifdef GCC
132         ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
133 #else
134         rBHelper.bDisposed
135 #endif
136         );
137 
138     if(m_pColumns && !m_pColumns->hasByName(colName))
139         throw NoSuchElementException(colName,*this);
140 
141 
142     if(!isNew())
143     {
144         beginTransAction();
145 
146         try
147         {
148             // first we have to check what should be altered
149             Reference<XPropertySet> xProp;
150             m_pColumns->getByName(colName) >>= xProp;
151             // first check the types
152             sal_Int32 nOldType = 0,nNewType = 0,nOldPrec = 0,nNewPrec = 0,nOldScale = 0,nNewScale = 0;
153 
154             xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))         >>= nOldType;
155             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))    >>= nNewType;
156             // and precsions and scale
157             xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))    >>= nOldPrec;
158             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))>>= nNewPrec;
159             xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))        >>= nOldScale;
160             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))   >>= nNewScale;
161 
162             if(nOldType != nNewType || nOldPrec != nNewPrec || nOldScale != nNewScale)
163                 alterColumnType(colName,descriptor);
164 
165             // second: check the "is nullable" value
166             sal_Int32 nOldNullable = 0,nNewNullable = 0;
167             xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))       >>= nOldNullable;
168             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))  >>= nNewNullable;
169             if(nNewNullable != nOldNullable)
170                 alterNotNullValue(nNewNullable,colName);
171 
172             // third: check the default values
173             ::rtl::OUString sNewDefault,sOldDefault;
174             xProp->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))     >>= sOldDefault;
175             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sNewDefault;
176 
177             if(sOldDefault.getLength())
178             {
179                 if(sNewDefault.getLength() && sOldDefault != sNewDefault)
180                     alterDefaultValue(sNewDefault,colName);
181                 else if(!sNewDefault.getLength())
182                     dropDefaultValue(colName);
183             }
184             else if(!sOldDefault.getLength() && sNewDefault.getLength())
185                 addDefaultValue(sNewDefault,colName);
186 
187             // now we should look if the name of the column changed
188             ::rtl::OUString sNewColumnName;
189             descriptor->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName;
190             if(!sNewColumnName.equalsIgnoreAsciiCase(colName))
191             {
192                 const ::rtl::OUString sQuote = m_pConnection->getMetaData()->getIdentifierQuoteString(  );
193                 const ::rtl::OUString& sDot = OAdabasCatalog::getDot();
194 
195                 ::rtl::OUString sSql = ::rtl::OUString::createFromAscii("RENAME COLUMN ") ;
196                 sSql += ::dbtools::quoteName(sQuote,m_SchemaName) + sDot + ::dbtools::quoteName(sQuote,m_Name);
197                 sSql += sDot + ::dbtools::quoteName(sQuote,colName);
198                 sSql += ::rtl::OUString::createFromAscii(" TO ");
199                 sSql += ::dbtools::quoteName(sQuote,sNewColumnName);
200 
201                 Reference< XStatement > xStmt = m_pConnection->createStatement(  );
202                 if(xStmt.is())
203                 {
204                     xStmt->execute(sSql);
205                     ::comphelper::disposeComponent(xStmt);
206                 }
207             }
208             m_pColumns->refresh();
209         }
210         catch(const SQLException&)
211         {
212             rollbackTransAction();
213             throw;
214         }
215         endTransAction();
216     }
217     else
218     {
219         if(m_pColumns)
220         {
221             m_pColumns->dropByName(colName);
222             m_pColumns->appendByDescriptor(descriptor);
223         }
224     }
225 
226 }
227 // -------------------------------------------------------------------------
228 ::rtl::OUString SAL_CALL OAdabasTable::getName() throw(::com::sun::star::uno::RuntimeException)
229 {
230     ::rtl::OUString sName = m_SchemaName;
231     if(m_SchemaName.getLength())
232     {
233         const ::rtl::OUString& sDot = OAdabasCatalog::getDot();
234         sName += sDot;
235     }
236     sName += m_Name;
237     return sName;
238 }
239 // -----------------------------------------------------------------------------
240 void OAdabasTable::alterColumnType(const ::rtl::OUString& _rColName, const Reference<XPropertySet>& _xDescriptor)
241 {
242     ::rtl::OUString sSql = getAlterTableColumnPart(_rColName);
243     sSql += ::rtl::OUString::createFromAscii(" ");
244     sSql += OTables::getColumnSqlType(_xDescriptor);
245 
246     Reference< XStatement > xStmt = m_pConnection->createStatement(  );
247     if(xStmt.is())
248     {
249         xStmt->execute(sSql);
250         ::comphelper::disposeComponent(xStmt);
251     }
252 }
253 // -----------------------------------------------------------------------------
254 void OAdabasTable::alterNotNullValue(sal_Int32 _nNewNullable,const ::rtl::OUString& _rColName)
255 {
256     ::rtl::OUString sSql = getAlterTableColumnPart(_rColName);
257 
258     if(_nNewNullable == ColumnValue::NO_NULLS)
259     {
260         sSql += ::rtl::OUString::createFromAscii(" NOT NULL");
261     }
262     else
263     {
264         sSql += ::rtl::OUString::createFromAscii(" DEFAULT NULL");
265     }
266 
267     Reference< XStatement > xStmt = m_pConnection->createStatement();
268     if(xStmt.is())
269     {
270         xStmt->execute(sSql);
271         ::comphelper::disposeComponent(xStmt);
272     }
273 }
274 // -----------------------------------------------------------------------------
275 void OAdabasTable::alterDefaultValue(const ::rtl::OUString& _sNewDefault,const ::rtl::OUString& _rColName)
276 {
277     ::rtl::OUString sSql = getAlterTableColumnPart(_rColName);
278     sSql += ::rtl::OUString::createFromAscii(" ALTER ") + _sNewDefault;
279 
280     Reference< XStatement > xStmt = m_pConnection->createStatement();
281     if(xStmt.is())
282     {
283         xStmt->execute(sSql);
284         ::comphelper::disposeComponent(xStmt);
285     }
286 }
287 // -----------------------------------------------------------------------------
288 void OAdabasTable::dropDefaultValue(const ::rtl::OUString& _rColName)
289 {
290     ::rtl::OUString sSql = getAlterTableColumnPart(_rColName);
291     sSql += ::rtl::OUString::createFromAscii(" DROP DEFAULT");
292 
293     Reference< XStatement > xStmt = m_pConnection->createStatement();
294     if(xStmt.is())
295     {
296         xStmt->execute(sSql);
297         ::comphelper::disposeComponent(xStmt);
298     }
299 }
300 // -----------------------------------------------------------------------------
301 void OAdabasTable::addDefaultValue(const ::rtl::OUString& _sNewDefault,const ::rtl::OUString& _rColName)
302 {
303     ::rtl::OUString sSql = getAlterTableColumnPart(_rColName);
304     sSql += ::rtl::OUString::createFromAscii(" ADD ") + _sNewDefault;
305 
306     Reference< XStatement > xStmt = m_pConnection->createStatement();
307     if(xStmt.is())
308     {
309         xStmt->execute(sSql);
310         ::comphelper::disposeComponent(xStmt);
311     }
312 }
313 // -----------------------------------------------------------------------------
314 void OAdabasTable::beginTransAction()
315 {
316     try
317     {
318         Reference< XStatement > xStmt = m_pConnection->createStatement();
319         if(xStmt.is())
320         {
321             xStmt->execute(::rtl::OUString::createFromAscii("SUBTRANS BEGIN") );
322             ::comphelper::disposeComponent(xStmt);
323         }
324     }
325     catch(const Exception&)
326     {
327     }
328 }
329 // -----------------------------------------------------------------------------
330 void OAdabasTable::endTransAction()
331 {
332     try
333     {
334         Reference< XStatement > xStmt = m_pConnection->createStatement();
335         if(xStmt.is())
336         {
337             xStmt->execute(::rtl::OUString::createFromAscii("SUBTRANS END") );
338             ::comphelper::disposeComponent(xStmt);
339         }
340     }
341     catch(const Exception&)
342     {
343     }
344 }
345 // -----------------------------------------------------------------------------
346 void OAdabasTable::rollbackTransAction()
347 {
348     try
349     {
350         Reference< XStatement > xStmt = m_pConnection->createStatement();
351         if(xStmt.is())
352         {
353             xStmt->execute(::rtl::OUString::createFromAscii("SUBTRANS ROLLBACK") );
354             ::comphelper::disposeComponent(xStmt);
355         }
356     }
357     catch(const Exception&)
358     {
359     }
360 }
361 // -----------------------------------------------------------------------------
362 ::rtl::OUString OAdabasTable::getAlterTableColumnPart(const ::rtl::OUString& _rsColumnName )
363 {
364     ::rtl::OUString sSql = ::rtl::OUString::createFromAscii("ALTER TABLE ");
365     const ::rtl::OUString sQuote = m_pConnection->getMetaData()->getIdentifierQuoteString(  );
366     const ::rtl::OUString& sDot = OAdabasCatalog::getDot();
367 
368     sSql += ::dbtools::quoteName(sQuote,m_SchemaName) + sDot + ::dbtools::quoteName(sQuote,m_Name)
369          + ::rtl::OUString::createFromAscii(" COLUMN ")
370          + ::dbtools::quoteName(sQuote,_rsColumnName);
371     return sSql;
372 }
373 // -----------------------------------------------------------------------------
374 
375 
376 
377