xref: /trunk/main/connectivity/inc/connectivity/sqliterator.hxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
28 #define _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
29 
30 #include "connectivity/dbtoolsdllapi.hxx"
31 #include "connectivity/sqlnode.hxx"
32 #include <connectivity/IParseContext.hxx>
33 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
34 #include <com/sun/star/sdbc/DataType.hpp>
35 #include <com/sun/star/sdbc/SQLWarning.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include "connectivity/CommonTools.hxx"
38 #include <vos/ref.hxx>
39 #include <cppuhelper/weak.hxx>
40 
41 #include <map>
42 #include <memory>
43 #include <vector>
44 
45 namespace connectivity
46 {
47 
48     class OSQLParseNode;
49     class OSQLParser;
50 
51     typedef ::std::pair<const OSQLParseNode*,const OSQLParseNode* > TNodePair;
52 
53     enum OSQLStatementType {
54         SQL_STATEMENT_UNKNOWN,
55         SQL_STATEMENT_SELECT,
56         SQL_STATEMENT_INSERT,
57         SQL_STATEMENT_UPDATE,
58         SQL_STATEMENT_DELETE,
59         SQL_STATEMENT_ODBC_CALL,
60         SQL_STATEMENT_CREATE_TABLE
61     };
62 
63     struct OSQLParseTreeIteratorImpl;
64 
65     class OOO_DLLPUBLIC_DBTOOLS OSQLParseTreeIterator
66     {
67     private:
68         ::com::sun::star::sdbc::SQLException            m_aErrors;          // conatins the error while iterating through the statement
69         const OSQLParseNode*                            m_pParseTree;       // aktueller ParseTree
70         const OSQLParser&                               m_rParser;          // if set used for general error messages from the context
71         OSQLStatementType                               m_eStatementType;   // Art des Statements
72         ::vos::ORef<OSQLColumns>                        m_aSelectColumns;   // alle Spalten aus dem Select-Clause
73         ::vos::ORef<OSQLColumns>                        m_aParameters;      // all parameters
74         ::vos::ORef<OSQLColumns>                        m_aGroupColumns;    // the group by columns
75         ::vos::ORef<OSQLColumns>                        m_aOrderColumns;    // the order by columns
76         ::vos::ORef<OSQLColumns>                        m_aCreateColumns;   // the columns for Create table clause
77 
78         ::std::auto_ptr< OSQLParseTreeIteratorImpl >    m_pImpl;
79 
80         void                traverseParameter(const OSQLParseNode* _pParseNode,const OSQLParseNode* _pColumnRef,const ::rtl::OUString& _aColumnName,const ::rtl::OUString& _aTableRange, const ::rtl::OUString& _rColumnAlias);
81         // F"ugt eine Tabelle in die Map ein
82         void                traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange );
83         void                traverseORCriteria(OSQLParseNode * pSearchCondition);
84         void                traverseANDCriteria(OSQLParseNode * pSearchCondition);
85         void                traverseOnePredicate(
86                                                 OSQLParseNode * pColumnRef,
87                                                 ::rtl::OUString& aValue,
88                                                 OSQLParseNode * pParameter);
89         void traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder);
90         void                traverseParameters(const OSQLParseNode* pSelectNode);
91 
92         const OSQLParseNode*    getTableNode( OSQLTables& _rTables, const OSQLParseNode* pTableRef, ::rtl::OUString& aTableRange );
93         void                    getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange );
94         void                    getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect);
95         ::rtl::OUString         getUniqueColumnName(const ::rtl::OUString & rColumnName)    const;
96 
97         /** finds the column with a given name, belonging to a given table, in a given tables collection
98             @param  _rTables
99                 the tables collection to look in
100             @param  rColumnName
101                 the column name to look for
102             @param  rTableRange
103                 the table alias name
104             @return
105                 the desired column object, or <NULL/> if no such column could be found
106         */
107         static ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn(
108             const OSQLTables& _rTables, const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange );
109 
110         /** finds a column with a given name, belonging to a given table
111             @param  rColumnName
112                 the column name to look for
113             @param  rTableRange
114                     the table alias name
115             @param  _bLookInSubTables
116                 <TRUE/> if and only if not only our direct tables, but also our sub tables (from sub selects)
117                 should be searched
118             @return
119         */
120         ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn(
121             const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables );
122 
123       protected:
124         void setSelectColumnName(::vos::ORef<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);
125         void appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable);
126         // Weitere Member-Variable, die in den "set"-Funktionen zur
127         // Verfuegung stehen sollen, koennen in der abgeleiteten Klasse
128         // definiert werden und z. B. in deren Konstruktor initialisiert
129         // bzw. nach Benutzung der "traverse"-Routinen mit Hilfe weiterer
130         // Funktionen abgefragt werden.
131 
132 
133       private:
134         OSQLParseTreeIterator();                                        // never implemented
135         OSQLParseTreeIterator(const OSQLParseTreeIterator & rIter);     // never implemented
136 
137       public:
138         OSQLParseTreeIterator(
139             const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
140             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxTables,
141             const OSQLParser& _rParser,
142             const OSQLParseNode* pRoot = NULL );
143         ~OSQLParseTreeIterator();
144 
145         inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
146             { return ::rtl_allocateMemory( nSize ); }
147         inline static void * SAL_CALL operator new( size_t,void* _pHint ) SAL_THROW( () )
148             { return _pHint; }
149         inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
150             { ::rtl_freeMemory( pMem ); }
151         inline static void SAL_CALL operator delete( void *,void* ) SAL_THROW( () )
152             {  }
153 
154         void dispose();
155         bool isCaseSensitive() const;
156         // Der zu analysierende/zu traversierende Parse Tree:
157         // bei "Ubergabe von NULL wird der aktuelle Parsetree gel"oscht und der Fehlerstatus gecleared
158         void setParseTree(const OSQLParseNode * pNewParseTree);
159 //      void setParser(const OSQLParser* _pParser) { m_pParser = _pParser; }
160         const OSQLParseNode * getParseTree() const { return m_pParseTree; };
161 
162         // Teilbaueme bei einem select statement
163         const OSQLParseNode* getWhereTree() const;
164         const OSQLParseNode* getOrderTree() const;
165         const OSQLParseNode* getGroupByTree() const;
166         const OSQLParseNode* getHavingTree() const;
167 
168         const OSQLParseNode* getSimpleWhereTree() const;
169         const OSQLParseNode* getSimpleOrderTree() const;
170         const OSQLParseNode* getSimpleGroupByTree() const;
171         const OSQLParseNode* getSimpleHavingTree() const;
172 
173         /** returns the errors which occured during parsing.
174 
175             The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
176         */
177         inline const ::com::sun::star::sdbc::SQLException&   getErrors() const { return m_aErrors; }
178         inline bool hasErrors() const { return m_aErrors.Message.getLength() > 0; }
179 
180         // Statement-Typ (wird bereits in setParseTree gesetzt):
181         OSQLStatementType getStatementType() const { return m_eStatementType; }
182 
183         /** traverses the complete statement tree, and fills all our data with
184             the information obatined during traversal.
185 
186             Implemented by calling the single traverse* methods in the proper
187             order (depending on the statement type).
188         */
189         void traverseAll();
190 
191         enum TraversalParts
192         {
193             Parameters      = 0x0001,
194             TableNames      = 0x0002,
195             SelectColumns   = 0x0006,   // note that this includes TableNames. No SelectColumns without TableNames
196 
197             // Those are not implemented currently
198             // GroupColumns    = 0x0008,
199             // OrderColumns    = 0x0010,
200             // SelectColumns   = 0x0020,
201             // CreateColumns   = 0x0040,
202 
203             All             = 0xFFFF
204         };
205         /** traverses selected parts of the statement tree, and fills our data with
206             the information obtained during traversal
207 
208             @param _nIncludeMask
209                 set of TraversalParts bits, specifying which information is to be collected.
210                 Note TraversalParts is currently not
211         */
212         void traverseSome( sal_uInt32 _nIncludeMask );
213 
214         // Die TableRangeMap enth"alt alle Tabellen unter dem zugeh"origen Rangenamen der zuerst gefunden wird
215         const OSQLTables& getTables() const;
216 
217         ::vos::ORef<OSQLColumns> getSelectColumns() const { return m_aSelectColumns;}
218         ::vos::ORef<OSQLColumns> getGroupColumns() const { return m_aGroupColumns;}
219         ::vos::ORef<OSQLColumns> getOrderColumns() const { return m_aOrderColumns;}
220         ::vos::ORef<OSQLColumns> getParameters()    const { return m_aParameters; }
221         ::vos::ORef<OSQLColumns> getCreateColumns() const { return m_aCreateColumns;}
222 
223         /** return the columname and the table range
224             @param  _pColumnRef
225                 The column ref parse node.
226             @param  _rColumnName
227                 The column name to be set.
228             @param  _rTableRange
229                 The table range to be set.
230         */
231         void getColumnRange(    const OSQLParseNode* _pColumnRef,
232                                 ::rtl::OUString &_rColumnName,
233                                 ::rtl::OUString& _rTableRange) const;
234 
235         /** retrieves a column's name, table range, and alias
236 
237             @param  _pColumnRef
238                 The column_ref parse node.
239             @param  _out_rColumnName
240                 The column name to be set.
241             @param  _out_rTableRange
242                 The table range to be set.
243             @param _out_rColumnAliasIfPresent
244                 If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
245                 this alias is returned here.
246         */
247         void getColumnRange(    const OSQLParseNode* _pColumnRef,
248                                 ::rtl::OUString& _out_rColumnName,
249                                 ::rtl::OUString& _out_rTableRange,
250                                 ::rtl::OUString& _out_rColumnAliasIfPresent
251                                 ) const;
252 
253         /** return the alias name of a column
254             @param  _pDerivedColumn
255                 The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
256             @return
257                 The alias name of the column or an empty string.
258         */
259         static ::rtl::OUString getColumnAlias(const OSQLParseNode* _pDerivedColumn);
260 
261         /** return the columname and the table range
262             @param  _pColumnRef
263                 The column ref parse node.
264             @param  _xMetaData
265                 The database meta data.
266             @param  _rColumnName
267                 The column name to be set.
268             @param  _rTableRange
269                 The table range to be set.
270         */
271         static void getColumnRange( const OSQLParseNode* _pColumnRef,
272                                     const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
273                                     ::rtl::OUString &_rColumnName,
274                                     ::rtl::OUString& _rTableRange);
275 
276         // Ermittelt fuer eine Funktion, Spalten den zugehoeren TableRange,
277         // wenn nicht eindeutig, dann leer
278         sal_Bool getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const;
279 
280         // return true when the tableNode is a rule like catalog_name, schema_name or table_name
281         sal_Bool isTableNode(const OSQLParseNode* _pTableNode) const;
282 
283         // tries to find the correct type of the function
284         sal_Int32 getFunctionReturnType(const OSQLParseNode* _pNode );
285 
286         // returns a lis of all joined columns
287         ::std::vector< TNodePair >& getJoinConditions() const;
288 
289     private:
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 ::rtl::OUString& rTableName, const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName );
318 
319         /** locates a record source (a table or query) with the given name
320         */
321         OSQLTable   impl_locateRecordSource(
322             const ::rtl::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 ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, sal_Bool bAscending);
334         void setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::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 occured
341             @param  _pReplaceToken1
342                 if not <NULL/>, the first occurance 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 occurance of '#'
346                 in the error message will be replaced with _rReplaceToken2
347         */
348         void impl_appendError( IParseContext::ErrorCode _eError,
349             const ::rtl::OUString* _pReplaceToken1 = NULL, const ::rtl::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         inline void impl_resetErrors()
358         {
359             m_aErrors = ::com::sun::star::sdbc::SQLException();
360         }
361         void impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition);
362     };
363 }
364 
365 #endif // _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
366 
367