Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/connectivity/sqliterator.hxx
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
#ifndef INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
20
#define INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
21
22
#include <connectivity/dbtoolsdllapi.hxx>
23
#include <connectivity/IParseContext.hxx>
24
#include <com/sun/star/sdbc/DataType.hpp>
25
#include <com/sun/star/sdbc/SQLException.hpp>
26
#include <connectivity/CommonTools.hxx>
27
#include <rtl/ref.hxx>
28
29
#include <memory>
30
#include <optional>
31
#include <vector>
32
#include <o3tl/typed_flags_set.hxx>
33
34
namespace com::sun::star::sdbc { class XConnection; }
35
namespace com::sun::star::beans { class XPropertySet; }
36
37
namespace connectivity
38
{
39
    enum class TraversalParts
40
    {
41
        Parameters      = 0x0001,
42
        TableNames      = 0x0002,
43
        SelectColumns   = 0x0006,   // note that this includes TableNames. No SelectColumns without TableNames
44
45
        // Those are not implemented currently
46
        // GroupColumns    = 0x0008,
47
        // OrderColumns    = 0x0010,
48
        // SelectColumns   = 0x0020,
49
        // CreateColumns   = 0x0040,
50
51
        All             = 0xFFFF
52
    };
53
}
54
namespace o3tl
55
{
56
    template<> struct typed_flags<connectivity::TraversalParts> : is_typed_flags<connectivity::TraversalParts, 0xffff> {};
57
}
58
59
namespace connectivity
60
{
61
62
    class OSQLParseNode;
63
    class OSQLParser;
64
65
    typedef ::std::pair<const OSQLParseNode*,const OSQLParseNode* > TNodePair;
66
67
    enum class OSQLStatementType {
68
        Unknown,
69
        Select,
70
        Insert,
71
        Update,
72
        Delete,
73
        OdbcCall,
74
        CreateTable
75
    };
76
77
    struct OSQLParseTreeIteratorImpl;
78
79
    class OSQLParseTreeIterator final
80
    {
81
    private:
82
        std::optional<css::sdbc::SQLException>              m_xErrors;          // contains the error while iterating through the statement
83
        const OSQLParseNode*                                m_pParseTree;       // current ParseTree
84
        const OSQLParser&                                   m_rParser;          // if set used for general error messages from the context
85
        OSQLStatementType                                   m_eStatementType;
86
        ::rtl::Reference<OSQLColumns>                       m_aSelectColumns;   // all columns from the Select clause
87
        ::rtl::Reference<OSQLColumns>                       m_aParameters;      // all parameters
88
        ::rtl::Reference<OSQLColumns>                       m_aGroupColumns;    // the group by columns
89
        ::rtl::Reference<OSQLColumns>                       m_aOrderColumns;    // the order by columns
90
        ::rtl::Reference<OSQLColumns>                       m_aCreateColumns;   // the columns for Create table clause
91
92
        ::std::unique_ptr< OSQLParseTreeIteratorImpl >  m_pImpl;
93
94
        void                traverseParameter(const OSQLParseNode* _pParseNode,const OSQLParseNode* _pColumnRef,const OUString& _aColumnName, OUString& _aTableRange, const OUString& _rColumnAlias);
95
        // inserts a table into the map
96
        void                traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const OUString & rTableRange );
97
        void                traverseSearchCondition(OSQLParseNode const * pSearchCondition);
98
        void                traverseOnePredicate(
99
                                                OSQLParseNode const * pColumnRef,
100
                                                OUString& aValue,
101
                                                OSQLParseNode const * pParameter);
102
        void traverseByColumnNames(const OSQLParseNode* pSelectNode, bool _bOrder);
103
        void                traverseParameters(const OSQLParseNode* pSelectNode);
104
105
        const OSQLParseNode*    getTableNode( OSQLTables& _rTables, const OSQLParseNode* pTableRef, OUString& aTableRange );
106
        void                    getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, OUString& aTableRange );
107
        void                    getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect);
108
        // get all the column names of m_aSelectColumns and return in a vector sorted by a UStringMixLess that's constructed from
109
        // isCaseSensitive()
110
        std::vector<OUString> getSelectColumnNames() const;
111
        // rColumnNames is expected to be sorted as returned by getSelectColumnNames
112
        OUString getUniqueColumnName(const std::vector<OUString>& rColumnNames, const OUString & rColumnName) const;
113
114
        /** finds the column with a given name, belonging to a given table, in a given tables collection
115
            @param  _rTables
116
                the tables collection to look in
117
            @param  rColumnName
118
                the column name to look for
119
            @param  rTableRange
120
                the table alias name; if empty, look in all tables
121
            @return
122
                the desired column object, or <NULL/> if no such column could be found
123
        */
124
        static css::uno::Reference< css::beans::XPropertySet > findColumn(
125
            const OSQLTables& _rTables, const OUString & rColumnName, OUString & rTableRange );
