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