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