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