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