126
127
        /** finds a column with a given name, belonging to a given table
128
            @param  rColumnName
129
                the column name to look for
130
            @param  rTableRange
131
                    the table alias name; if empty, look in all tables
132
            @param  _bLookInSubTables
133
                <TRUE/> if and only if not only our direct tables, but also our sub tables (from sub selects)
134
                should be searched
135
            @return
136
        */
137
        css::uno::Reference< css::beans::XPropertySet > findColumn(
138
            const OUString & rColumnName, OUString & rTableRange, bool _bLookInSubTables );
139
140
        /** finds a column with a given name among the select columns
141
            @param  rColumnName
142
                the column name to look for
143
            @return
144
        */
145
        css::uno::Reference< css::beans::XPropertySet > findSelectColumn(
146
            std::u16string_view rColumnName );
147
148
        void setSelectColumnName(const OUString& rColumnName, const OUString& rColumnAlias, const OUString& rTableRange, bool bFkt = false, sal_Int32 _nType = css::sdbc::DataType::VARCHAR, bool bAggFkt = false);
149
        void appendColumns(const OUString& _rTableAlias, const OSQLTable& _rTable);
150
        // Other member variables that should be available in the "set" functions
151
        // can be defined in the derived class. They can be initialized
152
        // in its constructor and, after the "traverse" routines have been used,
153
        // they can be queried using other functions.
154
155
        OSQLParseTreeIterator(const OSQLParseTreeIterator & rIter) = delete;
156
157
      public:
158
        OOO_DLLPUBLIC_DBTOOLS OSQLParseTreeIterator(
159
            const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
160
            const css::uno::Reference< css::container::XNameAccess >& _rxTables,
161
            const OSQLParser& _rParser );
162
        OOO_DLLPUBLIC_DBTOOLS ~OSQLParseTreeIterator();
163
164
        OOO_DLLPUBLIC_DBTOOLS void dispose();
165
        OOO_DLLPUBLIC_DBTOOLS bool isCaseSensitive() const;
166
        // The parse tree to be analysed/traversed:
167
        // If NULL is passed, the current parse tree will be deleted and the error status cleared.
168
        OOO_DLLPUBLIC_DBTOOLS void setParseTree(const OSQLParseNode * pNewParseTree);
169
161k
        const OSQLParseNode * getParseTree() const { return m_pParseTree; };
170
171
        // subtrees in case of a select statement
172
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getWhereTree() const;
173
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getOrderTree() const;
174
        const OSQLParseNode* getGroupByTree() const;
175
        const OSQLParseNode* getHavingTree() const;
176
177
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getSimpleWhereTree() const;
178
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getSimpleOrderTree() const;
179
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getSimpleGroupByTree() const;
180
        OOO_DLLPUBLIC_DBTOOLS const OSQLParseNode* getSimpleHavingTree() const;
181
182
        /** returns the errors which occurred during parsing.
183
184
            The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
185
        */
186
0
        const css::sdbc::SQLException&   getErrors() const { return *m_xErrors; }
187
311k
        bool hasErrors() const { return bool(m_xErrors); }
188
189
        // statement type (already set in setParseTree):
190
9.55M
        OSQLStatementType getStatementType() const { return m_eStatementType; }
191
192
        /** traverses the complete statement tree, and fills all our data with
193
            the information obatined during traversal.
194
195
            Implemented by calling the single traverse* methods in the proper
196
            order (depending on the statement type).
197
        */
198
        OOO_DLLPUBLIC_DBTOOLS void traverseAll();
199
200
        // The TableRangeMap contains all tables associated with the range name found first.
201
        OOO_DLLPUBLIC_DBTOOLS const OSQLTables& getTables() const;
202
203
161k
        const ::rtl::Reference<OSQLColumns>& getSelectColumns() const { return m_aSelectColumns;}
204
0
        const ::rtl::Reference<OSQLColumns>& getGroupColumns() const { return m_aGroupColumns;}
205
0
        const ::rtl::Reference<OSQLColumns>& getOrderColumns() const { return m_aOrderColumns;}
206
34.5k
        const ::rtl::Reference<OSQLColumns>& getParameters()   const { return m_aParameters; }
207
208
        /** return the columname and the table range
209
            @param  _pColumnRef
210
                The column ref parse node.
211
            @param  _rColumnName
212
                The column name to be set.
213
            @param  _rTableRange
214
                The table range to be set.
215
        */
216
        OOO_DLLPUBLIC_DBTOOLS void getColumnRange( const OSQLParseNode* _pColumnRef,
217
                                OUString &_rColumnName,
218
                                OUString& _rTableRange) const;
