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/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>
37 namespace connectivity
43 typedef ::std::pair
<const OSQLParseNode
*,const OSQLParseNode
* > TNodePair
;
45 enum OSQLStatementType
{
46 SQL_STATEMENT_UNKNOWN
,
51 SQL_STATEMENT_ODBC_CALL
,
52 SQL_STATEMENT_CREATE_TABLE
55 struct OSQLParseTreeIteratorImpl
;
57 class OOO_DLLPUBLIC_DBTOOLS OSQLParseTreeIterator
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
70 ::std::unique_ptr
< OSQLParseTreeIteratorImpl
> m_pImpl
;
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
,
79 OSQLParseNode
* pParameter
);
80 void traverseByColumnNames(const OSQLParseNode
* pSelectNode
, bool _bOrder
);
81 void traverseParameters(const OSQLParseNode
* pSelectNode
);
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;
88 /** finds the column with a given name, belonging to a given table, in a given tables collection
90 the tables collection to look in
92 the column name to look for
94 the table alias name; if empty, look in all tables
96 the desired column object, or <NULL/> if no such column could be found
98 static ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> findColumn(
99 const OSQLTables
& _rTables
, const OUString
& rColumnName
, OUString
& rTableRange
);
101 /** finds a column with a given name, belonging to a given table
103 the column name to look for
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)
111 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> findColumn(
112 const OUString
& rColumnName
, OUString
& rTableRange
, bool _bLookInSubTables
);
114 /** finds a column with a given name among the select columns
116 the column name to look for
119 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> findSelectColumn(
120 const OUString
& rColumnName
);
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.
132 OSQLParseTreeIterator(const OSQLParseTreeIterator
& rIter
) SAL_DELETED_FUNCTION
;
135 OSQLParseTreeIterator(
136 const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XConnection
>& _rxConnection
,
137 const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
>& _rxTables
,
138 const OSQLParser
& _rParser
,
139 const OSQLParseNode
* pRoot
= NULL
);
140 ~OSQLParseTreeIterator();
142 inline static void * SAL_CALL
operator new( size_t nSize
)
143 { return ::rtl_allocateMemory( nSize
); }
144 inline static void * SAL_CALL
operator new( size_t,void* _pHint
)
146 inline static void SAL_CALL
operator delete( void * pMem
)
147 { ::rtl_freeMemory( pMem
); }
148 inline static void SAL_CALL
operator delete( void *,void* )
152 bool isCaseSensitive() const;
153 // The parse tree to be analysed/traversed:
154 // If NULL is passed, the current parse tree will be deleted and the error status cleared.
155 void setParseTree(const OSQLParseNode
* pNewParseTree
);
156 // void setParser(const OSQLParser* _pParser) { m_pParser = _pParser; }
157 const OSQLParseNode
* getParseTree() const { return m_pParseTree
; };
159 // subtrees in case of a select statement
160 const OSQLParseNode
* getWhereTree() const;
161 const OSQLParseNode
* getOrderTree() const;
162 const OSQLParseNode
* getGroupByTree() const;
163 const OSQLParseNode
* getHavingTree() const;
165 const OSQLParseNode
* getSimpleWhereTree() const;
166 const OSQLParseNode
* getSimpleOrderTree() const;
167 const OSQLParseNode
* getSimpleGroupByTree() const;
168 const OSQLParseNode
* getSimpleHavingTree() const;
170 /** returns the errors which occurred during parsing.
172 The returned object contains a chain (via SQLException::NextException) of SQLExceptions.
174 inline const ::com::sun::star::sdbc::SQLException
& getErrors() const { return m_aErrors
; }
175 inline bool hasErrors() const { return !m_aErrors
.Message
.isEmpty(); }
177 // statement type (already set in setParseTree):
178 OSQLStatementType
getStatementType() const { return m_eStatementType
; }
180 /** traverses the complete statement tree, and fills all our data with
181 the information obatined during traversal.
183 Implemented by calling the single traverse* methods in the proper
184 order (depending on the statement type).
192 SelectColumns
= 0x0006, // note that this includes TableNames. No SelectColumns without TableNames
194 // Those are not implemented currently
195 // GroupColumns = 0x0008,
196 // OrderColumns = 0x0010,
197 // SelectColumns = 0x0020,
198 // CreateColumns = 0x0040,
202 /** traverses selected parts of the statement tree, and fills our data with
203 the information obtained during traversal
206 set of TraversalParts bits, specifying which information is to be collected.
207 Note TraversalParts is currently not
209 void traverseSome( sal_uInt32 _nIncludeMask
);
211 // The TableRangeMap contains all tables associated with the range name found first.
212 const OSQLTables
& getTables() const;
214 ::rtl::Reference
<OSQLColumns
> getSelectColumns() const { return m_aSelectColumns
;}
215 ::rtl::Reference
<OSQLColumns
> getGroupColumns() const { return m_aGroupColumns
;}
216 ::rtl::Reference
<OSQLColumns
> getOrderColumns() const { return m_aOrderColumns
;}
217 ::rtl::Reference
<OSQLColumns
> getParameters() const { return m_aParameters
; }
218 ::rtl::Reference
<OSQLColumns
> getCreateColumns() const { return m_aCreateColumns
;}
220 /** return the columname and the table range
222 The column ref parse node.
224 The column name to be set.
226 The table range to be set.
228 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
229 OUString
&_rColumnName
,
230 OUString
& _rTableRange
) const;
232 /** retrieves a column's name, table range, and alias
235 The column_ref parse node.
236 @param _out_rColumnName
237 The column name to be set.
238 @param _out_rTableRange
239 The table range to be set.
240 @param _out_rColumnAliasIfPresent
241 If the column specified by _pColumnRef is part of the select columns, and contains a column alias there,
242 this alias is returned here.
244 void getColumnRange( const OSQLParseNode
* _pColumnRef
,
245 OUString
& _out_rColumnName
,
246 OUString
& _out_rTableRange
,
247 OUString
& _out_rColumnAliasIfPresent
250 /** return the alias name of a column
251 @param _pDerivedColumn
252 The parse node where SQL_ISRULE(_pDerivedColumn,derived_column) must be true
254 The alias name of the column or an empty string.
256 static OUString
getColumnAlias(const OSQLParseNode
* _pDerivedColumn
);
258 /** return the columname and the table range
260 The column ref parse node.
262 The database meta data.
264 The column name to be set.
266 The table range to be set.
268 static void getColumnRange( const OSQLParseNode
* _pColumnRef
,
269 const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XConnection
>& _rxConnection
,
270 OUString
&_rColumnName
,
271 OUString
& _rTableRange
);
273 // empty if ambiguous
274 bool getColumnTableRange(const OSQLParseNode
* pNode
, OUString
&rTableRange
) const;
276 // return true when the tableNode is a rule like catalog_name, schema_name or table_name
277 static bool isTableNode(const OSQLParseNode
* _pTableNode
);
279 // tries to find the correct type of the function
280 sal_Int32
getFunctionReturnType(const OSQLParseNode
* _pNode
);
282 // returns a lis of all joined columns
283 ::std::vector
< TNodePair
>& getJoinConditions() const;
286 // helper to implement getColumnTableRange
287 bool impl_getColumnTableRange(const OSQLParseNode
* pNode
, OUString
&rTableRange
) const;
289 /** traverses the list of table names, and filles _rTables
291 bool traverseTableNames( OSQLTables
& _rTables
);
293 /// traverses columns in a SELECT statement
294 bool traverseSelectColumnNames(const OSQLParseNode
* pSelectNode
);
295 /// traverses columns in a CREATE TABLE statement
296 void traverseCreateColumns(const OSQLParseNode
* pSelectNode
);
298 bool traverseOrderByColumnNames(const OSQLParseNode
* pSelectNode
);
299 bool traverseGroupByColumnNames(const OSQLParseNode
* pSelectNode
);
301 bool traverseSelectionCriteria(const OSQLParseNode
* pSelectNode
);
304 /** constructs a new iterator, which inherits some of the settings from a parent iterator
306 OSQLParseTreeIterator(
307 const OSQLParseTreeIterator
& _rParentIterator
,
308 const OSQLParser
& _rParser
,
309 const OSQLParseNode
* pRoot
);
311 /** creates a table object and inserts it into our tables collection
313 only used when we're iterating through a CREATE TABLE statement
315 OSQLTable
impl_createTableObject(
316 const OUString
& rTableName
, const OUString
& rCatalogName
, const OUString
& rSchemaName
);
318 /** locates a record source (a table or query) with the given name
320 OSQLTable
impl_locateRecordSource(
321 const OUString
& _rComposedName
324 /** implementation for both traverseAll and traverseSome
326 void impl_traverse( sal_uInt32 _nIncludeMask
);
328 /** retrieves the parameter columns of the given query
330 void impl_getQueryParameterColumns( const OSQLTable
& _rQuery
);
332 void setOrderByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
, bool bAscending
);
333 void setGroupByColumnName(const OUString
& rColumnName
, OUString
& rTableRange
);
336 /** appends an SQLException corresponding to the given error code to our error collection
339 the code of the error which occurred
340 @param _pReplaceToken1
341 if not <NULL/>, the first occurrence of '#' in the error message will be replaced
343 @param _pReplaceToken2
344 if not <NULL/>, and if _rReplaceToken1 is not <NULL/>, the second occurrence of '#'
345 in the error message will be replaced with _rReplaceToken2
347 void impl_appendError( IParseContext::ErrorCode _eError
,
348 const OUString
* _pReplaceToken1
= NULL
, const OUString
* _pReplaceToken2
= NULL
);
350 /** appends an SQLException corresponding to the given error code to our error collection
352 void impl_appendError( const ::com::sun::star::sdbc::SQLException
& _rError
);
354 /** resets our errors
356 inline void impl_resetErrors()
358 m_aErrors
= ::com::sun::star::sdbc::SQLException();
360 void impl_fillJoinConditions(const OSQLParseNode
* i_pJoinCondition
);
364 #endif // INCLUDED_CONNECTIVITY_SQLITERATOR_HXX
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */