merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / parse / sqliterator.cxx
blobc92fc9b709bc51383e35983dc7049af620c61fed
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sqliterator.cxx,v $
10 * $Revision: 1.60 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "connectivity/sqliterator.hxx"
34 #include "connectivity/sdbcx/VTable.hxx"
35 #include <connectivity/sqlparse.hxx>
36 #include <connectivity/dbtools.hxx>
37 #include <connectivity/sqlerror.hxx>
38 #include <com/sun/star/sdbc/ColumnValue.hpp>
39 #include <com/sun/star/sdbc/DataType.hpp>
40 #include <com/sun/star/sdbc/XRow.hpp>
41 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
42 #include <com/sun/star/sdb/ErrorCondition.hpp>
43 #ifdef SQL_TEST_PARSETREEITERATOR
44 #include <iostream>
45 #endif
46 #include "connectivity/PColumn.hxx"
47 #include "connectivity/dbtools.hxx"
48 #include <tools/diagnose_ex.h>
49 #include "TConnection.hxx"
50 #include <comphelper/types.hxx>
51 #include <connectivity/dbmetadata.hxx>
52 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
53 #include "diagnose_ex.h"
54 #include <rtl/logfile.hxx>
56 using namespace ::comphelper;
57 using namespace ::connectivity;
58 using namespace ::connectivity::sdbcx;
59 using namespace ::dbtools;
60 using namespace ::connectivity::parse;
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::container;
64 using namespace ::com::sun::star::sdbcx;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::sdbc;
67 using namespace ::com::sun::star::sdb;
69 namespace connectivity
71 struct OSQLParseTreeIteratorImpl
73 Reference< XConnection > m_xConnection;
74 Reference< XDatabaseMetaData > m_xDatabaseMetaData;
75 Reference< XNameAccess > m_xTableContainer;
76 Reference< XNameAccess > m_xQueryContainer;
78 ::boost::shared_ptr< OSQLTables > m_pTables; /// all tables which participate in the SQL statement
79 ::boost::shared_ptr< OSQLTables > m_pSubTables; /// all tables from sub queries not the tables from the select tables
80 ::boost::shared_ptr< QueryNameSet > m_pForbiddenQueryNames;
82 sal_uInt32 m_nIncludeMask;
84 bool m_bIsCaseSensitive;
86 OSQLParseTreeIteratorImpl( const Reference< XConnection >& _rxConnection, const Reference< XNameAccess >& _rxTables )
87 :m_xConnection( _rxConnection )
88 ,m_nIncludeMask( OSQLParseTreeIterator::All )
89 ,m_bIsCaseSensitive( true )
91 OSL_PRECOND( m_xConnection.is(), "OSQLParseTreeIteratorImpl::OSQLParseTreeIteratorImpl: invalid connection!" );
92 m_xDatabaseMetaData = m_xConnection->getMetaData();
94 m_bIsCaseSensitive = m_xDatabaseMetaData.is() && m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers();
95 m_pTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
96 m_pSubTables.reset( new OSQLTables( m_bIsCaseSensitive ) );
98 m_xTableContainer = _rxTables;
100 DatabaseMetaData aMetaData( m_xConnection );
101 if ( aMetaData.supportsSubqueriesInFrom() )
103 // connections might support the XQueriesSupplier interface, if they implement the css.sdb.Connection
104 // service
105 Reference< XQueriesSupplier > xSuppQueries( m_xConnection, UNO_QUERY );
106 if ( xSuppQueries.is() )
107 m_xQueryContainer = xSuppQueries->getQueries();
111 public:
112 inline bool isQueryAllowed( const ::rtl::OUString& _rQueryName )
114 if ( !m_pForbiddenQueryNames.get() )
115 return true;
116 if ( m_pForbiddenQueryNames->find( _rQueryName ) == m_pForbiddenQueryNames->end() )
117 return true;
118 return false;
122 //-------------------------------------------------------------------------
123 /** helper class for temporarily adding a query name to a list of forbidden query names
125 class ForbidQueryName
127 ::boost::shared_ptr< QueryNameSet >& m_rpAllForbiddenNames;
128 ::rtl::OUString m_sForbiddenQueryName;
130 public:
131 ForbidQueryName( OSQLParseTreeIteratorImpl& _rIteratorImpl, const ::rtl::OUString _rForbiddenQueryName )
132 :m_rpAllForbiddenNames( _rIteratorImpl.m_pForbiddenQueryNames )
133 ,m_sForbiddenQueryName( _rForbiddenQueryName )
135 if ( !m_rpAllForbiddenNames.get() )
136 m_rpAllForbiddenNames.reset( new QueryNameSet );
137 m_rpAllForbiddenNames->insert( m_sForbiddenQueryName );
140 ~ForbidQueryName()
142 m_rpAllForbiddenNames->erase( m_sForbiddenQueryName );
146 //-----------------------------------------------------------------------------
147 OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XConnection >& _rxConnection,
148 const Reference< XNameAccess >& _rxTables,
149 const OSQLParser& _rParser,
150 const OSQLParseNode* pRoot )
151 :m_rParser( _rParser )
152 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rxConnection, _rxTables ) )
154 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
155 setParseTree(pRoot);
158 //-----------------------------------------------------------------------------
159 OSQLParseTreeIterator::OSQLParseTreeIterator( const OSQLParseTreeIterator& _rParentIterator, const OSQLParser& _rParser, const OSQLParseNode* pRoot )
160 :m_rParser( _rParser )
161 ,m_pImpl( new OSQLParseTreeIteratorImpl( _rParentIterator.m_pImpl->m_xConnection, _rParentIterator.m_pImpl->m_xTableContainer ) )
163 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::OSQLParseTreeIterator" );
164 m_pImpl->m_pForbiddenQueryNames = _rParentIterator.m_pImpl->m_pForbiddenQueryNames;
165 setParseTree( pRoot );
168 //-----------------------------------------------------------------------------
169 OSQLParseTreeIterator::~OSQLParseTreeIterator()
171 dispose();
174 // -----------------------------------------------------------------------------
175 const OSQLTables& OSQLParseTreeIterator::getTables() const
177 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTables" );
178 return *m_pImpl->m_pTables;
181 // -----------------------------------------------------------------------------
182 bool OSQLParseTreeIterator::isCaseSensitive() const
184 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isCaseSensitive" );
185 return m_pImpl->m_bIsCaseSensitive;
188 // -----------------------------------------------------------------------------
189 void OSQLParseTreeIterator::dispose()
191 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::dispose" );
192 m_aSelectColumns = NULL;
193 m_aGroupColumns = NULL;
194 m_aOrderColumns = NULL;
195 m_aParameters = NULL;
196 m_pImpl->m_xTableContainer = NULL;
197 m_pImpl->m_xDatabaseMetaData = NULL;
198 m_aCreateColumns = NULL;
199 m_pImpl->m_pTables->clear();
200 m_pImpl->m_pSubTables->clear();
202 //-----------------------------------------------------------------------------
203 void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree)
205 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setParseTree" );
206 m_pImpl->m_pTables->clear();
207 m_pImpl->m_pSubTables->clear();
209 m_aSelectColumns = new OSQLColumns();
210 m_aGroupColumns = new OSQLColumns();
211 m_aOrderColumns = new OSQLColumns();
212 m_aParameters = new OSQLColumns();
213 m_aCreateColumns = new OSQLColumns();
215 m_pParseTree = pNewParseTree;
216 if (!m_pParseTree)
218 m_eStatementType = SQL_STATEMENT_UNKNOWN;
219 return;
222 // falls m_pParseTree aber keine Connection, dann Fehler
223 if ( !m_pImpl->m_xTableContainer.is() )
224 return;
226 m_aErrors = SQLException();
229 // Statement-Typ ermitteln ...
230 if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) )
232 m_eStatementType = SQL_STATEMENT_SELECT;
234 else if (SQL_ISRULE(m_pParseTree,insert_statement))
236 m_eStatementType = SQL_STATEMENT_INSERT;
238 else if (SQL_ISRULE(m_pParseTree,update_statement_searched))
240 m_eStatementType = SQL_STATEMENT_UPDATE;
242 else if (SQL_ISRULE(m_pParseTree,delete_statement_searched))
244 m_eStatementType = SQL_STATEMENT_DELETE;
246 else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec))
248 m_eStatementType = SQL_STATEMENT_ODBC_CALL;
250 else if (SQL_ISRULE(m_pParseTree->getChild(0),base_table_def))
252 m_eStatementType = SQL_STATEMENT_CREATE_TABLE;
253 m_pParseTree = m_pParseTree->getChild(0);
255 else
257 m_eStatementType = SQL_STATEMENT_UNKNOWN;
258 //aIteratorStatus.setInvalidStatement();
259 return;
263 //-----------------------------------------------------------------------------
264 namespace
266 //.........................................................................
267 static void impl_getRowString( const Reference< XRow >& _rxRow, const sal_Int32 _nColumnIndex, ::rtl::OUString& _out_rString )
269 _out_rString = _rxRow->getString( _nColumnIndex );
270 if ( _rxRow->wasNull() )
271 _out_rString= ::rtl::OUString();
274 //.........................................................................
275 static ::rtl::OUString lcl_findTableInMetaData(
276 const Reference< XDatabaseMetaData >& _rxDBMeta, const ::rtl::OUString& _rCatalog,
277 const ::rtl::OUString& _rSchema, const ::rtl::OUString& _rTableName )
279 ::rtl::OUString sComposedName;
281 static const ::rtl::OUString s_sTableTypeView(RTL_CONSTASCII_USTRINGPARAM("VIEW"));
282 static const ::rtl::OUString s_sTableTypeTable(RTL_CONSTASCII_USTRINGPARAM("TABLE"));
283 static const ::rtl::OUString s_sWildcard = ::rtl::OUString::createFromAscii("%");
285 // we want all catalogues, all schemas, all tables
286 Sequence< ::rtl::OUString > sTableTypes(3);
287 sTableTypes[0] = s_sTableTypeView;
288 sTableTypes[1] = s_sTableTypeTable;
289 sTableTypes[2] = s_sWildcard; // just to be sure to include anything else ....
291 if ( _rxDBMeta.is() )
293 sComposedName = ::rtl::OUString();
295 Reference< XResultSet> xRes = _rxDBMeta->getTables(
296 _rCatalog.getLength() ? makeAny( _rCatalog ) : Any(), _rSchema.getLength() ? _rSchema : s_sWildcard, _rTableName, sTableTypes );
298 Reference< XRow > xCurrentRow( xRes, UNO_QUERY );
299 if ( xCurrentRow.is() && xRes->next() )
301 ::rtl::OUString sCatalog, sSchema, sName;
303 impl_getRowString( xCurrentRow, 1, sCatalog );
304 impl_getRowString( xCurrentRow, 2, sSchema );
305 impl_getRowString( xCurrentRow, 3, sName );
307 sComposedName = ::dbtools::composeTableName(
308 _rxDBMeta,
309 sCatalog,
310 sSchema,
311 sName,
312 sal_False,
313 ::dbtools::eInDataManipulation
317 return sComposedName;
321 //-----------------------------------------------------------------------------
322 void OSQLParseTreeIterator::impl_getQueryParameterColumns( const OSQLTable& _rQuery )
324 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_getQueryParameterColumns" );
325 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
326 // parameters not to be included in the traversal
327 return;
329 ::vos::ORef< OSQLColumns > pSubQueryParameterColumns( new OSQLColumns() );
331 // get the command and the EscapeProcessing properties from the sub query
332 ::rtl::OUString sSubQueryCommand;
333 sal_Bool bEscapeProcessing = sal_False;
336 Reference< XPropertySet > xQueryProperties( _rQuery, UNO_QUERY_THROW );
337 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_COMMAND ) ) >>= sSubQueryCommand );
338 OSL_VERIFY( xQueryProperties->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_ESCAPEPROCESSING ) ) >>= bEscapeProcessing );
340 catch( const Exception& )
342 DBG_UNHANDLED_EXCEPTION();
345 // parse the sub query
346 do {
348 if ( !bEscapeProcessing || ( sSubQueryCommand.getLength() == 0 ) )
349 break;
351 ::rtl::OUString sError;
352 ::std::auto_ptr< OSQLParseNode > pSubQueryNode( const_cast< OSQLParser& >( m_rParser ).parseTree( sError, sSubQueryCommand, sal_False ) );
353 if ( !pSubQueryNode.get() )
354 break;
356 OSQLParseTreeIterator aSubQueryIterator( *this, m_rParser, pSubQueryNode.get() );
357 aSubQueryIterator.traverseSome( Parameters | SelectColumns );
358 // SelectColumns might also contain parameters
359 // #i77635# - 2007-07-23 / frank.schoenheit@sun.com
360 pSubQueryParameterColumns = aSubQueryIterator.getParameters();
361 aSubQueryIterator.dispose();
363 } while ( false );
365 // copy the parameters of the sub query to our own parameter array
366 ::std::copy( pSubQueryParameterColumns->get().begin(), pSubQueryParameterColumns->get().end(),
367 ::std::insert_iterator< OSQLColumns::Vector >( m_aParameters->get(), m_aParameters->get().end() ) );
370 //-----------------------------------------------------------------------------
371 OSQLTable OSQLParseTreeIterator::impl_locateRecordSource( const ::rtl::OUString& _rComposedName )
373 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_locateRecordSource" );
374 if ( !_rComposedName.getLength() )
376 OSL_ENSURE( false, "OSQLParseTreeIterator::impl_locateRecordSource: no object name at all?" );
377 return OSQLTable();
380 OSQLTable aReturn;
381 ::rtl::OUString sComposedName( _rComposedName );
385 ::rtl::OUString sCatalog, sSchema, sName;
386 qualifiedNameComponents( m_pImpl->m_xDatabaseMetaData, sComposedName, sCatalog, sSchema, sName, ::dbtools::eInDataManipulation );
388 // check whether there is a query with the given name
389 bool bQueryDoesExist = m_pImpl->m_xQueryContainer.is() && m_pImpl->m_xQueryContainer->hasByName( sComposedName );
391 // check whether the table container contains an object with the given name
392 if ( !bQueryDoesExist && !m_pImpl->m_xTableContainer->hasByName( sComposedName ) )
393 sComposedName = lcl_findTableInMetaData( m_pImpl->m_xDatabaseMetaData, sCatalog, sSchema, sName );
394 bool bTableDoesExist = m_pImpl->m_xTableContainer->hasByName( sComposedName );
396 // now obtain the object
398 // if we're creating a table, and there already is a table or query with the same name,
399 // this is worth an error
400 if ( SQL_STATEMENT_CREATE_TABLE == m_eStatementType )
402 if ( bQueryDoesExist )
403 impl_appendError( IParseContext::ERROR_INVALID_QUERY_EXIST, &sName );
404 else if ( bTableDoesExist )
405 impl_appendError( IParseContext::ERROR_INVALID_TABLE_EXIST, &sName );
406 else
407 aReturn = impl_createTableObject( sName, sCatalog, sSchema );
409 else
411 // queries win over tables, so if there's a query with this name, take this, no matter if
412 // there's a table, too
413 if ( bQueryDoesExist )
415 if ( !m_pImpl->isQueryAllowed( sComposedName ) )
417 impl_appendError( m_rParser.getErrorHelper().getSQLException( sdb::ErrorCondition::PARSER_CYCLIC_SUB_QUERIES, NULL ) );
418 return NULL;
421 m_pImpl->m_xQueryContainer->getByName( sComposedName ) >>= aReturn;
423 // collect the parameters from the sub query
424 ForbidQueryName aForbidName( *m_pImpl, sComposedName );
425 impl_getQueryParameterColumns( aReturn );
427 else if ( bTableDoesExist )
428 m_pImpl->m_xTableContainer->getByName( sComposedName ) >>= aReturn;
429 else
431 if ( m_pImpl->m_xQueryContainer.is() )
432 // the connection on which we're working supports sub queries in from (else
433 // m_xQueryContainer would not have been set), so emit a better error message
434 impl_appendError( IParseContext::ERROR_INVALID_TABLE_OR_QUERY, &sName );
435 else
436 impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sName );
440 catch(Exception&)
442 impl_appendError( IParseContext::ERROR_INVALID_TABLE, &sComposedName );
445 return aReturn;
448 //-----------------------------------------------------------------------------
449 void OSQLParseTreeIterator::traverseOneTableName( OSQLTables& _rTables,const OSQLParseNode * pTableName, const ::rtl::OUString & rTableRange )
451 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOneTableName" );
452 if ( ( m_pImpl->m_nIncludeMask & TableNames ) != TableNames )
453 // tables should not be included in the traversal
454 return;
456 OSL_ENSURE(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL");
458 Any aCatalog;
459 ::rtl::OUString aSchema,aTableName,aComposedName;
460 ::rtl::OUString aTableRange(rTableRange);
462 // Tabellenname abholen
463 OSQLParseNode::getTableComponents(pTableName,aCatalog,aSchema,aTableName,m_pImpl->m_xDatabaseMetaData);
465 // create the composed name like DOMAIN.USER.TABLE1
466 aComposedName = ::dbtools::composeTableName(m_pImpl->m_xDatabaseMetaData,
467 aCatalog.hasValue() ? ::comphelper::getString(aCatalog) : ::rtl::OUString(),
468 aSchema,
469 aTableName,
470 sal_False,
471 ::dbtools::eInDataManipulation);
473 // if there is no alias for the table name assign the orignal name to it
474 if ( !aTableRange.getLength() )
475 aTableRange = aComposedName;
477 // get the object representing this table/query
478 OSQLTable aTable = impl_locateRecordSource( aComposedName );
479 if ( aTable.is() )
480 _rTables[ aTableRange ] = aTable;
483 //-----------------------------------------------------------------------------
484 void OSQLParseTreeIterator::getQualified_join( OSQLTables& _rTables, const OSQLParseNode *pTableRef, ::rtl::OUString& aTableRange )
486 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getQualified_join" );
487 OSL_PRECOND( SQL_ISRULE( pTableRef, cross_union ) || SQL_ISRULE( pTableRef, qualified_join ) ,
488 "OSQLParseTreeIterator::getQualified_join: illegal node!" );
490 aTableRange = ::rtl::OUString();
492 const OSQLParseNode* pNode = getTableNode(_rTables,pTableRef->getChild(0),aTableRange);
493 if ( isTableNode( pNode ) )
494 traverseOneTableName( _rTables, pNode, aTableRange );
496 sal_uInt32 nPos = 4;
497 if(SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL)
498 nPos = 3;
500 pNode = getTableNode(_rTables,pTableRef->getChild(nPos),aTableRange);
501 if ( isTableNode( pNode ) )
502 traverseOneTableName( _rTables, pNode, aTableRange );
504 //-----------------------------------------------------------------------------
505 const OSQLParseNode* OSQLParseTreeIterator::getTableNode( OSQLTables& _rTables, const OSQLParseNode *pTableRef,::rtl::OUString& rTableRange )
507 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getTableNode" );
508 OSL_PRECOND( SQL_ISRULE( pTableRef, table_ref ) || SQL_ISRULE( pTableRef, joined_table )
509 || SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ),
510 "OSQLParseTreeIterator::getTableNode: only to be called for table_ref nodes!" );
512 const OSQLParseNode* pTableNameNode = NULL;
514 if ( SQL_ISRULE( pTableRef, joined_table ) )
516 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
518 if ( SQL_ISRULE( pTableRef, qualified_join ) || SQL_ISRULE( pTableRef, cross_union ) )
520 getQualified_join( _rTables, pTableRef, rTableRange );
522 else
524 rTableRange = OSQLParseNode::getTableRange(pTableRef);
525 if ( ( pTableRef->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
526 || ( pTableRef->count() == 5 ) // '(' joined_table ')' range_variable op_column_commalist
529 getQualified_join( _rTables, pTableRef->getChild(6 - pTableRef->count()), rTableRange );
531 else if ( pTableRef->count() == 3 ) // subquery range_variable op_column_commalist || '(' joined_table ')'
533 const OSQLParseNode* pSubQuery = pTableRef->getChild(0);
534 if ( pSubQuery->isToken() )
536 getQualified_join( _rTables, pTableRef->getChild(1), rTableRange );
538 else
540 OSL_ENSURE( pSubQuery->count() == 3, "sub queries should have 3 children!" );
541 const OSQLParseNode* pQueryExpression = pSubQuery->getChild(1);
542 if ( SQL_ISRULE( pQueryExpression, select_statement ) )
544 getSelect_statement( *m_pImpl->m_pSubTables, pQueryExpression );
546 else
548 OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: subquery which is no select_statement: not yet implemented!" );
552 else if ( pTableRef->count() == 2 ) // table_node table_primary_as_range_column
554 pTableNameNode = pTableRef->getChild(0);
556 else
557 OSL_ENSURE( false, "OSQLParseTreeIterator::getTableNode: unhandled case!" );
560 return pTableNameNode;
562 //-----------------------------------------------------------------------------
563 void OSQLParseTreeIterator::getSelect_statement(OSQLTables& _rTables,const OSQLParseNode* pSelect)
565 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSelect_statement" );
566 if(SQL_ISRULE(pSelect,union_statement))
568 getSelect_statement(_rTables,pSelect->getChild(0));
569 //getSelect_statement(pSelect->getChild(3));
570 return;
572 OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1);
574 OSL_ENSURE(pTableRefCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
575 OSL_ENSURE(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: error in parse tree!");
577 const OSQLParseNode* pTableName = NULL;
578 ::rtl::OUString aTableRange;
579 for (sal_uInt32 i = 0; i < pTableRefCommalist->count(); i++)
580 { // from clause durchlaufen
581 aTableRange = ::rtl::OUString();
583 const OSQLParseNode* pTableListElement = pTableRefCommalist->getChild(i);
584 if ( isTableNode( pTableListElement ) )
586 traverseOneTableName( _rTables, pTableListElement, aTableRange );
588 else if ( SQL_ISRULE( pTableListElement, table_ref ) )
590 // Tabellenreferenz kann aus Tabellennamen, Tabellennamen (+),'('joined_table')'(+) bestehen
591 pTableName = pTableListElement->getChild(0);
592 if( isTableNode( pTableName ) )
593 { // Tabellennamen gefunden
594 aTableRange = OSQLParseNode::getTableRange(pTableListElement);
595 traverseOneTableName( _rTables, pTableName, aTableRange );
597 else if(SQL_ISPUNCTUATION(pTableName,"{"))
598 { // '{' SQL_TOKEN_OJ joined_table '}'
599 getQualified_join( _rTables, pTableListElement->getChild(2), aTableRange );
601 else
602 { // '(' joined_table ')' range_variable op_column_commalist
603 getTableNode( _rTables, pTableListElement, aTableRange );
606 else if (SQL_ISRULE( pTableListElement, qualified_join ) || SQL_ISRULE( pTableListElement, cross_union ) )
608 getQualified_join( _rTables, pTableListElement, aTableRange );
610 else if ( SQL_ISRULE( pTableListElement, joined_table ) )
612 getQualified_join( _rTables, pTableListElement->getChild(1), aTableRange );
615 // if (! aIteratorStatus.IsSuccessful()) break;
618 //-----------------------------------------------------------------------------
619 bool OSQLParseTreeIterator::traverseTableNames(OSQLTables& _rTables)
621 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseTableNames" );
622 if ( m_pParseTree == NULL )
623 return false;
625 OSQLParseNode* pTableName = NULL;
627 switch ( m_eStatementType )
629 case SQL_STATEMENT_SELECT:
630 getSelect_statement( _rTables, m_pParseTree );
631 break;
633 case SQL_STATEMENT_CREATE_TABLE:
634 case SQL_STATEMENT_INSERT:
635 case SQL_STATEMENT_DELETE:
636 pTableName = m_pParseTree->getChild(2);
637 break;
639 case SQL_STATEMENT_UPDATE:
640 pTableName = m_pParseTree->getChild(1);
641 break;
642 default:
643 break;
646 if ( pTableName )
648 ::rtl::OUString sTableRange;
649 traverseOneTableName( _rTables, pTableName, sTableRange );
652 return !hasErrors();
654 //-----------------------------------------------------------------------------
655 ::rtl::OUString OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* _pDerivedColumn)
657 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnAlias" );
658 OSL_ENSURE(SQL_ISRULE(_pDerivedColumn,derived_column),"No derived column!");
659 ::rtl::OUString sColumnAlias;
660 if(_pDerivedColumn->getChild(1)->count() == 2)
661 sColumnAlias = _pDerivedColumn->getChild(1)->getChild(1)->getTokenValue();
662 else if(!_pDerivedColumn->getChild(1)->isRule())
663 sColumnAlias = _pDerivedColumn->getChild(1)->getTokenValue();
664 return sColumnAlias;
667 // -----------------------------------------------------------------------------
668 namespace
670 void lcl_getColumnRange( const OSQLParseNode* _pColumnRef, const Reference< XConnection >& _rxConnection,
671 ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange,
672 const OSQLColumns* _pSelectColumns, ::rtl::OUString& _out_rColumnAliasIfPresent )
674 _out_rColumnName = _out_rTableRange = _out_rColumnAliasIfPresent = ::rtl::OUString();
675 if ( SQL_ISRULE( _pColumnRef, column_ref ) )
677 if( _pColumnRef->count() > 1 )
679 for ( sal_Int32 i=0; i<((sal_Int32)_pColumnRef->count())-2; ++i )
680 _pColumnRef->getChild(i)->parseNodeToStr( _out_rTableRange, _rxConnection, NULL, sal_False, sal_False );
681 _out_rColumnName = _pColumnRef->getChild( _pColumnRef->count()-1 )->getChild(0)->getTokenValue();
683 else
684 _out_rColumnName = _pColumnRef->getChild(0)->getTokenValue();
686 // look up the column in the select column, to find an possible alias
687 if ( _pSelectColumns )
689 for ( OSQLColumns::Vector::const_iterator lookupColumn = _pSelectColumns->get().begin();
690 lookupColumn != _pSelectColumns->get().end();
691 ++lookupColumn
694 Reference< XPropertySet > xColumn( *lookupColumn );
697 ::rtl::OUString sName, sTableName;
698 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_REALNAME ) ) >>= sName;
699 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_TABLENAME ) ) >>= sTableName;
700 if ( sName == _out_rColumnName && sTableName == _out_rTableRange )
701 xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= _out_rColumnAliasIfPresent;
703 catch( const Exception& )
705 DBG_UNHANDLED_EXCEPTION();
710 else if(SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec))
711 { // Funktion
712 _pColumnRef->parseNodeToStr( _out_rColumnName, _rxConnection );
714 else if(_pColumnRef->getNodeType() == SQL_NODE_NAME)
715 _out_rColumnName = _pColumnRef->getTokenValue();
719 // -----------------------------------------------------------------------------
720 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
721 ::rtl::OUString& _rColumnName,
722 ::rtl::OUString& _rTableRange) const
724 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
725 ::rtl::OUString sDummy;
726 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, NULL, sDummy );
729 // -----------------------------------------------------------------------------
730 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
731 ::rtl::OUString& _rColumnName,
732 ::rtl::OUString& _rTableRange,
733 ::rtl::OUString& _out_rColumnAliasIfPresent ) const
735 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
736 lcl_getColumnRange( _pColumnRef, m_pImpl->m_xConnection, _rColumnName, _rTableRange, &*m_aSelectColumns, _out_rColumnAliasIfPresent );
739 //-----------------------------------------------------------------------------
740 void OSQLParseTreeIterator::getColumnRange( const OSQLParseNode* _pColumnRef,
741 const Reference< XConnection >& _rxConnection, ::rtl::OUString& _out_rColumnName, ::rtl::OUString& _out_rTableRange )
743 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnRange" );
744 ::rtl::OUString sDummy;
745 lcl_getColumnRange( _pColumnRef, _rxConnection, _out_rColumnName, _out_rTableRange, NULL, sDummy );
748 //-----------------------------------------------------------------------------
749 sal_Bool OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, ::rtl::OUString &rTableRange) const
751 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getColumnTableRange" );
752 // Ermitteln ob alle Spalten zu einer Tabelle gehoeren
753 if (SQL_ISRULE(pNode,column_ref))
755 ::rtl::OUString aColName, aTableRange;
756 getColumnRange(pNode, aColName, aTableRange);
757 if (!aTableRange.getLength()) // keinen gefunden
759 // dann die Spalte in den Tabellen suchen
760 for (ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter)
762 if (aIter->second.is())
766 Reference< XNameAccess > xColumns = aIter->second->getColumns();
767 if(xColumns->hasByName(aColName))
769 Reference< XPropertySet > xColumn;
770 if (xColumns->getByName(aColName) >>= xColumn)
772 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
773 aTableRange = aIter->first;
774 break;
778 catch(Exception&)
783 if (!aTableRange.getLength())
784 return sal_False;
788 if (!rTableRange.getLength())
789 rTableRange = aTableRange;
790 else if (rTableRange != aTableRange)
791 return sal_False;
793 else
795 for (sal_uInt32 i = 0, ncount = pNode->count(); i < ncount; i++)
797 if (!getColumnTableRange(pNode->getChild(i), rTableRange))
798 return sal_False;
801 return sal_True;
804 //-----------------------------------------------------------------------------
805 void OSQLParseTreeIterator::traverseCreateColumns(const OSQLParseNode* pSelectNode)
807 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseCreateColumns" );
808 // aIteratorStatus.Clear();
810 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_CREATE_TABLE || m_pImpl->m_pTables->empty())
812 impl_appendError( IParseContext::ERROR_GENERAL );
813 return;
815 if (!SQL_ISRULE(pSelectNode,base_table_element_commalist))
816 return ;
818 for (sal_uInt32 i = 0; i < pSelectNode->count(); i++)
820 OSQLParseNode *pColumnRef = pSelectNode->getChild(i);
822 if (SQL_ISRULE(pColumnRef,column_def))
824 ::rtl::OUString aColumnName;
825 ::rtl::OUString aTypeName;
826 ::rtl::OUString aTableRange;
827 sal_Int32 nType = DataType::VARCHAR;
828 sal_Int32 nLen = 0;
829 aColumnName = pColumnRef->getChild(0)->getTokenValue();
831 OSQLParseNode *pDatatype = pColumnRef->getChild(1);
832 if (pDatatype && SQL_ISRULE(pDatatype,data_type))
834 //data type
835 // 0 | 1| 2 |3
836 //char ( 20 )
837 aTypeName = pDatatype->getChild(0)->getTokenValue();
838 if (pDatatype->count() == 4
839 && SQL_ISPUNCTUATION(pDatatype->getChild(1), "(")
840 && SQL_ISPUNCTUATION(pDatatype->getChild(3) , ")") )
842 nLen = pDatatype->getChild(2)->getTokenValue().toInt32();
845 else if(pDatatype && pDatatype->getNodeType() == SQL_NODE_KEYWORD)
847 aTypeName = ::rtl::OUString::createFromAscii("VARCHAR");
850 if (aTypeName.getLength())
852 //TO DO:Create a new class for create statement to handle field length
853 OParseColumn* pColumn = new OParseColumn(aColumnName,aTypeName,::rtl::OUString(),
854 ColumnValue::NULLABLE_UNKNOWN,0,0,nType,sal_False,sal_False,isCaseSensitive());
855 pColumn->setFunction(sal_False);
856 pColumn->setRealName(aColumnName);
858 Reference< XPropertySet> xCol = pColumn;
859 m_aCreateColumns->get().push_back(xCol);
865 //-----------------------------------------------------------------------------
866 bool OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode)
868 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectColumnNames" );
869 if ( ( m_pImpl->m_nIncludeMask & SelectColumns ) != SelectColumns )
870 return true;
872 if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || m_pImpl->m_pTables->empty())
874 impl_appendError( IParseContext::ERROR_GENERAL );
875 return false;
878 if(SQL_ISRULE(pSelectNode,union_statement))
880 return traverseSelectColumnNames( pSelectNode->getChild( 0 ) )
881 /*&& traverseSelectColumnNames( pSelectNode->getChild( 3 ) )*/;
884 static ::rtl::OUString aEmptyString;
885 // nyi: mehr Pruefung auf korrekte Struktur!
886 if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*"))
888 // SELECT * ...
889 setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aEmptyString);
891 else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist))
893 // SELECT column[,column] oder SELECT COUNT(*) ...
894 OSQLParseNode * pSelection = pSelectNode->getChild(2);
896 for (sal_uInt32 i = 0; i < pSelection->count(); i++)
898 OSQLParseNode *pColumnRef = pSelection->getChild(i);
900 //if (SQL_ISRULE(pColumnRef,select_sublist))
901 if (SQL_ISRULE(pColumnRef,derived_column) &&
902 SQL_ISRULE(pColumnRef->getChild(0),column_ref) &&
903 pColumnRef->getChild(0)->count() == 3 &&
904 SQL_ISPUNCTUATION(pColumnRef->getChild(0)->getChild(2),"*"))
906 // alle Spalten der Tabelle
907 ::rtl::OUString aTableRange;
908 pColumnRef->getChild(0)->parseNodeToStr( aTableRange, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
909 setSelectColumnName(m_aSelectColumns,::rtl::OUString::createFromAscii("*"), aEmptyString,aTableRange);
910 continue;
912 else if (SQL_ISRULE(pColumnRef,derived_column))
914 ::rtl::OUString aColumnAlias(getColumnAlias(pColumnRef)); // kann leer sein
915 ::rtl::OUString sColumnName;
916 ::rtl::OUString aTableRange;
917 sal_Int32 nType = DataType::VARCHAR;
918 sal_Bool bFkt(sal_False);
919 pColumnRef = pColumnRef->getChild(0);
920 if (
921 pColumnRef->count() == 3 &&
922 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
923 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
925 pColumnRef = pColumnRef->getChild(1);
927 if (SQL_ISRULE(pColumnRef,column_ref))
929 getColumnRange(pColumnRef,sColumnName,aTableRange);
930 OSL_ENSURE(sColumnName.getLength(),"Columnname darf nicht leer sein");
932 else /*if (SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec) ||
933 SQL_ISRULE(pColumnRef,position_exp) || SQL_ISRULE(pColumnRef,extract_exp) ||
934 SQL_ISRULE(pColumnRef,length_exp) || SQL_ISRULE(pColumnRef,char_value_fct)||
935 SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))*/
937 /* Funktionsaufruf vorhanden */
938 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_True );
939 ::rtl::OUString sTableRange;
940 // check if the column is also a parameter
941 traverseORCriteria(pColumnRef); // num_value_exp
943 // gehoeren alle beteiligten Spalten der Funktion zu einer Tabelle
944 if (m_pImpl->m_pTables->size() == 1)
946 aTableRange = m_pImpl->m_pTables->begin()->first;
948 else
950 getColumnTableRange(pColumnRef,aTableRange);
952 if ( pColumnRef->isRule() )
954 bFkt = sal_True;
955 if ( SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term) || SQL_ISRULE(pColumnRef,factor) )
957 nType = DataType::DOUBLE;
959 else
961 ::rtl::OUString sFunctionName;
962 if ( SQL_ISRULE(pColumnRef,length_exp) )
963 pColumnRef->getChild(0)->getChild(0)->parseNodeToStr(
964 sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
965 else
966 pColumnRef->getChild(0)->parseNodeToStr(
967 sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
968 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
973 else
975 aIteratorStatus.setStatementTooComplex();
976 return;
979 if(!aColumnAlias.getLength())
980 aColumnAlias = sColumnName;
981 setSelectColumnName(m_aSelectColumns,sColumnName,aColumnAlias,aTableRange,bFkt,nType,SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec));
986 return !hasErrors();
990 //-----------------------------------------------------------------------------
991 bool OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode)
993 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOrderByColumnNames" );
994 traverseByColumnNames( pSelectNode, sal_True );
995 return !hasErrors();
997 //-----------------------------------------------------------------------------
998 void OSQLParseTreeIterator::traverseByColumnNames(const OSQLParseNode* pSelectNode,sal_Bool _bOrder)
1000 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseByColumnNames" );
1001 // aIteratorStatus.Clear();
1003 if (pSelectNode == NULL)
1005 //aIteratorStatus.setInvalidStatement();
1006 return;
1009 if (m_eStatementType != SQL_STATEMENT_SELECT)
1011 //aIteratorStatus.setInvalidStatement();
1012 return;
1015 if(SQL_ISRULE(pSelectNode,union_statement))
1017 traverseByColumnNames(pSelectNode->getChild(0),_bOrder);
1018 return;
1021 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1023 OSQLParseNode * pTableExp = pSelectNode->getChild(3);
1024 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1025 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator:table_exp error in parse tree!");
1026 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1028 sal_uInt32 nPos = ( _bOrder ? 4 : 2 );
1030 OSQLParseNode * pOptByClause = pTableExp->getChild(nPos);
1031 OSL_ENSURE(pOptByClause != NULL,"OSQLParseTreeIterator: error in parse tree!");
1032 if ( pOptByClause->count() == 0 )
1033 return;
1035 OSL_ENSURE(pOptByClause->count() == 3,"OSQLParseTreeIterator: error in parse tree!");
1037 OSQLParseNode * pOrderingSpecCommalist = pOptByClause->getChild(2);
1038 OSL_ENSURE(pOrderingSpecCommalist != NULL,"OSQLParseTreeIterator: error in parse tree!");
1039 OSL_ENSURE(!_bOrder || SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OSQLParseTreeIterator:ordering_spec_commalist error in parse tree!");
1040 OSL_ENSURE(pOrderingSpecCommalist->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
1042 ::rtl::OUString sColumnName,aColumnAlias;
1043 ::rtl::OUString aTableRange;
1044 sal_uInt32 nCount = pOrderingSpecCommalist->count();
1045 for (sal_uInt32 i = 0; i < nCount; ++i)
1047 OSQLParseNode* pColumnRef = pOrderingSpecCommalist->getChild(i);
1048 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
1049 if ( _bOrder )
1051 OSL_ENSURE(SQL_ISRULE(pColumnRef,ordering_spec),"OSQLParseTreeIterator:ordering_spec error in parse tree!");
1052 OSL_ENSURE(pColumnRef->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1054 pColumnRef = pColumnRef->getChild(0);
1056 aTableRange = ::rtl::OUString();
1057 sColumnName = ::rtl::OUString();
1058 if ( SQL_ISRULE(pColumnRef,column_ref) )
1060 // Column-Name (und TableRange):
1061 if(SQL_ISRULE(pColumnRef,column_ref))
1062 getColumnRange(pColumnRef,sColumnName,aTableRange);
1063 else // eine Expression
1064 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1066 OSL_ENSURE(sColumnName.getLength(),"sColumnName darf nicht leer sein");
1068 else
1069 { // here I found a predicate
1070 pColumnRef->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1072 OSL_ENSURE(pColumnRef != NULL,"OSQLParseTreeIterator: error in parse tree!");
1073 if ( _bOrder )
1075 // Ascending/Descending
1076 OSQLParseNode * pOptAscDesc = pColumnRef->getParent()->getChild(1);
1077 OSL_ENSURE(pOptAscDesc != NULL,"OSQLParseTreeIterator: error in parse tree!");
1079 sal_Bool bAscending = pOptAscDesc && SQL_ISTOKEN(pOptAscDesc,ASC);
1080 setOrderByColumnName(sColumnName, aTableRange,bAscending);
1082 else
1083 setGroupByColumnName(sColumnName, aTableRange);
1086 //-----------------------------------------------------------------------------
1087 bool OSQLParseTreeIterator::traverseGroupByColumnNames(const OSQLParseNode* pSelectNode)
1089 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseGroupByColumnNames" );
1090 traverseByColumnNames( pSelectNode, sal_False );
1091 return !hasErrors();
1094 // -----------------------------------------------------------------------------
1095 namespace
1097 ::rtl::OUString lcl_generateParameterName( const OSQLParseNode& _rParentNode, const OSQLParseNode& _rParamNode )
1099 ::rtl::OUString sColumnName( RTL_CONSTASCII_USTRINGPARAM( "param" ) );
1100 const sal_Int32 nCount = (sal_Int32)_rParentNode.count();
1101 for ( sal_Int32 i = 0; i < nCount; ++i )
1103 if ( _rParentNode.getChild(i) == &_rParamNode )
1105 sColumnName += ::rtl::OUString::valueOf( i+1 );
1106 break;
1109 return sColumnName;
1113 // -----------------------------------------------------------------------------
1114 void OSQLParseTreeIterator::traverseParameters(const OSQLParseNode* _pNode)
1116 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameters" );
1117 if ( _pNode == NULL )
1118 return;
1120 ::rtl::OUString sColumnName, sTableRange, aColumnAlias;
1121 const OSQLParseNode* pParent = _pNode->getParent();
1122 if ( pParent != NULL )
1124 if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1126 sal_uInt32 nPos = 0;
1127 if ( pParent->getChild(nPos) == _pNode )
1128 nPos = 2;
1129 const OSQLParseNode* pOther = pParent->getChild(nPos);
1130 if ( SQL_ISRULE( pOther, column_ref ) )
1131 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1132 else
1133 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1134 } // if ( SQL_ISRULE(pParent,comparison_predicate) ) // x = X
1135 else if ( SQL_ISRULE(pParent,like_predicate) )
1137 const OSQLParseNode* pOther = pParent->getChild(0);
1138 if ( SQL_ISRULE( pOther, column_ref ) )
1139 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1140 else
1141 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1143 else if ( SQL_ISRULE(pParent,between_predicate) )
1145 const OSQLParseNode* pOther = pParent->getChild(0);
1146 if ( SQL_ISRULE( pOther, column_ref ) )
1147 getColumnRange( pOther, sColumnName, sTableRange, aColumnAlias);
1148 else
1150 pOther->parseNodeToStr( sColumnName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1151 lcl_generateParameterName( *pParent, *_pNode );
1154 else if ( pParent->getNodeType() == SQL_NODE_COMMALISTRULE )
1156 lcl_generateParameterName( *pParent, *_pNode );
1159 traverseParameter( _pNode, pParent, sColumnName, sTableRange, aColumnAlias );
1160 const sal_uInt32 nCount = _pNode->count();
1161 for (sal_uInt32 i = 0; i < nCount; ++i)
1163 const OSQLParseNode* pChild = _pNode->getChild(i);
1164 traverseParameters( pChild );
1167 //-----------------------------------------------------------------------------
1168 bool OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode)
1170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSelectionCriteria" );
1171 if ( pSelectNode == NULL )
1172 return false;
1175 // Parse Tree analysieren (je nach Statement-Typ)
1176 // und Zeiger auf WHERE-Klausel setzen:
1177 OSQLParseNode * pWhereClause = NULL;
1179 if (m_eStatementType == SQL_STATEMENT_SELECT)
1181 if(SQL_ISRULE(pSelectNode,union_statement))
1183 return traverseSelectionCriteria( pSelectNode->getChild( 0 ) )
1184 && traverseSelectionCriteria( pSelectNode->getChild( 3 ) );
1186 OSL_ENSURE(pSelectNode->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1188 OSQLParseNode * pTableExp = pSelectNode->getChild(3);
1189 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1190 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1191 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1193 pWhereClause = pTableExp->getChild(1);
1194 } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) {
1195 OSL_ENSURE(pSelectNode->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1196 pWhereClause = pSelectNode->getChild(4);
1197 } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) {
1198 OSL_ENSURE(pSelectNode->count() == 4,"OSQLParseTreeIterator: error in parse tree!");
1199 pWhereClause = pSelectNode->getChild(3);
1200 } else if (SQL_ISRULE(pSelectNode,delete_statement_positioned)) {
1201 // nyi
1202 OSL_ASSERT("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi");
1203 } else {
1204 // Anderes Statement. Keine Selektionskriterien.
1205 return false;
1208 if (! SQL_ISRULE(pWhereClause,where_clause)) {
1209 // Die Where Clause ist meistens optional, d. h. es koennte sich auch
1210 // um "optional_where_clause" handeln.
1211 OSL_ENSURE(SQL_ISRULE(pWhereClause,opt_where_clause),"OSQLParseTreeIterator: error in parse tree!");
1212 return false;
1215 // Wenn es aber eine where_clause ist, dann darf sie nicht leer sein:
1216 OSL_ENSURE(pWhereClause->count() == 2,"OSQLParseTreeIterator: error in parse tree!");
1218 OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1);
1219 OSL_ENSURE(pComparisonPredicate != NULL,"OSQLParseTreeIterator: error in parse tree!");
1222 // Und nun die Vergleichskriterien abarbeiten (rekursiv, alles ist erstmal ein OR-Kriterium):
1225 traverseORCriteria(pComparisonPredicate);
1227 return !hasErrors();
1230 //-----------------------------------------------------------------------------
1231 void OSQLParseTreeIterator::traverseORCriteria(OSQLParseNode * pSearchCondition)
1233 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseORCriteria" );
1236 if (
1237 pSearchCondition->count() == 3 &&
1238 SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
1239 SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
1242 // Runde Klammern um den Ausdruck
1243 traverseORCriteria(pSearchCondition->getChild(1));
1244 } else if (SQL_ISRULE(pSearchCondition,search_condition) &&
1245 pSearchCondition->count() == 3 &&
1246 SQL_ISTOKEN(pSearchCondition->getChild(1),OR))
1248 // OR-Verknuepfung:
1250 for (int i = 0; i < 3; i++) {
1251 if (i == 1) continue; // Schluesselwort OR ueberspringen
1253 // Ist das erste Element wieder eine OR-Verknuepfung?
1254 if (i == 0 &&
1255 SQL_ISRULE(pSearchCondition->getChild(0),search_condition) &&
1256 pSearchCondition->getChild(0)->count() == 3 &&
1257 SQL_ISTOKEN(pSearchCondition->getChild(0)->getChild(1),OR))
1259 // Dann rekursiv absteigen ...
1260 traverseORCriteria(pSearchCondition->getChild(0));
1262 } else {
1263 // AND-Kriterien ...
1264 traverseANDCriteria(pSearchCondition->getChild(i));
1265 // if (! aIteratorStatus.IsSuccessful()) break;
1268 // if (! aIteratorStatus.IsSuccessful()) break;
1270 } else {
1271 // Nur *ein* Kriterium oder eine AND-Verknuepfung von Kriterien.
1272 // Direkt die AND-Kriterien behandeln.
1273 traverseANDCriteria(pSearchCondition);
1274 // if (! aIteratorStatus.IsSuccessful()) return;
1277 // Fehler einfach weiterreichen.
1280 //-----------------------------------------------------------------------------
1281 void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition)
1283 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseANDCriteria" );
1286 if (
1287 SQL_ISRULE(pSearchCondition,boolean_primary) &&
1288 pSearchCondition->count() == 3 &&
1289 SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") &&
1290 SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")
1293 // Runde Klammern
1294 traverseANDCriteria(pSearchCondition->getChild(1));
1296 // Das erste Element ist eine OR-Verknuepfung
1297 else if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 )
1299 // Dann rekursiv absteigen (dieselbe Row benutzen) ...
1300 traverseORCriteria(pSearchCondition->getChild(0));
1301 // if (! aIteratorStatus.IsSuccessful())
1302 // return;
1304 // Und mit dem rechten Child weitermachen:
1305 traverseANDCriteria(pSearchCondition->getChild(2));
1307 // Das erste Element ist (wieder) eine AND-Verknuepfung
1308 else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 )
1310 // Dann rekursiv absteigen (dieselbe Row benutzen) ...
1311 traverseANDCriteria(pSearchCondition->getChild(0));
1312 // if (! aIteratorStatus.IsSuccessful())
1313 // return;
1315 // Und mit dem rechten Child weitermachen:
1316 traverseANDCriteria(pSearchCondition->getChild(2));
1318 // Sonst einzelne Suchkriterien wie =, !=, ..., LIKE, IS NULL usw. behandeln:
1319 else if (SQL_ISRULE(pSearchCondition,comparison_predicate) )
1321 ::rtl::OUString aValue;
1322 pSearchCondition->getChild(2)->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1323 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pSearchCondition->getChild(2));
1324 // if (! aIteratorStatus.IsSuccessful())
1325 // return;
1327 else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1329 OSL_ENSURE(pSearchCondition->count() >= 4,"OSQLParseTreeIterator: error in parse tree!");
1331 sal_Int32 nCurentPos = pSearchCondition->count()-2;
1333 OSQLParseNode * pNum_value_exp = pSearchCondition->getChild(nCurentPos);
1334 OSQLParseNode * pOptEscape = pSearchCondition->getChild(nCurentPos+1);
1336 OSL_ENSURE(pNum_value_exp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1337 OSL_ENSURE(pOptEscape != NULL,"OSQLParseTreeIterator: error in parse tree!");
1339 if (pOptEscape->count() != 0)
1341 // aIteratorStatus.setStatementTooComplex();
1342 return;
1345 ::rtl::OUString aValue;
1346 OSQLParseNode * pParam = NULL;
1347 if (SQL_ISRULE(pNum_value_exp,parameter))
1348 pParam = pNum_value_exp;
1349 else if(pNum_value_exp->isToken())
1350 // Normaler Wert
1351 aValue = pNum_value_exp->getTokenValue();
1352 else
1354 pNum_value_exp->parseNodeToStr( aValue, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1355 pParam = pNum_value_exp;
1358 traverseOnePredicate(pSearchCondition->getChild(0),aValue,pParam);
1359 // if (! aIteratorStatus.IsSuccessful())
1360 // return;
1362 else if (SQL_ISRULE(pSearchCondition,in_predicate))
1364 OSL_ENSURE(pSearchCondition->count() == 4,"OSQLParseTreeIterator: error in parse tree!");
1366 traverseORCriteria(pSearchCondition->getChild(0));
1367 // if (! aIteratorStatus.IsSuccessful()) return;
1369 OSQLParseNode* pChild = pSearchCondition->getChild(3);
1370 if ( SQL_ISRULE(pChild->getChild(0),subquery) )
1372 traverseTableNames( *m_pImpl->m_pSubTables );
1373 traverseSelectionCriteria(pChild->getChild(0)->getChild(1));
1375 else
1376 { // '(' value_exp_commalist ')'
1377 pChild = pChild->getChild(1);
1378 sal_Int32 nCount = pChild->count();
1379 for (sal_Int32 i=0; i < nCount; ++i)
1381 traverseANDCriteria(pChild->getChild(i));
1385 else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/)
1387 OSL_ENSURE(pSearchCondition->count() >= 3,"OSQLParseTreeIterator: error in parse tree!");
1388 OSL_ENSURE(SQL_ISTOKEN(pSearchCondition->getChild(1),IS),"OSQLParseTreeIterator: error in parse tree!");
1390 ::rtl::OUString aString;
1391 traverseOnePredicate(pSearchCondition->getChild(0),aString,NULL);
1392 // if (! aIteratorStatus.IsSuccessful()) return;
1394 else if (SQL_ISRULE(pSearchCondition,num_value_exp) || SQL_ISRULE(pSearchCondition,term))
1396 ::rtl::OUString aString;
1397 traverseOnePredicate(pSearchCondition->getChild(0),aString,pSearchCondition->getChild(0));
1398 traverseOnePredicate(pSearchCondition->getChild(2),aString,pSearchCondition->getChild(2));
1400 // Fehler einfach weiterreichen.
1402 //-----------------------------------------------------------------------------
1403 void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode
1404 ,const OSQLParseNode* _pColumnRef
1405 ,const ::rtl::OUString& _aColumnName
1406 ,const ::rtl::OUString& _aTableRange
1407 ,const ::rtl::OUString& _rColumnAlias)
1409 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseParameter" );
1410 if ( !SQL_ISRULE( _pParseNode, parameter ) )
1411 return;
1413 if ( ( m_pImpl->m_nIncludeMask & Parameters ) != Parameters )
1414 // parameters not to be included in the traversal
1415 return;
1417 OSL_ENSURE(_pParseNode->count() > 0,"OSQLParseTreeIterator: error in parse tree!");
1418 OSQLParseNode * pMark = _pParseNode->getChild(0);
1419 ::rtl::OUString sParameterName;
1421 if (SQL_ISPUNCTUATION(pMark,"?"))
1423 sParameterName = _rColumnAlias.getLength()
1424 ? _rColumnAlias
1425 : _aColumnName.getLength()
1426 ? _aColumnName
1427 : ::rtl::OUString::createFromAscii("?");
1429 else if (SQL_ISPUNCTUATION(pMark,":"))
1431 sParameterName = _pParseNode->getChild(1)->getTokenValue();
1433 else if (SQL_ISPUNCTUATION(pMark,"["))
1435 sParameterName = _pParseNode->getChild(1)->getTokenValue();
1437 else
1439 OSL_ASSERT("OSQLParseTreeIterator: error in parse tree!");
1442 // found a parameter
1443 if ( _pColumnRef && (SQL_ISRULE(_pColumnRef,general_set_fct) || SQL_ISRULE(_pColumnRef,set_fct_spec)) )
1444 {// found a function as column_ref
1445 ::rtl::OUString sFunctionName;
1446 _pColumnRef->getChild(0)->parseNodeToStr( sFunctionName, m_pImpl->m_xConnection, NULL, sal_False, sal_False );
1447 sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType( sFunctionName, &m_rParser.getContext() );
1449 OParseColumn* pColumn = new OParseColumn( sParameterName,
1450 ::rtl::OUString(),
1451 ::rtl::OUString(),
1452 ColumnValue::NULLABLE_UNKNOWN,
1455 nType,
1456 sal_False,
1457 sal_False,
1458 isCaseSensitive());
1459 pColumn->setFunction(sal_True);
1460 pColumn->setAggregateFunction(sal_True);
1461 pColumn->setRealName(sFunctionName);
1462 m_aParameters->get().push_back(pColumn);
1464 else
1466 sal_Bool bNotFound = sal_True;
1467 OSQLColumns::Vector::const_iterator aIter = ::connectivity::find(
1468 m_aSelectColumns->get().begin(),
1469 m_aSelectColumns->get().end(),
1470 _aColumnName,::comphelper::UStringMixEqual( isCaseSensitive() )
1472 if(aIter != m_aSelectColumns->get().end())
1474 OParseColumn* pNewColumn = new OParseColumn(*aIter,isCaseSensitive());
1475 pNewColumn->setName(sParameterName);
1476 pNewColumn->setRealName(_aColumnName);
1477 m_aParameters->get().push_back(pNewColumn);
1478 bNotFound = sal_False;
1480 else if(_aColumnName.getLength())// search in the tables for the right one
1483 Reference<XPropertySet> xColumn = findColumn( _aColumnName, _aTableRange, true );
1485 if ( xColumn.is() )
1487 OParseColumn* pNewColumn = new OParseColumn(xColumn,isCaseSensitive());
1488 pNewColumn->setName(sParameterName);
1489 pNewColumn->setRealName(_aColumnName);
1490 m_aParameters->get().push_back(pNewColumn);
1491 bNotFound = sal_False;
1494 if ( bNotFound )
1496 sal_Int32 nType = DataType::VARCHAR;
1497 OSQLParseNode* pParent = _pColumnRef ? _pColumnRef->getParent() : NULL;
1498 if ( pParent && (SQL_ISRULE(pParent,general_set_fct) || SQL_ISRULE(pParent,set_fct_spec)) )
1500 const sal_uInt32 nCount = _pColumnRef->count();
1501 sal_uInt32 i = 0;
1502 for(; i < nCount;++i)
1504 if ( _pColumnRef->getChild(i) == _pParseNode )
1505 break;
1507 nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1);
1510 ::rtl::OUString aNewColName( getUniqueColumnName( sParameterName ) );
1512 OParseColumn* pColumn = new OParseColumn(aNewColName,
1513 ::rtl::OUString(),
1514 ::rtl::OUString(),
1515 ColumnValue::NULLABLE_UNKNOWN,
1518 nType,
1519 sal_False,
1520 sal_False,
1521 isCaseSensitive() );
1522 pColumn->setName(aNewColName);
1523 pColumn->setRealName(sParameterName);
1524 m_aParameters->get().push_back(pColumn);
1528 //-----------------------------------------------------------------------------
1529 void OSQLParseTreeIterator::traverseOnePredicate(
1530 OSQLParseNode * pColumnRef,
1531 ::rtl::OUString& rValue,
1532 OSQLParseNode * pParseNode)
1534 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseOnePredicate" );
1535 if ( !pParseNode )
1536 return;
1538 // Column-Name (und TableRange):
1539 ::rtl::OUString aColumnName, aTableRange, sColumnAlias;
1540 getColumnRange( pColumnRef, aColumnName, aTableRange, sColumnAlias);
1542 ::rtl::OUString aName;
1544 /*if (SQL_ISRULE(pParseNode,parameter))
1545 traverseParameter( pParseNode, pColumnRef, aColumnName, aTableRange, sColumnAlias );
1546 else */if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange):
1547 getColumnRange(pParseNode,aName,rValue);
1548 else
1550 traverseORCriteria(pParseNode);
1551 // if (! aIteratorStatus.IsSuccessful()) return;
1555 //-----------------------------------------------------------------------------
1556 void OSQLParseTreeIterator::traverseSome( sal_uInt32 _nIncludeMask )
1558 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseSome" );
1559 impl_traverse( _nIncludeMask );
1562 //-----------------------------------------------------------------------------
1563 void OSQLParseTreeIterator::traverseAll()
1565 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::traverseAll" );
1566 impl_traverse( All );
1569 //-----------------------------------------------------------------------------
1570 void OSQLParseTreeIterator::impl_traverse( sal_uInt32 _nIncludeMask )
1572 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_traverse" );
1573 impl_resetErrors();
1574 m_pImpl->m_nIncludeMask = _nIncludeMask;
1576 if ( !traverseTableNames( *m_pImpl->m_pTables ) )
1577 return;
1579 switch ( m_eStatementType )
1581 case SQL_STATEMENT_SELECT:
1583 const OSQLParseNode* pSelectNode = m_pParseTree;
1584 traverseParameters( pSelectNode );
1585 if ( !traverseSelectColumnNames( pSelectNode )
1586 || !traverseOrderByColumnNames( pSelectNode )
1587 || !traverseGroupByColumnNames( pSelectNode )
1588 || !traverseSelectionCriteria( pSelectNode )
1590 return;
1592 break;
1593 case SQL_STATEMENT_CREATE_TABLE:
1595 //0 | 1 | 2 |3| 4 |5
1596 //create table sc.foo ( a char(20), b char )
1597 const OSQLParseNode* pCreateNode = m_pParseTree->getChild(4);
1598 traverseCreateColumns(pCreateNode);
1600 break;
1601 case SQL_STATEMENT_INSERT:
1602 break;
1603 default:
1604 OSL_ENSURE( false, "OSQLParseTreeIterator::traverseAll: not yet implemented for this statement type!" );
1605 break;
1609 // Dummy-Implementationen:
1611 //-----------------------------------------------------------------------------
1612 OSQLTable OSQLParseTreeIterator::impl_createTableObject( const ::rtl::OUString& rTableName,
1613 const ::rtl::OUString& rCatalogName, const ::rtl::OUString& rSchemaName )
1615 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_createTableObject" );
1616 OSL_PRECOND( m_eStatementType == SQL_STATEMENT_CREATE_TABLE,
1617 "OSQLParseTreeIterator::impl_createTableObject: only to be called for CREATE TABLE statements!" );
1618 // (in all other cases, m_pTables is to contain the table objects as obtained from the tables
1619 // container of the connection (m_xTablesContainer)
1621 OSQLTable aReturnTable = new OTable(
1622 NULL,
1623 sal_False,
1624 rTableName,
1625 ::rtl::OUString::createFromAscii("Table"),
1626 ::rtl::OUString::createFromAscii("New Created Table"),
1627 rSchemaName,
1628 rCatalogName
1630 return aReturnTable;
1632 //-----------------------------------------------------------------------------
1633 void OSQLParseTreeIterator::appendColumns(::vos::ORef<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable)
1635 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::appendColumns" );
1637 if (!_rTable.is())
1638 return;
1640 Reference<XNameAccess> xColumns = _rTable->getColumns();
1641 if ( !xColumns.is() )
1642 return;
1644 Sequence< ::rtl::OUString > aColNames = xColumns->getElementNames();
1645 const ::rtl::OUString* pBegin = aColNames.getConstArray();
1646 const ::rtl::OUString* pEnd = pBegin + aColNames.getLength();
1648 for(;pBegin != pEnd;++pBegin)
1651 ::rtl::OUString aName(getUniqueColumnName(*pBegin));
1652 Reference< XPropertySet > xColumn;
1653 if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is())
1655 OParseColumn* pColumn = new OParseColumn(aName
1656 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPENAME)))
1657 , getString(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DEFAULTVALUE)))
1658 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISNULLABLE)))
1659 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)))
1660 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCALE)))
1661 , getINT32(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)))
1662 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)))
1663 , getBOOL(xColumn->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISCURRENCY)))
1664 , isCaseSensitive() );
1666 pColumn->setTableName(_rTableAlias);
1667 pColumn->setRealName(*pBegin);
1668 Reference< XPropertySet> xCol = pColumn;
1669 _rColumns->get().push_back(xCol);
1671 else
1672 impl_appendError( IParseContext::ERROR_INVALID_COLUMN, pBegin, &_rTableAlias );
1675 //-----------------------------------------------------------------------------
1676 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)
1678 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setSelectColumnName" );
1679 if(rColumnName.toChar() == '*' && !rTableRange.getLength())
1680 { // SELECT * ...
1681 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1682 for(ConstOSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end();++aIter)
1683 appendColumns(_rColumns,aIter->first,aIter->second);
1685 else if( rColumnName.toChar() == '*' && rTableRange.getLength() )
1686 { // SELECT <table>.*
1687 OSL_ENSURE(_rColumns == m_aSelectColumns,"Invalid columns used here!");
1688 ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
1690 if(aFind != m_pImpl->m_pTables->end())
1691 appendColumns(_rColumns,rTableRange,aFind->second);
1693 else if ( !rTableRange.getLength() )
1694 { // SELECT <something> ...
1695 // without table specified
1696 if ( !bFkt )
1698 Reference< XPropertySet> xNewColumn;
1700 for ( OSQLTablesIterator aIter = m_pImpl->m_pTables->begin(); aIter != m_pImpl->m_pTables->end(); ++aIter )
1702 if ( !aIter->second.is() )
1703 continue;
1705 Reference<XNameAccess> xColumns = aIter->second->getColumns();
1706 Reference< XPropertySet > xColumn;
1707 if ( !xColumns->hasByName( rColumnName )
1708 || !( xColumns->getByName( rColumnName ) >>= xColumn )
1710 continue;
1712 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1714 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1715 xNewColumn = pColumn;
1716 pColumn->setTableName(aIter->first);
1717 pColumn->setName(aNewColName);
1718 pColumn->setRealName(rColumnName);
1720 break;
1723 if ( !xNewColumn.is() )
1725 // no function (due to the above !bFkt), no existing column
1726 // => assume an expression
1727 ::rtl::OUString aNewColName( getUniqueColumnName( rColumnAlias ) );
1728 // did not find a column with this name in any of the tables
1729 OParseColumn* pColumn = new OParseColumn(
1730 aNewColName,
1731 ::rtl::OUString::createFromAscii( "VARCHAR" ),
1732 // TODO: does this match with _nType?
1733 // Or should be fill this from the getTypeInfo of the connection?
1734 ::rtl::OUString(),
1735 ColumnValue::NULLABLE_UNKNOWN,
1738 _nType,
1739 sal_False,
1740 sal_False,
1741 isCaseSensitive()
1744 xNewColumn = pColumn;
1745 pColumn->setRealName( rColumnName );
1748 _rColumns->get().push_back( xNewColumn );
1750 else
1752 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1754 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),
1755 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
1756 pColumn->setFunction(sal_True);
1757 pColumn->setAggregateFunction(bAggFkt);
1758 pColumn->setRealName(rColumnName);
1760 Reference< XPropertySet> xCol = pColumn;
1761 _rColumns->get().push_back(xCol);
1764 else // ColumnName und Tablename vorhanden
1766 ConstOSQLTablesIterator aFind = m_pImpl->m_pTables->find(rTableRange);
1768 sal_Bool bError = sal_False;
1769 if (aFind != m_pImpl->m_pTables->end() && aFind->second.is())
1771 if (bFkt)
1773 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1775 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),
1776 ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,sal_False,sal_False,isCaseSensitive());
1777 pColumn->setFunction(sal_True);
1778 pColumn->setAggregateFunction(bAggFkt);
1779 pColumn->setRealName(rColumnName);
1780 pColumn->setTableName(aFind->first);
1782 Reference< XPropertySet> xCol = pColumn;
1783 _rColumns->get().push_back(xCol);
1785 else
1787 Reference< XPropertySet > xColumn;
1788 if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn))
1790 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1792 OParseColumn* pColumn = new OParseColumn(xColumn,isCaseSensitive());
1793 pColumn->setName(aNewColName);
1794 pColumn->setRealName(rColumnName);
1795 pColumn->setTableName(aFind->first);
1797 Reference< XPropertySet> xCol = pColumn;
1798 _rColumns->get().push_back(xCol);
1800 else
1801 bError = sal_True;
1804 else
1805 bError = sal_True;
1807 // Tabelle existiert nicht oder Feld nicht vorhanden
1808 if (bError)
1810 ::rtl::OUString aNewColName(getUniqueColumnName(rColumnAlias));
1812 OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(),
1813 ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,isCaseSensitive());
1814 pColumn->setFunction(sal_True);
1815 pColumn->setAggregateFunction(bAggFkt);
1817 Reference< XPropertySet> xCol = pColumn;
1818 _rColumns->get().push_back(xCol);
1822 //-----------------------------------------------------------------------------
1823 ::rtl::OUString OSQLParseTreeIterator::getUniqueColumnName(const ::rtl::OUString & rColumnName) const
1825 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getUniqueColumnName" );
1826 ::rtl::OUString aAlias(rColumnName);
1828 OSQLColumns::Vector::const_iterator aIter = find(
1829 m_aSelectColumns->get().begin(),
1830 m_aSelectColumns->get().end(),
1831 aAlias,
1832 ::comphelper::UStringMixEqual( isCaseSensitive() )
1834 sal_Int32 i=1;
1835 while(aIter != m_aSelectColumns->get().end())
1837 (aAlias = rColumnName) += ::rtl::OUString::valueOf(i++);
1838 aIter = find(
1839 m_aSelectColumns->get().begin(),
1840 m_aSelectColumns->get().end(),
1841 aAlias,
1842 ::comphelper::UStringMixEqual( isCaseSensitive() )
1845 return aAlias;
1847 //-----------------------------------------------------------------------------
1848 void OSQLParseTreeIterator::setOrderByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange,sal_Bool bAscending)
1850 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setOrderByColumnName" );
1851 Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
1852 if ( xColumn.is() )
1853 m_aOrderColumns->get().push_back(new OOrderColumn(xColumn,isCaseSensitive(),bAscending));
1854 else
1856 sal_Int32 nId = rColumnName.toInt32();
1857 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1858 m_aOrderColumns->get().push_back(new OOrderColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive(),bAscending));
1861 #ifdef SQL_TEST_PARSETREEITERATOR
1862 cout << "OSQLParseTreeIterator::setOrderByColumnName: "
1863 << (const char *) rColumnName << ", "
1864 << (const char *) rTableRange << ", "
1865 << (bAscending ? "sal_True" : "sal_False")
1866 << "\n";
1867 #endif
1869 //-----------------------------------------------------------------------------
1870 void OSQLParseTreeIterator::setGroupByColumnName(const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
1872 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::setGroupByColumnName" );
1873 Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false );
1874 if ( xColumn.is() )
1875 m_aGroupColumns->get().push_back(new OParseColumn(xColumn,isCaseSensitive()));
1876 else
1878 sal_Int32 nId = rColumnName.toInt32();
1879 if ( nId > 0 && nId < static_cast<sal_Int32>(m_aSelectColumns->get().size()) )
1880 m_aGroupColumns->get().push_back(new OParseColumn((m_aSelectColumns->get())[nId-1],isCaseSensitive()));
1883 #ifdef SQL_TEST_PARSETREEITERATOR
1884 cout << "OSQLParseTreeIterator::setOrderByColumnName: "
1885 << (const char *) rColumnName << ", "
1886 << (const char *) rTableRange << ", "
1887 << (bAscending ? "sal_True" : "sal_False")
1888 << "\n";
1889 #endif
1892 //-----------------------------------------------------------------------------
1893 const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const
1895 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getWhereTree" );
1898 if (!m_pParseTree)
1899 return NULL;
1901 // Parse Tree analysieren (je nach Statement-Typ)
1902 // und Zeiger auf WHERE-Klausel setzen:
1903 OSQLParseNode * pWhereClause = NULL;
1904 if(getStatementType() == SQL_STATEMENT_SELECT)
1906 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1907 OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1908 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1909 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1910 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1912 pWhereClause = pTableExp->getChild(1);
1914 else if (SQL_ISRULE(m_pParseTree,update_statement_searched) ||
1915 SQL_ISRULE(m_pParseTree,delete_statement_searched))
1917 pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1);
1919 if(pWhereClause->count() != 2)
1920 pWhereClause = NULL;
1921 return pWhereClause;
1924 //-----------------------------------------------------------------------------
1925 const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const
1927 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getOrderTree" );
1930 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1931 return NULL;
1933 // Parse Tree analysieren (je nach Statement-Typ)
1934 // und Zeiger auf ORDER-Klausel setzen:
1935 OSQLParseNode * pOrderClause = NULL;
1936 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1937 OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1938 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1939 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1940 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1942 pOrderClause = pTableExp->getChild(4);
1943 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
1944 if(pOrderClause->count() != 3)
1945 pOrderClause = NULL;
1946 return pOrderClause;
1948 //-----------------------------------------------------------------------------
1949 const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const
1951 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getGroupByTree" );
1952 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1953 return NULL;
1955 // Parse Tree analysieren (je nach Statement-Typ)
1956 // und Zeiger auf ORDER-Klausel setzen:
1957 OSQLParseNode * pGroupClause = NULL;
1958 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1959 OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1960 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1961 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1962 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1964 pGroupClause = pTableExp->getChild(2);
1965 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
1966 if(pGroupClause->count() != 3)
1967 pGroupClause = NULL;
1968 return pGroupClause;
1970 //-----------------------------------------------------------------------------
1971 const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const
1973 if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT)
1974 return NULL;
1976 // Parse Tree analysieren (je nach Statement-Typ)
1977 // und Zeiger auf ORDER-Klausel setzen:
1978 OSQLParseNode * pHavingClause = NULL;
1979 OSL_ENSURE(m_pParseTree->count() >= 4,"ParseTreeIterator: error in parse tree!");
1980 OSQLParseNode * pTableExp = m_pParseTree->getChild(3);
1981 OSL_ENSURE(pTableExp != NULL,"OSQLParseTreeIterator: error in parse tree!");
1982 OSL_ENSURE(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: error in parse tree!");
1983 OSL_ENSURE(pTableExp->count() == 5,"OSQLParseTreeIterator: error in parse tree!");
1985 pHavingClause = pTableExp->getChild(3);
1986 // Wenn es aber eine order_by ist, dann darf sie nicht leer sein:
1987 if(pHavingClause->count() < 1)
1988 pHavingClause = NULL;
1989 return pHavingClause;
1991 // -----------------------------------------------------------------------------
1992 sal_Bool OSQLParseTreeIterator::isTableNode(const OSQLParseNode* _pTableNode) const
1994 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::isTableNode" );
1995 return _pTableNode && (SQL_ISRULE(_pTableNode,catalog_name) ||
1996 SQL_ISRULE(_pTableNode,schema_name) ||
1997 SQL_ISRULE(_pTableNode,table_name));
1999 // -----------------------------------------------------------------------------
2000 const OSQLParseNode* OSQLParseTreeIterator::getSimpleWhereTree() const
2002 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleWhereTree" );
2003 const OSQLParseNode* pNode = getWhereTree();
2004 return pNode ? pNode->getChild(1) : NULL;
2006 // -----------------------------------------------------------------------------
2007 const OSQLParseNode* OSQLParseTreeIterator::getSimpleOrderTree() const
2009 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleOrderTree" );
2010 const OSQLParseNode* pNode = getOrderTree();
2011 return pNode ? pNode->getChild(2) : NULL;
2013 // -----------------------------------------------------------------------------
2014 const OSQLParseNode* OSQLParseTreeIterator::getSimpleGroupByTree() const
2016 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleGroupByTree" );
2017 const OSQLParseNode* pNode = getGroupByTree();
2018 return pNode ? pNode->getChild(2) : NULL;
2020 // -----------------------------------------------------------------------------
2021 const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const
2023 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::getSimpleHavingTree" );
2024 const OSQLParseNode* pNode = getHavingTree();
2025 return pNode ? pNode->getChild(1) : NULL;
2028 // -----------------------------------------------------------------------------
2029 Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange, bool _bLookInSubTables )
2031 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
2032 Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange );
2033 if ( !xColumn.is() && _bLookInSubTables )
2034 xColumn = findColumn( *m_pImpl->m_pSubTables, rColumnName, rTableRange );
2035 return xColumn;
2038 // -----------------------------------------------------------------------------
2039 Reference< XPropertySet > OSQLParseTreeIterator::findColumn(const OSQLTables& _rTables,const ::rtl::OUString & rColumnName, const ::rtl::OUString & rTableRange)
2041 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::findColumn" );
2042 Reference< XPropertySet > xColumn;
2043 if ( rTableRange.getLength() )
2045 ConstOSQLTablesIterator aFind = _rTables.find(rTableRange);
2047 if ( aFind != _rTables.end()
2048 && aFind->second.is()
2049 && aFind->second->getColumns().is()
2050 && aFind->second->getColumns()->hasByName(rColumnName) )
2051 aFind->second->getColumns()->getByName(rColumnName) >>= xColumn;
2053 if ( !xColumn.is() )
2055 OSQLTables::const_iterator aEnd = _rTables.end();
2056 for(OSQLTables::const_iterator aIter = _rTables.begin(); aIter != aEnd; ++aIter)
2058 if ( aIter->second.is() )
2060 Reference<XNameAccess> xColumns = aIter->second->getColumns();
2061 if( xColumns.is() && xColumns->hasByName(rColumnName) && (xColumns->getByName(rColumnName) >>= xColumn) )
2063 OSL_ENSURE(xColumn.is(),"Column isn't a propertyset!");
2064 break; // diese Column darf nur einmal vorkommen
2069 return xColumn;
2072 // -----------------------------------------------------------------------------
2073 void OSQLParseTreeIterator::impl_appendError( IParseContext::ErrorCode _eError, const ::rtl::OUString* _pReplaceToken1, const ::rtl::OUString* _pReplaceToken2 )
2075 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
2076 ::rtl::OUString sErrorMessage = m_rParser.getContext().getErrorMessage( _eError );
2077 if ( _pReplaceToken1 )
2079 bool bTwoTokens = ( _pReplaceToken2 != NULL );
2080 const sal_Char* pPlaceHolder1 = bTwoTokens ? "#1" : "#";
2081 const ::rtl::OUString sPlaceHolder1 = ::rtl::OUString::createFromAscii( pPlaceHolder1 );
2083 sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( sPlaceHolder1 ), sPlaceHolder1.getLength(), *_pReplaceToken1 );
2084 if ( _pReplaceToken2 )
2085 sErrorMessage = sErrorMessage.replaceAt( sErrorMessage.indexOf( ::rtl::OUString::createFromAscii( "#2" ) ), 2, *_pReplaceToken2 );
2088 impl_appendError( SQLException(
2089 sErrorMessage, NULL, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ) );
2092 // -----------------------------------------------------------------------------
2093 void OSQLParseTreeIterator::impl_appendError( const SQLException& _rError )
2095 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "Ocke.Janssen@sun.com", "OSQLParseTreeIterator::impl_appendError" );
2096 if ( m_aErrors.Message.getLength() )
2098 SQLException* pErrorChain = &m_aErrors;
2099 while ( pErrorChain->NextException.hasValue() )
2100 pErrorChain = static_cast< SQLException* >( pErrorChain->NextException.pData );
2101 pErrorChain->NextException <<= _rError;
2103 else
2104 m_aErrors = _rError;
2106 // -----------------------------------------------------------------------------