Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/connectivity/source/commontools/sqlerror.cxx
Line
Count
Source
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
20
21
#include <memory>
22
#include <connectivity/sqlerror.hxx>
23
24
#include <com/sun/star/sdbc/SQLException.hpp>
25
#include <com/sun/star/sdb/ErrorCondition.hpp>
26
27
#include <cppuhelper/exc_hlp.hxx>
28
#include <unotools/resmgr.hxx>
29
#include <osl/diagnose.h>
30
31
#include <strings.hrc>
32
#include <strings.hxx>
33
#include <string.h>
34
35
namespace connectivity
36
{
37
38
39
    using ::com::sun::star::uno::Reference;
40
    using ::com::sun::star::uno::Any;
41
    using ::com::sun::star::uno::XInterface;
42
    using ::com::sun::star::sdbc::SQLException;
43
    using ::com::sun::star::uno::Type;
44
45
    class SQLError_Impl
46
    {
47
    public:
48
        explicit SQLError_Impl();
49
50
        // versions of the public SQLError methods which are just delegated to this impl-class
51
        static const OUString& getMessagePrefix();
52
        OUString     getErrorMessage( const ErrorCondition _eCondition, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 ) const;
53
        static ErrorCode    getErrorCode( const ErrorCondition _eCondition );
54
        void                raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 );
55
        void                raiseException( const ErrorCondition _eCondition, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 );
56
        void                raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const Type& _rExceptionType, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 );
57
        SQLException        getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 );
58
59
    private:
60
        /// returns the basic error message associated with the given error condition, without any parameter replacements
61
        OUString impl_getErrorMessage( ErrorCondition _eCondition ) const;
62
63
        /// returns the SQLState associated with the given error condition
64
        static OUString
65
                impl_getSQLState( ErrorCondition _eCondition );
66
67
        /// returns an SQLException describing the given error condition
68
        SQLException
69
                impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
70
                    const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 );
71
    private:
72
        std::locale                                             m_aResources;
73
    };
74
75
    SQLError_Impl::SQLError_Impl()
76
58.1k
        : m_aResources(Translate::Create("cnr"))
77
58.1k
    {
78
58.1k
    }
79
80
    const OUString& SQLError_Impl::getMessagePrefix()
81
0
    {
82
0
        static constexpr OUString s_sMessagePrefix( u"[OOoBase]"_ustr );
83
0
        return s_sMessagePrefix;
84
0
    }
85
86
    namespace
