summaryrefslogtreecommitdiff
path: root/include/connectivity/parameters.hxx
blob: 8d526c983af5505087ce567d70950d07d59d49e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_CONNECTIVITY_PARAMETERS_HXX
#define INCLUDED_CONNECTIVITY_PARAMETERS_HXX

#include <map>
#include <utility>
#include <vector>

#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>

#include <connectivity/dbtoolsdllapi.hxx>
#include <connectivity/paramwrapper.hxx>
#include <unotools/sharedunocomponent.hxx>
#include <comphelper/interfacecontainer3.hxx>

namespace com::sun::star::beans { class XPropertySet; }
namespace com::sun::star::container { class XIndexAccess; }
namespace com::sun::star::form { class XDatabaseParameterListener; }
namespace com::sun::star::io { class XInputStream; }
namespace com::sun::star::sdbc { class XArray; }
namespace com::sun::star::sdbc { class XBlob; }
namespace com::sun::star::sdbc { class XClob; }
namespace com::sun::star::sdbc { class XConnection; }
namespace com::sun::star::sdbc { class XDatabaseMetaData; }
namespace com::sun::star::sdbc { class XParameters; }
namespace com::sun::star::sdbc { class XRef; }
namespace com::sun::star::task { class XInteractionHandler; }
namespace com::sun::star::uno { class XAggregation; }
namespace com::sun::star::uno { class XComponentContext; }

namespace dbtools
{


    typedef ::utl::SharedUNOComponent< css::sdb::XSingleSelectQueryComposer, ::utl::DisposableComponent >
            SharedQueryComposer;


    //= ParameterManager

    class FilterManager;
    class OOO_DLLPUBLIC_DBTOOLS ParameterManager
    {
    public:
        /// classifies the origin of the data to fill a parameter
        enum class ParameterClassification
        {
            /** parameters which are filled from the master-detail relationship, where the detail
                name is an explicit parameter name
            */
            LinkedByParamName,
            /** parameters which are filled from the master-detail relationship, where the detail
                name is a column name, so an implicit parameter had to be generated for it
            */
            LinkedByColumnName,
            /** parameters which are filled externally (i.e. by XParameters::setXXX, or by the parameter listeners)
            */
            FilledExternally
        };
        /** meta data about an inner parameter
        */
    private:
        struct ParameterMetaData
        {
            /// the type of the parameter
            ParameterClassification     eType;
            /// the column object for this parameter, as returned by the query composer
            css::uno::Reference< css::beans::XPropertySet >
                                        xComposerColumn;
            /// the indices of inner parameters which need to be filled when this concrete parameter is set
            ::std::vector< sal_Int32 >  aInnerIndexes;

            /// ctor with composer column
            ParameterMetaData( css::uno::Reference< css::beans::XPropertySet > _xColumn )
                :eType           ( ParameterClassification::FilledExternally )
                ,xComposerColumn (std::move( _xColumn         ))
            {
            }
        };

        typedef ::std::map< OUString, ParameterMetaData >    ParameterInformation;

    private:
        ::osl::Mutex&                       m_rMutex;
        ::comphelper::OInterfaceContainerHelper3<css::form::XDatabaseParameterListener> m_aParameterListeners;

        css::uno::Reference< css::uno::XComponentContext >
                                            m_xContext;

        css::uno::WeakReference< css::beans::XPropertySet >
                                            m_xComponent;                // the database component whose parameters we're handling
        css::uno::Reference< css::uno::XAggregation >
                                            m_xAggregatedRowSet;    // the aggregated row set - necessary for unwrapped access to some interfaces
        css::uno::Reference< css::sdbc::XParameters >
                                            m_xInnerParamUpdate;    // write access to the inner parameters
        SharedQueryComposer                 m_xComposer;            // query composer wrapping the statement which the *aggregate* is based on
        SharedQueryComposer                 m_xParentComposer;      // query composer wrapping the statement of our parent database component
        css::uno::Reference< css::container::XIndexAccess >
                                            m_xInnerParamColumns;   // index access to the parameter columns, as got from the query composer

        ::dbtools::param::ParametersContainerRef
                                            m_pOuterParameters;     // the container of parameters which still need to be filled in by
                                                                    // external instances
        sal_Int32                           m_nInnerCount;          // overall number of parameters as required by the database component's aggregate

        ParameterInformation                m_aParameterInformation;

        std::vector< OUString >             m_aMasterFields;
        std::vector< OUString >             m_aDetailFields;

        OUString                            m_sIdentifierQuoteString;
        OUString                            m_sSpecialCharacters;
        css::uno::Reference< css::sdbc::XDatabaseMetaData > m_xConnectionMetadata;

        ::std::vector< bool >               m_aParametersVisited;

