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 occurred 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 occurred 337 @param _pReplaceToken1 338 if not <NULL/>, the first occurrence 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 occurrence 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