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 .
19 #ifndef INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
20 #define INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
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>
32 #include <o3tl/typed_flags_set.hxx>
34 namespace com::sun::star::sdbc
{ class XConnection
; }
35 namespace com::sun::star::beans
{ class XPropertySet
; }
37 namespace connectivity
39 enum class TraversalParts
43 SelectColumns
= 0x0006, // note that this includes TableNames. No SelectColumns without TableNames
45 // Those are not implemented currently
46 // GroupColumns = 0x0008,
47 // OrderColumns = 0x0010,
48 // SelectColumns = 0x0020,
49 // CreateColumns = 0x0040,
56 template<> struct typed_flags
<connectivity::TraversalParts
> : is_typed_flags
<connectivity::TraversalParts
, 0xffff> {};
59 namespace connectivity
65 typedef ::std::pair
<const OSQLParseNode
*,const OSQLParseNode
* > TNodePair
;
67 enum class OSQLStatementType
{
77 struct OSQLParseTreeIteratorImpl
;
79 class OSQLParseTreeIterator final
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
92 ::std::unique_ptr
< OSQLParseTreeIteratorImpl
> m_pImpl
;
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
,
101 OSQLParseNode
const * pParameter
);
102 void traverseByColumnNames(const OSQLParseNode
* pSelectNode
, bool _bOrder
);
103 void traverseParameters(const OSQLParseNode
* pSelectNode
);
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
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;
114 /** finds the column with a given name, belonging to a given table, in a given tables collection
116 the tables collection to look in
118 the column name to look for
120 the table alias name; if empty, look in all tables
122 the desired column object, or <NULL/> if no such column could be found
124 static css::uno::Reference
< css::beans::XPropertySet
> findColumn(
125 const OSQLTables
& _rTables
, const OUString
& rColumnName
, OUString
& rTableRange
);
127 /** finds a column with a given name, belonging to a given table
129 the column name to look for
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)
137 css::uno::Reference
< css::beans::XPropertySet
> findColumn(
138 const OUString
& rColumnName
, OUString
& rTableRange
, bool _bLookInSubTables
);
140 /** finds a column with a given name among the select columns
142 the column name to look for
145 css::uno::Reference
< css::beans::XPropertySet
> findSelectColumn(
146 std::u16string_view rColumnName
);
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.
155 OSQLParseTreeIterator(const OSQLParseTreeIterator
& rIter
) = delete;
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();
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 const OSQLParseNode
* getParseTree() const { return m_pParseTree
; };
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;
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;
182 /** returns the errors which occurred during parsing.
184 The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
186 const css::sdbc::SQLException
& getErrors() const { return *m_xErrors
; }
187 bool hasErrors() const { return bool(m_xErrors
); }
189 // statement type (already set in setParseTree):
190 OSQLStatementType
getStatementType() const { return m_eStatementType
; }
192 /** traverses the complete statement tree, and fills all our data with
193 the information obatined during traversal.
195 Implemented by calling the single traverse* methods in the proper
196 order (depending on the statement type).
198 OOO_DLLPUBLIC_DBTOOLS
void traverseAll();
200 // The TableRangeMap contains all tables associated with the range name found first.
201 OOO_DLLPUBLIC_DBTOOLS
const OSQLTables
& getTables() const;
203 const ::rtl::Reference
<OSQLColumns
>& getSelectColumns() const { return m_aSelectColumns
;}
204 const ::rtl::Reference
<OSQLColumns
>& getGroupColumns() const { return m_aGroupColumns
;}
205 const ::rtl::Reference
<OSQLColumns
>& getOrderColumns() const { return m_aOrderColumns
;}
206 const ::rtl::Reference
<OSQLColumns
>& getParameters() const { return m_aParameters
; }
208 /** return the columname and the table range
210 The column ref parse node.
212 The column name to be set.
214 The table range to be set.
216 OOO_DLLPUBLIC_DBTOOLS
void getColumnRange( const OSQLParseNode
* _pColumnRef
,
217 OUString
&_rColumnName
,
218 OUString
& _rTableRange
) const;
220 /** retrieves a column's name, table range, and alias
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.
232 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
233 OUString
& _out_rColumnName
,
234 OUString
& _out_rTableRange
,
235 OUString
& _out_rColumnAliasIfPresent
238 /** return the alias name of a column
239 @param _pDerivedColumn
240 The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
242 The alias name of the column or an empty string.
244 OOO_DLLPUBLIC_DBTOOLS
static OUString
getColumnAlias(const OSQLParseNode
* _pDerivedColumn
);
246 /** return the columname and the table range
248 The column ref parse node.
250 The database meta data.
252 The column name to be set.
254 The table range to be set.
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
);
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
);
264 // tries to find the correct type of the function
265 sal_Int32
getFunctionReturnType(const OSQLParseNode
* _pNode
);
267 // returns a lis of all joined columns
268 OOO_DLLPUBLIC_DBTOOLS ::std::vector
< TNodePair
>& getJoinConditions() const;
272 /** traverses the list of table names, and fills _rTables
274 bool traverseTableNames( OSQLTables
& _rTables
);
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
);
281 bool traverseOrderByColumnNames(const OSQLParseNode
* pSelectNode
);
282 bool traverseGroupByColumnNames(const OSQLParseNode
* pSelectNode
);
284 bool traverseSelectionCriteria(const OSQLParseNode
* pSelectNode
);
286 /** constructs a new iterator, which inherits some of the settings from a parent iterator
288 OSQLParseTreeIterator(
289 const OSQLParseTreeIterator
& _rParentIterator
,
290 const OSQLParser
& _rParser
,
291 const OSQLParseNode
* pRoot
);
293 /** creates a table object and inserts it into our tables collection
295 only used when we're iterating through a CREATE TABLE statement
297 OSQLTable
impl_createTableObject(
298 const OUString
& rTableName
, const OUString
& rCatalogName
, const OUString
& rSchemaName
);
300 /** locates a record source (a table or query) with the given name
302 OSQLTable
impl_locateRecordSource(
303 const OUString
& _rComposedName
306 /** implementation for both traverseAll and traverseSome
308 void impl_traverse( TraversalParts _nIncludeMask
);
310 /** retrieves the parameter columns of the given query
312 void impl_getQueryParameterColumns( const OSQLTable
& _rQuery
);
314 void setOrderByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
, bool bAscending
);
315 void setGroupByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
);
317 /** appends an SQLException corresponding to the given error code to our error collection
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
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
328 void impl_appendError( IParseContext::ErrorCode _eError
,
329 const OUString
* _pReplaceToken1
= nullptr, const OUString
* _pReplaceToken2
= nullptr );
331 /** appends an SQLException corresponding to the given error code to our error collection
333 void impl_appendError( const css::sdbc::SQLException
& _rError
);
335 void impl_fillJoinConditions(const OSQLParseNode
* i_pJoinCondition
);
339 #endif // INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
341 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */