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