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