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