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 <connectivity/dbexception.hxx> 31 #include <comphelper/types.hxx> 32 #include <cppuhelper/exc_hlp.hxx> 33 #include <osl/diagnose.h> 34 #include <com/sun/star/sdb/SQLContext.hpp> 35 #include <com/sun/star/sdbc/SQLWarning.hpp> 36 #include <com/sun/star/sdb/SQLErrorEvent.hpp> 37 #include "TConnection.hxx" 38 #include "resource/common_res.hrc" 39 #include "resource/sharedresources.hxx" 40 41 //......................................................................... 42 namespace dbtools 43 { 44 //......................................................................... 45 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::sdb; 48 using namespace ::com::sun::star::sdbc; 49 using namespace ::comphelper; 50 using namespace ::connectivity; 51 52 //============================================================================== 53 //= SQLExceptionInfo - encapsulating the type info of an SQLException-derived class 54 //============================================================================== 55 //------------------------------------------------------------------------------ 56 SQLExceptionInfo::SQLExceptionInfo() 57 :m_eType(UNDEFINED) 58 { 59 } 60 61 //------------------------------------------------------------------------------ 62 SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdbc::SQLException& _rError) 63 { 64 m_aContent <<= _rError; 65 implDetermineType(); 66 } 67 68 //------------------------------------------------------------------------------ 69 SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdbc::SQLWarning& _rError) 70 { 71 m_aContent <<= _rError; 72 implDetermineType(); 73 } 74 75 //------------------------------------------------------------------------------ 76 SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdb::SQLContext& _rError) 77 { 78 m_aContent <<= _rError; 79 implDetermineType(); 80 } 81 82 //------------------------------------------------------------------------------ 83 SQLExceptionInfo::SQLExceptionInfo( const ::rtl::OUString& _rSimpleErrorMessage ) 84 { 85 SQLException aError; 86 aError.Message = _rSimpleErrorMessage; 87 m_aContent <<= aError; 88 implDetermineType(); 89 } 90 91 //------------------------------------------------------------------------------ 92 SQLExceptionInfo::SQLExceptionInfo(const SQLExceptionInfo& _rCopySource) 93 :m_aContent(_rCopySource.m_aContent) 94 ,m_eType(_rCopySource.m_eType) 95 { 96 } 97 98 //------------------------------------------------------------------------------ 99 const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdbc::SQLException& _rError) 100 { 101 m_aContent <<= _rError; 102 implDetermineType(); 103 return *this; 104 } 105 106 //------------------------------------------------------------------------------ 107 const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdbc::SQLWarning& _rError) 108 { 109 m_aContent <<= _rError; 110 implDetermineType(); 111 return *this; 112 } 113 114 //------------------------------------------------------------------------------ 115 const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdb::SQLContext& _rError) 116 { 117 m_aContent <<= _rError; 118 implDetermineType(); 119 return *this; 120 } 121 122 //------------------------------------------------------------------------------ 123 const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::sdb::SQLErrorEvent& _rErrorEvent) 124 { 125 m_aContent = _rErrorEvent.Reason; 126 implDetermineType(); 127 return *this; 128 } 129 130 //------------------------------------------------------------------------------ 131 const SQLExceptionInfo& SQLExceptionInfo::operator=(const ::com::sun::star::uno::Any& _rCaughtSQLException) 132 { 133 m_aContent = _rCaughtSQLException; 134 implDetermineType(); 135 return *this; 136 } 137 138 //------------------------------------------------------------------------------ 139 SQLExceptionInfo::SQLExceptionInfo(const ::com::sun::star::sdb::SQLErrorEvent& _rError) 140 { 141 m_aContent = _rError.Reason; 142 implDetermineType(); 143 } 144 145 //------------------------------------------------------------------------------ 146 SQLExceptionInfo::SQLExceptionInfo(const staruno::Any& _rError) 147 { 148 const staruno::Type& aSQLExceptionType = ::getCppuType(reinterpret_cast< ::com::sun::star::sdbc::SQLException*>(NULL)); 149 sal_Bool bValid = isAssignableFrom(aSQLExceptionType, _rError.getValueType()); 150 if (bValid) 151 m_aContent = _rError; 152 // no assertion here : if used with the NextException member of an SQLException bValid==sal_False is allowed. 153 154 implDetermineType(); 155 } 156 157 //------------------------------------------------------------------------------ 158 void SQLExceptionInfo::implDetermineType() 159 { 160 staruno::Type aContentType = m_aContent.getValueType(); 161 162 const Type& aSQLExceptionType = ::getCppuType( reinterpret_cast< SQLException* >( NULL ) ); 163 const Type& aSQLWarningType = ::getCppuType( reinterpret_cast< SQLWarning* >( NULL ) ); 164 const Type& aSQLContextType = ::getCppuType( reinterpret_cast< SQLContext* >( NULL ) ); 165 166 if ( isAssignableFrom( aSQLContextType, m_aContent.getValueType() ) ) 167 m_eType = SQL_CONTEXT; 168 else if ( isAssignableFrom( aSQLWarningType, m_aContent.getValueType() ) ) 169 m_eType = SQL_WARNING; 170 else if ( isAssignableFrom( aSQLExceptionType, m_aContent.getValueType() ) ) 171 m_eType = SQL_EXCEPTION; 172 else 173 { 174 m_eType = UNDEFINED; 175 m_aContent.clear(); 176 } 177 } 178 179 //------------------------------------------------------------------------------ 180 sal_Bool SQLExceptionInfo::isKindOf(TYPE _eType) const 181 { 182 switch (_eType) 183 { 184 case SQL_CONTEXT: 185 return (m_eType == SQL_CONTEXT); 186 case SQL_WARNING: 187 return (m_eType == SQL_CONTEXT) || (m_eType == SQL_WARNING); 188 case SQL_EXCEPTION: 189 return (m_eType == SQL_CONTEXT) || (m_eType == SQL_WARNING) || (m_eType == SQL_EXCEPTION); 190 case UNDEFINED: 191 return (m_eType == UNDEFINED); 192 } 193 return sal_False; 194 } 195 196 //------------------------------------------------------------------------------ 197 SQLExceptionInfo::operator const ::com::sun::star::sdbc::SQLException*() const 198 { 199 OSL_ENSURE(isKindOf(SQL_EXCEPTION), "SQLExceptionInfo::operator SQLException* : invalid call !"); 200 return reinterpret_cast<const ::com::sun::star::sdbc::SQLException*>(m_aContent.getValue()); 201 } 202 203 //------------------------------------------------------------------------------ 204 SQLExceptionInfo::operator const ::com::sun::star::sdbc::SQLWarning*() const 205 { 206 OSL_ENSURE(isKindOf(SQL_WARNING), "SQLExceptionInfo::operator SQLException* : invalid call !"); 207 return reinterpret_cast<const ::com::sun::star::sdbc::SQLWarning*>(m_aContent.getValue()); 208 } 209 210 //------------------------------------------------------------------------------ 211 SQLExceptionInfo::operator const ::com::sun::star::sdb::SQLContext*() const 212 { 213 OSL_ENSURE(isKindOf(SQL_CONTEXT), "SQLExceptionInfo::operator SQLException* : invalid call !"); 214 return reinterpret_cast<const ::com::sun::star::sdb::SQLContext*>(m_aContent.getValue()); 215 } 216 217 //------------------------------------------------------------------------------ 218 void SQLExceptionInfo::prepend( const ::rtl::OUString& _rErrorMessage, const sal_Char* _pAsciiSQLState, const sal_Int32 _nErrorCode ) 219 { 220 SQLException aException; 221 aException.Message = _rErrorMessage; 222 aException.ErrorCode = _nErrorCode; 223 aException.SQLState = ::rtl::OUString::createFromAscii( _pAsciiSQLState ? _pAsciiSQLState : "S1000" ); 224 aException.NextException = m_aContent; 225 m_aContent <<= aException; 226 227 m_eType = SQL_EXCEPTION; 228 } 229 230 //------------------------------------------------------------------------------ 231 void SQLExceptionInfo::append( TYPE _eType, const ::rtl::OUString& _rErrorMessage, const sal_Char* _pAsciiSQLState, const sal_Int32 _nErrorCode ) 232 { 233 // create the to-be-appended exception 234 Any aAppend; 235 switch ( _eType ) 236 { 237 case SQL_EXCEPTION: aAppend <<= SQLException(); break; 238 case SQL_WARNING: aAppend <<= SQLWarning(); break; 239 case SQL_CONTEXT: aAppend <<= SQLContext(); break; 240 default: 241 OSL_ENSURE( false, "SQLExceptionInfo::append: invalid exception type: this will crash!" ); 242 break; 243 } 244 245 SQLException* pAppendException( static_cast< SQLException* >( const_cast< void* >( aAppend.getValue() ) ) ); 246 pAppendException->Message = _rErrorMessage; 247 pAppendException->SQLState = ::rtl::OUString::createFromAscii( _pAsciiSQLState ); 248 pAppendException->ErrorCode = _nErrorCode; 249 250 // find the end of the current chain 251 Any* pChainIterator = &m_aContent; 252 SQLException* pLastException = NULL; 253 const Type& aSQLExceptionType( ::getCppuType< SQLException >() ); 254 while ( pChainIterator ) 255 { 256 if ( !pChainIterator->hasValue() ) 257 break; 258 259 if ( !isAssignableFrom( aSQLExceptionType, pChainIterator->getValueType() ) ) 260 break; 261 262 pLastException = static_cast< SQLException* >( const_cast< void* >( pChainIterator->getValue() ) ); 263 pChainIterator = &pLastException->NextException; 264 } 265 266 // append 267 if ( pLastException ) 268 pLastException->NextException = aAppend; 269 else 270 { 271 m_aContent = aAppend; 272 m_eType = _eType; 273 } 274 } 275 276 //------------------------------------------------------------------------------ 277 void SQLExceptionInfo::doThrow() 278 { 279 if ( m_aContent.getValueTypeClass() == TypeClass_EXCEPTION ) 280 ::cppu::throwException( m_aContent ); 281 throw RuntimeException(); 282 } 283 284 //============================================================================== 285 //= SQLExceptionIteratorHelper 286 //============================================================================== 287 288 //------------------------------------------------------------------------------ 289 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const SQLExceptionInfo& _rChainStart ) 290 :m_pCurrent( NULL ) 291 ,m_eCurrentType( SQLExceptionInfo::UNDEFINED ) 292 { 293 if ( _rChainStart.isValid() ) 294 { 295 m_pCurrent = (const SQLException*)_rChainStart; 296 m_eCurrentType = _rChainStart.getType(); 297 } 298 } 299 300 //------------------------------------------------------------------------------ 301 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdbc::SQLException& _rChainStart ) 302 :m_pCurrent( &_rChainStart ) 303 ,m_eCurrentType( SQLExceptionInfo::SQL_EXCEPTION ) 304 { 305 } 306 307 //------------------------------------------------------------------------------ 308 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdbc::SQLWarning& _rChainStart ) 309 :m_pCurrent( &_rChainStart ) 310 ,m_eCurrentType( SQLExceptionInfo::SQL_WARNING ) 311 { 312 } 313 314 //------------------------------------------------------------------------------ 315 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const ::com::sun::star::sdb::SQLContext& _rChainStart ) 316 :m_pCurrent( &_rChainStart ) 317 ,m_eCurrentType( SQLExceptionInfo::SQL_CONTEXT ) 318 { 319 } 320 321 //------------------------------------------------------------------------------ 322 void SQLExceptionIteratorHelper::current( SQLExceptionInfo& _out_rInfo ) const 323 { 324 switch ( m_eCurrentType ) 325 { 326 case SQLExceptionInfo::SQL_EXCEPTION: 327 _out_rInfo = *m_pCurrent; 328 break; 329 330 case SQLExceptionInfo::SQL_WARNING: 331 _out_rInfo = *static_cast< const SQLWarning* >( m_pCurrent ); 332 break; 333 334 case SQLExceptionInfo::SQL_CONTEXT: 335 _out_rInfo = *static_cast< const SQLContext* >( m_pCurrent ); 336 break; 337 338 default: 339 _out_rInfo = Any(); 340 break; 341 } 342 } 343 344 //------------------------------------------------------------------------------ 345 const ::com::sun::star::sdbc::SQLException* SQLExceptionIteratorHelper::next() 346 { 347 OSL_ENSURE( hasMoreElements(), "SQLExceptionIteratorHelper::next : invalid call (please use hasMoreElements)!" ); 348 349 const ::com::sun::star::sdbc::SQLException* pReturn = current(); 350 if ( !m_pCurrent ) 351 return pReturn; 352 353 // check for the next element within the chain 354 const Type aTypeException( ::cppu::UnoType< SQLException >::get() ); 355 356 Type aNextElementType = m_pCurrent->NextException.getValueType(); 357 if ( !isAssignableFrom( aTypeException, aNextElementType ) ) 358 { 359 // no SQLException at all in the next chain element 360 m_pCurrent = NULL; 361 m_eCurrentType = SQLExceptionInfo::UNDEFINED; 362 return pReturn; 363 } 364 365 m_pCurrent = static_cast< const SQLException* >( m_pCurrent->NextException.getValue() ); 366 367 // no finally determine the proper type of the exception 368 const Type aTypeContext( ::cppu::UnoType< SQLContext >::get() ); 369 if ( isAssignableFrom( aTypeContext, aNextElementType ) ) 370 { 371 m_eCurrentType = SQLExceptionInfo::SQL_CONTEXT; 372 return pReturn; 373 } 374 375 const Type aTypeWarning( ::cppu::UnoType< SQLWarning >::get() ); 376 if ( isAssignableFrom( aTypeWarning, aNextElementType ) ) 377 { 378 m_eCurrentType = SQLExceptionInfo::SQL_WARNING; 379 return pReturn; 380 } 381 382 // a simple SQLException 383 m_eCurrentType = SQLExceptionInfo::SQL_EXCEPTION; 384 return pReturn; 385 } 386 387 //------------------------------------------------------------------------------ 388 void SQLExceptionIteratorHelper::next( SQLExceptionInfo& _out_rInfo ) 389 { 390 current( _out_rInfo ); 391 next(); 392 } 393 394 //------------------------------------------------------------ 395 void throwFunctionSequenceException(const Reference< XInterface >& _Context, const Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) 396 { 397 ::connectivity::SharedResources aResources; 398 throw SQLException( 399 aResources.getResourceString(STR_ERRORMSG_SEQUENCE), 400 _Context, 401 getStandardSQLState( SQL_FUNCTION_SEQUENCE_ERROR ), 402 0, 403 _Next 404 ); 405 } 406 // ----------------------------------------------------------------------------- 407 void throwInvalidIndexException(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _Context, 408 const ::com::sun::star::uno::Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) 409 { 410 ::connectivity::SharedResources aResources; 411 throw SQLException( 412 aResources.getResourceString(STR_INVALID_INDEX), 413 _Context, 414 getStandardSQLState( SQL_INVALID_DESCRIPTOR_INDEX ), 415 0, 416 _Next 417 ); 418 } 419 // ----------------------------------------------------------------------------- 420 void throwFunctionNotSupportedException(const ::rtl::OUString& _rMsg, 421 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _Context, 422 const ::com::sun::star::uno::Any& _Next) throw ( ::com::sun::star::sdbc::SQLException ) 423 { 424 throw SQLException( 425 _rMsg, 426 _Context, 427 getStandardSQLState( SQL_FUNCTION_NOT_SUPPORTED ), 428 0, 429 _Next 430 ); 431 } 432 // ----------------------------------------------------------------------------- 433 void throwFunctionNotSupportedException( const sal_Char* _pAsciiFunctionName, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContext, 434 const ::com::sun::star::uno::Any* _pNextException ) throw ( ::com::sun::star::sdbc::SQLException ) 435 { 436 ::connectivity::SharedResources aResources; 437 const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution( 438 STR_UNSUPPORTED_FUNCTION, 439 "$functionname$", ::rtl::OUString::createFromAscii( _pAsciiFunctionName ) 440 ) ); 441 throw SQLException( 442 sError, 443 _rxContext, 444 getStandardSQLState( SQL_FUNCTION_NOT_SUPPORTED ), 445 0, 446 _pNextException ? *_pNextException : Any() 447 ); 448 } 449 // ----------------------------------------------------------------------------- 450 void throwGenericSQLException(const ::rtl::OUString& _rMsg, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxSource) 451 throw (::com::sun::star::sdbc::SQLException) 452 { 453 throwGenericSQLException(_rMsg, _rxSource, Any()); 454 } 455 456 // ----------------------------------------------------------------------------- 457 void throwGenericSQLException(const ::rtl::OUString& _rMsg, const Reference< XInterface >& _rxSource, const Any& _rNextException) 458 throw (SQLException) 459 { 460 throw SQLException( _rMsg, _rxSource, getStandardSQLState( SQL_GENERAL_ERROR ), 0, _rNextException); 461 } 462 463 // ----------------------------------------------------------------------------- 464 void throwFeatureNotImplementedException( const sal_Char* _pAsciiFeatureName, const Reference< XInterface >& _rxContext, const Any* _pNextException ) 465 throw (SQLException) 466 { 467 ::connectivity::SharedResources aResources; 468 const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution( 469 STR_UNSUPPORTED_FEATURE, 470 "$featurename$", ::rtl::OUString::createFromAscii( _pAsciiFeatureName ) 471 ) ); 472 473 throw SQLException( 474 sError, 475 _rxContext, 476 getStandardSQLState( SQL_FEATURE_NOT_IMPLEMENTED ), 477 0, 478 _pNextException ? *_pNextException : Any() 479 ); 480 } 481 482 // ----------------------------------------------------------------------------- 483 void throwSQLException( const sal_Char* _pAsciiMessage, const sal_Char* _pAsciiState, 484 const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, const Any* _pNextException ) throw (SQLException) 485 { 486 throw SQLException( 487 ::rtl::OUString::createFromAscii( _pAsciiMessage ), 488 _rxContext, 489 ::rtl::OUString::createFromAscii( _pAsciiState ), 490 _nErrorCode, 491 _pNextException ? *_pNextException : Any() 492 ); 493 } 494 495 // ----------------------------------------------------------------------------- 496 void throwSQLException( const sal_Char* _pAsciiMessage, StandardSQLState _eSQLState, 497 const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, 498 const Any* _pNextException ) throw (SQLException) 499 { 500 throwSQLException( _pAsciiMessage, getStandardSQLStateAscii( _eSQLState ), _rxContext, _nErrorCode, _pNextException ); 501 } 502 503 // ----------------------------------------------------------------------------- 504 void throwSQLException( const ::rtl::OUString& _rMessage, StandardSQLState _eSQLState, 505 const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode, 506 const Any* _pNextException ) throw (SQLException) 507 { 508 throw SQLException( 509 _rMessage, 510 _rxContext, 511 getStandardSQLState( _eSQLState ), 512 _nErrorCode, 513 _pNextException ? *_pNextException : Any() 514 ); 515 } 516 517 // ----------------------------------------------------------------------------- 518 const sal_Char* getStandardSQLStateAscii( StandardSQLState _eState ) 519 { 520 const sal_Char* pAsciiState = NULL; 521 switch ( _eState ) 522 { 523 case SQL_WRONG_PARAMETER_NUMBER: pAsciiState = "07001"; break; 524 case SQL_INVALID_DESCRIPTOR_INDEX: pAsciiState = "07009"; break; 525 case SQL_UNABLE_TO_CONNECT: pAsciiState = "08001"; break; 526 case SQL_NUMERIC_OUT_OF_RANGE: pAsciiState = "22003"; break; 527 case SQL_INVALID_DATE_TIME: pAsciiState = "22007"; break; 528 case SQL_INVALID_CURSOR_STATE: pAsciiState = "24000"; break; 529 case SQL_TABLE_OR_VIEW_EXISTS: pAsciiState = "42S01"; break; 530 case SQL_TABLE_OR_VIEW_NOT_FOUND: pAsciiState = "42S02"; break; 531 case SQL_INDEX_ESISTS: pAsciiState = "42S11"; break; 532 case SQL_INDEX_NOT_FOUND: pAsciiState = "42S12"; break; 533 case SQL_COLUMN_EXISTS: pAsciiState = "42S21"; break; 534 case SQL_COLUMN_NOT_FOUND: pAsciiState = "42S22"; break; 535 case SQL_GENERAL_ERROR: pAsciiState = "HY000"; break; 536 case SQL_INVALID_SQL_DATA_TYPE: pAsciiState = "HY004"; break; 537 case SQL_OPERATION_CANCELED: pAsciiState = "HY008"; break; 538 case SQL_FUNCTION_SEQUENCE_ERROR: pAsciiState = "HY010"; break; 539 case SQL_INVALID_CURSOR_POSITION: pAsciiState = "HY109"; break; 540 case SQL_INVALID_BOOKMARK_VALUE: pAsciiState = "HY111"; break; 541 case SQL_FEATURE_NOT_IMPLEMENTED: pAsciiState = "HYC00"; break; 542 case SQL_FUNCTION_NOT_SUPPORTED: pAsciiState = "IM001"; break; 543 case SQL_CONNECTION_DOES_NOT_EXIST: pAsciiState = "08003"; break; 544 545 default: 546 break; 547 } 548 if ( !pAsciiState ) 549 throw RuntimeException(); 550 return pAsciiState; 551 } 552 553 // ----------------------------------------------------------------------------- 554 ::rtl::OUString getStandardSQLState( StandardSQLState _eState ) 555 { 556 return ::rtl::OUString::createFromAscii( getStandardSQLStateAscii( _eState ) ); 557 } 558 559 // ----------------------------------------------------------------------------- 560 //......................................................................... 561 } // namespace dbtools 562 //......................................................................... 563 564 565