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 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 // ------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 83 sdbcx::OCollection* OAdabasTable::createColumns(const TStringVector& _rNames) 84 { 85 return new OColumns(this,m_aMutex,_rNames); 86 } 87 // ----------------------------------------------------------------------------- 88 sdbcx::OCollection* OAdabasTable::createKeys(const TStringVector& _rNames) 89 { 90 return new OKeys(this,m_aMutex,_rNames); 91 } 92 // ----------------------------------------------------------------------------- 93 sdbcx::OCollection* OAdabasTable::createIndexes(const TStringVector& _rNames) 94 { 95 return new OIndexes(this,m_aMutex,_rNames); 96 } 97 //-------------------------------------------------------------------------- 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 //------------------------------------------------------------------ 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 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 // ------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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