1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
24 #define _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
25 
26 #include "connectivity/dbtoolsdllapi.hxx"
27 #include "connectivity/sqlnode.hxx"
28 #include <connectivity/IParseContext.hxx>
29 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
30 #include <com/sun/star/sdbc/DataType.hpp>
31 #include <com/sun/star/sdbc/SQLWarning.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include "connectivity/CommonTools.hxx"
34 #include <vos/ref.hxx>
35 #include <cppuhelper/weak.hxx>
36 
37 #include <map>
38 #include <memory>
39 #include <vector>
40 
41 namespace connectivity
42 {
43 
44 	class OSQLParseNode;
45 	class OSQLParser;
46 
47     typedef ::std::pair<const OSQLParseNode*,const OSQLParseNode* > TNodePair;
48 
49 	enum OSQLStatementType {
50 		SQL_STATEMENT_UNKNOWN,
51 		SQL_STATEMENT_SELECT,
52 		SQL_STATEMENT_INSERT,
53 		SQL_STATEMENT_UPDATE,
54 		SQL_STATEMENT_DELETE,
55 		SQL_STATEMENT_ODBC_CALL,
56 		SQL_STATEMENT_CREATE_TABLE
57 	};
58 
59 	struct OSQLParseTreeIteratorImpl;
60 
61     class OOO_DLLPUBLIC_DBTOOLS OSQLParseTreeIterator
62 	{
63 	private:
64 		::com::sun::star::sdbc::SQLException            m_aErrors;		    // conatins the error while iterating through the statement
65 		const OSQLParseNode*				            m_pParseTree;		// aktueller ParseTree
66 		const OSQLParser&					            m_rParser;			// if set used for general error messages from the context
67 		OSQLStatementType					            m_eStatementType;	// Art des Statements
68 		::vos::ORef<OSQLColumns>			            m_aSelectColumns;	// alle Spalten aus dem Select-Clause
69 		::vos::ORef<OSQLColumns>			            m_aParameters;		// all parameters
70 		::vos::ORef<OSQLColumns>			            m_aGroupColumns;	// the group by columns
71 		::vos::ORef<OSQLColumns>			            m_aOrderColumns;	// the order by columns
72 		::vos::ORef<OSQLColumns>			            m_aCreateColumns;	// the columns for Create table clause
73 
74         ::std::auto_ptr< OSQLParseTreeIteratorImpl >    m_pImpl;
75 
76         void				traverseParameter(const OSQLParseNode* _pParseNode,const OSQLParseNode* _pColumnRef,const ::rtl::OUString& _aColumnName,const ::rtl::OUString& _aTableRange, const ::rtl::OUString& _rColumnAlias);
77 		// F"ugt eine Tabelle in die Map ein
78 		void				traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange );
79 		void				traverseORCriteria(OSQLParseNode * pSearchCondition);
80 		void				traverseANDCriteria(OSQLParseNode * pSearchCondition);
81 		void				traverseOnePredicate(
82 												OSQLParseNode * pColumnRef,
83 												::rtl::OUString& aValue,
84 												OSQLParseNode * pParameter);
85 		void traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder);
86         void                traverseParameters(const OSQLParseNode* pSelectNode);
87 
88 		const OSQLParseNode*    getTableNode( OSQLTables& _rTables, const OSQLParseNode* pTableRef, ::rtl::OUString& aTableRange );
89 		void                    getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange );
90 		void				    getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect);
91 		::rtl::OUString		    getUniqueColumnName(const ::rtl::OUString & rColumnName)	const;
92 
93         /** finds the column with a given name, belonging to a given table, in a given tables collection
94             @param  _rTables
95                 the tables collection to look in
96             @param  rColumnName
97                 the column name to look for
98             @param  rTableRange
99                 the table alias name
100             @return
101                 the desired column object, or <NULL/> if no such column could be found
102         */
103         static ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn(
104             const OSQLTables& _rTables, const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange );
105 
106         /** finds a column with a given name, belonging to a given table
107             @param  rColumnName
108                 the column name to look for
109             @param  rTableRange
110                     the table alias name
111             @param  _bLookInSubTables
112                 <TRUE/> if and only if not only our direct tables, but also our sub tables (from sub selects)
113                 should be searched
114             @return
115         */
116         ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn(
117             const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables );
118 
119 	  protected:
120 		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);
121 		void appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable);
122 		// Weitere Member-Variable, die in den "set"-Funktionen zur
123 		// Verfuegung stehen sollen, koennen in der abgeleiteten Klasse
124 		// definiert werden und z. B. in deren Konstruktor initialisiert
125 		// bzw. nach Benutzung der "traverse"-Routinen mit Hilfe weiterer
126 		// Funktionen abgefragt werden.
127 
128 
129       private:
130         OSQLParseTreeIterator();                                        // never implemented
131 		OSQLParseTreeIterator(const OSQLParseTreeIterator & rIter);     // never implemented
132 
133 	  public:
134 		OSQLParseTreeIterator(
135             const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
136             const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxTables,
137             const OSQLParser& _rParser,
138             const OSQLParseNode* pRoot = NULL );
139 		~OSQLParseTreeIterator();
140 
operator new(size_t nSize)141 		inline static void * SAL_CALL operator new( size_t nSize ) SAL_THROW( () )
142 			{ return ::rtl_allocateMemory( nSize ); }
operator new(size_t,void * _pHint)143 		inline static void * SAL_CALL operator new( size_t,void* _pHint ) SAL_THROW( () )
144 			{ return _pHint; }
operator delete(void * pMem)145 		inline static void SAL_CALL operator delete( void * pMem ) SAL_THROW( () )
146 			{ ::rtl_freeMemory( pMem ); }
operator delete(void *,void *)147 		inline static void SAL_CALL operator delete( void *,void* ) SAL_THROW( () )
148 			{  }
149 
150 		void dispose();
151         bool isCaseSensitive() const;
152 		// Der zu analysierende/zu traversierende Parse Tree:
153 		// bei "Ubergabe von NULL wird der aktuelle Parsetree gel"oscht und der Fehlerstatus gecleared
154 		void setParseTree(const OSQLParseNode * pNewParseTree);
155 //		void setParser(const OSQLParser* _pParser) { m_pParser = _pParser; }
getParseTree() const156 		const OSQLParseNode * getParseTree() const { return m_pParseTree; };
157 
158 		// Teilbaueme bei einem select statement
159 		const OSQLParseNode* getWhereTree() const;
160 		const OSQLParseNode* getOrderTree() const;
161 		const OSQLParseNode* getGroupByTree() const;
162 		const OSQLParseNode* getHavingTree() const;
163 
164 		const OSQLParseNode* getSimpleWhereTree() const;
165 		const OSQLParseNode* getSimpleOrderTree() const;
166 		const OSQLParseNode* getSimpleGroupByTree() const;
167 		const OSQLParseNode* getSimpleHavingTree() const;
168 
169         /** returns the errors which occured during parsing.
170 
171             The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
172         */
getErrors() const173 		inline const ::com::sun::star::sdbc::SQLException&   getErrors() const { return m_aErrors; }
hasErrors() const174         inline bool hasErrors() const { return m_aErrors.Message.getLength() > 0; }
175 
176 		// Statement-Typ (wird bereits in setParseTree gesetzt):
getStatementType() const177 		OSQLStatementType getStatementType() const { return m_eStatementType; }
178 
179         /** traverses the complete statement tree, and fills all our data with
180             the information obatined during traversal.
181 
182             Implemented by calling the single traverse* methods in the proper
183             order (depending on the statement type).
184         */
185         void traverseAll();
186 
187         enum TraversalParts
188         {
189             Parameters      = 0x0001,
190             TableNames      = 0x0002,
191             SelectColumns   = 0x0006,   // note that this includes TableNames. No SelectColumns without TableNames
192 
193             // Those are not implemented currently
194             // GroupColumns    = 0x0008,
195             // OrderColumns    = 0x0010,
196             // SelectColumns   = 0x0020,
197             // CreateColumns   = 0x0040,
198 
199             All             = 0xFFFF
200         };
201         /** traverses selected parts of the statement tree, and fills our data with
202             the information obtained during traversal
203 
204             @param _nIncludeMask
205                 set of TraversalParts bits, specifying which information is to be collected.
206                 Note TraversalParts is currently not
207         */
208         void traverseSome( sal_uInt32 _nIncludeMask );
209 
210 		// Die TableRangeMap enth"alt alle Tabellen unter dem zugeh"origen Rangenamen der zuerst gefunden wird
211 		const OSQLTables& getTables() const;
212 
getSelectColumns() const213 		::vos::ORef<OSQLColumns> getSelectColumns() const { return m_aSelectColumns;}
getGroupColumns() const214 		::vos::ORef<OSQLColumns> getGroupColumns() const { return m_aGroupColumns;}
getOrderColumns() const215 		::vos::ORef<OSQLColumns> getOrderColumns() const { return m_aOrderColumns;}
getParameters() const216 		::vos::ORef<OSQLColumns> getParameters()	const { return m_aParameters; }
getCreateColumns() const217 		::vos::ORef<OSQLColumns> getCreateColumns() const { return m_aCreateColumns;}
218 
219 		/** return the columname and the table range
220 			@param	_pColumnRef
221 				The column ref parse node.
222 			@param	_rColumnName
223 				The column name to be set.
224 			@param	_rTableRange
225 				The table range to be set.
226 		*/
227 		void getColumnRange(	const OSQLParseNode* _pColumnRef,
228 								::rtl::OUString &_rColumnName,
229 								::rtl::OUString& _rTableRange) const;
230 
231 		/** retrieves a column's name, table range, and alias
232 
233             @param	_pColumnRef
234 				The column_ref parse node.
235 			@param	_out_rColumnName
236 				The column name to be set.
237 			@param	_out_rTableRange
238 				The table range to be set.
239             @param _out_rColumnAliasIfPresent
240                 If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
241                 this alias is returned here.
242 		*/
243         void getColumnRange(    const OSQLParseNode* _pColumnRef,
244 								::rtl::OUString& _out_rColumnName,
245 								::rtl::OUString& _out_rTableRange,
246                                 ::rtl::OUString& _out_rColumnAliasIfPresent
247                                 ) const;
248 
249 		/** return the alias name of a column
250 			@param	_pDerivedColumn
251 				The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
252 			@return
253 				The alias name of the column or an empty string.
254 		*/
255 		static ::rtl::OUString getColumnAlias(const OSQLParseNode* _pDerivedColumn);
256 
257 		/** return the columname and the table range
258 			@param	_pColumnRef
259 				The column ref parse node.
260 			@param	_xMetaData
261 				The database meta data.
262 			@param	_rColumnName
263 				The column name to be set.
264 			@param	_rTableRange
265 				The table range to be set.
266 		*/
267 		static void getColumnRange(	const OSQLParseNode* _pColumnRef,
268 									const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _rxConnection,
269 									::rtl::OUString &_rColumnName,
270 									::rtl::OUString& _rTableRange);
271 
272 		// Ermittelt fuer eine Funktion, Spalten den zugehoeren TableRange,
273 		// wenn nicht eindeutig, dann leer
274 		sal_Bool getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const;
275 
276 		// return true when the tableNode is a rule like catalog_name, schema_name or table_name
277 		sal_Bool isTableNode(const OSQLParseNode* _pTableNode) const;
278 
279         // tries to find the correct type of the function
280         sal_Int32 getFunctionReturnType(const OSQLParseNode* _pNode );
281 
282         // returns a lis of all joined columns
283         ::std::vector< TNodePair >& getJoinConditions() const;
284 
285     private:
286         /** traverses the list of table names, and filles _rTables
287         */
288 		bool traverseTableNames( OSQLTables& _rTables );
289 
290         /// traverses columns in a SELECT statement
291 		bool traverseSelectColumnNames(const OSQLParseNode* pSelectNode);
292         /// traverses columns in a CREATE TABLE statement
293 		void traverseCreateColumns(const OSQLParseNode* pSelectNode);
294 
295 		bool traverseOrderByColumnNames(const OSQLParseNode* pSelectNode);
296 		bool traverseGroupByColumnNames(const OSQLParseNode* pSelectNode);
297 
298 		bool traverseSelectionCriteria(const OSQLParseNode* pSelectNode);
299 
300     private:
301         /** constructs a new iterator, which inherits some of the settings from a parent iterator
302         */
303 		OSQLParseTreeIterator(
304             const OSQLParseTreeIterator& _rParentIterator,
305             const OSQLParser& _rParser,
306             const OSQLParseNode* pRoot );
307 
308         /** creates a table object and inserts it into our tables collection
309 
310             only used when we're iterating through a CREATE TABLE statement
311         */
312 		OSQLTable   impl_createTableObject(
313             const ::rtl::OUString& rTableName, const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName );
314 
315         /** locates a record source (a table or query) with the given name
316         */
317         OSQLTable   impl_locateRecordSource(
318             const ::rtl::OUString& _rComposedName
319         );
320 
321         /** implementation for both traverseAll and traverseSome
322         */
323         void    impl_traverse( sal_uInt32 _nIncludeMask );
324 
325         /** retrieves the parameter columns of the given query
326         */
327         void    impl_getQueryParameterColumns( const OSQLTable& _rQuery );
328 
329         void setOrderByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, sal_Bool bAscending);
330 		void setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange);
331 
332     private:
333         /** appends an SQLException corresponding to the given error code to our error collection
334 
335             @param  _eError
336                 the code of the error which occured
337             @param  _pReplaceToken1
338                 if not <NULL/>, the first occurance of '#' in the error message will be replaced
339                 with the given token
340             @param  _pReplaceToken2
341                 if not <NULL/>, and if _rReplaceToken1 is not <NULL/>, the second occurance of '#'
342                 in the error message will be replaced with _rReplaceToken2
343         */
344         void impl_appendError( IParseContext::ErrorCode _eError,
345             const ::rtl::OUString* _pReplaceToken1 = NULL, const ::rtl::OUString* _pReplaceToken2 = NULL );
346 
347         /** appends an SQLException corresponding to the given error code to our error collection
348         */
349         void impl_appendError( const ::com::sun::star::sdbc::SQLException& _rError );
350 
351         /** resets our errors
352         */
impl_resetErrors()353         inline void impl_resetErrors()
354         {
355             m_aErrors = ::com::sun::star::sdbc::SQLException();
356         }
357         void impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition);
358 	};
359 }
360 
361 #endif // _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
362 
363