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>
31 #include <o3tl/typed_flags_set.hxx>
33 namespace com::sun::star::sdbc
{ class XConnection
; }
34 namespace com::sun::star::beans
{ class XPropertySet
; }
36 namespace connectivity
38 enum class TraversalParts
42 SelectColumns
= 0x0006, // note that this includes TableNames. No SelectColumns without TableNames
44 // Those are not implemented currently
45 // GroupColumns = 0x0008,
46 // OrderColumns = 0x0010,
47 // SelectColumns = 0x0020,
48 // CreateColumns = 0x0040,
55 template<> struct typed_flags
<connectivity::TraversalParts
> : is_typed_flags
<connectivity::TraversalParts
, 0xffff> {};
58 namespace connectivity
64 typedef ::std::pair
<const OSQLParseNode
*,const OSQLParseNode
* > TNodePair
;
66 enum class OSQLStatementType
{
76 struct OSQLParseTreeIteratorImpl
;
78 class OOO_DLLPUBLIC_DBTOOLS OSQLParseTreeIterator final
81 css::sdbc::SQLException m_aErrors
; // contains the error while iterating through the statement
82 const OSQLParseNode
* m_pParseTree
; // current ParseTree
83 const OSQLParser
& m_rParser
; // if set used for general error messages from the context
84 OSQLStatementType m_eStatementType
;
85 ::rtl::Reference
<OSQLColumns
> m_aSelectColumns
; // all columns from the Select clause
86 ::rtl::Reference
<OSQLColumns
> m_aParameters
; // all parameters
87 ::rtl::Reference
<OSQLColumns
> m_aGroupColumns
; // the group by columns
88 ::rtl::Reference
<OSQLColumns
> m_aOrderColumns
; // the order by columns
89 ::rtl::Reference
<OSQLColumns
> m_aCreateColumns
; // the columns for Create table clause
91 ::std::unique_ptr
< OSQLParseTreeIteratorImpl
> m_pImpl
;
93 void traverseParameter(const OSQLParseNode
* _pParseNode
,const OSQLParseNode
* _pColumnRef
,const OUString
& _aColumnName
, OUString
& _aTableRange
, const OUString
& _rColumnAlias
);
94 // inserts a table into the map
95 void traverseOneTableName( OSQLTables
& _rTables
,const OSQLParseNode
* pTableName
, const OUString
& rTableRange
);
96 void traverseSearchCondition(OSQLParseNode
const * pSearchCondition
);
97 void traverseOnePredicate(
98 OSQLParseNode
const * pColumnRef
,
100 OSQLParseNode
const * pParameter
);
101 void traverseByColumnNames(const OSQLParseNode
* pSelectNode
, bool _bOrder
);
102 void traverseParameters(const OSQLParseNode
* pSelectNode
);
104 const OSQLParseNode
* getTableNode( OSQLTables
& _rTables
, const OSQLParseNode
* pTableRef
, OUString
& aTableRange
);
105 void getQualified_join( OSQLTables
& _rTables
, const OSQLParseNode
*pTableRef
, OUString
& aTableRange
);
106 void getSelect_statement(OSQLTables
& _rTables
,const OSQLParseNode
* pSelect
);
107 OUString
getUniqueColumnName(const OUString
& rColumnName
) const;
109 /** finds the column with a given name, belonging to a given table, in a given tables collection
111 the tables collection to look in
113 the column name to look for
115 the table alias name; if empty, look in all tables
117 the desired column object, or <NULL/> if no such column could be found
119 static css::uno::Reference
< css::beans::XPropertySet
> findColumn(
120 const OSQLTables
& _rTables
, const OUString
& rColumnName
, OUString
& rTableRange
);
122 /** finds a column with a given name, belonging to a given table
124 the column name to look for
126 the table alias name; if empty, look in all tables
127 @param _bLookInSubTables
128 <TRUE/> if and only if not only our direct tables, but also our sub tables (from sub selects)
132 css::uno::Reference
< css::beans::XPropertySet
> findColumn(
133 const OUString
& rColumnName
, OUString
& rTableRange
, bool _bLookInSubTables
);
135 /** finds a column with a given name among the select columns
137 the column name to look for
140 css::uno::Reference
< css::beans::XPropertySet
> findSelectColumn(
141 const OUString
& rColumnName
);
143 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);
144 void appendColumns(::rtl::Reference
<OSQLColumns
> const & _rColumns
,const OUString
& _rTableAlias
,const OSQLTable
& _rTable
);
145 // Other member variables that should be available in the "set" functions
146 // can be defined in the derived class. They can be initialized
147 // in its constructor and, after the "traverse" routines have been used,
148 // they can be queried using other functions.
150 OSQLParseTreeIterator(const OSQLParseTreeIterator
& rIter
) = delete;
153 OSQLParseTreeIterator(
154 const css::uno::Reference
< css::sdbc::XConnection
>& _rxConnection
,
155 const css::uno::Reference
< css::container::XNameAccess
>& _rxTables
,
156 const OSQLParser
& _rParser
);
157 ~OSQLParseTreeIterator();
160 bool isCaseSensitive() const;
161 // The parse tree to be analysed/traversed:
162 // If NULL is passed, the current parse tree will be deleted and the error status cleared.
163 void setParseTree(const OSQLParseNode
* pNewParseTree
);
164 const OSQLParseNode
* getParseTree() const { return m_pParseTree
; };
166 // subtrees in case of a select statement
167 const OSQLParseNode
* getWhereTree() const;
168 const OSQLParseNode
* getOrderTree() const;
169 const OSQLParseNode
* getGroupByTree() const;
170 const OSQLParseNode
* getHavingTree() const;
172 const OSQLParseNode
* getSimpleWhereTree() const;
173 const OSQLParseNode
* getSimpleOrderTree() const;
174 const OSQLParseNode
* getSimpleGroupByTree() const;
175 const OSQLParseNode
* getSimpleHavingTree() const;
177 /** returns the errors which occurred during parsing.
179 The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
181 const css::sdbc::SQLException
& getErrors() const { return m_aErrors
; }
182 bool hasErrors() const { return !m_aErrors
.Message
.isEmpty(); }
184 // statement type (already set in setParseTree):
185 OSQLStatementType
getStatementType() const { return m_eStatementType
; }
187 /** traverses the complete statement tree, and fills all our data with
188 the information obatined during traversal.
190 Implemented by calling the single traverse* methods in the proper
191 order (depending on the statement type).
195 // The TableRangeMap contains all tables associated with the range name found first.
196 const OSQLTables
& getTables() const;
198 const ::rtl::Reference
<OSQLColumns
>& getSelectColumns() const { return m_aSelectColumns
;}
199 const ::rtl::Reference
<OSQLColumns
>& getGroupColumns() const { return m_aGroupColumns
;}
200 const ::rtl::Reference
<OSQLColumns
>& getOrderColumns() const { return m_aOrderColumns
;}
201 const ::rtl::Reference
<OSQLColumns
>& getParameters() const { return m_aParameters
; }
203 /** return the columname and the table range
205 The column ref parse node.
207 The column name to be set.
209 The table range to be set.
211 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
212 OUString
&_rColumnName
,
213 OUString
& _rTableRange
) const;
215 /** retrieves a column's name, table range, and alias
218 The column_ref parse node.
219 @param _out_rColumnName
220 The column name to be set.
221 @param _out_rTableRange
222 The table range to be set.
223 @param _out_rColumnAliasIfPresent
224 If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
225 this alias is returned here.
227 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
228 OUString
& _out_rColumnName
,
229 OUString
& _out_rTableRange
,
230 OUString
& _out_rColumnAliasIfPresent
233 /** return the alias name of a column
234 @param _pDerivedColumn
235 The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
237 The alias name of the column or an empty string.
239 static OUString
getColumnAlias(const OSQLParseNode
* _pDerivedColumn
);
241 /** return the columname and the table range
243 The column ref parse node.
245 The database meta data.
247 The column name to be set.
249 The table range to be set.
251 static void getColumnRange( const OSQLParseNode
* _pColumnRef
,
252 const css::uno::Reference
< css::sdbc::XConnection
>& _rxConnection
,
253 OUString
&_rColumnName
,
254 OUString
& _rTableRange
);
256 // return true when the tableNode is a rule like catalog_name, schema_name or table_name
257 static bool isTableNode(const OSQLParseNode
* _pTableNode
);
259 // tries to find the correct type of the function
260 sal_Int32
getFunctionReturnType(const OSQLParseNode
* _pNode
);
262 // returns a lis of all joined columns
263 ::std::vector
< TNodePair
>& getJoinConditions() const;
267 /** traverses the list of table names, and fills _rTables
269 bool traverseTableNames( OSQLTables
& _rTables
);
271 /// traverses columns in a SELECT statement
272 bool traverseSelectColumnNames(const OSQLParseNode
* pSelectNode
);
273 /// traverses columns in a CREATE TABLE statement
274 void traverseCreateColumns(const OSQLParseNode
* pSelectNode
);
276 bool traverseOrderByColumnNames(const OSQLParseNode
* pSelectNode
);
277 bool traverseGroupByColumnNames(const OSQLParseNode
* pSelectNode
);
279 bool traverseSelectionCriteria(const OSQLParseNode
* pSelectNode
);
281 /** constructs a new iterator, which inherits some of the settings from a parent iterator
283 OSQLParseTreeIterator(
284 const OSQLParseTreeIterator
& _rParentIterator
,
285 const OSQLParser
& _rParser
,
286 const OSQLParseNode
* pRoot
);
288 /** creates a table object and inserts it into our tables collection
290 only used when we're iterating through a CREATE TABLE statement
292 OSQLTable
impl_createTableObject(
293 const OUString
& rTableName
, const OUString
& rCatalogName
, const OUString
& rSchemaName
);
295 /** locates a record source (a table or query) with the given name
297 OSQLTable
impl_locateRecordSource(
298 const OUString
& _rComposedName
301 /** implementation for both traverseAll and traverseSome
303 void impl_traverse( TraversalParts _nIncludeMask
);
305 /** retrieves the parameter columns of the given query
307 void impl_getQueryParameterColumns( const OSQLTable
& _rQuery
);
309 void setOrderByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
, bool bAscending
);
310 void setGroupByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
);
312 /** appends an SQLException corresponding to the given error code to our error collection
315 the code of the error which occurred
316 @param _pReplaceToken1
317 if not <NULL/>, the first occurrence of '#' in the error message will be replaced
319 @param _pReplaceToken2
320 if not <NULL/>, and if _rReplaceToken1 is not <NULL/>, the second occurrence of '#'
321 in the error message will be replaced with _rReplaceToken2
323 void impl_appendError( IParseContext::ErrorCode _eError
,
324 const OUString
* _pReplaceToken1
= nullptr, const OUString
* _pReplaceToken2
= nullptr );
326 /** appends an SQLException corresponding to the given error code to our error collection
328 void impl_appendError( const css::sdbc::SQLException
& _rError
);
330 void impl_fillJoinConditions(const OSQLParseNode
* i_pJoinCondition
);
334 #endif // INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */