LibreOffice Module connectivity (master) 1
dbexception.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21#include <comphelper/types.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 <strings.hrc>
31
32namespace dbtools
33{
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;
39
42{
43}
44
45
46SQLExceptionInfo::SQLExceptionInfo(const css::sdbc::SQLException& _rError)
47{
48 m_aContent <<= _rError;
50}
51
52
53SQLExceptionInfo::SQLExceptionInfo(const css::sdbc::SQLWarning& _rError)
54{
55 m_aContent <<= _rError;
57}
58
59
60SQLExceptionInfo::SQLExceptionInfo(const css::sdb::SQLContext& _rError)
61{
62 m_aContent <<= _rError;
64}
65
66
67SQLExceptionInfo::SQLExceptionInfo( const OUString& _rSimpleErrorMessage )
68{
69 SQLException aError;
70 aError.Message = _rSimpleErrorMessage;
71 m_aContent <<= aError;
73}
74
75SQLExceptionInfo& SQLExceptionInfo::operator=(const css::sdbc::SQLException& _rError)
76{
77 m_aContent <<= _rError;
79 return *this;
80}
81
82
83SQLExceptionInfo& SQLExceptionInfo::operator=(const css::sdbc::SQLWarning& _rError)
84{
85 m_aContent <<= _rError;
87 return *this;
88}
89
90
91SQLExceptionInfo& SQLExceptionInfo::operator=(const css::sdb::SQLContext& _rError)
92{
93 m_aContent <<= _rError;
95 return *this;
96}
97
98
99SQLExceptionInfo& SQLExceptionInfo::operator=(const css::sdb::SQLErrorEvent& _rErrorEvent)
100{
101 m_aContent = _rErrorEvent.Reason;
103 return *this;
104}
105
106
107SQLExceptionInfo& SQLExceptionInfo::operator=(const css::uno::Any& _rCaughtSQLException)
108{
109 m_aContent = _rCaughtSQLException;
111 return *this;
112}
113
114
115SQLExceptionInfo::SQLExceptionInfo(const css::uno::Any& _rError)
116{
117 const css::uno::Type& aSQLExceptionType = cppu::UnoType<css::sdbc::SQLException>::get();
118 bool bValid = isAssignableFrom(aSQLExceptionType, _rError.getValueType());
119 if (bValid)
120 m_aContent = _rError;
121 // no assertion here : if used with the NextException member of an SQLException bValid==sal_False is allowed.
122
124}
125
126
128{
129 const Type& aSQLExceptionType = ::cppu::UnoType<SQLException>::get();
130 const Type& aSQLWarningType = ::cppu::UnoType<SQLWarning>::get();
131 const Type& aSQLContextType = ::cppu::UnoType<SQLContext>::get();
132
133 if ( isAssignableFrom( aSQLContextType, m_aContent.getValueType() ) )
135 else if ( isAssignableFrom( aSQLWarningType, m_aContent.getValueType() ) )
137 else if ( isAssignableFrom( aSQLExceptionType, m_aContent.getValueType() ) )
139 else
140 {
142 m_aContent.clear();
143 }
144}
145
146
148{
149 switch (_eType)
150 {
151 case TYPE::SQLContext:
152 return (m_eType == TYPE::SQLContext);
153 case TYPE::SQLWarning:
157 case TYPE::Undefined:
158 return (m_eType == TYPE::Undefined);
159 }
160 return false;
161}
162
163
164SQLExceptionInfo::operator const css::sdbc::SQLException*() const
165{
166 OSL_ENSURE(isKindOf(TYPE::SQLException), "SQLExceptionInfo::operator SQLException* : invalid call !");
167 return o3tl::doAccess<css::sdbc::SQLException>(m_aContent);
168}
169
170
171SQLExceptionInfo::operator const css::sdb::SQLContext*() const
172{
173 OSL_ENSURE(isKindOf(TYPE::SQLContext), "SQLExceptionInfo::operator SQLException* : invalid call !");
174 return o3tl::doAccess<css::sdb::SQLContext>(m_aContent);
175}
176
177
178void SQLExceptionInfo::prepend( const OUString& _rErrorMessage )
179{
180 SQLException aException;
181 aException.Message = _rErrorMessage;
182 aException.ErrorCode = 0;
183 aException.SQLState = "S1000";
184 aException.NextException = m_aContent;
185 m_aContent <<= aException;
186
188}
189
190// create the to-be-appended exception
191Any SQLExceptionInfo::createException(TYPE eType, const OUString& rErrorMessage, const OUString& rSQLState, const sal_Int32 nErrorCode)
192{
193 Any aAppend;
194 switch (eType)
195 {
197 aAppend <<= SQLException();
198 break;
199 case TYPE::SQLWarning:
200 aAppend <<= SQLWarning();
201 break;
202 case TYPE::SQLContext:
203 aAppend <<= SQLContext();
204 break;
205 default:
206 TOOLS_WARN_EXCEPTION("connectivity.commontools", "SQLExceptionInfo::createException: invalid exception type: this will crash!");
207 break;
208 }
209
210 SQLException& pAppendException = const_cast<SQLException &>(*o3tl::forceAccess<SQLException>(aAppend));
211 pAppendException.Message = rErrorMessage;
212 pAppendException.SQLState = rSQLState;
213 pAppendException.ErrorCode = nErrorCode;
214
215 return aAppend;
216}
217
218// find the end of the exception chain
219SQLException* SQLExceptionInfo::getLastException(SQLException* pLastException)
220{
221 SQLException* pException = pLastException;
222 while (pException)
223 {
224 pException = const_cast<SQLException*>(o3tl::tryAccess<SQLException>(pException->NextException));
225 if (!pException)
226 break;
227 pLastException = pException;
228 }
229 return pLastException;
230}
231
232void SQLExceptionInfo::append( TYPE _eType, const OUString& _rErrorMessage, const OUString& _rSQLState, const sal_Int32 _nErrorCode )
233{
234 // create the to-be-appended exception
235 Any aAppend = createException(_eType, _rErrorMessage, _rSQLState, _nErrorCode);
236
237 // find the end of the current chain
238 SQLException* pLastException = getLastException(const_cast<SQLException*>(o3tl::tryAccess<SQLException>(m_aContent)));
239
240 // append
241 if (pLastException)
242 pLastException->NextException = aAppend;
243 else
244 {
245 m_aContent = aAppend;
246 m_eType = _eType;
247 }
248}
249
251{
252 if ( m_aContent.getValueTypeClass() == TypeClass_EXCEPTION )
253 ::cppu::throwException( m_aContent );
254 throw RuntimeException();
255}
256
258 :m_pCurrent( nullptr )
259 ,m_eCurrentType( SQLExceptionInfo::TYPE::Undefined )
260{
261 if ( _rChainStart.isValid() )
262 {
263 m_pCurrent = _rChainStart;
264 m_eCurrentType = _rChainStart.getType();
265 }
266}
267
268
269SQLExceptionIteratorHelper::SQLExceptionIteratorHelper( const css::sdbc::SQLException& _rChainStart )
270 :m_pCurrent( &_rChainStart )
271 ,m_eCurrentType( SQLExceptionInfo::TYPE::SQLException )
272{
273}
274
275
277{
278 switch ( m_eCurrentType )
279 {
281 _out_rInfo = *m_pCurrent;
282 break;
283
285 _out_rInfo = *static_cast< const SQLWarning* >( m_pCurrent );
286 break;
287
289 _out_rInfo = *static_cast< const SQLContext* >( m_pCurrent );
290 break;
291
292 default:
293 _out_rInfo = Any();
294 break;
295 }
296}
297
298
299const css::sdbc::SQLException* SQLExceptionIteratorHelper::next()
300{
301 OSL_ENSURE( hasMoreElements(), "SQLExceptionIteratorHelper::next : invalid call (please use hasMoreElements)!" );
302
303 const css::sdbc::SQLException* pReturn = m_pCurrent;
304 if ( !m_pCurrent )
305 return pReturn;
306
307 // check for the next element within the chain
308 const Type aTypeException( ::cppu::UnoType< SQLException >::get() );
309
310 Type aNextElementType = m_pCurrent->NextException.getValueType();
311 if ( !isAssignableFrom( aTypeException, aNextElementType ) )
312 {
313 // no SQLException at all in the next chain element
314 m_pCurrent = nullptr;
316 return pReturn;
317 }
318
319 m_pCurrent = o3tl::doAccess< SQLException >( m_pCurrent->NextException );
320
321 // no finally determine the proper type of the exception
322 const Type aTypeContext( ::cppu::UnoType< SQLContext >::get() );
323 if ( isAssignableFrom( aTypeContext, aNextElementType ) )
324 {
326 return pReturn;
327 }
328
329 const Type aTypeWarning( ::cppu::UnoType< SQLWarning >::get() );
330 if ( isAssignableFrom( aTypeWarning, aNextElementType ) )
331 {
333 return pReturn;
334 }
335
336 // a simple SQLException
338 return pReturn;
339}
340
341
343{
344 current( _out_rInfo );
345 next();
346}
347
348
349void throwFunctionSequenceException(const Reference< XInterface >& Context, const Any& Next)
350{
352 throw SQLException(
353 aResources.getResourceString(STR_ERRORMSG_SEQUENCE),
354 Context,
356 0,
357 Next
358 );
359}
360
361void throwInvalidIndexException(const css::uno::Reference< css::uno::XInterface >& Context,
362 const css::uno::Any& Next)
363{
365 throw SQLException(
366 aResources.getResourceString(STR_INVALID_INDEX),
367 Context,
369 0,
370 Next
371 );
372}
373
374void throwFunctionNotSupportedSQLException(const OUString& _rFunctionName,
375 const css::uno::Reference<css::uno::XInterface>& _rxContext)
376{
378 const OUString sError( aResources.getResourceStringWithSubstitution(
379 STR_UNSUPPORTED_FUNCTION,
380 "$functionname$", _rFunctionName
381 ) );
382 throw SQLException(
383 sError,
384 _rxContext,
386 0,
387 css::uno::Any()
388 );
389}
390
391void throwFunctionNotSupportedRuntimeException(const OUString& _rFunctionName,
392 const css::uno::Reference<css::uno::XInterface>& _rxContext)
393{
395 const OUString sError( aResources.getResourceStringWithSubstitution(
396 STR_UNSUPPORTED_FUNCTION,
397 "$functionname$", _rFunctionName
398 ) );
399 throw RuntimeException(
400 sError,
401 _rxContext
402 );
403}
404
405void throwGenericSQLException(const OUString& _rMsg, const css::uno::Reference< css::uno::XInterface >& _rxSource)
406{
407 throwGenericSQLException(_rMsg, _rxSource, Any());
408}
409
410
411void throwGenericSQLException(const OUString& _rMsg, const Reference< XInterface >& _rxSource, const Any& _rNextException)
412{
413 throw SQLException( _rMsg, _rxSource, getStandardSQLState( StandardSQLState::GENERAL_ERROR ), 0, _rNextException);
414}
415
416void throwFeatureNotImplementedSQLException( const OUString& _rFeatureName, const Reference< XInterface >& _rxContext, const Any& _rNextException )
417{
419 const OUString sError( aResources.getResourceStringWithSubstitution(
420 STR_UNSUPPORTED_FEATURE,
421 "$featurename$", _rFeatureName
422 ) );
423
424 throw SQLException(
425 sError,
426 _rxContext,
428 0,
429 _rNextException
430 );
431}
432
433void throwFeatureNotImplementedRuntimeException(const OUString& _rFeatureName, const Reference< XInterface >& _rxContext)
434{
436 const OUString sError( aResources.getResourceStringWithSubstitution(
437 STR_UNSUPPORTED_FEATURE,
438 "$featurename$", _rFeatureName
439 ) );
440
441 throw RuntimeException(sError, _rxContext);
442}
443
444void throwInvalidColumnException( const OUString& _rColumnName, const Reference< XInterface >& _rxContext)
445{
447 OUString sErrorMessage( aResources.getResourceStringWithSubstitution(
448 STR_INVALID_COLUMNNAME,
449 "$columnname$",_rColumnName) );
450 throwSQLException( sErrorMessage, StandardSQLState::COLUMN_NOT_FOUND, _rxContext );
451}
452
453void throwSQLException( const OUString& _rMessage, const OUString& _rSQLState,
454 const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode )
455{
456 throw SQLException(
457 _rMessage,
458 _rxContext,
459 _rSQLState,
460 _nErrorCode,
461 Any()
462 );
463}
464
465
466void throwSQLException( const OUString& _rMessage, StandardSQLState _eSQLState,
467 const Reference< XInterface >& _rxContext, const sal_Int32 _nErrorCode )
468{
469 throwSQLException( _rMessage, getStandardSQLState( _eSQLState ), _rxContext, _nErrorCode );
470}
471
472
474{
475 switch ( _eState )
476 {
478 case StandardSQLState::INVALID_CURSOR_STATE: return "24000";
479 case StandardSQLState::COLUMN_NOT_FOUND: return "42S22";
480 case StandardSQLState::GENERAL_ERROR: return "HY000";
481 case StandardSQLState::INVALID_SQL_DATA_TYPE: return "HY004";
485 case StandardSQLState::FUNCTION_NOT_SUPPORTED: return "IM001";
487 default: return "HY001"; // General Error
488 }
489}
490
491
492} // namespace dbtools
493
494
495/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
OUString getResourceStringWithSubstitution(TranslateId pResId, const char *_pAsciiPatternToReplace, const OUString &_rStringToSubstitute) const
loads a string from the shared resource file, and replaces a given ASCII pattern with a given string
css::uno::Type const & get()
static css::sdbc::SQLException * getLastException(css::sdbc::SQLException *pLastException)
bool isKindOf(TYPE _eType) const
SQLExceptionInfo & operator=(const css::sdbc::SQLException &_rError)
Definition: dbexception.cxx:75
void prepend(const OUString &_rErrorMessage)
prepends a plain error message to the chain of exceptions
static css::uno::Any createException(TYPE eType, const OUString &rErrorMessage, const OUString &rSQLState, const sal_Int32 nErrorCode)
void doThrow()
throws (properly typed) the exception contained in the object @precond isValid() returns <TRUE>
void append(TYPE _eType, const OUString &_rErrorMessage, const OUString &_rSQLState=OUString(), const sal_Int32 _nErrorCode=0)
appends a plain message to the chain of exceptions
bool hasMoreElements() const
determines whether there are more elements in the exception chain
const css::sdbc::SQLException * m_pCurrent
const css::sdbc::SQLException * next()
proceeds to the next element in the chain
void current(SQLExceptionInfo &_out_rInfo) const
retrieves the current element in the chain, or <NULL> if the chain has been completely traveled.
SQLExceptionInfo::TYPE m_eCurrentType
SQLExceptionIteratorHelper(const css::sdbc::SQLException &_rChainStart)
constructs an iterator instance from an SQLException
#define TOOLS_WARN_EXCEPTION(area, stream)
const EnumerationType m_eType
DocumentType eType
bool isAssignableFrom(const Type &_rAssignable, const Type &_rFrom)
Type
void throwFunctionSequenceException(const Reference< XInterface > &Context, const Any &Next)
void throwFeatureNotImplementedRuntimeException(const OUString &_rFeatureName, const Reference< XInterface > &_rxContext)
void throwInvalidIndexException(const css::uno::Reference< css::uno::XInterface > &Context, const css::uno::Any &Next)
throw an invalid index sqlexception
StandardSQLState
standard SQLStates to be used with an SQLException
void throwFunctionNotSupportedRuntimeException(const OUString &_rFunctionName, const css::uno::Reference< css::uno::XInterface > &_rxContext)
void throwFeatureNotImplementedSQLException(const OUString &_rFeatureName, const Reference< XInterface > &_rxContext, const Any &_rNextException)
void throwFunctionNotSupportedSQLException(const OUString &_rFunctionName, const css::uno::Reference< css::uno::XInterface > &_rxContext)
throws an exception with SQL state IM001, saying that a certain function is not supported
void throwSQLException(const OUString &_rMessage, const OUString &_rSQLState, const Reference< XInterface > &_rxContext, const sal_Int32 _nErrorCode)
void throwInvalidColumnException(const OUString &_rColumnName, const Reference< XInterface > &_rxContext)
OUString getStandardSQLState(StandardSQLState _eState)
returns a standard error string for a given SQLState
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
throw a generic SQLException, i.e.
TYPE
::ucbhelper::Content m_aContent