        bool                                m_bUpToDate;

    public:
        /** ctor
        */
        explicit ParameterManager(
            ::osl::Mutex& _rMutex,
            const css::uno::Reference< css::uno::XComponentContext >& _rxContext
        );

        /// late ctor
        void    initialize(
                    const css::uno::Reference< css::beans::XPropertySet >& _rxComponent,
                    const css::uno::Reference< css::uno::XAggregation >& _rxComponentAggregate
                );

        /// makes the object forgetting the references to the database component
        void    dispose( );

        /// clears the instance data
                void    clearAllParameterInformation();

        /// checks whether the parameter information is up-to-date
        bool    isUpToDate() const { return m_bUpToDate; }

        /** updates all parameter information represented by the instance
        */
        void    updateParameterInfo( FilterManager& _rFilterManager );

        /** fills parameter values, as extensive as possible

            <p>In particular, all values which can be filled from the master-detail relationship of
            between our database component and its parent are filled in.</p>

            @param _rxCompletionHandler
                an interaction handler which should be used to fill all parameters which
                cannot be filled by other means. May be <NULL/>
            @param _rClearForNotifies
                the mutex guard to be (temporarily) cleared for notifications

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>

            @return
                <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
        */
        bool    fillParameterValues(
                    const css::uno::Reference< css::task::XInteractionHandler >& _rxCompletionHandler,
                    ::osl::ResettableMutexGuard& _rClearForNotifies
                );

        /** sets all parameter values to null (via <member>XParameters::setNull</member>)

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
        */
        void    setAllParametersNull();

        /** resets all detail columns which are, via a parameter, linked to a master column, to
            the value of this master column.

            For instance, if the database component is bound to a statement <code>SELECT * from invoice where inv_id = :cid</code>,
            and there is <em>one</em> master-detail link from

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
        */
        void    resetParameterValues();

        /** adds the given listener to the list of parameter listeners
        */
        void    addParameterListener(
                    const css::uno::Reference< css::form::XDatabaseParameterListener >& _rxListener
                );

        /** removes the given listener from the list of parameter listeners
        */
        void    removeParameterListener(
                    const css::uno::Reference< css::form::XDatabaseParameterListener >& _rxListener
                );

