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