87
    {
88
89
        /** substitutes a given placeholder in the given message with the given value
90
        */
91
        void lcl_substitutePlaceholder(OUString& _rMessage, const char* _pPlaceholder, const std::optional<OUString>& rParamValue)
92
0
        {
93
0
            size_t nPlaceholderLen( strlen( _pPlaceholder ) );
94
0
            sal_Int32 nIndex = _rMessage.indexOfAsciiL( _pPlaceholder, nPlaceholderLen );
95
96
0
            bool bHasPlaceholder = ( nIndex != -1 );
97
0
            bool bWantsPlaceholder = rParamValue.has_value();
98
0
            OSL_ENSURE( bHasPlaceholder == bWantsPlaceholder, "lcl_substitutePlaceholder: placeholder where none is expected, or no placeholder where one is needed!" );
99
100
0
            if ( bHasPlaceholder && bWantsPlaceholder )
101
0
                _rMessage = _rMessage.replaceAt( nIndex, nPlaceholderLen, *rParamValue );
102
0
        }
103
104
        TranslateId lcl_getResourceErrorID(const ErrorCondition _eCondition)
105
0
        {
106
0
            switch (_eCondition)
107
0
            {
108
0
                case css::sdb::ErrorCondition::ROW_SET_OPERATION_VETOED:
109
0
                    return STR_ROW_SET_OPERATION_VETOED;
110
0
                case css::sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES:
111
0
                    return STR_PARSER_CYCLIC_SUB_QUERIES;
112
0
                case css::sdb::ErrorCondition::DB_OBJECT_NAME_WITH_SLASHES:
113
0
                    return STR_DB_OBJECT_NAME_WITH_SLASHES;
114
0
                case css::sdb::ErrorCondition::DB_INVALID_SQL_NAME:
115
0
                    return STR_DB_INVALID_SQL_NAME;
116
0
                case css::sdb::ErrorCondition::DB_QUERY_NAME_WITH_QUOTES:
117
0
                    return STR_DB_QUERY_NAME_WITH_QUOTES;
118
0
                case css::sdb::ErrorCondition::DB_OBJECT_NAME_IS_USED:
119
0
                    return STR_DB_OBJECT_NAME_IS_USED;
120
0
                case css::sdb::ErrorCondition::DB_NOT_CONNECTED:
121
0
                    return STR_DB_NOT_CONNECTED;
122
0
                case css::sdb::ErrorCondition::AB_ADDRESSBOOK_NOT_FOUND:
123
0
                    return STR_AB_ADDRESSBOOK_NOT_FOUND;
124
0
                case css::sdb::ErrorCondition::DATA_CANNOT_SELECT_UNFILTERED:
125
0
                    return STR_DATA_CANNOT_SELECT_UNFILTERED;
126
0
            }
127
0
            return {};
128
0
        }
129
130
        const OUString & lcl_getResourceState(const ErrorCondition _eCondition)
131
0
        {
132
0
            switch (_eCondition)
133
0
            {
134
0
                case css::sdb::ErrorCondition::DB_NOT_CONNECTED:
135
0
                    return STR_DB_NOT_CONNECTED_STATE;
136
0
                case css::sdb::ErrorCondition::DATA_CANNOT_SELECT_UNFILTERED:
137
0
                    return STR_DATA_CANNOT_SELECT_UNFILTERED_STATE;
138
0
            }
139
0
            return EMPTY_OUSTRING;
140
0
        }
141
    }
142
143
    OUString SQLError_Impl::getErrorMessage( const ErrorCondition _eCondition, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 ) const
144
0
    {
145
0
        OUString sErrorMessage( impl_getErrorMessage( _eCondition ) );
146
147
0
        lcl_substitutePlaceholder( sErrorMessage, "$1$", _rParamValue1 );
148
0
        lcl_substitutePlaceholder( sErrorMessage, "$2$", _rParamValue2 );
149
0
        lcl_substitutePlaceholder( sErrorMessage, "$3$", _rParamValue3 );
150
151
0
        return sErrorMessage;
152
0
    }
153
154
155
    ErrorCode SQLError_Impl::getErrorCode( const ErrorCondition _eCondition )
156
0
    {
157
0
        return 0 - ::sal::static_int_cast< ErrorCode, ErrorCondition >( _eCondition );
158
0
    }
159
160
161
    void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 )
162
0
    {
163
0
        raiseTypedException(
164
0
            _eCondition,
165
0
            _rxContext,
166
0
            ::cppu::UnoType< SQLException >::get(),
167
0
            _rParamValue1,
168
0
            _rParamValue2,
169
0
            _rParamValue3
170
0
        );
171
0
    }
172
173
174
    void SQLError_Impl::raiseException( const ErrorCondition _eCondition, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 )
175
0
    {
176
0
        raiseTypedException(
177
0
            _eCondition,
178
0
            nullptr,
179
0
            ::cppu::UnoType< SQLException >::get(),
180
0
            _rParamValue1,
181
0
            _rParamValue2,
182
0
            _rParamValue3
183
0
        );
184
0
    }
185
186
    void SQLError_Impl::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
187
        const Type& _rExceptionType, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 )
188
0
    {
189
0
        if ( !::cppu::UnoType< SQLException >::get().isAssignableFrom( _rExceptionType ) )
190
0
            throw std::bad_cast();
191
192
        // default-construct an exception of the desired type
193
0
        Any aException( nullptr, _rExceptionType );
194
195
        // fill it
196
0
        SQLException* pException = static_cast< SQLException* >( aException.pData );
197
0
        *pException = impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
198
199
        // throw it
200
0
        ::cppu::throwException( aException );
201
0
    }