        // XParameters equivalents
        void setNull            ( sal_Int32 _nIndex, sal_Int32 sqlType);
        void setObjectNull      ( sal_Int32 _nIndex, sal_Int32 sqlType, const OUString& typeName);
        void setBoolean         ( sal_Int32 _nIndex, bool x);
        void setByte            ( sal_Int32 _nIndex, sal_Int8 x);
        void setShort           ( sal_Int32 _nIndex, sal_Int16 x);
        void setInt             ( sal_Int32 _nIndex, sal_Int32 x);
        void setLong            ( sal_Int32 _nIndex, sal_Int64 x);
        void setFloat           ( sal_Int32 _nIndex, float x);
        void setDouble          ( sal_Int32 _nIndex, double x);
        void setString          ( sal_Int32 _nIndex, const OUString& x);
        void setBytes           ( sal_Int32 _nIndex, const css::uno::Sequence< sal_Int8 >& x);
        void setDate            ( sal_Int32 _nIndex, const css::util::Date& x);
        void setTime            ( sal_Int32 _nIndex, const css::util::Time& x);
        void setTimestamp       ( sal_Int32 _nIndex, const css::util::DateTime& x);
        void setBinaryStream    ( sal_Int32 _nIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length);
        void setCharacterStream ( sal_Int32 _nIndex, const css::uno::Reference< css::io::XInputStream>& x, sal_Int32 length);
        void setObject          ( sal_Int32 _nIndex, const css::uno::Any& x);
        void setObjectWithInfo  ( sal_Int32 _nIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale);
        void setRef             ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XRef>& x);
        void setBlob            ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XBlob>& x);
        void setClob            ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XClob>& x);
        void setArray           ( sal_Int32 _nIndex, const css::uno::Reference< css::sdbc::XArray>& x);
        void clearParameters();

    private:
        /// checks whether the object is already initialized, and not yet disposed
        bool    isAlive() const { return m_xComponent.get().is() && m_xInnerParamUpdate.is(); }

        /** creates a filter expression from a master-detail link where the detail denotes a column name
        */
        OUString
                createFilterConditionFromColumnLink(
                    const OUString& /* [in]  */ _rMasterColumn,
                    const css::uno::Reference< css::beans::XPropertySet >& /* [in]  */ xDetailColumn,
                          OUString& /* [out] */ _rNewParamName
                );

        /** initializes our query composer, and the collection of inner parameter columns

            @param _rxComponent
                the database component to initialize from. Must not be <NULL/>
            @return
                <TRUE/> if and only if the initialization was successful

            @postcond
                if and only if <TRUE/> is returned, then <member>m_xInnerParamColumns</member> contains the collection of
                inner parameters
        */
        bool    initializeComposerByComponent(
                    const css::uno::Reference< css::beans::XPropertySet >& _rxComponent
                );

        /** collects initial meta information about inner parameters (i.e. it initially fills
            <member>m_aParameterInformation</member>).

            @param _bSecondRun
                if <TRUE/>, this is the second run, because we ourself previously extended the filter of
                the RowSet

            @precond
                <member>m_xInnerParamColumns</member> is not <NULL/>
        */
        void    collectInnerParameters( bool _bSecondRun );

        /** analyzes the master-detail links for our database component, and initializes m_aMasterFields and m_aDetailFields

            @param _rFilterManager
                the filter manager of the database component
            @param _rColumnsInLinkDetails
                will be set to <TRUE/> if and only if there were link pairs where the detail field denoted
                a column name of our database component

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
        */
        void    analyzeFieldLinks( FilterManager& _rFilterManager, bool& /* [out] */ _rColumnsInLinkDetails );

        /** classifies the link pairs

            @param  _rxParentColumns
                the columns of the parent database component

            @param  _rxColumns
                the columns of our own database component

            @param  _out_rAdditionalFilterComponents
                the additional filter components which are required for master-detail relationships where
                the detail part denotes a column name. In such a case, an additional filter needs to be created,
                containing a new parameter.

            @param  _out_rAdditionalHavingComponents
                the additional having clause components which are required for master-detail relationships where
                the detail part denotes a column name. In such a case, an additional filter needs to be created,
                containing a new parameter.

            @precond
                <member>m_aMasterFields</member> and <member>m_aDetailFields</member> have the same length
        */
        void    classifyLinks(
                    const css::uno::Reference< css::container::XNameAccess >& _rxParentColumns,
                    const css::uno::Reference< css::container::XNameAccess >& _rxColumns,
                    ::std::vector< OUString >& _out_rAdditionalFilterComponents,
                    ::std::vector< OUString >& _out_rAdditionalHavingComponents
                );

        /** finalizes our <member>m_pOuterParameters</member> so that it can be used for
            external parameter listeners

            @precond
                <member>m_pOuterParameters</member> is <NULL/>
            @precond
                <member>m_xInnerParamUpdate</member> is not <NULL/>
        */
        void    createOuterParameters();

        /** fills in the parameters values which result from the master-detail relationship
            between the database component and its parent

            @param _rxParentColumns
                the columns of the parameter database component. Must not be <NULL/>
            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
        */
        void    fillLinkedParameters(
                    const css::uno::Reference< css::container::XNameAccess >& _rxParentColumns
                );

        /** completes all missing parameters via an interaction handler

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>

            @return
                <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
        */
        bool    completeParameters(
                    const css::uno::Reference< css::task::XInteractionHandler >& _rxCompletionHandler,
                    const css::uno::Reference< css::sdbc::XConnection >& _rxConnection
                );

        /** asks the parameter listeners to fill in final values

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>

            @return
                <TRUE/> if and only if the parameter filling has <em>not</em> been cancelled by the user
        */
        bool    consultParameterListeners( ::osl::ResettableMutexGuard& _rClearForNotifies );

        /** mark an externally filled parameter as visited
        */
        void    externalParameterVisited( sal_Int32 _nIndex );

    private:
        /** retrieves the columns of the parent database component

            @precond
                the instance is alive, i.e. <member>isAlive</member> returns <TRUE/>
            @return
                <TRUE/> if and only if the columns could be successfully retrieved
        */
        bool    getParentColumns(
                    css::uno::Reference< css::container::XNameAccess >& /* [out] */ _out_rxParentColumns,
                    bool _bFromComposer
                );

        /** retrieves the columns of our database component

            @param _bFromComposer
                if <TRUE/>, the columns are obtained from the composer, else from the living database component itself
            @return
                <TRUE/> if and only if the columns could be successfully retrieved
        */
        bool    getColumns(
                    css::uno::Reference< css::container::XNameAccess >& /* [out] */ _rxColumns,
                    bool _bFromComposer
                );

        /** retrieves the active connection of the database component
        */
        void    getConnection(
                    css::uno::Reference< css::sdbc::XConnection >& /* [out] */ _rxConnection
                );

        /** caches some info about the connection of our database component
        */
        void    cacheConnectionInfo();

    private:
        ParameterManager( const ParameterManager& ) = delete;
        ParameterManager& operator=( const ParameterManager& ) = delete;
    };


} // namespacefrm


#endif // INCLUDED_CONNECTIVITY_PARAMETERS_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */