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