202
203
    SQLException SQLError_Impl::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
204
        const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 )
205
0
    {
206
0
        return impl_buildSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
207
0
    }
208
209
    SQLException SQLError_Impl::impl_buildSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
210
        const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 )
211
0
    {
212
0
        return SQLException(
213
0
            getErrorMessage( _eCondition, _rParamValue1, _rParamValue2, _rParamValue3 ),
214
0
            _rxContext,
215
0
            impl_getSQLState( _eCondition ),
216
0
            getErrorCode( _eCondition ),
217
0
            Any()
218
0
        );
219
0
    }
220
221
    OUString SQLError_Impl::impl_getErrorMessage( ErrorCondition _eCondition ) const
222
0
    {
223
0
        OUString sResMessage(Translate::get(lcl_getResourceErrorID(_eCondition), m_aResources));
224
0
        OSL_ENSURE( !sResMessage.isEmpty(), "SQLError_Impl::impl_getErrorMessage: illegal error condition, or invalid resource!" );
225
0
        return getMessagePrefix() + " " + sResMessage;
226
0
    }
227
228
    OUString SQLError_Impl::impl_getSQLState( ErrorCondition _eCondition )
229
0
    {
230
0
        static constexpr OUStringLiteral DEFAULT_STATE = u"S1000";
231
0
        OUString sState = lcl_getResourceState(_eCondition);
232
0
        if (sState.isEmpty())
233
0
            sState = DEFAULT_STATE;
234
0
        return sState;
235
0
    }
236
237
    SQLError::SQLError()
238
58.1k
        :m_pImpl( std::make_shared<SQLError_Impl>() )
239
58.1k
    {
240
58.1k
    }
241
242
243
    SQLError::~SQLError()
244
58.1k
    {
245
58.1k
    }
246
247
248
    const OUString& SQLError::getMessagePrefix()
249
0
    {
250
0
        return SQLError_Impl::getMessagePrefix();
251
0
    }
252
253
254
    OUString SQLError::getErrorMessage( const ErrorCondition _eCondition ) const
255
0
    {
256
0
        return m_pImpl->getErrorMessage( _eCondition, std::optional<OUString>(), std::optional<OUString>(), std::optional<OUString>() );
257
0
    }
258
259
260
    ErrorCode SQLError::getErrorCode( const ErrorCondition _eCondition )
261
0
    {
262
0
        return SQLError_Impl::getErrorCode( _eCondition );
263
0
    }
264
265
266
    void SQLError::raiseException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext, const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 ) const
267
0
    {
268
0
        m_pImpl->raiseException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
269
0
    }
270
271
272
    void SQLError::raiseException( const ErrorCondition _eCondition ) const
273
0
    {
274
0
        m_pImpl->raiseException( _eCondition, std::optional<OUString>(), std::optional<OUString>(), std::optional<OUString>() );
275
0
    }
276
277
278
    void SQLError::raiseTypedException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
279
        const Type& _rExceptionType ) const
280
0
    {
281
0
        m_pImpl->raiseTypedException( _eCondition, _rxContext, _rExceptionType, std::optional<OUString>(), std::optional<OUString>(), std::optional<OUString>() );
282
0
    }
283
284
285
    SQLException SQLError::getSQLException( const ErrorCondition _eCondition, const Reference< XInterface >& _rxContext,
286
        const std::optional<OUString>& _rParamValue1, const std::optional<OUString>& _rParamValue2, const std::optional<OUString>& _rParamValue3 ) const
287
0
    {
288
0
        return m_pImpl->getSQLException( _eCondition, _rxContext, _rParamValue1, _rParamValue2, _rParamValue3 );
289
0
    }
290
291
292
} // namespace connectivity
293
294
295
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */