LCOV - code coverage report
Current view: top level - connectivity/source/parse - sqliterator.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 538 992 54.2 %
Date: 2014-11-03 Functions: 49 65 75.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10