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 OOO_DLLPUBLIC_DBTOOLS 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 OUString
getUniqueColumnName(const OUString
& rColumnName
) const;
110 /** finds the column with a given name, belonging to a given table, in a given tables collection
112 the tables collection to look in
114 the column name to look for
116 the table alias name; if empty, look in all tables
118 the desired column object, or <NULL/> if no such column could be found
120 static css::uno::Reference
< css::beans::XPropertySet
> findColumn(
121 const OSQLTables
& _rTables
, const OUString
& rColumnName
, OUString
& rTableRange
);
123 /** finds a column with a given name, belonging to a given table
125 the column name to look for
127 the table alias name; if empty, look in all tables
128 @param _bLookInSubTables
129 <TRUE/> if and only if not only our direct tables, but also our sub tables (from sub selects)
133 css::uno::Reference
< css::beans::XPropertySet
> findColumn(
134 const OUString
& rColumnName
, OUString
& rTableRange
, bool _bLookInSubTables
);
136 /** finds a column with a given name among the select columns
138 the column name to look for
141 css::uno::Reference
< css::beans::XPropertySet
> findSelectColumn(
142 const OUString
& rColumnName
);
144 void setSelectColumnName(::rtl::Reference
<OSQLColumns
> const & _rColumns
,const OUString
& rColumnName
,const OUString
& rColumnAlias
, const OUString
& rTableRange
, bool bFkt
=false, sal_Int32 _nType
= css::sdbc::DataType::VARCHAR
, bool bAggFkt
=false);
145 void appendColumns(::rtl::Reference
<OSQLColumns
> const & _rColumns
,const OUString
& _rTableAlias
,const OSQLTable
& _rTable
);
146 // Other member variables that should be available in the "set" functions
147 // can be defined in the derived class. They can be initialized
148 // in its constructor and, after the "traverse" routines have been used,
149 // they can be queried using other functions.
151 OSQLParseTreeIterator(const OSQLParseTreeIterator
& rIter
) = delete;
154 OSQLParseTreeIterator(
155 const css::uno::Reference
< css::sdbc::XConnection
>& _rxConnection
,
156 const css::uno::Reference
< css::container::XNameAccess
>& _rxTables
,
157 const OSQLParser
& _rParser
);
158 ~OSQLParseTreeIterator();
161 bool isCaseSensitive() const;
162 // The parse tree to be analysed/traversed:
163 // If NULL is passed, the current parse tree will be deleted and the error status cleared.
164 void setParseTree(const OSQLParseNode
* pNewParseTree
);
165 const OSQLParseNode
* getParseTree() const { return m_pParseTree
; };
167 // subtrees in case of a select statement
168 const OSQLParseNode
* getWhereTree() const;
169 const OSQLParseNode
* getOrderTree() const;
170 const OSQLParseNode
* getGroupByTree() const;
171 const OSQLParseNode
* getHavingTree() const;
173 const OSQLParseNode
* getSimpleWhereTree() const;
174 const OSQLParseNode
* getSimpleOrderTree() const;
175 const OSQLParseNode
* getSimpleGroupByTree() const;
176 const OSQLParseNode
* getSimpleHavingTree() const;
178 /** returns the errors which occurred during parsing.
180 The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
182 const css::sdbc::SQLException
& getErrors() const { return *m_xErrors
; }
183 bool hasErrors() const { return bool(m_xErrors
); }
185 // statement type (already set in setParseTree):
186 OSQLStatementType
getStatementType() const { return m_eStatementType
; }
188 /** traverses the complete statement tree, and fills all our data with
189 the information obatined during traversal.
191 Implemented by calling the single traverse* methods in the proper
192 order (depending on the statement type).
196 // The TableRangeMap contains all tables associated with the range name found first.
197 const OSQLTables
& getTables() const;
199 const ::rtl::Reference
<OSQLColumns
>& getSelectColumns() const { return m_aSelectColumns
;}
200 const ::rtl::Reference
<OSQLColumns
>& getGroupColumns() const { return m_aGroupColumns
;}
201 const ::rtl::Reference
<OSQLColumns
>& getOrderColumns() const { return m_aOrderColumns
;}
202 const ::rtl::Reference
<OSQLColumns
>& getParameters() const { return m_aParameters
; }
204 /** return the columname and the table range
206 The column ref parse node.
208 The column name to be set.
210 The table range to be set.
212 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
213 OUString
&_rColumnName
,
214 OUString
& _rTableRange
) const;
216 /** retrieves a column's name, table range, and alias
219 The column_ref parse node.
220 @param _out_rColumnName
221 The column name to be set.
222 @param _out_rTableRange
223 The table range to be set.
224 @param _out_rColumnAliasIfPresent
225 If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
226 this alias is returned here.
228 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
229 OUString
& _out_rColumnName
,
230 OUString
& _out_rTableRange
,
231 OUString
& _out_rColumnAliasIfPresent
234 /** return the alias name of a column
235 @param _pDerivedColumn
236 The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
238 The alias name of the column or an empty string.
240 static OUString
getColumnAlias(const OSQLParseNode
* _pDerivedColumn
);
242 /** return the columname and the table range
244 The column ref parse node.
246 The database meta data.
248 The column name to be set.
250 The table range to be set.
252 static void getColumnRange( const OSQLParseNode
* _pColumnRef
,
253 const css::uno::Reference
< css::sdbc::XConnection
>& _rxConnection
,
254 OUString
&_rColumnName
,
255 OUString
& _rTableRange
);
257 // return true when the tableNode is a rule like catalog_name, schema_name or table_name
258 static bool isTableNode(const OSQLParseNode
* _pTableNode
);
260 // tries to find the correct type of the function
261 sal_Int32
getFunctionReturnType(const OSQLParseNode
* _pNode
);
263 // returns a lis of all joined columns
264 ::std::vector
< TNodePair
>& getJoinConditions() const;
268 /** traverses the list of table names, and fills _rTables
270 bool traverseTableNames( OSQLTables
& _rTables
);
272 /// traverses columns in a SELECT statement
273 bool traverseSelectColumnNames(const OSQLParseNode
* pSelectNode
);
274 /// traverses columns in a CREATE TABLE statement
275 void traverseCreateColumns(const OSQLParseNode
* pSelectNode
);
277 bool traverseOrderByColumnNames(const OSQLParseNode
* pSelectNode
);
278 bool traverseGroupByColumnNames(const OSQLParseNode
* pSelectNode
);
280 bool traverseSelectionCriteria(const OSQLParseNode
* pSelectNode
);
282 /** constructs a new iterator, which inherits some of the settings from a parent iterator
284 OSQLParseTreeIterator(
285 const OSQLParseTreeIterator
& _rParentIterator
,
286 const OSQLParser
& _rParser
,
287 const OSQLParseNode
* pRoot
);
289 /** creates a table object and inserts it into our tables collection
291 only used when we're iterating through a CREATE TABLE statement
293 OSQLTable
impl_createTableObject(
294 const OUString
& rTableName
, const OUString
& rCatalogName
, const OUString
& rSchemaName
);
296 /** locates a record source (a table or query) with the given name
298 OSQLTable
impl_locateRecordSource(
299 const OUString
& _rComposedName
302 /** implementation for both traverseAll and traverseSome
304 void impl_traverse( TraversalParts _nIncludeMask
);
306 /** retrieves the parameter columns of the given query
308 void impl_getQueryParameterColumns( const OSQLTable
& _rQuery
);
310 void setOrderByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
, bool bAscending
);
311 void setGroupByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
);
313 /** appends an SQLException corresponding to the given error code to our error collection
316 the code of the error which occurred
317 @param _pReplaceToken1
318 if not <NULL/>, the first occurrence of '#' in the error message will be replaced
320 @param _pReplaceToken2
321 if not <NULL/>, and if _rReplaceToken1 is not <NULL/>, the second occurrence of '#'
322 in the error message will be replaced with _rReplaceToken2
324 void impl_appendError( IParseContext::ErrorCode _eError
,
325 const OUString
* _pReplaceToken1
= nullptr, const OUString
* _pReplaceToken2
= nullptr );
327 /** appends an SQLException corresponding to the given error code to our error collection
329 void impl_appendError( const css::sdbc::SQLException
& _rError
);
331 void impl_fillJoinConditions(const OSQLParseNode
* i_pJoinCondition
);
335 #endif // INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */