1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <connectivity/dbexception.hxx>
21 #include <comphelper/types.hxx>
22 #include <cppuhelper/exc_hlp.hxx>
23 #include <o3tl/any.hxx>
24 #include <osl/diagnose.h>
25 #include <com/sun/star/sdb/SQLContext.hpp>
26 #include <com/sun/star/sdbc/SQLWarning.hpp>
27 #include <com/sun/star/sdb/SQLErrorEvent.hpp>
28 #include <TConnection.hxx>
29 #include <strings.hrc>
30 #include <resource/sharedresources.hxx>
34 using namespace ::com::sun::star::uno
;
35 using namespace ::com::sun::star::sdb
;
36 using namespace ::com::sun::star::sdbc
;
37 using namespace ::comphelper
;
38 using namespace ::connectivity
;
40 SQLExceptionInfo::SQLExceptionInfo()
41 :m_eType(TYPE::Undefined
)
46 SQLExceptionInfo::SQLExceptionInfo(const css::sdbc::SQLException
& _rError
)
48 m_aContent
<<= _rError
;
53 SQLExceptionInfo::SQLExceptionInfo(const css::sdbc::SQLWarning
& _rError
)
55 m_aContent
<<= _rError
;
60 SQLExceptionInfo::SQLExceptionInfo(const css::sdb::SQLContext
& _rError
)
62 m_aContent
<<= _rError
;
67 SQLExceptionInfo::SQLExceptionInfo( const OUString
& _rSimpleErrorMessage
)
70 aError
.Message
= _rSimpleErrorMessage
;
71 m_aContent
<<= aError
;
75 SQLExceptionInfo
& SQLExceptionInfo::operator=(const css::sdbc::SQLException
& _rError
)
77 m_aContent
<<= _rError
;
83 SQLExceptionInfo
& SQLExceptionInfo::operator=(const css::sdbc::SQLWarning
& _rError
)
85 m_aContent
<<= _rError
;
91 SQLExceptionInfo
& SQLExceptionInfo::operator=(const css::sdb::SQLContext
& _rError
)
93 m_aContent
<<= _rError
;
99 SQLExceptionInfo
& SQLExceptionInfo::operator=(const css::sdb::SQLErrorEvent
& _rErrorEvent
)
101 m_aContent
= _rErrorEvent
.Reason
;
107 SQLExceptionInfo
& SQLExceptionInfo::operator=(const css::uno::Any
& _rCaughtSQLException
)
109 m_aContent
= _rCaughtSQLException
;
115 SQLExceptionInfo::SQLExceptionInfo(const css::uno::Any
& _rError
)
117 const css::uno::Type
& aSQLExceptionType
= cppu::UnoType
<css::sdbc::SQLException
>::get();
118 bool bValid
= isAssignableFrom(aSQLExceptionType
, _rError
.getValueType());
120 m_aContent
= _rError
;
121 // no assertion here : if used with the NextException member of an SQLException bValid==sal_False is allowed.
127 void SQLExceptionInfo::implDetermineType()
129 const Type
& aSQLExceptionType
= ::cppu::UnoType
<SQLException
>::get();
130 const Type
& aSQLWarningType
= ::cppu::UnoType
<SQLWarning
>::get();
131 const Type
& aSQLContextType
= ::cppu::UnoType
<SQLContext
>::get();
133 if ( isAssignableFrom( aSQLContextType
, m_aContent
.getValueType() ) )
134 m_eType
= TYPE::SQLContext
;
135 else if ( isAssignableFrom( aSQLWarningType
, m_aContent
.getValueType() ) )
136 m_eType
= TYPE::SQLWarning
;
137 else if ( isAssignableFrom( aSQLExceptionType
, m_aContent
.getValueType() ) )
138 m_eType
= TYPE::SQLException
;
141 m_eType
= TYPE::Undefined
;
147 bool SQLExceptionInfo::isKindOf(TYPE _eType
) const
151 case TYPE::SQLContext
:
152 return (m_eType
== TYPE::SQLContext
);
153 case TYPE::SQLWarning
:
154 return (m_eType
== TYPE::SQLContext
) || (m_eType
== TYPE::SQLWarning
);
155 case TYPE::SQLException
:
156 return (m_eType
== TYPE::SQLContext
) || (m_eType
== TYPE::SQLWarning
) || (m_eType
== TYPE::SQLException
);
157 case TYPE::Undefined
:
158 return (m_eType
== TYPE::Undefined
);
164 SQLExceptionInfo::operator const css::sdbc::SQLException
*() const
166 OSL_ENSURE(isKindOf(TYPE::SQLException
), "SQLExceptionInfo::operator SQLException* : invalid call !");
167 return o3tl::doAccess
<css::sdbc::SQLException
>(m_aContent
);
171 SQLExceptionInfo::operator const css::sdb::SQLContext
*() const
173 OSL_ENSURE(isKindOf(TYPE::SQLContext
), "SQLExceptionInfo::operator SQLException* : invalid call !");
174 return o3tl::doAccess
<css::sdb::SQLContext
>(m_aContent
);
178 void SQLExceptionInfo::prepend( const OUString
& _rErrorMessage
)
180 SQLException aException
;
181 aException
.Message
= _rErrorMessage
;
182 aException
.ErrorCode
= 0;
183 aException
.SQLState
= "S1000";
184 aException
.NextException
= m_aContent
;
185 m_aContent
<<= aException
;
187 m_eType
= TYPE::SQLException
;
191 void SQLExceptionInfo::append( TYPE _eType
, const OUString
& _rErrorMessage
, const OUString
& _rSQLState
, const sal_Int32 _nErrorCode
)
193 // create the to-be-appended exception
197 case TYPE::SQLException
: aAppend
<<= SQLException(); break;
198 case TYPE::SQLWarning
: aAppend
<<= SQLWarning(); break;
199 case TYPE::SQLContext
: aAppend
<<= SQLContext(); break;
201 OSL_FAIL( "SQLExceptionInfo::append: invalid exception type: this will crash!" );
205 SQLException
& pAppendException
= const_cast<SQLException
&>(*o3tl::forceAccess
<SQLException
>(aAppend
));
206 pAppendException
.Message
= _rErrorMessage
;
207 pAppendException
.SQLState
= _rSQLState
;
208 pAppendException
.ErrorCode
= _nErrorCode
;
210 // find the end of the current chain
211 Any
* pChainIterator
= &m_aContent
;
212 SQLException
* pLastException
= nullptr;
213 const Type
& aSQLExceptionType( cppu::UnoType
<SQLException
>::get() );
214 while ( pChainIterator
)
216 if ( !pChainIterator
->hasValue() )
219 if ( !isAssignableFrom( aSQLExceptionType
, pChainIterator
->getValueType() ) )
222 pLastException
= const_cast< SQLException
* >( o3tl::doAccess
<SQLException
>( *pChainIterator
) );
223 pChainIterator
= &pLastException
->NextException
;
227 if ( pLastException
)
228 pLastException
->NextException
= aAppend
;
231 m_aContent
= aAppend
;
237 void SQLExceptionInfo::doThrow()
239 if ( m_aContent
.getValueTypeClass() == TypeClass_EXCEPTION
)
240 ::cppu::throwException( m_aContent
);
241 throw RuntimeException();
244 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const SQLExceptionInfo
& _rChainStart
)
245 :m_pCurrent( nullptr )
246 ,m_eCurrentType( SQLExceptionInfo::TYPE::Undefined
)
248 if ( _rChainStart
.isValid() )
250 m_pCurrent
= static_cast<const SQLException
*>(_rChainStart
);
251 m_eCurrentType
= _rChainStart
.getType();
256 SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const css::sdbc::SQLException
& _rChainStart
)
257 :m_pCurrent( &_rChainStart
)
258 ,m_eCurrentType( SQLExceptionInfo::TYPE::SQLException
)
263 void SQLExceptionIteratorHelper::current( SQLExceptionInfo
& _out_rInfo
) const
265 switch ( m_eCurrentType
)
267 case SQLExceptionInfo::TYPE::SQLException
:
268 _out_rInfo
= *m_pCurrent
;
271 case SQLExceptionInfo::TYPE::SQLWarning
:
272 _out_rInfo
= *static_cast< const SQLWarning
* >( m_pCurrent
);
275 case SQLExceptionInfo::TYPE::SQLContext
:
276 _out_rInfo
= *static_cast< const SQLContext
* >( m_pCurrent
);
286 const css::sdbc::SQLException
* SQLExceptionIteratorHelper::next()
288 OSL_ENSURE( hasMoreElements(), "SQLExceptionIteratorHelper::next : invalid call (please use hasMoreElements)!" );
290 const css::sdbc::SQLException
* pReturn
= m_pCurrent
;
294 // check for the next element within the chain
295 const Type
aTypeException( ::cppu::UnoType
< SQLException
>::get() );
297 Type aNextElementType
= m_pCurrent
->NextException
.getValueType();
298 if ( !isAssignableFrom( aTypeException
, aNextElementType
) )
300 // no SQLException at all in the next chain element
301 m_pCurrent
= nullptr;
302 m_eCurrentType
= SQLExceptionInfo::TYPE::Undefined
;
306 m_pCurrent
= o3tl::doAccess
< SQLException
>( m_pCurrent
->NextException
);
308 // no finally determine the proper type of the exception
309 const Type
aTypeContext( ::cppu::UnoType
< SQLContext
>::get() );
310 if ( isAssignableFrom( aTypeContext
, aNextElementType
) )
312 m_eCurrentType
= SQLExceptionInfo::TYPE::SQLContext
;
316 const Type
aTypeWarning( ::cppu::UnoType
< SQLWarning
>::get() );
317 if ( isAssignableFrom( aTypeWarning
, aNextElementType
) )
319 m_eCurrentType
= SQLExceptionInfo::TYPE::SQLWarning
;
323 // a simple SQLException
324 m_eCurrentType
= SQLExceptionInfo::TYPE::SQLException
;
329 void SQLExceptionIteratorHelper::next( SQLExceptionInfo
& _out_rInfo
)
331 current( _out_rInfo
);
336 void throwFunctionSequenceException(const Reference
< XInterface
>& Context
, const Any
& Next
)
338 ::connectivity::SharedResources aResources
;
340 aResources
.getResourceString(STR_ERRORMSG_SEQUENCE
),
342 getStandardSQLState( StandardSQLState::FUNCTION_SEQUENCE_ERROR
),
348 void throwInvalidIndexException(const css::uno::Reference
< css::uno::XInterface
>& Context
,
349 const css::uno::Any
& Next
)
351 ::connectivity::SharedResources aResources
;
353 aResources
.getResourceString(STR_INVALID_INDEX
),
355 getStandardSQLState( StandardSQLState::INVALID_DESCRIPTOR_INDEX
),
361 void throwFunctionNotSupportedSQLException(const OUString
& _rFunctionName
,
362 const css::uno::Reference
<css::uno::XInterface
>& _rxContext
)
364 ::connectivity::SharedResources aResources
;
365 const OUString
sError( aResources
.getResourceStringWithSubstitution(
366 STR_UNSUPPORTED_FUNCTION
,
367 "$functionname$", _rFunctionName
372 getStandardSQLState( StandardSQLState::FUNCTION_NOT_SUPPORTED
),
378 void throwFunctionNotSupportedRuntimeException(const OUString
& _rFunctionName
,
379 const css::uno::Reference
<css::uno::XInterface
>& _rxContext
)
381 ::connectivity::SharedResources aResources
;
382 const OUString
sError( aResources
.getResourceStringWithSubstitution(
383 STR_UNSUPPORTED_FUNCTION
,
384 "$functionname$", _rFunctionName
386 throw RuntimeException(
392 void throwGenericSQLException(const OUString
& _rMsg
, const css::uno::Reference
< css::uno::XInterface
>& _rxSource
)
394 throwGenericSQLException(_rMsg
, _rxSource
, Any());
398 void throwGenericSQLException(const OUString
& _rMsg
, const Reference
< XInterface
>& _rxSource
, const Any
& _rNextException
)
400 throw SQLException( _rMsg
, _rxSource
, getStandardSQLState( StandardSQLState::GENERAL_ERROR
), 0, _rNextException
);
403 void throwFeatureNotImplementedSQLException( const OUString
& _rFeatureName
, const Reference
< XInterface
>& _rxContext
, const Any
& _rNextException
)
405 ::connectivity::SharedResources aResources
;
406 const OUString
sError( aResources
.getResourceStringWithSubstitution(
407 STR_UNSUPPORTED_FEATURE
,
408 "$featurename$", _rFeatureName
414 getStandardSQLState( StandardSQLState::FEATURE_NOT_IMPLEMENTED
),
420 void throwFeatureNotImplementedRuntimeException(const OUString
& _rFeatureName
, const Reference
< XInterface
>& _rxContext
)
422 ::connectivity::SharedResources aResources
;
423 const OUString
sError( aResources
.getResourceStringWithSubstitution(
424 STR_UNSUPPORTED_FEATURE
,
425 "$featurename$", _rFeatureName
428 throw RuntimeException(sError
, _rxContext
);
431 void throwInvalidColumnException( const OUString
& _rColumnName
, const Reference
< XInterface
>& _rxContext
)
433 ::connectivity::SharedResources aResources
;
434 OUString
sErrorMessage( aResources
.getResourceStringWithSubstitution(
435 STR_INVALID_COLUMNNAME
,
436 "$columnname$",_rColumnName
) );
437 throwSQLException( sErrorMessage
, StandardSQLState::COLUMN_NOT_FOUND
, _rxContext
);
440 void throwSQLException( const OUString
& _rMessage
, const OUString
& _rSQLState
,
441 const Reference
< XInterface
>& _rxContext
, const sal_Int32 _nErrorCode
)
453 void throwSQLException( const OUString
& _rMessage
, StandardSQLState _eSQLState
,
454 const Reference
< XInterface
>& _rxContext
, const sal_Int32 _nErrorCode
)
456 throwSQLException( _rMessage
, getStandardSQLState( _eSQLState
), _rxContext
, _nErrorCode
);
460 OUString
getStandardSQLState( StandardSQLState _eState
)
464 case StandardSQLState::INVALID_DESCRIPTOR_INDEX
: return OUString("07009");
465 case StandardSQLState::INVALID_CURSOR_STATE
: return OUString("24000");
466 case StandardSQLState::COLUMN_NOT_FOUND
: return OUString("42S22");
467 case StandardSQLState::GENERAL_ERROR
: return OUString("HY000");
468 case StandardSQLState::INVALID_SQL_DATA_TYPE
: return OUString("HY004");
469 case StandardSQLState::FUNCTION_SEQUENCE_ERROR
: return OUString("HY010");
470 case StandardSQLState::INVALID_CURSOR_POSITION
: return OUString("HY109");
471 case StandardSQLState::FEATURE_NOT_IMPLEMENTED
: return OUString("HYC00");
472 case StandardSQLState::FUNCTION_NOT_SUPPORTED
: return OUString("IM001");
473 case StandardSQLState::CONNECTION_DOES_NOT_EXIST
: return OUString("08003");
474 default: return OUString("HY001"); // General Error
479 } // namespace dbtools
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */