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 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_connectivity.hxx" 26 #include "connectivity/sqliterator.hxx" 27 #include "connectivity/sdbcx/VTable.hxx" 28 #include <connectivity/sqlparse.hxx> 29 #include <connectivity/dbtools.hxx> 30 #include <connectivity/sqlerror.hxx> 31 #include <com/sun/star/sdbc/ColumnValue.hpp> 32 #include <com/sun/star/sdbc/DataType.hpp> 33 #include <com/sun/star/sdbc/XRow.hpp> 34 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 35 #include <com/sun/star/sdb/ErrorCondition.hpp> 36 #ifdef SQL_TEST_PARSETREEITERATOR 37 #include <iostream> 38 #endif 39 #include "connectivity/PColumn.hxx" 40 #include "connectivity/dbtools.hxx" 41 #include <tools/diagnose_ex.h> 42 #include "TConnection.hxx" 43 #include <comphelper/types.hxx> 44 #include <connectivity/dbmetadata.hxx> 45 #include <com/sun/star/sdb/SQLFilterOperator.hpp> 46 #include "diagnose_ex.h" 47 #include <rtl/logfile.hxx> 48 49 #define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\ 50 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \ 51 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2))) 52 53 using namespace ::comphelper; 54 using namespace ::connectivity; 55 using namespace ::connectivity::sdbcx; 56 using namespace ::dbtools; 57 using namespace ::connectivity::parse; 58 using namespace ::com::sun::star; 59 using namespace ::com::sun::star::uno; 60 using namespace ::com::sun::star::container; 61 using namespace ::com::sun::star::sdbcx; 62 using namespace ::com::sun::star::beans; 63 using namespace ::com::sun::star::sdbc; 64 using namespace ::com::sun::star::sdb; 65 66 namespace connectivity 67 { 68 struct OSQLParseTreeIteratorImpl 69 { 70 ::std::vector< TNodePair > m_aJoinConditions; 71 Reference< XConnection > m_xConnection; 72 Reference< XDatabaseMetaData > m_xDatabaseMetaData; 73 Reference< XNameAccess > m_xTableContainer; 74 Reference< XNameAccess > m_xQueryContainer; 75 76 ::boost::shared_ptr< OSQLTables > m_pTables; /// all tables which participate in the SQL statement 77 ::boost::shared_ptr< OSQLTables > m_pSubTables; /// all tables from sub queries not the tables from the select tables 78 ::boost::shared_ptr< QueryNameSet > m_pForbiddenQueryNames; 79 80 sal_uInt32 m_nIncludeMask; 81 82 bool m_bIsCaseSensitive; 83 84 OSQLParseTreeIteratorImpl( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxTables ) 85 :m_xConnection( _rxConnection ) 86 ,m_nIncludeMask( OSQLParseTreeIterator::All ) 87 ,m_bIsCaseSensitive( true ) 88 { 89 OSL_PRECOND( m_xConnection.is(), "OSQLParseTreeIteratorImpl::OSQLParseTreeIteratorImpl: invalid connection!" ); 90 m_xDatabaseMetaData = m_xConnection->getMetaData(); 91 92 m_bIsCaseSensitive = m_xDatabaseMetaData.is() && m_xDatabaseMetaData->supportsMixedCaseQuotedIdentifiers(); 93 m_pTables.reset( new OSQLTables( m_bIsCaseSensitive ) ); 94 m_pSubTables.reset( new OSQLTables( m_bIsCaseSensitive ) ); 95 96 m_xTableContainer = _rxTables; 97 98 DatabaseMetaData aMetaData( m_xConnection ); 99 if ( aMetaData.supportsSubqueriesInFrom() ) 100 { 101 // connections might support the XQueriesSupplier interface, if they implement the css.sdb.Connection 102 // service 103 Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY ); 104 if ( xSuppQueries.is() ) 105 m_xQueryContainer = xSuppQueries->getQueries(); 106 } 107 } 108 109 public: 110 inline bool isQueryAllowed( const ::rtl::OUString& _rQueryName ) 111 { 112 if ( !m_pForbiddenQueryNames.get() ) 113 return true; 114 if ( m_pForbiddenQueryNames->find( _rQueryName ) == m_pForbiddenQueryNames->end() ) 115 return true; 116 return false; 117 } 118 }; 119 120 //------------------------------------------------------------------------- 121 /** helper class for temporarily adding a query name to a list of forbidden query names 122 */ 123 class ForbidQueryName 124 { 125 ::boost::shared_ptr< QueryNameSet >& m_rpAllForbiddenNames; 126 ::rtl::OUString m_sForbiddenQueryName; 127 128 public: 129 ForbidQueryName( OSQLParseTreeIteratorImpl& _rIteratorImpl, const ::rtl::OUString _rForbiddenQueryName ) 130 :m_rpAllForbiddenNames( _rIteratorImpl.m_pForbiddenQueryNames ) 131 ,m_sForbiddenQueryName( _rForbiddenQueryName ) 132 { 133 if ( !m_rpAllForbiddenNames.get() ) 134 m_rpAllForbiddenNames.reset( new QueryNameSet ); 135 m_rpAllForbiddenNames->insert( m_sForbiddenQueryName ); 136 } 137 138 ~ForbidQueryName() 139 { 140 m_rpAllForbiddenNames->erase( m_sForbiddenQueryName ); 141 } 142 }; 143 } 144 //----------------------------------------------------------------------------- 145 OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XConnection >& _rxConnection, 146 const Reference< XNameAccess >& _rxTables, 147 const OSQLParser& _rParser, 148 const OSQLParseNode* pRoot ) 149 :m_rParser( _rParser ) 150 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rxConnection, _rxTables ) ) 151 { 152 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" ); 153 setParseTree(pRoot); 154 } 155 156 //----------------------------------------------------------------------------- 157 OSQLParseTreeIterator::OSQLParseTreeIterator( const OSQLParseTreeIterator& _rParentIterator, const OSQLParser& _rParser, const OSQLParseNode* pRoot ) 158 :m_rParser( _rParser ) 159 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rParentIterator.m_pImpl->m_xConnection, _rParentIterator.m_pImpl->m_xTableContainer ) ) 160 { 161 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" ); 162 m_pImpl->m_pForbiddenQueryNames = _rParentIterator.m_pImpl->m_pForbiddenQueryNames; 163 setParseTree( pRoot ); 164 } 165 166 //----------------------------------------------------------------------------- 167 OSQLParseTreeIterator::~OSQLParseTreeIterator() 168 { 169 dispose(); 170 } 171 172 // ----------------------------------------------------------------------------- 173 const OSQLTables& OSQLParseTreeIterator::getTables() const 174 { 175 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTables" ); 176 return *m_pImpl->m_pTables; 177 } 178 179 // ----------------------------------------------------------------------------- 180 bool OSQLParseTreeIterator::isCaseSensitive() const 181 { 182 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isCaseSensitive" ); 183 return m_pImpl->m_bIsCaseSensitive; 184 } 185 186 // ----------------------------------------------------------------------------- 187 void OSQLParseTreeIterator::dispose() 188 { 189 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::dispose" ); 190 m_aSelectColumns = NULL; 191 m_aGroupColumns = NULL; 192 m_aOrderColumns = NULL; 193 m_aParameters = NULL; 194 m_pImpl->m_xTableContainer = NULL; 195 m_pImpl->m_xDatabaseMetaData = NULL; 196 m_aCreateColumns = NULL; 197 m_pImpl->m_pTables->clear(); 198 m_pImpl->m_pSubTables->clear(); 199 } 200 //----------------------------------------------------------------------------- 201 void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree) 202 { 203 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setParseTree" ); 204 m_pImpl->m_pTables->clear(); 205 m_pImpl->m_pSubTables->clear(); 206 207 m_aSelectColumns = new OSQLColumns(); 208 m_aGroupColumns = new OSQLColumns(); 209 m_aOrderColumns = new OSQLColumns(); 210 m_aParameters = new OSQLColumns(); 211 m_aCreateColumns = new OSQLColumns(); 212 213 m_pParseTree = pNewParseTree; 214 if (!m_pParseTree) 215 { 216 m_eStatementType = SQL_STATEMENT_UNKNOWN; 217 return; 218 } 219 220 // falls m_pParseTree aber keine Connection, dann Fehler 221 if ( !m_pImpl->m_xTableContainer.is() ) 222 return; 223 224 m_aErrors = SQLException(); 225 226 227 // Statement-Typ ermitteln ... 228 if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) ) 229 { 230 m_eStatementType = SQL_STATEMENT_SELECT; 231 } 232 else if (SQL_ISRULE(m_pParseTree,insert_statement)) 233 { 234 m_eStatementType = SQL_STATEMENT_INSERT; 235 } 236 else if (SQL_ISRULE(m_pParseTree,update_statement_searched)) 237 { 238 m_eStatementType = SQL_STATEMENT_UPDATE; 239 } 240 else if (SQL_ISRULE(m_pParseTree,delete_statement_searched)) 241 { 242 m_eStatementType = SQL_STATEMENT_DELETE; 243 } 244 else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec)) 245 { 246 m_eStatementType = SQL_STATEMENT_ODBC_CALL; 247 } 248 else if (SQL_ISRULE(m_pParseTree->getChild(0),base_table_def)) 249 { 250 m_eStatementType = SQL_STATEMENT_CREATE_TABLE; 251 m_pParseTree = m_pParseTree->getChild(0); 252 } 253 else 254 { 255 m_eStatementType = SQL_STATEMENT_UNKNOWN; 256 //aIteratorStatus.setInvalidStatement(); 257 return; 258 } 259 } 260 261 //----------------------------------------------------------------------------- 262 namespace 263 { 264 //......................................................................... 265 static void impl_getRowString( const Reference< XRow >& _rxRow, const sal_Int32 _nColumnIndex, ::rtl::OUString& _out_rString ) 266 { 267 _out_rString = _rxRow->getString( _nColumnIndex ); 268 if ( _rxRow->wasNull() ) 269 _out_rString= ::rtl::OUString(); 270 } 271 272 //......................................................................... 273 static ::rtl::OUString lcl_findTableInMetaData( 274 const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rCatalog, 275 const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rTableName ) 276 { 277 ::rtl::OUString sComposedName; 278 279 static const ::rtl::OUString s_sTableTypeView(RTL_CONSTASCII_USTRINGPARAM("VIEW")); 280 static const ::rtl::OUString s_sTableTypeTable(RTL_CONSTASCII_USTRINGPARAM("TABLE")); 281 static const ::rtl::OUString s_sWildcard = ::rtl::OUString::createFromAscii("%"); 282 283 // we want all catalogues, all schemas, all tables 284 Sequence< ::rtl::OUString > sTableTypes(3); 285 sTableTypes[0] = s_sTableTypeView; 286 sTableTypes[1] = s_sTableTypeTable; 287 sTableTypes[2] = s_sWildcard; // just to be sure to include anything else .... 288 289 if ( _rxDBMeta.is() ) 290 { 291 sComposedName = ::rtl::OUString(); 292 293 Reference< XResultSet> xRes = _rxDBMeta->getTables( 294 _rCatalog.getLength() ? makeAny( _rCatalog ) : Any(), _rSchema.getLength() ? _rSchema : s_sWildcard, _rTableName, sTableTypes ); 295 296 Reference< XRow > xCurrentRow( xRes, UNO_QUERY ); 297 if ( xCurrentRow.is() && xRes->next() ) 298 { 299 ::rtl::OUString sCatalog, sSchema, sName; 300 301 impl_getRowString( xCurrentRow, 1, sCatalog ); 302 impl_getRowString( xCurrentRow, 2, sSchema ); 303 impl_getRowString( xCurrentRow, 3, sName ); 304 305 sComposedName = ::dbtools::composeTableName( 306 _rxDBMeta, 307 sCatalog, 308 sSchema, 309 sName, 310 sal_False, 311 ::dbtools::eInDataManipulation 312 ); 313 } 314 } 315 return sComposedName; 316 } 317 } 318 319 //----------------------------------------------------------------------------- 320 void OSQLParseTreeIterator::impl_getQueryParameterColumns( const OSQLTable& _rQuery ) 321 { 322 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_getQueryParameterColumns" ); 323 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters ) 324 // parameters not to be included in the traversal 325 return; 326 327 ::vos::ORef< OSQLColumns > pSubQueryParameterColumns( new OSQLColumns() ); 328 329 // get the command and the EscapeProcessing properties from the sub query 330 ::rtl::OUString sSubQueryCommand; 331 sal_Bool bEscapeProcessing = sal_False; 332 try 333 { 334 Reference< XPropertySet > xQueryProperties( _rQuery, UNO_QUERY_THROW ); 335 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sSubQueryCommand ); 336 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing ); 337 } 338 catch( const Exception& ) 339 { 340 DBG_UNHANDLED_EXCEPTION(); 341 } 342 343 // parse the sub query 344 do { 345 346 if ( !bEscapeProcessing || ( sSubQueryCommand.getLength() == 0 ) ) 347 break; 348 349 ::rtl::OUString sError; 350 ::std::auto_ptr< OSQLParseNode > pSubQueryNode( const_cast< OSQLParser& >( m_rParser ).parseTree( sError, sSubQueryCommand, sal_False ) ); 351 if ( !pSubQueryNode.get() ) 352 break; 353 354 OSQLParseTreeIterator aSubQueryIterator( *this, m_rParser, pSubQueryNode.get() ); 355 aSubQueryIterator.traverseSome( Parameters | SelectColumns ); 356 // SelectColumns might also contain parameters 357 // #i77635# - 2007-07-23 / frank.schoenheit@sun.com 358 pSubQueryParameterColumns = aSubQueryIterator.getParameters(); 359 aSubQueryIterator.dispose(); 360 361 } while ( false ); 362 363 // copy the parameters of the sub query to our own parameter array 364 ::std::copy( pSubQueryParameterColumns->get().begin(), pSubQueryParameterColumns->get().end(), 365 ::std::insert_iterator< OSQLColumns::Vector >( m_aParameters->get(), m_aParameters->get().end() ) ); 366 } 367 368 //----------------------------------------------------------------------------- 369 OSQLTable OSQLParseTreeIterator::impl_locateRecordSource( const ::rtl::OUString& _rComposedName ) 370 { 371 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_locateRecordSource" ); 372 if ( !_rComposedName.getLength() ) 373 { 374 OSL_ENSURE( false, "OSQLParseTreeIterator::impl_locateRecordSource: no object name at all?" ); 375 return OSQLTable(); 376 } 377 378 OSQLTable aReturn; 379 ::rtl::OUString sComposedName( _rComposedName ); 380 381 try 382 { 383 ::rtl::OUString sCatalog, sSchema, sName; 384 qualifiedNameComponents( m_pImpl->m_xDatabaseMetaData, sComposedName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation ); 385 386 // check whether there is a query with the given name 387 bool bQueryDoesExist = m_pImpl->m_xQueryContainer.is() && m_pImpl->m_xQueryContainer->hasByName( sComposedName ); 388 389 // check whether the table container contains an object with the given name 390 if ( !bQueryDoesExist && !m_pImpl->m_xTableContainer->hasByName( sComposedName ) ) 391 sComposedName = lcl_findTableInMetaData( m_pImpl->m_xDatabaseMetaData, sCatalog, sSchema, sName ); 392 bool bTableDoesExist = m_pImpl->m_xTableContainer->hasByName( sComposedName ); 393 394 // now obtain the object 395 396 // if we're creating a table, and there already is a table or query with the same name, 397 // this is worth an error 398 if ( SQL_STATEMENT_CREATE_TABLE == m_eStatementType ) 399 { 400 if ( bQueryDoesExist ) 401 impl_appendError( IParseContext::ERROR_INVALID_QUERY_EXIST, &sName ); 402 else if ( bTableDoesExist ) 403 impl_appendError( IParseContext::ERROR_INVALID_TABLE_EXIST, &sName ); 404 else 405 aReturn = impl_createTableObject( sName, sCatalog, sSchema ); 406 } 407 else 408 { 409 // queries win over tables, so if there's a query with this name, take this, no matter if 410 // there's a table, too 411 if ( bQueryDoesExist ) 412 { 413 if ( !m_pImpl->isQueryAllowed( sComposedName ) ) 414 { 415 impl_appendError( m_rParser.getErrorHelper().getSQLException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES, NULL ) ); 416 return NULL; 417 } 418 419 m_pImpl->m_xQueryContainer->getByName( sComposedName ) >>= aReturn; 420 421 // collect the parameters from the sub query 422 ForbidQueryName aForbidName( *m_pImpl, sComposedName ); 423 impl_getQueryParameterColumns( aReturn ); 424 } 425 else if ( bTableDoesExist ) 426 m_pImpl->m_xTableContainer->getByName( sComposedName ) >>= aReturn; 427 else 428 { 429 if ( m_pImpl->m_xQueryContainer.is() ) 430 // the connection on which we're working supports sub queries in from (else 431 // m_xQueryContainer would not have been set), so emit a better error message 432 impl_appendError( IParseContext::ERROR_INVALID_TABLE_OR_QUERY, &sName ); 433 else 434 impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sName ); 435 } 436 } 437 } 438 catch(Exception&) 439 { 440 impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sComposedName ); 441 } 442 443 return aReturn; 444 } 445 446 //----------------------------------------------------------------------------- 447 void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange ) 448 { 449 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOneTableName" ); 450 if ( ( m_pImpl->m_nIncludeMask & TableNames ) != TableNames ) 451 // tables should not be included in the traversal 452 return; 453 454 OSL_ENSURE(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL"); 455 456 Any aCatalog; 457 ::rtl::OUString aSchema,aTableName,aComposedName; 458 ::rtl::OUString aTableRange(rTableRange); 459 460 // Tabellenname abholen 461 OSQLParseNode::getTableComponents(pTableName,aCatalog,aSchema,aTableName,m_pImpl->m_xDatabaseMetaData); 462 463 // create the composed name like DOMAIN.USER.TABLE1 464 aComposedName = ::dbtools::composeTableName(m_pImpl->m_xDatabaseMetaData, 465 aCatalog.hasValue() ? ::comphelper::getString(aCatalog) : ::rtl::OUString(), 466 aSchema, 467 aTableName, 468 sal_False, 469 ::dbtools::eInDataManipulation); 470 471 // if there is no alias for the table name assign the orignal name to it 472 if ( !aTableRange.getLength() ) 473 aTableRange = aComposedName; 474 475 // get the object representing this table/query 476 OSQLTable aTable = impl_locateRecordSource( aComposedName ); 477 if ( aTable.is() ) 478 _rTables[ aTableRange ] = aTable; 479 } 480 //----------------------------------------------------------------------------- 481 void OSQLParseTreeIterator::impl_fillJoinConditions(const OSQLParseNode* i_pJoinCondition) 482 { 483 if (i_pJoinCondition->count() == 3 && // Ausdruck is geklammert 484 SQL_ISPUNCTUATION(i_pJoinCondition->getChild(0),"(") && 485 SQL_ISPUNCTUATION(i_pJoinCondition->getChild(2),")")) 486 { 487 impl_fillJoinConditions(i_pJoinCondition->getChild(1)); 488 } 489 else if (SQL_ISRULEOR2(i_pJoinCondition,search_condition,boolean_term) && // AND/OR-Verknuepfung: 490 i_pJoinCondition->count() == 3) 491 { 492 // nur AND Verkn�pfung zulassen 493 if ( SQL_ISTOKEN(i_pJoinCondition->getChild(1),AND) ) 494 { 495 impl_fillJoinConditions(i_pJoinCondition->getChild(0)); 496 impl_fillJoinConditions(i_pJoinCondition->getChild(1)); 497 } 498 } 499 else if (SQL_ISRULE(i_pJoinCondition,comparison_predicate)) 500 { 501 // only the comparison of columns is allowed 502 OSL_ENSURE(i_pJoinCondition->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree"); 503 if (SQL_ISRULE(i_pJoinCondition->getChild(0),column_ref) && 504 SQL_ISRULE(i_pJoinCondition->getChild(2),column_ref) && 505 i_pJoinCondition->getChild(1)->getNodeType() == SQL_NODE_EQUAL) 506 { 507 m_pImpl->m_aJoinConditions.push_back( TNodePair(i_pJoinCondition->getChild(0),i_pJoinCondition->getChild(2)) ); 508 } 509 } 510 } 511 //----------------------------------------------------------------------------- 512 ::std::vector< TNodePair >& OSQLParseTreeIterator::getJoinConditions() const 513 { 514 return m_pImpl->m_aJoinConditions; 515 } 516 //----------------------------------------------------------------------------- 517 void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange ) 518 { 519 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getQualified_join" ); 520 OSL_PRECOND( SQL_ISRULE( pTableRef, cross_union ) || SQL_ISRULE( pTableRef, qualified_join ) , 521 "OSQLParseTreeIterator::getQualified_join: illegal node!" ); 522 523 aTableRange = ::rtl::OUString(); 524 525 const OSQLParseNode* pNode = getTableNode(_rTables,pTableRef->getChild(0),aTableRange); 526 if ( isTableNode( pNode ) ) 527 traverseOneTableName( _rTables, pNode, aTableRange ); 528 529 sal_uInt32 nPos = 4; 530 if( SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL) 531 { 532 nPos = 3; 533 // join_condition,named_columns_join 534 if ( SQL_ISRULE( pTableRef, qualified_join ) ) 535 { 536 const OSQLParseNode* pJoin_spec = pTableRef->getChild(4); 537 if ( SQL_ISRULE( pJoin_spec, join_condition ) ) 538 { 539 impl_fillJoinConditions(pJoin_spec->getChild(1)); 540 } 541 else 542 { 543 const OSQLParseNode* pColumnCommalist = pJoin_spec->getChild(2); 544 // Alle Columns in der column_commalist ... 545 for (sal_uInt32 i = 0; i < pColumnCommalist->count(); i++) 546 { 547 const OSQLParseNode * pCol = pColumnCommalist->getChild(i); 548 // add twice because the column must exists in both tables 549 m_pImpl->m_aJoinConditions.push_back( TNodePair(pCol,pCol) ); 550 } 551 } 552 } 553 } 554 555 pNode = getTableNode(_rTables,pTableRef->getChild(nPos),aTableRange); 556 if ( isTableNode( pNode ) ) 557 traverseOneTableName( _rTables, pNode, aTableRange ); 558 } 559 //----------------------------------------------------------------------------- 560 const OSQLParseNode* OSQLParseTreeIterator::getTableNode( OSQLTables& _rTables, const OSQLParseNode *pTableRef,::rtl::OUString& rTableRange ) 561 { 562 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTableNode" ); 563 OSL_PRECOND( SQL_ISRULE( pTableRef, table_ref ) || SQL_ISRULE( pTableRef, joined_table ) 564 || SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ), 565 "OSQLParseTreeIterator::getTableNode: only to be called for table_ref nodes!" ); 566 567 const OSQLParseNode* pTableNameNode = NULL; 568 569 if ( SQL_ISRULE( pTableRef, joined_table ) ) 570 { 571 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange ); 572 } 573 if ( SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ) ) 574 { 575 getQualified_join( _rTables, pTableRef, rTableRange ); 576 } 577 else 578 { 579 rTableRange = OSQLParseNode::getTableRange(pTableRef); 580 if ( ( pTableRef->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}' 581 || ( pTableRef->count() == 5 ) // '(' joined_table ')' range_variable op_column_commalist 582 ) 583 { 584 getQualified_join( _rTables, pTableRef->getChild(6 - pTableRef->count()), rTableRange ); 585 } 586 else if ( pTableRef->count() == 3 ) // subquery range_variable op_column_commalist || '(' joined_table ')' 587 { 588 const OSQLParseNode* pSubQuery = pTableRef->getChild(0); 589 if ( pSubQuery->isToken() ) 590 { 591 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange ); 592 } 593 else 594 { 595 OSL_ENSURE( pSubQuery->count() == 3, "sub queries should have 3 children!" ); 596 const OSQLParseNode* pQueryExpression = pSubQuery->getChild(1); 597 if ( SQL_ISRULE( pQueryExpression, select_statement ) ) 598 { 599 getSelect_statement( *m_pImpl->m_pSubTables, pQueryExpression ); 600 } 601 else 602 { 603 OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: subquery which is no select_statement: not yet implemented!" ); 604 } 605 } 606 } 607 else if ( pTableRef->count() == 2 ) // table_node table_primary_as_range_column 608 { 609 pTableNameNode = pTableRef->getChild(0); 610 } 611 else 612 OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: unhandled case!" ); 613 } 614 615 return pTableNameNode; 616 } 617 //----------------------------------------------------------------------------- 618 void OSQLParseTreeIterator::getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect) 619 { 620 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSelect_statement" ); 621 if(SQL_ISRULE(pSelect,union_statement)) 622 { 623 getSelect_statement(_rTables,pSelect->getChild(0)); 624 //getSelect_statement(pSelect->getChild(3)); 625 return; 626 } 627 OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1); 628 629 OSL_ENSURE(pTableRefCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!"); 630 OSL_ENSURE(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: error in parse tree!"); 631 632 const OSQLParseNode* pTableName = NULL; 633 ::rtl::OUString aTableRange; 634 for (sal_uInt32 i = 0; i < pTableRefCommalist->count(); i++) 635 { // from clause durchlaufen 636 aTableRange = ::rtl::OUString(); 637 638 const OSQLParseNode* pTableListElement = pTableRefCommalist->getChild(i); 639 if ( isTableNode( pTableListElement ) ) 640 { 641 traverseOneTableName( _rTables, pTableListElement, aTableRange ); 642 } 643 else if ( SQL_ISRULE( pTableListElement, table_ref ) ) 644 { 645 // Tabellenreferenz kann aus Tabellennamen, Tabellennamen (+),'('joined_table')'(+) bestehen 646 pTableName = pTableListElement->getChild(0); 647 if( isTableNode( pTableName ) ) 648 { // Tabellennamen gefunden 649 aTableRange = OSQLParseNode::getTableRange(pTableListElement); 650 traverseOneTableName( _rTables, pTableName, aTableRange ); 651 } 652 else if(SQL_ISPUNCTUATION(pTableName,"{")) 653 { // '{' SQL_TOKEN_OJ joined_table '}' 654 getQualified_join( _rTables, pTableListElement->getChild(2), aTableRange ); 655 } 656 else 657 { // '(' joined_table ')' range_variable op_column_commalist 658 getTableNode( _rTables, pTableListElement, aTableRange ); 659 } 660 } 661 else if (SQL_ISRULE( pTableListElement, qualified_join ) || SQL_ISRULE( pTableListElement, cross_union ) ) 662 { 663 getQualified_join( _rTables, pTableListElement, aTableRange ); 664 } 665 else if ( SQL_ISRULE( pTableListElement, joined_table ) ) 666 { 667 getQualified_join( _rTables, pTableListElement->getChild(1), aTableRange ); 668 } 669 670 // if (! aIteratorStatus.IsSuccessful()) break; 671 } 672 } 673 //----------------------------------------------------------------------------- 674 bool OSQLParseTreeIterator::traverseTableNames(OSQLTables& _rTables) 675 { 676 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseTableNames" ); 677 if ( m_pParseTree == NULL ) 678 return false; 679 680 OSQLParseNode* pTableName = NULL; 681 682 switch ( m_eStatementType ) 683 { 684 case SQL_STATEMENT_SELECT: 685 getSelect_statement( _rTables, m_pParseTree ); 686 break; 687 688 case SQL_STATEMENT_CREATE_TABLE: 689 case SQL_STATEMENT_INSERT: 690 case SQL_STATEMENT_DELETE: 691 pTableName = m_pParseTree->getChild(2); 692 break; 693 694 case SQL_STATEMENT_UPDATE: 695 pTableName = m_pParseTree->getChild(1); 696 break; 697 default: 698 break; 699 } 700 701 if ( pTableName ) 702 { 703 ::rtl::OUString sTableRange; 704 traverseOneTableName( _rTables, pTableName, sTableRange ); 705 } 706 707 return !hasErrors(); 708 } 709 //----------------------------------------------------------------------------- 710 ::rtl::OUString OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* _pDerivedColumn) 711 { 712 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnAlias" ); 713 OSL_ENSURE(SQL_ISRULE(_pDerivedColumn,derived_column),"No derived column!"); 714 ::rtl::OUString sColumnAlias; 715 if(_pDerivedColumn->getChild(1)->count() == 2) 716 sColumnAlias = _pDerivedColumn->getChild(1)->getChild(1)->getTokenValue(); 717 else if(!_pDerivedColumn->getChild(1)->isRule()) 718 sColumnAlias = _pDerivedColumn->getChild(1)->getTokenValue(); 719 return sColumnAlias; 720 } 721 722 // ----------------------------------------------------------------------------- 723 namespace 724 { 725 void lcl_getColumnRange( const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection, 726 ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange, 727 const OSQLColumns* _pSelectColumns, ::rtl::OUString& _out_rColumnAliasIfPresent ) 728 { 729 _out_rColumnName = _out_rTableRange = _out_rColumnAliasIfPresent = ::rtl::OUString(); 730 if ( SQL_ISRULE( _pColumnRef, column_ref ) ) 731 { 732 if( _pColumnRef->count() > 1 ) 733 { 734 for ( sal_Int32 i=0; i<((sal_Int32)_pColumnRef->count())-2; ++i ) 735 _pColumnRef->getChild(i)->parseNodeToStr( _out_rTableRange, _rxConnection, NULL, sal_False, sal_False ); 736 _out_rColumnName = _pColumnRef->getChild( _pColumnRef->count()-1 )->getChild(0)->getTokenValue(); 737 } 738 else 739 _out_rColumnName = _pColumnRef->getChild(0)->getTokenValue(); 740 741 // look up the column in the select column, to find an possible alias 742 if ( _pSelectColumns ) 743 { 744 for ( OSQLColumns::Vector::const_iterator lookupColumn = _pSelectColumns->get().begin(); 745 lookupColumn != _pSelectColumns->get().end(); 746 ++lookupColumn 747 ) 748 { 749 Reference< XPropertySet > xColumn( *lookupColumn ); 750 try 751 { 752 ::rtl::OUString sName, sTableName; 753 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) >>= sName; 754 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sTableName; 755 if ( sName == _out_rColumnName && sTableName == _out_rTableRange ) 756 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= _out_rColumnAliasIfPresent; 757 } 758 catch( const Exception& ) 759 { 760 DBG_UNHANDLED_EXCEPTION(); 761 } 762 } 763 } 764 } 765 else if(SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec)) 766 { // Funktion 767 _pColumnRef->parseNodeToStr( _out_rColumnName, _rxConnection ); 768 } 769 else if(_pColumnRef->getNodeType() == SQL_NODE_NAME) 770 _out_rColumnName = _pColumnRef->getTokenValue(); 771 } 772 } 773 774 // ----------------------------------------------------------------------------- 775 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef, 776 ::rtl::OUString& _rColumnName, 777 ::rtl::OUString& _rTableRange) const 778 { 779 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" ); 780 ::rtl::OUString sDummy; 781 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, NULL, sDummy ); 782 } 783 784 // ----------------------------------------------------------------------------- 785 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef, 786 ::rtl::OUString& _rColumnName, 787 ::rtl::OUString& _rTableRange, 788 ::rtl::OUString& _out_rColumnAliasIfPresent ) const 789 { 790 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" ); 791 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, &*m_aSelectColumns, _out_rColumnAliasIfPresent ); 792 } 793 794 //----------------------------------------------------------------------------- 795 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef, 796 const Reference< XConnection >& _rxConnection, ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange ) 797 { 798 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" ); 799 ::rtl::OUString sDummy; 800 lcl_getColumnRange( _pColumnRef, _rxConnection, _out_rColumnName, _out_rTableRange, NULL, sDummy ); 801 } 802 803 //----------------------------------------------------------------------------- 804 sal_Bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const 805 { 806 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnTableRange" ); 807 // Ermitteln ob alle Spalten zu einer Tabelle gehoeren 808 if (SQL_ISRULE(pNode,column_ref)) 809 { 810 ::rtl::OUString aColName, aTableRange; 811 getColumnRange(pNode, aColName, aTableRange); 812 if (!aTableRange.getLength()) // keinen gefunden 813 { 814 // dann die Spalte in den Tabellen suchen 815 for (ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter) 816 { 817 if (aIter->second.is()) 818 { 819 try 820 { 821 Reference< XNameAccess > xColumns = aIter->second->getColumns(); 822 if(xColumns->hasByName(aColName)) 823 { 824 Reference< XPropertySet > xColumn; 825 if (xColumns->getByName(aColName) >>= xColumn) 826 { 827 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!"); 828 aTableRange = aIter->first; 829 break; 830 } 831 } 832 } 833 catch(Exception&) 834 { 835 } 836 } 837 } 838 if (!aTableRange.getLength()) 839 return sal_False; 840 } 841 842 843 if (!rTableRange.getLength()) 844 rTableRange = aTableRange; 845 else if (rTableRange != aTableRange) 846 return sal_False; 847 } 848 else 849 { 850 for (sal_uInt32 i = 0, ncount = pNode->count(); i < ncount; i++) 851 { 852 if (!getColumnTableRange(pNode->getChild(i), rTableRange)) 853 return sal_False; 854 } 855 } 856 return sal_True; 857 } 858 859 //----------------------------------------------------------------------------- 860 void OSQLParseTreeIterator::traverseCreateColumns(const OSQLParseNode* pSelectNode) 861 { 862 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseCreateColumns" ); 863 // aIteratorStatus.Clear(); 864 865 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_CREATE_TABLE || m_pImpl->m_pTables->empty()) 866 { 867 impl_appendError( IParseContext::ERROR_GENERAL ); 868 return; 869 } 870 if (!SQL_ISRULE(pSelectNode,base_table_element_commalist)) 871 return ; 872 873 for (sal_uInt32 i = 0; i < pSelectNode->count(); i++) 874 { 875 OSQLParseNode *pColumnRef = pSelectNode->getChild(i); 876 877 if (SQL_ISRULE(pColumnRef,column_def)) 878 { 879 ::rtl::OUString aColumnName; 880 ::rtl::OUString aTypeName; 881 ::rtl::OUString aTableRange; 882 sal_Int32 nType = DataType::VARCHAR; 883 sal_Int32 nLen = 0; 884 aColumnName = pColumnRef->getChild(0)->getTokenValue(); 885 886 OSQLParseNode *pDatatype = pColumnRef->getChild(1); 887 if (pDatatype && SQL_ISRULE(pDatatype,character_string_type)) 888 { 889 const OSQLParseNode *pType = pDatatype->getChild(0); 890 aTypeName = pType->getTokenValue(); 891 if (pDatatype->count() == 2 && (pType->getTokenID() == SQL_TOKEN_CHAR || pType->getTokenID() == SQL_TOKEN_CHARACTER )) 892 nType = DataType::CHAR; 893 894 const OSQLParseNode *pParams = pDatatype->getChild(pDatatype->count()-1); 895 if ( pParams->count() ) 896 { 897 nLen = pParams->getChild(1)->getTokenValue().toInt32(); 898 } 899 } 900 else if(pDatatype && pDatatype->getNodeType() == SQL_NODE_KEYWORD) 901 { 902 aTypeName = ::rtl::OUString::createFromAscii("VARCHAR"); 903 } 904 905 if (aTypeName.getLength()) 906 { 907 //TODO:Create a new class for create statement to handle field length 908 OParseColumn* pColumn = new OParseColumn(aColumnName,aTypeName,::rtl::OUString(),::rtl::OUString(), 909 ColumnValue::NULLABLE_UNKNOWN,0,0,nType,sal_False,sal_False,isCaseSensitive()); 910 pColumn->setFunction(sal_False); 911 pColumn->setRealName(aColumnName); 912 913 Reference< XPropertySet> xCol = pColumn; 914 m_aCreateColumns->get().push_back(xCol); 915 } 916 } 917 918 } 919 } 920 //----------------------------------------------------------------------------- 921 bool OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode) 922 { 923 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectColumnNames" ); 924 if ( ( m_pImpl->m_nIncludeMask & SelectColumns ) != SelectColumns ) 925 return true; 926 927 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || m_pImpl->m_pTables->empty()) 928 { 929 impl_appendError( IParseContext::ERROR_GENERAL ); 930 return false; 931 } 932 933 if(SQL_ISRULE(pSelectNode,union_statement)) 934 { 935 return traverseSelectColumnNames( pSelectNode->getChild( 0 ) ) 936 /*&& traverseSelectColumnNames( pSelectNode->getChild( 3 ) )*/; 937 } 938 939 static ::rtl::OUString aEmptyString; 940 // nyi: mehr Pruefung auf korrekte Struktur! 941 if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*")) 942 { 943 // SELECT * ... 944 setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aEmptyString); 945 } 946 else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist)) 947 { 948 // SELECT column[,column] oder SELECT COUNT(*) ... 949 OSQLParseNode * pSelection = pSelectNode->getChild(2); 950 951 for (sal_uInt32 i = 0; i < pSelection->count(); i++) 952 { 953 OSQLParseNode *pColumnRef = pSelection->getChild(i); 954 955 //if (SQL_ISRULE(pColumnRef,select_sublist)) 956 if (SQL_ISRULE(pColumnRef,derived_column) && 957 SQL_ISRULE(pColumnRef->getChild(0),column_ref) && 958 pColumnRef->getChild(0)->count() == 3 && 959 SQL_ISPUNCTUATION(pColumnRef->getChild(0)->getChild(2),"*")) 960 { 961 // alle Spalten der Tabelle 962 ::rtl::OUString aTableRange; 963 pColumnRef->getChild(0)->parseNodeToStr( aTableRange, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 964 setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aTableRange); 965 continue; 966 } 967 else if (SQL_ISRULE(pColumnRef,derived_column)) 968 { 969 ::rtl::OUString aColumnAlias(getColumnAlias(pColumnRef)); // kann leer sein 970 ::rtl::OUString sColumnName; 971 ::rtl::OUString aTableRange; 972 sal_Int32 nType = DataType::VARCHAR; 973 sal_Bool bFkt(sal_False); 974 pColumnRef = pColumnRef->getChild(0); 975 if ( 976 pColumnRef->count() == 3 && 977 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") && 978 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")") 979 ) 980 pColumnRef = pColumnRef->getChild(1); 981 982 if (SQL_ISRULE(pColumnRef,column_ref)) 983 { 984 getColumnRange(pColumnRef,sColumnName,aTableRange); 985 OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein"); 986 } 987 else /*if (SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec) || 988 SQL_ISRULE(pColumnRef,position_exp) || SQL_ISRULE(pColumnRef,extract_exp) || 989 SQL_ISRULE(pColumnRef,length_exp) || SQL_ISRULE(pColumnRef,char_value_fct)|| 990 SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))*/ 991 { 992 /* Funktionsaufruf vorhanden */ 993 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_True ); 994 ::rtl::OUString sTableRange; 995 // check if the column is also a parameter 996 traverseORCriteria(pColumnRef); // num_value_exp 997 998 // gehoeren alle beteiligten Spalten der Funktion zu einer Tabelle 999 if (m_pImpl->m_pTables->size() == 1) 1000 { 1001 aTableRange = m_pImpl->m_pTables->begin()->first; 1002 } 1003 else 1004 { 1005 getColumnTableRange(pColumnRef,aTableRange); 1006 } 1007 if ( pColumnRef->isRule() ) 1008 { 1009 bFkt = sal_True; 1010 nType = getFunctionReturnType(pColumnRef); 1011 } 1012 } 1013 /* 1014 else 1015 { 1016 aIteratorStatus.setStatementTooComplex(); 1017 return; 1018 } 1019 */ 1020 if(!aColumnAlias.getLength()) 1021 aColumnAlias = sColumnName; 1022 setSelectColumnName(m_aSelectColumns,sColumnName,aColumnAlias,aTableRange,bFkt,nType,SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec)); 1023 } 1024 } 1025 } 1026 1027 return !hasErrors(); 1028 } 1029 1030 1031 //----------------------------------------------------------------------------- 1032 bool OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode) 1033 { 1034 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOrderByColumnNames" ); 1035 traverseByColumnNames( pSelectNode, sal_True ); 1036 return !hasErrors(); 1037 } 1038 //----------------------------------------------------------------------------- 1039 void OSQLParseTreeIterator::traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder) 1040 { 1041 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseByColumnNames" ); 1042 // aIteratorStatus.Clear(); 1043 1044 if (pSelectNode == NULL) 1045 { 1046 //aIteratorStatus.setInvalidStatement(); 1047 return; 1048 } 1049 1050 if (m_eStatementType != SQL_STATEMENT_SELECT) 1051 { 1052 //aIteratorStatus.setInvalidStatement(); 1053 return; 1054 } 1055 1056 if(SQL_ISRULE(pSelectNode,union_statement)) 1057 { 1058 traverseByColumnNames(pSelectNode->getChild(0),_bOrder); 1059 return; 1060 } 1061 1062 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!"); 1063 1064 OSQLParseNode * pTableExp = pSelectNode->getChild(3); 1065 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1066 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator:table_exp error in parse tree!"); 1067 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 1068 1069 sal_uInt32 nPos = ( _bOrder ? ORDER_BY_CHILD_POS : 2 ); 1070 1071 OSQLParseNode * pOptByClause = pTableExp->getChild(nPos); 1072 OSL_ENSURE(pOptByClause != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1073 if ( pOptByClause->count() == 0 ) 1074 return; 1075 1076 OSL_ENSURE(pOptByClause->count() == 3,"OSQLParseTreeIterator: error in parse tree!"); 1077 1078 OSQLParseNode * pOrderingSpecCommalist = pOptByClause->getChild(2); 1079 OSL_ENSURE(pOrderingSpecCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1080 OSL_ENSURE(!_bOrder || SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OSQLParseTreeIterator:ordering_spec_commalist error in parse tree!"); 1081 OSL_ENSURE(pOrderingSpecCommalist->count() > 0,"OSQLParseTreeIterator: error in parse tree!"); 1082 1083 ::rtl::OUString sColumnName,aColumnAlias; 1084 ::rtl::OUString aTableRange; 1085 sal_uInt32 nCount = pOrderingSpecCommalist->count(); 1086 for (sal_uInt32 i = 0; i < nCount; ++i) 1087 { 1088 OSQLParseNode* pColumnRef = pOrderingSpecCommalist->getChild(i); 1089 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1090 if ( _bOrder ) 1091 { 1092 OSL_ENSURE(SQL_ISRULE(pColumnRef,ordering_spec),"OSQLParseTreeIterator:ordering_spec error in parse tree!"); 1093 OSL_ENSURE(pColumnRef->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); 1094 1095 pColumnRef = pColumnRef->getChild(0); 1096 } 1097 aTableRange = ::rtl::OUString(); 1098 sColumnName = ::rtl::OUString(); 1099 if ( SQL_ISRULE(pColumnRef,column_ref) ) 1100 { 1101 // Column-Name (und TableRange): 1102 if(SQL_ISRULE(pColumnRef,column_ref)) 1103 getColumnRange(pColumnRef,sColumnName,aTableRange); 1104 else // eine Expression 1105 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1106 1107 OSL_ENSURE(sColumnName.getLength(),"sColumnName darf nicht leer sein"); 1108 } 1109 else 1110 { // here I found a predicate 1111 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1112 } 1113 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1114 if ( _bOrder ) 1115 { 1116 // Ascending/Descending 1117 OSQLParseNode * pOptAscDesc = pColumnRef->getParent()->getChild(1); 1118 OSL_ENSURE(pOptAscDesc != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1119 1120 sal_Bool bAscending = pOptAscDesc && SQL_ISTOKEN(pOptAscDesc,ASC); 1121 setOrderByColumnName(sColumnName, aTableRange,bAscending); 1122 } 1123 else 1124 setGroupByColumnName(sColumnName, aTableRange); 1125 } 1126 } 1127 //----------------------------------------------------------------------------- 1128 bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode* pSelectNode) 1129 { 1130 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseGroupByColumnNames" ); 1131 traverseByColumnNames( pSelectNode, sal_False ); 1132 return !hasErrors(); 1133 } 1134 1135 // ----------------------------------------------------------------------------- 1136 namespace 1137 { 1138 ::rtl::OUString lcl_generateParameterName( const OSQLParseNode& _rParentNode, const OSQLParseNode& _rParamNode ) 1139 { 1140 ::rtl::OUString sColumnName( RTL_CONSTASCII_USTRINGPARAM( "param" ) ); 1141 const sal_Int32 nCount = (sal_Int32)_rParentNode.count(); 1142 for ( sal_Int32 i = 0; i < nCount; ++i ) 1143 { 1144 if ( _rParentNode.getChild(i) == &_rParamNode ) 1145 { 1146 sColumnName += ::rtl::OUString::valueOf( i+1 ); 1147 break; 1148 } 1149 } 1150 return sColumnName; 1151 } 1152 } 1153 1154 // ----------------------------------------------------------------------------- 1155 void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode) 1156 { 1157 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameters" ); 1158 if ( _pNode == NULL ) 1159 return; 1160 1161 ::rtl::OUString sColumnName, sTableRange, aColumnAlias; 1162 const OSQLParseNode* pParent = _pNode->getParent(); 1163 if ( pParent != NULL ) 1164 { 1165 if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X 1166 { 1167 sal_uInt32 nPos = 0; 1168 if ( pParent->getChild(nPos) == _pNode ) 1169 nPos = 2; 1170 const OSQLParseNode* pOther = pParent->getChild(nPos); 1171 if ( SQL_ISRULE( pOther, column_ref ) ) 1172 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias); 1173 else 1174 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1175 } // if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X 1176 else if ( SQL_ISRULE(pParent,other_like_predicate_part_2) ) 1177 { 1178 const OSQLParseNode* pOther = pParent->getParent()->getChild(0); 1179 if ( SQL_ISRULE( pOther, column_ref ) ) 1180 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias); 1181 else 1182 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1183 } 1184 else if ( SQL_ISRULE(pParent,between_predicate_part_2) ) 1185 { 1186 const OSQLParseNode* pOther = pParent->getParent()->getChild(0); 1187 if ( SQL_ISRULE( pOther, column_ref ) ) 1188 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias); 1189 else 1190 { 1191 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1192 lcl_generateParameterName( *pParent, *_pNode ); 1193 } 1194 } 1195 else if ( pParent->getNodeType() == SQL_NODE_COMMALISTRULE ) 1196 { 1197 lcl_generateParameterName( *pParent, *_pNode ); 1198 } 1199 } 1200 traverseParameter( _pNode, pParent, sColumnName, sTableRange, aColumnAlias ); 1201 const sal_uInt32 nCount = _pNode->count(); 1202 for (sal_uInt32 i = 0; i < nCount; ++i) 1203 { 1204 const OSQLParseNode* pChild = _pNode->getChild(i); 1205 traverseParameters( pChild ); 1206 } 1207 } 1208 //----------------------------------------------------------------------------- 1209 bool OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode) 1210 { 1211 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectionCriteria" ); 1212 if ( pSelectNode == NULL ) 1213 return false; 1214 1215 1216 // Parse Tree analysieren (je nach Statement-Typ) 1217 // und Zeiger auf WHERE-Klausel setzen: 1218 OSQLParseNode * pWhereClause = NULL; 1219 1220 if (m_eStatementType == SQL_STATEMENT_SELECT) 1221 { 1222 if(SQL_ISRULE(pSelectNode,union_statement)) 1223 { 1224 return traverseSelectionCriteria( pSelectNode->getChild( 0 ) ) 1225 && traverseSelectionCriteria( pSelectNode->getChild( 3 ) ); 1226 } 1227 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!"); 1228 1229 OSQLParseNode * pTableExp = pSelectNode->getChild(3); 1230 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1231 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!"); 1232 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 1233 1234 pWhereClause = pTableExp->getChild(1); 1235 } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) { 1236 OSL_ENSURE(pSelectNode->count() == 5,"OSQLParseTreeIterator: error in parse tree!"); 1237 pWhereClause = pSelectNode->getChild(4); 1238 } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) { 1239 OSL_ENSURE(pSelectNode->count() == 4,"OSQLParseTreeIterator: error in parse tree!"); 1240 pWhereClause = pSelectNode->getChild(3); 1241 } else if (SQL_ISRULE(pSelectNode,delete_statement_positioned)) { 1242 // nyi 1243 OSL_ASSERT("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi"); 1244 } else { 1245 // Anderes Statement. Keine Selektionskriterien. 1246 return false; 1247 } 1248 1249 if (! SQL_ISRULE(pWhereClause,where_clause)) { 1250 // Die Where Clause ist meistens optional, d. h. es koennte sich auch 1251 // um "optional_where_clause" handeln. 1252 OSL_ENSURE(SQL_ISRULE(pWhereClause,opt_where_clause),"OSQLParseTreeIterator: error in parse tree!"); 1253 return false; 1254 } 1255 1256 // Wenn es aber eine where_clause ist, dann darf sie nicht leer sein: 1257 OSL_ENSURE(pWhereClause->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); 1258 1259 OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1); 1260 OSL_ENSURE(pComparisonPredicate != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1261 1262 // 1263 // Und nun die Vergleichskriterien abarbeiten (rekursiv, alles ist erstmal ein OR-Kriterium): 1264 // 1265 1266 traverseORCriteria(pComparisonPredicate); 1267 1268 return !hasErrors(); 1269 } 1270 1271 //----------------------------------------------------------------------------- 1272 void OSQLParseTreeIterator::traverseORCriteria(OSQLParseNode * pSearchCondition) 1273 { 1274 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseORCriteria" ); 1275 1276 1277 if ( 1278 pSearchCondition->count() == 3 && 1279 SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && 1280 SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")") 1281 ) 1282 { 1283 // Runde Klammern um den Ausdruck 1284 traverseORCriteria(pSearchCondition->getChild(1)); 1285 } else if (SQL_ISRULE(pSearchCondition,search_condition) && 1286 pSearchCondition->count() == 3 && 1287 SQL_ISTOKEN(pSearchCondition->getChild(1),OR)) 1288 { 1289 // OR-Verknuepfung: 1290 1291 for (int i = 0; i < 3; i++) { 1292 if (i == 1) continue; // Schluesselwort OR ueberspringen 1293 1294 // Ist das erste Element wieder eine OR-Verknuepfung? 1295 if (i == 0 && 1296 SQL_ISRULE(pSearchCondition->getChild(0),search_condition) && 1297 pSearchCondition->getChild(0)->count() == 3 && 1298 SQL_ISTOKEN(pSearchCondition->getChild(0)->getChild(1),OR)) 1299 { 1300 // Dann rekursiv absteigen ... 1301 traverseORCriteria(pSearchCondition->getChild(0)); 1302 1303 } else { 1304 // AND-Kriterien ... 1305 traverseANDCriteria(pSearchCondition->getChild(i)); 1306 // if (! aIteratorStatus.IsSuccessful()) break; 1307 } 1308 1309 // if (! aIteratorStatus.IsSuccessful()) break; 1310 } 1311 } else { 1312 // Nur *ein* Kriterium oder eine AND-Verknuepfung von Kriterien. 1313 // Direkt die AND-Kriterien behandeln. 1314 traverseANDCriteria(pSearchCondition); 1315 // if (! aIteratorStatus.IsSuccessful()) return; 1316 } 1317 1318 // Fehler einfach weiterreichen. 1319 } 1320 1321 //----------------------------------------------------------------------------- 1322 void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition) 1323 { 1324 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseANDCriteria" ); 1325 1326 1327 if ( 1328 SQL_ISRULE(pSearchCondition,boolean_primary) && 1329 pSearchCondition->count() == 3 && 1330 SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && 1331 SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")") 1332 ) 1333 { 1334 // Runde Klammern 1335 traverseANDCriteria(pSearchCondition->getChild(1)); 1336 } 1337 // Das erste Element ist eine OR-Verknuepfung 1338 else if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 ) 1339 { 1340 // Dann rekursiv absteigen (dieselbe Row benutzen) ... 1341 traverseORCriteria(pSearchCondition->getChild(0)); 1342 // if (! aIteratorStatus.IsSuccessful()) 1343 // return; 1344 1345 // Und mit dem rechten Child weitermachen: 1346 traverseANDCriteria(pSearchCondition->getChild(2)); 1347 } 1348 // Das erste Element ist (wieder) eine AND-Verknuepfung 1349 else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 ) 1350 { 1351 // Dann rekursiv absteigen (dieselbe Row benutzen) ... 1352 traverseANDCriteria(pSearchCondition->getChild(0)); 1353 // if (! aIteratorStatus.IsSuccessful()) 1354 // return; 1355 1356 // Und mit dem rechten Child weitermachen: 1357 traverseANDCriteria(pSearchCondition->getChild(2)); 1358 } 1359 // Sonst einzelne Suchkriterien wie =, !=, ..., LIKE, IS NULL usw. behandeln: 1360 else if (SQL_ISRULE(pSearchCondition,comparison_predicate) ) 1361 { 1362 ::rtl::OUString aValue; 1363 pSearchCondition->getChild(2)->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1364 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pSearchCondition->getChild(2)); 1365 impl_fillJoinConditions(pSearchCondition); 1366 // if (! aIteratorStatus.IsSuccessful()) 1367 // return; 1368 } 1369 else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) 1370 { 1371 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); 1372 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); 1373 1374 sal_Int32 nCurentPos = pPart2->count()-2; 1375 1376 OSQLParseNode * pNum_value_exp = pPart2->getChild(nCurentPos); 1377 OSQLParseNode * pOptEscape = pPart2->getChild(nCurentPos+1); 1378 1379 OSL_ENSURE(pNum_value_exp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1380 OSL_ENSURE(pOptEscape != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1381 1382 if (pOptEscape->count() != 0) 1383 { 1384 // aIteratorStatus.setStatementTooComplex(); 1385 return; 1386 } 1387 1388 ::rtl::OUString aValue; 1389 OSQLParseNode * pParam = NULL; 1390 if (SQL_ISRULE(pNum_value_exp,parameter)) 1391 pParam = pNum_value_exp; 1392 else if(pNum_value_exp->isToken()) 1393 // Normaler Wert 1394 aValue = pNum_value_exp->getTokenValue(); 1395 else 1396 { 1397 pNum_value_exp->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1398 pParam = pNum_value_exp; 1399 } 1400 1401 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pParam); 1402 // if (! aIteratorStatus.IsSuccessful()) 1403 // return; 1404 } 1405 else if (SQL_ISRULE(pSearchCondition,in_predicate)) 1406 { 1407 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); 1408 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); 1409 1410 traverseORCriteria(pSearchCondition->getChild(0)); 1411 // if (! aIteratorStatus.IsSuccessful()) return; 1412 1413 OSQLParseNode* pChild = pPart2->getChild(2); 1414 if ( SQL_ISRULE(pChild->getChild(0),subquery) ) 1415 { 1416 traverseTableNames( *m_pImpl->m_pSubTables ); 1417 traverseSelectionCriteria(pChild->getChild(0)->getChild(1)); 1418 } 1419 else 1420 { // '(' value_exp_commalist ')' 1421 pChild = pChild->getChild(1); 1422 sal_Int32 nCount = pChild->count(); 1423 for (sal_Int32 i=0; i < nCount; ++i) 1424 { 1425 traverseANDCriteria(pChild->getChild(i)); 1426 } 1427 } 1428 } 1429 else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) 1430 { 1431 OSL_ENSURE(pSearchCondition->count() == 2,"OSQLParseTreeIterator: error in parse tree!"); 1432 const OSQLParseNode* pPart2 = pSearchCondition->getChild(1); 1433 (void)pPart2; 1434 OSL_ENSURE(SQL_ISTOKEN(pPart2->getChild(0),IS),"OSQLParseTreeIterator: error in parse tree!"); 1435 1436 ::rtl::OUString aString; 1437 traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL); 1438 // if (! aIteratorStatus.IsSuccessful()) return; 1439 } 1440 else if (SQL_ISRULE(pSearchCondition,num_value_exp) || SQL_ISRULE(pSearchCondition,term)) 1441 { 1442 ::rtl::OUString aString; 1443 traverseOnePredicate(pSearchCondition->getChild(0),aString,pSearchCondition->getChild(0)); 1444 traverseOnePredicate(pSearchCondition->getChild(2),aString,pSearchCondition->getChild(2)); 1445 } 1446 // Fehler einfach weiterreichen. 1447 } 1448 //----------------------------------------------------------------------------- 1449 void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode 1450 ,const OSQLParseNode* _pParentNode 1451 ,const ::rtl::OUString& _aColumnName 1452 ,const ::rtl::OUString& _aTableRange 1453 ,const ::rtl::OUString& _rColumnAlias) 1454 { 1455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameter" ); 1456 if ( !SQL_ISRULE( _pParseNode, parameter ) ) 1457 return; 1458 1459 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters ) 1460 // parameters not to be included in the traversal 1461 return; 1462 1463 OSL_ENSURE(_pParseNode->count() > 0,"OSQLParseTreeIterator: error in parse tree!"); 1464 OSQLParseNode * pMark = _pParseNode->getChild(0); 1465 ::rtl::OUString sParameterName; 1466 1467 if (SQL_ISPUNCTUATION(pMark,"?")) 1468 { 1469 sParameterName = _rColumnAlias.getLength() 1470 ? _rColumnAlias 1471 : _aColumnName.getLength() 1472 ? _aColumnName 1473 : ::rtl::OUString::createFromAscii("?"); 1474 } 1475 else if (SQL_ISPUNCTUATION(pMark,":")) 1476 { 1477 sParameterName = _pParseNode->getChild(1)->getTokenValue(); 1478 } 1479 else if (SQL_ISPUNCTUATION(pMark,"[")) 1480 { 1481 sParameterName = _pParseNode->getChild(1)->getTokenValue(); 1482 } 1483 else 1484 { 1485 OSL_ASSERT("OSQLParseTreeIterator: error in parse tree!"); 1486 } 1487 1488 // found a parameter 1489 if ( _pParentNode && (SQL_ISRULE(_pParentNode,general_set_fct) || SQL_ISRULE(_pParentNode,set_fct_spec)) ) 1490 {// found a function as column_ref 1491 ::rtl::OUString sFunctionName; 1492 _pParentNode->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 1493 const sal_uInt32 nCount = _pParentNode->count(); 1494 sal_uInt32 i = 0; 1495 for(; i < nCount;++i) 1496 { 1497 if ( _pParentNode->getChild(i) == _pParseNode ) 1498 break; 1499 } 1500 sal_Int32 nType = ::connectivity::OSQLParser::getFunctionParameterType( _pParentNode->getChild(0)->getTokenID(), i-1); 1501 1502 OParseColumn* pColumn = new OParseColumn( sParameterName, 1503 ::rtl::OUString(), 1504 ::rtl::OUString(), 1505 ::rtl::OUString(), 1506 ColumnValue::NULLABLE_UNKNOWN, 1507 0, 1508 0, 1509 nType, 1510 sal_False, 1511 sal_False, 1512 isCaseSensitive()); 1513 pColumn->setFunction(sal_True); 1514 pColumn->setAggregateFunction(sal_True); 1515 pColumn->setRealName(sFunctionName); 1516 m_aParameters->get().push_back(pColumn); 1517 } 1518 else 1519 { 1520 sal_Bool bNotFound = sal_True; 1521 OSQLColumns::Vector::const_iterator aIter = ::connectivity::find( 1522 m_aSelectColumns->get().begin(), 1523 m_aSelectColumns->get().end(), 1524 _aColumnName,::comphelper::UStringMixEqual( isCaseSensitive() ) 1525 ); 1526 if(aIter != m_aSelectColumns->get().end()) 1527 { 1528 OParseColumn* pNewColumn = new OParseColumn(*aIter,isCaseSensitive()); 1529 pNewColumn->setName(sParameterName); 1530 pNewColumn->setRealName(_aColumnName); 1531 m_aParameters->get().push_back(pNewColumn); 1532 bNotFound = sal_False; 1533 } 1534 else if(_aColumnName.getLength())// search in the tables for the right one 1535 { 1536 1537 Reference<XPropertySet> xColumn = findColumn( _aColumnName, _aTableRange, true ); 1538 1539 if ( xColumn.is() ) 1540 { 1541 OParseColumn* pNewColumn = new OParseColumn(xColumn,isCaseSensitive()); 1542 pNewColumn->setName(sParameterName); 1543 pNewColumn->setRealName(_aColumnName); 1544 m_aParameters->get().push_back(pNewColumn); 1545 bNotFound = sal_False; 1546 } 1547 } 1548 if ( bNotFound ) 1549 { 1550 sal_Int32 nType = DataType::VARCHAR; 1551 OSQLParseNode* pParent = _pParentNode ? _pParentNode->getParent() : NULL; 1552 if ( pParent && (SQL_ISRULE(pParent,general_set_fct) || SQL_ISRULE(pParent,set_fct_spec)) ) 1553 { 1554 const sal_uInt32 nCount = _pParentNode->count(); 1555 sal_uInt32 i = 0; 1556 for(; i < nCount;++i) 1557 { 1558 if ( _pParentNode->getChild(i) == _pParseNode ) 1559 break; 1560 } 1561 nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1); 1562 } 1563 1564 ::rtl::OUString aNewColName( getUniqueColumnName( sParameterName ) ); 1565 1566 OParseColumn* pColumn = new OParseColumn(aNewColName, 1567 ::rtl::OUString(), 1568 ::rtl::OUString(), 1569 ::rtl::OUString(), 1570 ColumnValue::NULLABLE_UNKNOWN, 1571 0, 1572 0, 1573 nType, 1574 sal_False, 1575 sal_False, 1576 isCaseSensitive() ); 1577 pColumn->setName(aNewColName); 1578 pColumn->setRealName(sParameterName); 1579 m_aParameters->get().push_back(pColumn); 1580 } 1581 } 1582 } 1583 //----------------------------------------------------------------------------- 1584 void OSQLParseTreeIterator::traverseOnePredicate( 1585 OSQLParseNode * pColumnRef, 1586 ::rtl::OUString& rValue, 1587 OSQLParseNode * pParseNode) 1588 { 1589 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOnePredicate" ); 1590 if ( !pParseNode ) 1591 return; 1592 1593 // Column-Name (und TableRange): 1594 ::rtl::OUString aColumnName, aTableRange, sColumnAlias; 1595 getColumnRange( pColumnRef, aColumnName, aTableRange, sColumnAlias); 1596 1597 ::rtl::OUString aName; 1598 1599 /*if (SQL_ISRULE(pParseNode,parameter)) 1600 traverseParameter( pParseNode, pColumnRef, aColumnName, aTableRange, sColumnAlias ); 1601 else */if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange): 1602 getColumnRange(pParseNode,aName,rValue); 1603 else 1604 { 1605 traverseORCriteria(pParseNode); 1606 // if (! aIteratorStatus.IsSuccessful()) return; 1607 } 1608 } 1609 1610 //----------------------------------------------------------------------------- 1611 void OSQLParseTreeIterator::traverseSome( sal_uInt32 _nIncludeMask ) 1612 { 1613 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSome" ); 1614 impl_traverse( _nIncludeMask ); 1615 } 1616 1617 //----------------------------------------------------------------------------- 1618 void OSQLParseTreeIterator::traverseAll() 1619 { 1620 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseAll" ); 1621 impl_traverse( All ); 1622 } 1623 1624 //----------------------------------------------------------------------------- 1625 void OSQLParseTreeIterator::impl_traverse( sal_uInt32 _nIncludeMask ) 1626 { 1627 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_traverse" ); 1628 impl_resetErrors(); 1629 m_pImpl->m_nIncludeMask = _nIncludeMask; 1630 1631 if ( !traverseTableNames( *m_pImpl->m_pTables ) ) 1632 return; 1633 1634 switch ( m_eStatementType ) 1635 { 1636 case SQL_STATEMENT_SELECT: 1637 { 1638 const OSQLParseNode* pSelectNode = m_pParseTree; 1639 traverseParameters( pSelectNode ); 1640 if ( !traverseSelectColumnNames( pSelectNode ) 1641 || !traverseOrderByColumnNames( pSelectNode ) 1642 || !traverseGroupByColumnNames( pSelectNode ) 1643 || !traverseSelectionCriteria( pSelectNode ) 1644 ) 1645 return; 1646 } 1647 break; 1648 case SQL_STATEMENT_CREATE_TABLE: 1649 { 1650 //0 | 1 | 2 |3| 4 |5 1651 //create table sc.foo ( a char(20), b char ) 1652 const OSQLParseNode* pCreateNode = m_pParseTree->getChild(4); 1653 traverseCreateColumns(pCreateNode); 1654 } 1655 break; 1656 case SQL_STATEMENT_INSERT: 1657 break; 1658 default: 1659 break; 1660 } 1661 } 1662 1663 // Dummy-Implementationen: 1664 1665 //----------------------------------------------------------------------------- 1666 OSQLTable OSQLParseTreeIterator::impl_createTableObject( const ::rtl::OUString& rTableName, 1667 const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName ) 1668 { 1669 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_createTableObject" ); 1670 OSL_PRECOND( m_eStatementType == SQL_STATEMENT_CREATE_TABLE, 1671 "OSQLParseTreeIterator::impl_createTableObject: only to be called for CREATE TABLE statements!" ); 1672 // (in all other cases, m_pTables is to contain the table objects as obtained from the tables 1673 // container of the connection (m_xTablesContainer) 1674 1675 OSQLTable aReturnTable = new OTable( 1676 NULL, 1677 sal_False, 1678 rTableName, 1679 ::rtl::OUString::createFromAscii("Table"), 1680 ::rtl::OUString::createFromAscii("New Created Table"), 1681 rSchemaName, 1682 rCatalogName 1683 ); 1684 return aReturnTable; 1685 } 1686 //----------------------------------------------------------------------------- 1687 void OSQLParseTreeIterator::appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable) 1688 { 1689 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::appendColumns" ); 1690 1691 if (!_rTable.is()) 1692 return; 1693 1694 Reference<XNameAccess> xColumns = _rTable->getColumns(); 1695 if ( !xColumns.is() ) 1696 return; 1697 1698 Sequence< ::rtl::OUString > aColNames = xColumns->getElementNames(); 1699 const ::rtl::OUString* pBegin = aColNames.getConstArray(); 1700 const ::rtl::OUString* pEnd = pBegin + aColNames.getLength(); 1701 1702 for(;pBegin != pEnd;++pBegin) 1703 { 1704 1705 ::rtl::OUString aName(getUniqueColumnName(*pBegin)); 1706 Reference< XPropertySet > xColumn; 1707 if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is()) 1708 { 1709 OParseColumn* pColumn = new OParseColumn(aName 1710 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME))) 1711 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE))) 1712 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION))) 1713 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE))) 1714 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))) 1715 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE))) 1716 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE))) 1717 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))) 1718 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY))) 1719 , isCaseSensitive() ); 1720 1721 pColumn->setTableName(_rTableAlias); 1722 pColumn->setRealName(*pBegin); 1723 Reference< XPropertySet> xCol = pColumn; 1724 _rColumns->get().push_back(xCol); 1725 } 1726 else 1727 impl_appendError( IParseContext::ERROR_INVALID_COLUMN, pBegin, &_rTableAlias ); 1728 } 1729 } 1730 //----------------------------------------------------------------------------- 1731 void OSQLParseTreeIterator::setSelectColumnName(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString & rColumnName,const ::rtl::OUString & rColumnAlias, const ::rtl::OUString & rTableRange,sal_Bool bFkt,sal_Int32 _nType,sal_Bool bAggFkt) 1732 { 1733 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setSelectColumnName" ); 1734 if(rColumnName.toChar() == '*' && !rTableRange.getLength()) 1735 { // SELECT * ... 1736 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!"); 1737 for(ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end();++aIter) 1738 appendColumns(_rColumns,aIter->first,aIter->second); 1739 } 1740 else if( rColumnName.toChar() == '*' && rTableRange.getLength() ) 1741 { // SELECT <table>.* 1742 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!"); 1743 ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange); 1744 1745 if(aFind != m_pImpl->m_pTables->end()) 1746 appendColumns(_rColumns,rTableRange,aFind->second); 1747 } 1748 else if ( !rTableRange.getLength() ) 1749 { // SELECT <something> ... 1750 // without table specified 1751 if ( !bFkt ) 1752 { 1753 Reference< XPropertySet> xNewColumn; 1754 1755 for ( OSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter ) 1756 { 1757 if ( !aIter->second.is() ) 1758 continue; 1759 1760 Reference<XNameAccess> xColumns = aIter->second->getColumns(); 1761 Reference< XPropertySet > xColumn; 1762 if ( !xColumns->hasByName( rColumnName ) 1763 || !( xColumns->getByName( rColumnName ) >>= xColumn ) 1764 ) 1765 continue; 1766 1767 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias)); 1768 1769 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive()); 1770 xNewColumn = pColumn; 1771 pColumn->setTableName(aIter->first); 1772 pColumn->setName(aNewColName); 1773 pColumn->setRealName(rColumnName); 1774 1775 break; 1776 } 1777 1778 if ( !xNewColumn.is() ) 1779 { 1780 // no function (due to the above !bFkt), no existing column 1781 // => assume an expression 1782 ::rtl::OUString aNewColName( getUniqueColumnName( rColumnAlias ) ); 1783 // did not find a column with this name in any of the tables 1784 OParseColumn* pColumn = new OParseColumn( 1785 aNewColName, 1786 ::rtl::OUString::createFromAscii( "VARCHAR" ), 1787 // TODO: does this match with _nType? 1788 // Or should be fill this from the getTypeInfo of the connection? 1789 ::rtl::OUString(), 1790 ::rtl::OUString(), 1791 ColumnValue::NULLABLE_UNKNOWN, 1792 0, 1793 0, 1794 _nType, 1795 sal_False, 1796 sal_False, 1797 isCaseSensitive() 1798 ); 1799 1800 xNewColumn = pColumn; 1801 pColumn->setRealName( rColumnName ); 1802 } 1803 1804 _rColumns->get().push_back( xNewColumn ); 1805 } 1806 else 1807 { 1808 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias)); 1809 1810 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(), 1811 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive()); 1812 pColumn->setFunction(sal_True); 1813 pColumn->setAggregateFunction(bAggFkt); 1814 pColumn->setRealName(rColumnName); 1815 1816 Reference< XPropertySet> xCol = pColumn; 1817 _rColumns->get().push_back(xCol); 1818 } 1819 } 1820 else // ColumnName und Tablename vorhanden 1821 { 1822 ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange); 1823 1824 sal_Bool bError = sal_False; 1825 if (aFind != m_pImpl->m_pTables->end() && aFind->second.is()) 1826 { 1827 if (bFkt) 1828 { 1829 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias)); 1830 1831 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(), 1832 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive()); 1833 pColumn->setFunction(sal_True); 1834 pColumn->setAggregateFunction(bAggFkt); 1835 pColumn->setRealName(rColumnName); 1836 pColumn->setTableName(aFind->first); 1837 1838 Reference< XPropertySet> xCol = pColumn; 1839 _rColumns->get().push_back(xCol); 1840 } 1841 else 1842 { 1843 Reference< XPropertySet > xColumn; 1844 if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn)) 1845 { 1846 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias)); 1847 1848 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive()); 1849 pColumn->setName(aNewColName); 1850 pColumn->setRealName(rColumnName); 1851 pColumn->setTableName(aFind->first); 1852 1853 Reference< XPropertySet> xCol = pColumn; 1854 _rColumns->get().push_back(xCol); 1855 } 1856 else 1857 bError = sal_True; 1858 } 1859 } 1860 else 1861 bError = sal_True; 1862 1863 // Tabelle existiert nicht oder Feld nicht vorhanden 1864 if (bError) 1865 { 1866 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias)); 1867 1868 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),::rtl::OUString(), 1869 ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,isCaseSensitive()); 1870 pColumn->setFunction(sal_True); 1871 pColumn->setAggregateFunction(bAggFkt); 1872 1873 Reference< XPropertySet> xCol = pColumn; 1874 _rColumns->get().push_back(xCol); 1875 } 1876 } 1877 } 1878 //----------------------------------------------------------------------------- 1879 ::rtl::OUString OSQLParseTreeIterator::getUniqueColumnName(const ::rtl::OUString & rColumnName) const 1880 { 1881 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getUniqueColumnName" ); 1882 ::rtl::OUString aAlias(rColumnName); 1883 1884 OSQLColumns::Vector::const_iterator aIter = find( 1885 m_aSelectColumns->get().begin(), 1886 m_aSelectColumns->get().end(), 1887 aAlias, 1888 ::comphelper::UStringMixEqual( isCaseSensitive() ) 1889 ); 1890 sal_Int32 i=1; 1891 while(aIter != m_aSelectColumns->get().end()) 1892 { 1893 (aAlias = rColumnName) += ::rtl::OUString::valueOf(i++); 1894 aIter = find( 1895 m_aSelectColumns->get().begin(), 1896 m_aSelectColumns->get().end(), 1897 aAlias, 1898 ::comphelper::UStringMixEqual( isCaseSensitive() ) 1899 ); 1900 } 1901 return aAlias; 1902 } 1903 //----------------------------------------------------------------------------- 1904 void OSQLParseTreeIterator::setOrderByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange,sal_Bool bAscending) 1905 { 1906 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setOrderByColumnName" ); 1907 Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false ); 1908 if ( xColumn.is() ) 1909 m_aOrderColumns->get().push_back(new OOrderColumn( xColumn, rTableRange, isCaseSensitive(), bAscending ) ); 1910 else 1911 { 1912 sal_Int32 nId = rColumnName.toInt32(); 1913 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) ) 1914 m_aOrderColumns->get().push_back( new OOrderColumn( ( m_aSelectColumns->get() )[nId-1], isCaseSensitive(), bAscending ) ); 1915 } 1916 1917 #ifdef SQL_TEST_PARSETREEITERATOR 1918 cout << "OSQLParseTreeIterator::setOrderByColumnName: " 1919 << (const char *) rColumnName << ", " 1920 << (const char *) rTableRange << ", " 1921 << (bAscending ? "sal_True" : "sal_False") 1922 << "\n"; 1923 #endif 1924 } 1925 //----------------------------------------------------------------------------- 1926 void OSQLParseTreeIterator::setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange) 1927 { 1928 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setGroupByColumnName" ); 1929 Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false ); 1930 if ( xColumn.is() ) 1931 m_aGroupColumns->get().push_back(new OParseColumn(xColumn,isCaseSensitive())); 1932 else 1933 { 1934 sal_Int32 nId = rColumnName.toInt32(); 1935 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) ) 1936 m_aGroupColumns->get().push_back(new OParseColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive())); 1937 } 1938 1939 #ifdef SQL_TEST_PARSETREEITERATOR 1940 cout << "OSQLParseTreeIterator::setOrderByColumnName: " 1941 << (const char *) rColumnName << ", " 1942 << (const char *) rTableRange << ", " 1943 << (bAscending ? "sal_True" : "sal_False") 1944 << "\n"; 1945 #endif 1946 } 1947 1948 //----------------------------------------------------------------------------- 1949 const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const 1950 { 1951 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getWhereTree" ); 1952 1953 1954 if (!m_pParseTree) 1955 return NULL; 1956 1957 // Parse Tree analysieren (je nach Statement-Typ) 1958 // und Zeiger auf WHERE-Klausel setzen: 1959 OSQLParseNode * pWhereClause = NULL; 1960 if(getStatementType() == SQL_STATEMENT_SELECT) 1961 { 1962 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!"); 1963 OSQLParseNode * pTableExp = m_pParseTree->getChild(3); 1964 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1965 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!"); 1966 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 1967 1968 pWhereClause = pTableExp->getChild(1); 1969 } 1970 else if (SQL_ISRULE(m_pParseTree,update_statement_searched) || 1971 SQL_ISRULE(m_pParseTree,delete_statement_searched)) 1972 { 1973 pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1); 1974 } 1975 if(pWhereClause->count() != 2) 1976 pWhereClause = NULL; 1977 return pWhereClause; 1978 } 1979 1980 //----------------------------------------------------------------------------- 1981 const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const 1982 { 1983 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getOrderTree" ); 1984 1985 1986 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) 1987 return NULL; 1988 1989 // Parse Tree analysieren (je nach Statement-Typ) 1990 // und Zeiger auf ORDER-Klausel setzen: 1991 OSQLParseNode * pOrderClause = NULL; 1992 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!"); 1993 OSQLParseNode * pTableExp = m_pParseTree->getChild(3); 1994 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 1995 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!"); 1996 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 1997 1998 pOrderClause = pTableExp->getChild(ORDER_BY_CHILD_POS); 1999 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: 2000 if(pOrderClause->count() != 3) 2001 pOrderClause = NULL; 2002 return pOrderClause; 2003 } 2004 //----------------------------------------------------------------------------- 2005 const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const 2006 { 2007 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getGroupByTree" ); 2008 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) 2009 return NULL; 2010 2011 // Parse Tree analysieren (je nach Statement-Typ) 2012 // und Zeiger auf ORDER-Klausel setzen: 2013 OSQLParseNode * pGroupClause = NULL; 2014 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!"); 2015 OSQLParseNode * pTableExp = m_pParseTree->getChild(3); 2016 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 2017 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!"); 2018 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 2019 2020 pGroupClause = pTableExp->getChild(2); 2021 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: 2022 if(pGroupClause->count() != 3) 2023 pGroupClause = NULL; 2024 return pGroupClause; 2025 } 2026 //----------------------------------------------------------------------------- 2027 const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const 2028 { 2029 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) 2030 return NULL; 2031 2032 // Parse Tree analysieren (je nach Statement-Typ) 2033 // und Zeiger auf ORDER-Klausel setzen: 2034 OSQLParseNode * pHavingClause = NULL; 2035 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!"); 2036 OSQLParseNode * pTableExp = m_pParseTree->getChild(3); 2037 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!"); 2038 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!"); 2039 OSL_ENSURE(pTableExp->count() == TABLE_EXPRESSION_CHILD_COUNT,"OSQLParseTreeIterator: error in parse tree!"); 2040 2041 pHavingClause = pTableExp->getChild(3); 2042 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: 2043 if(pHavingClause->count() < 1) 2044 pHavingClause = NULL; 2045 return pHavingClause; 2046 } 2047 // ----------------------------------------------------------------------------- 2048 sal_Bool OSQLParseTreeIterator::isTableNode(const OSQLParseNode* _pTableNode) const 2049 { 2050 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isTableNode" ); 2051 return _pTableNode && (SQL_ISRULE(_pTableNode,catalog_name) || 2052 SQL_ISRULE(_pTableNode,schema_name) || 2053 SQL_ISRULE(_pTableNode,table_name)); 2054 } 2055 // ----------------------------------------------------------------------------- 2056 const OSQLParseNode* OSQLParseTreeIterator::getSimpleWhereTree() const 2057 { 2058 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleWhereTree" ); 2059 const OSQLParseNode* pNode = getWhereTree(); 2060 return pNode ? pNode->getChild(1) : NULL; 2061 } 2062 // ----------------------------------------------------------------------------- 2063 const OSQLParseNode* OSQLParseTreeIterator::getSimpleOrderTree() const 2064 { 2065 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleOrderTree" ); 2066 const OSQLParseNode* pNode = getOrderTree(); 2067 return pNode ? pNode->getChild(2) : NULL; 2068 } 2069 // ----------------------------------------------------------------------------- 2070 const OSQLParseNode* OSQLParseTreeIterator::getSimpleGroupByTree() const 2071 { 2072 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleGroupByTree" ); 2073 const OSQLParseNode* pNode = getGroupByTree(); 2074 return pNode ? pNode->getChild(2) : NULL; 2075 } 2076 // ----------------------------------------------------------------------------- 2077 const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const 2078 { 2079 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleHavingTree" ); 2080 const OSQLParseNode* pNode = getHavingTree(); 2081 return pNode ? pNode->getChild(1) : NULL; 2082 } 2083 2084 // ----------------------------------------------------------------------------- 2085 Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables ) 2086 { 2087 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" ); 2088 Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange ); 2089 if ( !xColumn.is() && _bLookInSubTables ) 2090 xColumn = findColumn( *m_pImpl->m_pSubTables, rColumnName, rTableRange ); 2091 return xColumn; 2092 } 2093 2094 // ----------------------------------------------------------------------------- 2095 Reference< XPropertySet > OSQLParseTreeIterator::findColumn(const OSQLTables& _rTables,const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange) 2096 { 2097 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" ); 2098 Reference< XPropertySet > xColumn; 2099 if ( rTableRange.getLength() ) 2100 { 2101 ConstOSQLTablesIterator aFind = _rTables.find(rTableRange); 2102 2103 if ( aFind != _rTables.end() 2104 && aFind->second.is() 2105 && aFind->second->getColumns().is() 2106 && aFind->second->getColumns()->hasByName(rColumnName) ) 2107 aFind->second->getColumns()->getByName(rColumnName) >>= xColumn; 2108 } 2109 if ( !xColumn.is() ) 2110 { 2111 OSQLTables::const_iterator aEnd = _rTables.end(); 2112 for(OSQLTables::const_iterator aIter = _rTables.begin(); aIter != aEnd; ++aIter) 2113 { 2114 if ( aIter->second.is() ) 2115 { 2116 Reference<XNameAccess> xColumns = aIter->second->getColumns(); 2117 if( xColumns.is() && xColumns->hasByName(rColumnName) && (xColumns->getByName(rColumnName) >>= xColumn) ) 2118 { 2119 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!"); 2120 break; // diese Column darf nur einmal vorkommen 2121 } 2122 } 2123 } 2124 } 2125 return xColumn; 2126 } 2127 2128 // ----------------------------------------------------------------------------- 2129 void OSQLParseTreeIterator::impl_appendError( IParseContext::ErrorCode _eError, const ::rtl::OUString* _pReplaceToken1, const ::rtl::OUString* _pReplaceToken2 ) 2130 { 2131 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" ); 2132 ::rtl::OUString sErrorMessage = m_rParser.getContext().getErrorMessage( _eError ); 2133 if ( _pReplaceToken1 ) 2134 { 2135 bool bTwoTokens = ( _pReplaceToken2 != NULL ); 2136 const sal_Char* pPlaceHolder1 = bTwoTokens ? "#1" : "#"; 2137 const ::rtl::OUString sPlaceHolder1 = ::rtl::OUString::createFromAscii( pPlaceHolder1 ); 2138 2139 sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( sPlaceHolder1 ), sPlaceHolder1.getLength(), *_pReplaceToken1 ); 2140 if ( _pReplaceToken2 ) 2141 sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( ::rtl::OUString::createFromAscii( "#2" ) ), 2, *_pReplaceToken2 ); 2142 } 2143 2144 impl_appendError( SQLException( 2145 sErrorMessage, NULL, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ) ); 2146 } 2147 2148 // ----------------------------------------------------------------------------- 2149 void OSQLParseTreeIterator::impl_appendError( const SQLException& _rError ) 2150 { 2151 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" ); 2152 if ( m_aErrors.Message.getLength() ) 2153 { 2154 SQLException* pErrorChain = &m_aErrors; 2155 while ( pErrorChain->NextException.hasValue() ) 2156 pErrorChain = static_cast< SQLException* >( pErrorChain->NextException.pData ); 2157 pErrorChain->NextException <<= _rError; 2158 } 2159 else 2160 m_aErrors = _rError; 2161 } 2162 // ----------------------------------------------------------------------------- 2163 sal_Int32 OSQLParseTreeIterator::getFunctionReturnType(const OSQLParseNode* _pNode ) 2164 { 2165 sal_Int32 nType = DataType::OTHER; 2166 ::rtl::OUString sFunctionName; 2167 if ( SQL_ISRULE(_pNode,length_exp) ) 2168 { 2169 _pNode->getChild(0)->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 2170 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() ); 2171 } 2172 else if ( SQL_ISRULE(_pNode,num_value_exp) || SQL_ISRULE(_pNode,term) || SQL_ISRULE(_pNode,factor) ) 2173 { 2174 nType = DataType::DOUBLE; 2175 } 2176 else 2177 { 2178 _pNode->getChild(0)->parseNodeToStr(sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False ); 2179 2180 // MIN and MAX have another return type, we have to check the expression itself. 2181 // @see http://qa.openoffice.org/issues/show_bug.cgi?id=99566 2182 if ( SQL_ISRULE(_pNode,general_set_fct) && (SQL_ISTOKEN(_pNode->getChild(0),MIN) || SQL_ISTOKEN(_pNode->getChild(0),MAX) )) 2183 { 2184 const OSQLParseNode* pValueExp = _pNode->getChild(3); 2185 if (SQL_ISRULE(pValueExp,column_ref)) 2186 { 2187 ::rtl::OUString sColumnName; 2188 ::rtl::OUString aTableRange; 2189 getColumnRange(pValueExp,sColumnName,aTableRange); 2190 OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein"); 2191 Reference<XPropertySet> xColumn = findColumn( sColumnName, aTableRange, true ); 2192 2193 if ( xColumn.is() ) 2194 { 2195 xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TYPE)) >>= nType; 2196 } 2197 } 2198 else 2199 { 2200 if ( SQL_ISRULE(pValueExp,num_value_exp) || SQL_ISRULE(pValueExp,term) || SQL_ISRULE(pValueExp,factor) ) 2201 { 2202 nType = DataType::DOUBLE; 2203 } 2204 else if ( SQL_ISRULE(pValueExp,datetime_primary) ) 2205 { 2206 switch(pValueExp->getChild(0)->getTokenID() ) 2207 { 2208 case SQL_TOKEN_CURRENT_DATE: 2209 nType = DataType::DATE; 2210 break; 2211 case SQL_TOKEN_CURRENT_TIME: 2212 nType = DataType::TIME; 2213 break; 2214 case SQL_TOKEN_CURRENT_TIMESTAMP: 2215 nType = DataType::TIMESTAMP; 2216 break; 2217 } 2218 } 2219 else if ( SQL_ISRULE(pValueExp,value_exp_primary) ) 2220 { 2221 nType = getFunctionReturnType(pValueExp->getChild(1)); 2222 } 2223 else if ( SQL_ISRULE(pValueExp,concatenation) 2224 || SQL_ISRULE(pValueExp,char_factor) 2225 || SQL_ISRULE(pValueExp,bit_value_fct) 2226 || SQL_ISRULE(pValueExp,char_value_fct) 2227 || SQL_ISRULE(pValueExp,char_substring_fct) 2228 || SQL_ISRULE(pValueExp,fold) 2229 || SQL_ISTOKEN(pValueExp,STRING) ) 2230 { 2231 nType = DataType::VARCHAR; 2232 } 2233 } 2234 if ( nType == DataType::OTHER ) 2235 nType = DataType::DOUBLE; 2236 } 2237 else 2238 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() ); 2239 } 2240 2241 return nType; 2242 } 2243 2244