219
220
        /** retrieves a column's name, table range, and alias
221
222
            @param  _pColumnRef
223
                The column_ref parse node.
224
            @param  _out_rColumnName
225
                The column name to be set.
226
            @param  _out_rTableRange
227
                The table range to be set.
228
            @param _out_rColumnAliasIfPresent
229
                If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
230
                this alias is returned here.
231
        */
232
        void getColumnRange(    const OSQLParseNode* _pColumnRef,
233
                                OUString& _out_rColumnName,
234
                                OUString& _out_rTableRange,
235
                                OUString& _out_rColumnAliasIfPresent
236
                                ) const;
237
238
        /** return the alias name of a column
239
            @param  _pDerivedColumn
240
                The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
241
            @return
242
                The alias name of the column or an empty string.
243
        */
244
        OOO_DLLPUBLIC_DBTOOLS static OUString getColumnAlias(const OSQLParseNode* _pDerivedColumn);
245
246
        /** return the columname and the table range
247
            @param  _pColumnRef
248
                The column ref parse node.
249
            @param  _xMetaData
250
                The database meta data.
251
            @param  _rColumnName
252
                The column name to be set.
253
            @param  _rTableRange
254
                The table range to be set.
255
        */
256
        OOO_DLLPUBLIC_DBTOOLS static void getColumnRange( const OSQLParseNode* _pColumnRef,
257
                                    const css::uno::Reference< css::sdbc::XConnection >& _rxConnection,
258
                                    OUString &_rColumnName,
259
                                    OUString& _rTableRange);
260
261
        // return true when the tableNode is a rule like catalog_name, schema_name or table_name
262
        OOO_DLLPUBLIC_DBTOOLS static bool isTableNode(const OSQLParseNode* _pTableNode);
263
264
        // tries to find the correct type of the function
265
        sal_Int32 getFunctionReturnType(const OSQLParseNode* _pNode );
266
267
        // returns a lis of all joined columns
268
        OOO_DLLPUBLIC_DBTOOLS ::std::vector< TNodePair >& getJoinConditions() const;
269
270
    private:
271
272
        /** traverses the list of table names, and fills _rTables
273
        */
274
        bool traverseTableNames( OSQLTables& _rTables );
275
276
        /// traverses columns in a SELECT statement
277
        bool traverseSelectColumnNames(const OSQLParseNode* pSelectNode);
278
        /// traverses columns in a CREATE TABLE statement
279
        void traverseCreateColumns(const OSQLParseNode* pSelectNode);
280
281
        bool traverseOrderByColumnNames(const OSQLParseNode* pSelectNode);
282
        bool traverseGroupByColumnNames(const OSQLParseNode* pSelectNode);
283
284
        bool traverseSelectionCriteria(const OSQLParseNode* pSelectNode);
285
286
        /** constructs a new iterator, which inherits some of the settings from a parent iterator
287
        */
288
        OSQLParseTreeIterator(
289
            const OSQLParseTreeIterator& _rParentIterator,
290
            const OSQLParser& _rParser,
291
            const OSQLParseNode* pRoot );
292
293
        /** creates a table object and inserts it into our tables collection
294
295
            only used when we're iterating through a CREATE TABLE statement
296
        */
297
        OSQLTable   impl_createTableObject(
298
            const OUString& rTableName, const OUString& rCatalogName, const OUString& rSchemaName );
299
300
        /** locates a record source (a table or query) with the given name
301
        */
302
        OSQLTable   impl_locateRecordSource(
303
            const OUString& _rComposedName
304
        );
305
306
        /** implementation for both traverseAll and traverseSome
307
        */
308
        void    impl_traverse( TraversalParts _nIncludeMask );
309
310
        /** retrieves the parameter columns of the given query
311
        */
312
        void    impl_getQueryParameterColumns( const OSQLTable& _rQuery );
313
314
        void setOrderByColumnName(const OUString & rColumnName, OUString & rTableRange, bool bAscending);
315
        void setGroupByColumnName(const OUString & rColumnName, OUString & rTableRange);
316
317
        /** appends an SQLException corresponding to the given error code to our error collection
318
319
            @param  _eError
320
                the code of the error which occurred
321
            @param  _pReplaceToken1
322
                if not <NULL/>, the first occurrence of '#' in the error message will be replaced
323
                with the given token
324
            @param  _pReplaceToken2
325
                if not <NULL/>, and if _rReplaceToken1 is not <NULL/>, the second occurrence of '#'
326
                in the error message will be replaced with _rReplaceToken2
327
        */
328
        void impl_appendError( IParseContext::ErrorCode _eError,
329
            const OUString* _pReplaceToken1 = nullptr, const OUString* _pReplaceToken2 = nullptr );
330
331
        /** appends an SQLException corresponding to the given error code to our error collection
332
        */
333
        void impl_appendError( const css::sdbc::SQLException& _rError );
334
335
        void impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition);
336
    };
337
}
338
339
#endif // INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
340
341
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */