1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 
31 #include "composertools.hxx"
32 #include "core_resource.hrc"
33 #include "core_resource.hxx"
34 #include "dbastrings.hrc"
35 #include "HelperCollections.hxx"
36 #include "SingleSelectQueryComposer.hxx"
37 #include "sdbcoretools.hxx"
38 
39 /** === begin UNO includes === **/
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/i18n/XLocaleData.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
45 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/sdb/CommandType.hpp>
48 #include <com/sun/star/sdbc/ColumnSearch.hpp>
49 #include <com/sun/star/sdbc/DataType.hpp>
50 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
51 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
52 #include <com/sun/star/sdbc/XParameters.hpp>
53 #include <com/sun/star/uno/XAggregation.hpp>
54 #include <com/sun/star/util/XNumberFormatter.hpp>
55 /** === end UNO includes === **/
56 
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/sequence.hxx>
59 #include <comphelper/types.hxx>
60 #include <cppuhelper/typeprovider.hxx>
61 #include <connectivity/predicateinput.hxx>
62 #include <rtl/logfile.hxx>
63 #include <unotools/syslocale.hxx>
64 #include <tools/debug.hxx>
65 #include <tools/diagnose_ex.h>
66 #include <unotools/configmgr.hxx>
67 #include <unotools/sharedunocomponent.hxx>
68 
69 #include <memory>
70 
71 using namespace ::dbaccess;
72 using namespace ::dbtools;
73 using namespace ::comphelper;
74 using namespace ::connectivity;
75 using namespace ::com::sun::star::uno;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::sdbc;
78 using namespace ::com::sun::star::sdb;
79 using namespace ::com::sun::star::sdbcx;
80 using namespace ::com::sun::star::container;
81 using namespace ::com::sun::star::i18n;
82 using namespace ::com::sun::star::lang;
83 using namespace ::com::sun::star::script;
84 using namespace ::com::sun::star::util;
85 using namespace ::cppu;
86 using namespace ::osl;
87 using namespace ::utl;
88 
89 namespace dbaccess {
90 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
91 }
92 
93 #define STR_SELECT		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT "))
94 #define STR_FROM		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM "))
95 #define STR_WHERE		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" WHERE "))
96 #define STR_GROUP_BY	::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" GROUP BY "))
97 #define STR_HAVING		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" HAVING "))
98 #define STR_ORDER_BY	::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ORDER BY "))
99 #define STR_AND			::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" AND "))
100 #define STR_OR			::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" OR "))
101 #define STR_LIKE		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE "))
102 #define STR_EQUAL		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = "))
103 #define L_BRACKET		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("))
104 #define R_BRACKET		::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"))
105 #define COMMA			::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","))
106 
107 // -------------------------------------------------------------------------
108 namespace
109 {
110     // .....................................................................
111     /** parses the given statement, using the given parser, returns a parse node representing
112         the statement
113 
114         If the statement cannot be parsed, an error is thrown.
115     */
116     const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement, const Reference< XInterface >& _rxContext )
117     {
118         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
119 	    ::rtl::OUString aErrorMsg;
120 	    const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
121 	    if ( !pNewSqlParseNode )
122 	    {
123             ::rtl::OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
124 		    SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
125 		    SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
126 		    throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
127 	    }
128         return pNewSqlParseNode;
129     }
130 
131     // .....................................................................
132     /** checks whether the given parse node describes a valid single select statement, throws
133         an error if not
134     */
135     void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
136         const Reference< XInterface >& _rxContext, const ::rtl::OUString& _rOriginatingCommand )
137     {
138         const OSQLParseNode* pOldNode = _rIterator.getParseTree();
139 
140         // determine the statement type
141 	    _rIterator.setParseTree( pStatementNode );
142 	    _rIterator.traverseAll();
143         bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
144 
145         // throw the error, if necessary
146 	    if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
147 	    {
148             // restore the old node before throwing the exception
149             _rIterator.setParseTree( pOldNode );
150             // and now really ...
151 		    SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
152 		    throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
153 			    getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
154 	    }
155 
156         delete pOldNode;
157     }
158 
159     // .....................................................................
160     /** combines parseStatement_throwError and checkForSingleSelect_throwError
161     */
162     void parseAndCheck_throwError( OSQLParser& _rParser, const ::rtl::OUString& _rStatement,
163         OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
164     {
165         RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
166         const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
167         checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
168     }
169 
170     // .....................................................................
171     /** transforms a parse node describing a complete statement into a pure select
172         statement, without any filter/order/groupby/having clauses
173     */
174     ::rtl::OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
175     {
176         ::rtl::OUString sSQL = STR_SELECT;
177 	    _pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
178 	    _pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
179 	    sSQL += STR_FROM;
180 	    _pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
181         return sSQL;
182     }
183 
184     /** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
185     */
186     void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
187     {
188 	    const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
189 	    _rIterator.setParseTree(NULL);
190 	    delete pSqlParseNode;
191         if ( _bDispose )
192 	        _rIterator.dispose();
193     }
194     void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const ::rtl::OUString& i_sValue,::rtl::OUStringBuffer& o_sRet)
195     {
196         switch( i_nFilterOperator )
197 	    {
198 		    case SQLFilterOperator::EQUAL:
199 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" = ")));
200 			    o_sRet.append(i_sValue);
201 			    break;
202 		    case SQLFilterOperator::NOT_EQUAL:
203 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <> ")));
204 			    o_sRet.append(i_sValue);
205 			    break;
206 		    case SQLFilterOperator::LESS:
207 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" < ")));
208 			    o_sRet.append(i_sValue);
209 			    break;
210 		    case SQLFilterOperator::GREATER:
211 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" > ")));
212 			    o_sRet.append(i_sValue);
213 			    break;
214 		    case SQLFilterOperator::LESS_EQUAL:
215 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" <= ")));
216 			    o_sRet.append(i_sValue);
217 			    break;
218 		    case SQLFilterOperator::GREATER_EQUAL:
219 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" >= ")));
220 			    o_sRet.append(i_sValue);
221 			    break;
222 		    case SQLFilterOperator::LIKE:
223 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" LIKE ")));
224 			    o_sRet.append(i_sValue);
225 			    break;
226 		    case SQLFilterOperator::NOT_LIKE:
227 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" NOT LIKE ")));
228 			    o_sRet.append(i_sValue);
229 			    break;
230 		    case SQLFilterOperator::SQLNULL:
231 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NULL")) );
232 			    break;
233 		    case SQLFilterOperator::NOT_SQLNULL:
234 			    o_sRet.append(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" IS NOT NULL")) );
235 			    break;
236 		    default:
237 			    throw SQLException();
238 	    }
239     }
240 
241 }
242 
243 DBG_NAME(OSingleSelectQueryComposer)
244 // -------------------------------------------------------------------------
245 OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
246 							   const Reference< XConnection>& _xConnection,
247                                const ::comphelper::ComponentContext& _rContext )
248     :OSubComponent(m_aMutex,_xConnection)
249     ,OPropertyContainer(m_aBHelper)
250     ,m_aSqlParser( _rContext.getLegacyServiceFactory() )
251     ,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
252     ,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
253     ,m_aElementaryParts( (size_t)SQLPartCount )
254     ,m_xConnection(_xConnection)
255     ,m_xMetaData(_xConnection->getMetaData())
256     ,m_xConnectionTables( _rxTables )
257     ,m_aContext( _rContext )
258     ,m_pTables(NULL)
259     ,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
260     ,m_nCommandType(CommandType::COMMAND)
261 {
262     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
263 	DBG_CTOR(OSingleSelectQueryComposer,NULL);
264 
265     if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
266         throw IllegalArgumentException();
267 
268     registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
269 
270 	m_aCurrentColumns.resize(4);
271 
272 	m_aLocale = SvtSysLocale().GetLocaleData().getLocale();
273 	m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getLegacyServiceFactory() );
274     Reference< XLocaleData > xLocaleData;
275     m_aContext.createComponent( "com.sun.star.i18n.LocaleData", xLocaleData );
276 	LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
277 	m_sDecimalSep = aData.decimalSeparator;
278 	OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
279 	try
280 	{
281         Any aValue;
282         Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
283         if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
284         {
285             OSL_VERIFY( aValue >>= m_nBoolCompareMode );
286         }
287         Reference< XQueriesSupplier >  xQueriesAccess(m_xConnection, UNO_QUERY);
288 		if (xQueriesAccess.is())
289 			m_xConnectionQueries = xQueriesAccess->getQueries();
290 	}
291 	catch(Exception&)
292 	{
293 	}
294 }
295 // -------------------------------------------------------------------------
296 OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
297 {
298 	DBG_DTOR(OSingleSelectQueryComposer,NULL);
299 	::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
300 	::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
301 	for(;aColIter != aEnd;++aColIter)
302 		delete *aColIter;
303 
304 	::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
305     ::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
306 	for(;aTabIter != aTabEnd;++aTabIter)
307 		delete *aTabIter;
308 }
309 // -------------------------------------------------------------------------
310 // OComponentHelper
311 void SAL_CALL OSingleSelectQueryComposer::disposing(void)
312 {
313     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
314 	OSubComponent::disposing();
315 
316 	MutexGuard aGuard(m_aMutex);
317 
318     resetIterator( m_aSqlIterator, true );
319     resetIterator( m_aAdditiveIterator, true );
320 
321 	m_xConnectionTables	= NULL;
322 	m_xConnection		= NULL;
323 
324 	clearCurrentCollections();
325 }
326 IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
327 IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER)
328 IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
329 IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
330 
331 // -------------------------------------------------------------------------
332 // com::sun::star::lang::XUnoTunnel
333 sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
334 {
335     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
336 	if (rId.getLength() == 16 && 0 == rtl_compareMemory(getImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
337 		return reinterpret_cast<sal_Int64>(this);
338 
339 	return sal_Int64(0);
340 }
341 
342 // -------------------------------------------------------------------------
343 // XSingleSelectQueryAnalyzer
344 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQuery(  ) throw(RuntimeException)
345 {
346     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
347 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
348 	::osl::MutexGuard aGuard( m_aMutex );
349 
350 	TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
351 	return getStatementPart(F_tmp,m_aSqlIterator);
352 }
353 
354 // -------------------------------------------------------------------------
355 void SAL_CALL OSingleSelectQueryComposer::setQuery( const ::rtl::OUString& command ) throw(SQLException, RuntimeException)
356 {
357     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
358 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
359 
360 	::osl::MutexGuard aGuard( m_aMutex );
361     m_nCommandType = CommandType::COMMAND;
362 	// first clear the tables and columns
363 	clearCurrentCollections();
364 	// now set the new one
365 	setQuery_Impl(command);
366     m_sOrignal = command;
367 
368     // reset the additive iterator to the same statement
369     parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
370 
371     // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
372     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
373         m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
374 }
375 // -------------------------------------------------------------------------
376 void SAL_CALL OSingleSelectQueryComposer::setCommand( const ::rtl::OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException)
377 {
378     ::rtl::OUStringBuffer sSQL;
379     switch(_nCommandType)
380     {
381         case CommandType::COMMAND:
382             setElementaryQuery(Command);
383             return;
384         case CommandType::TABLE:
385             if ( m_xConnectionTables->hasByName(Command) )
386             {
387                 sSQL.appendAscii("SELECT * FROM ");
388                 Reference< XPropertySet > xTable;
389 			    try
390 			    {
391                     m_xConnectionTables->getByName( Command ) >>= xTable;
392 			    }
393 			    catch(const WrappedTargetException& e)
394 			    {
395 				    SQLException e2;
396 				    if ( e.TargetException >>= e2 )
397 					    throw e2;
398 			    }
399 			    catch(Exception&)
400 			    {
401                     DBG_UNHANDLED_EXCEPTION();
402 			    }
403 
404                 sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
405             }
406             else
407             {
408                 String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
409                 sMessage.SearchAndReplaceAscii( "$table$", Command );
410                 throwGenericSQLException(sMessage,*this);
411 		    }
412             break;
413         case CommandType::QUERY:
414             if ( m_xConnectionQueries->hasByName(Command) )
415             {
416 
417                 Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
418                 ::rtl::OUString sCommand;
419                 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
420                 sSQL.append(sCommand);
421             }
422             else
423             {
424                 String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
425                 sMessage.SearchAndReplaceAscii( "$table$", Command );
426                 throwGenericSQLException(sMessage,*this);
427             }
428 
429             break;
430         default:
431             break;
432     }
433 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
434 
435 	::osl::MutexGuard aGuard( m_aMutex );
436     m_nCommandType = _nCommandType;
437     m_sCommand = Command;
438 	// first clear the tables and columns
439 	clearCurrentCollections();
440 	// now set the new one
441     ::rtl::OUString sCommand = sSQL.makeStringAndClear();
442 	setElementaryQuery(sCommand);
443     m_sOrignal = sCommand;
444 /*
445     // reset the additive iterator to the same statement
446     parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
447 
448     // we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
449     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
450         m_aElementaryParts[ eLoopParts ] = ::rtl::OUString();
451 */
452 }
453 // -----------------------------------------------------------------------------
454 void OSingleSelectQueryComposer::setQuery_Impl( const ::rtl::OUString& command )
455 {
456     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
457     // parse this
458     parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
459 
460     // strip it from all clauses, to have the pure SELECT statement
461     m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
462 
463     // update columns and tables
464     // why? Shouldn't this be done on request only?
465 	// otherwise nothing is working anymore :-)
466 //	getColumns();
467 	getTables();
468 }
469 // -----------------------------------------------------------------------------
470 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause(  ) throw (RuntimeException)
471 {
472     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
473 	TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
474 	return getStructuredCondition(F_tmp);
475 }
476 // -------------------------------------------------------------------------
477 Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter(  ) throw(RuntimeException)
478 {
479     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
480 	TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
481 	return getStructuredCondition(F_tmp);
482 }
483 // -----------------------------------------------------------------------------
484 void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException)
485 {
486     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
487 	::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
488 	setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
489 }
490 // -----------------------------------------------------------------------------
491 void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException)
492 {
493     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
494 	::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
495 	setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
496 }
497 // -----------------------------------------------------------------------------
498 ::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
499 {
500     ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
501 
502     getColumns();
503 	if ( !column.is()
504 		|| !m_aCurrentColumns[SelectColumns]
505 		|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
506 		)
507 		{
508 			String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
509 			sError.SearchAndReplaceAscii("%value", ::rtl::OUString(PROPERTY_NAME));
510 			SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
511 			throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
512 		}
513 
514 	::rtl::OUString aName,aNewName;
515 	column->getPropertyValue(PROPERTY_NAME)			>>= aName;
516 
517 	if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
518 	{
519 		String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
520 		sError.SearchAndReplaceAscii("%name", aName);
521 		throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
522 	}
523 
524 	// filter anhaengen
525 	// select ohne where und order by aufbauen
526 	::rtl::OUString aQuote	= m_xMetaData->getIdentifierQuoteString();
527 	if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
528 	{
529 		Reference<XPropertySet> xColumn;
530 		m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
531 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
532 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
533 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!");
534 
535 		::rtl::OUString sRealName,sTableName;
536 		xColumn->getPropertyValue(PROPERTY_REALNAME)	>>= sRealName;
537 		xColumn->getPropertyValue(PROPERTY_TABLENAME)	>>= sTableName;
538 		sal_Bool bFunction = sal_False;
539 		xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))	>>= bFunction;
540 		if ( sRealName == aName )
541 		{
542 			if ( bFunction )
543 				aNewName = aName;
544 			else
545 			{
546 				if(sTableName.indexOf('.',0) != -1)
547 				{
548 					::rtl::OUString aCatlog,aSchema,aTable;
549 					::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
550 					sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
551 				}
552 				else
553 					sTableName = ::dbtools::quoteName(aQuote,sTableName);
554 
555 				aNewName =  sTableName;
556 				aNewName += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
557 				aNewName += ::dbtools::quoteName(aQuote,sRealName);
558 			}
559 		}
560 		else
561 			aNewName = ::dbtools::quoteName(aQuote,aName);
562 	}
563 	else
564 		aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
565     return aNewName;
566 }
567 // -------------------------------------------------------------------------
568 void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException)
569 {
570     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
571     ::osl::MutexGuard aGuard( m_aMutex );
572     ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
573 	::rtl::OUString sOrder = getOrder();
574 	if ( (sOrder.getLength() != 0) && sColumnName.getLength() )
575 		sOrder += COMMA;
576 	sOrder += sColumnName;
577 	if ( !ascending && sColumnName.getLength() )
578 		sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DESC "));
579 
580 	setOrder(sOrder);
581 }
582 
583 // -------------------------------------------------------------------------
584 void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException)
585 {
586     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
587     ::osl::MutexGuard aGuard( m_aMutex );
588     ::rtl::OUString sColumnName( impl_getColumnName_throw(column) );
589     OrderCreator aComposer;
590     aComposer.append( getGroup() );
591     aComposer.append( sColumnName );
592     setGroup( aComposer.getComposedAndClear() );
593 }
594 // -------------------------------------------------------------------------
595 ::rtl::OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts )
596 {
597     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
598     DBG_ASSERT( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
599 
600     ::rtl::OUStringBuffer aSql( m_aPureSelectSQL );
601     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
602         if ( _rParts[ eLoopParts ].getLength() )
603         {
604             aSql.append( getKeyword( eLoopParts ) );
605             aSql.append( _rParts[ eLoopParts ] );
606         }
607 
608     return aSql.makeStringAndClear();
609 }
610 
611 // -------------------------------------------------------------------------
612 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException)
613 {
614     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
615     return composeStatementFromParts( m_aElementaryParts );
616 }
617 
618 // -------------------------------------------------------------------------
619 void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const ::rtl::OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
620 {
621     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
622 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
623 	::osl::MutexGuard aGuard( m_aMutex );
624 
625     // remember the 4 current "additive" clauses
626     ::std::vector< ::rtl::OUString > aAdditiveClauses( SQLPartCount );
627     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
628         aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
629 
630     // clear the tables and columns
631     clearCurrentCollections();
632     // set and parse the new query
633     setQuery_Impl( _rElementary );
634 
635     // get the 4 elementary parts of the statement
636     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
637         m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
638 
639     // reset the the AdditiveIterator: m_aPureSelectSQL may have changed
640     try
641     {
642         parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
643     }
644     catch( const Exception& e )
645     {
646         (void)e;
647         DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
648         // every part of the additive statement should have passed other tests already, and should not
649         // be able to cause any errors ... me thinks
650     }
651 }
652 
653 // -------------------------------------------------------------------------
654 namespace
655 {
656     ::rtl::OUString getComposedClause( const ::rtl::OUString _rElementaryClause, const ::rtl::OUString _rAdditionalClause,
657         TokenComposer& _rComposer, const ::rtl::OUString _rKeyword )
658     {
659         _rComposer.clear();
660         _rComposer.append( _rElementaryClause );
661         _rComposer.append( _rAdditionalClause );
662         ::rtl::OUString sComposed = _rComposer.getComposedAndClear();
663         if ( sComposed.getLength() )
664             sComposed = _rKeyword + sComposed;
665         return sComposed;
666     }
667 }
668 
669 // -------------------------------------------------------------------------
670 void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const ::rtl::OUString& _rClause )
671 {
672     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
673 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
674 	::osl::MutexGuard aGuard( m_aMutex );
675 
676     // if nothing is changed, do nothing
677     if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
678         return;
679 
680     // collect the 4 single parts as they're currently set
681     ::std::vector< ::rtl::OUString > aClauses;
682     aClauses.reserve( (size_t)SQLPartCount );
683     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
684         aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
685 
686     // overwrite the one part in question here
687     ::std::auto_ptr< TokenComposer > pComposer;
688     if ( ( _ePart == Where ) || ( _ePart == Having ) )
689         pComposer.reset( new FilterCreator );
690     else
691         pComposer.reset( new OrderCreator );
692     aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
693         *pComposer, getKeyword( _ePart ) );
694 
695     // construct the complete statement
696     ::rtl::OUStringBuffer aSql(m_aPureSelectSQL);
697     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
698         aSql.append(aClauses[ eLoopParts ]);
699 
700     // set the query
701 	setQuery_Impl(aSql.makeStringAndClear());
702 
703     // clear column collections which (might) have changed
704     clearColumns( ParameterColumns );
705     if ( _ePart == Order )
706         clearColumns( OrderColumns );
707     if ( _ePart == Group )
708         clearColumns( GroupByColumns );
709 
710     // also, since the "additive filter" change, we need to rebuild our "additive" statement
711     aSql = m_aPureSelectSQL;
712     // again, first get all the old additive parts
713     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
714         aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
715     // then overwrite the one in question
716     aClauses[ _ePart ] = getComposedClause( ::rtl::OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
717     // and parse it, so that m_aAdditiveIterator is up to date
718     for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
719         aSql.append(aClauses[ eLoopParts ]);
720     try
721     {
722         parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
723     }
724     catch( const Exception& e )
725     {
726         (void)e;
727         DBG_ERROR( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
728         // every part of the additive statement should have passed other tests already, and should not
729         // be able to cause any errors ... me thinks
730     }
731 }
732 
733 // -------------------------------------------------------------------------
734 void SAL_CALL OSingleSelectQueryComposer::setFilter( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
735 {
736     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
737     setSingleAdditiveClause( Where, filter );
738 }
739 
740 // -------------------------------------------------------------------------
741 void SAL_CALL OSingleSelectQueryComposer::setOrder( const ::rtl::OUString& order ) throw(SQLException, RuntimeException)
742 {
743     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
744     setSingleAdditiveClause( Order, order );
745 }
746 // -----------------------------------------------------------------------------
747 void SAL_CALL OSingleSelectQueryComposer::setGroup( const ::rtl::OUString& group ) throw (SQLException, RuntimeException)
748 {
749     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
750     setSingleAdditiveClause( Group, group );
751 }
752 // -------------------------------------------------------------------------
753 void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const ::rtl::OUString& filter ) throw(SQLException, RuntimeException)
754 {
755     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
756     setSingleAdditiveClause( Having, filter );
757 }
758 
759 // -------------------------------------------------------------------------
760 // XTablesSupplier
761 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables(  ) throw(RuntimeException)
762 {
763     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
764 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
765 
766 	::osl::MutexGuard aGuard( m_aMutex );
767 	if ( !m_pTables )
768 	{
769 		const OSQLTables& aTables = m_aSqlIterator.getTables();
770 		::std::vector< ::rtl::OUString> aNames;
771         OSQLTables::const_iterator aEnd = aTables.end();
772 		for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
773 			aNames.push_back(aIter->first);
774 
775 		m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
776 	}
777 
778 	return m_pTables;
779 }
780 // -------------------------------------------------------------------------
781 // XColumnsSupplier
782 Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns(  ) throw(RuntimeException)
783 {
784     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
785 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
786 	::osl::MutexGuard aGuard( m_aMutex );
787 	if ( !!m_aCurrentColumns[SelectColumns] )
788         return m_aCurrentColumns[SelectColumns];
789 
790     ::std::vector< ::rtl::OUString> aNames;
791 	::vos::ORef< OSQLColumns> aSelectColumns;
792 	sal_Bool bCase = sal_True;
793     Reference< XNameAccess>	xQueryColumns;
794     if ( m_nCommandType == CommandType::QUERY )
795     {
796         Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
797 	    if(xSup.is())
798 		    xQueryColumns = xSup->getColumns();
799     }
800 
801     do {
802 
803 	try
804 	{
805         SharedUNOComponent< XStatement, DisposableComponent > xStatement;
806         SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
807 
808         bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
809 		aSelectColumns = m_aSqlIterator.getSelectColumns();
810 
811         ::rtl::OUStringBuffer aSQL;
812         aSQL.append( m_aPureSelectSQL );
813         aSQL.append( STR_WHERE );
814 
815         // preserve the original WHERE clause
816         // #i102234# / 2009-06-02 / frank.schoenheit@sun.com
817         ::rtl::OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
818 		if ( sOriginalWhereClause.getLength() )
819         {
820             aSQL.appendAscii( " ( 0 = 1 ) AND ( " );
821             aSQL.append( sOriginalWhereClause );
822             aSQL.appendAscii( " ) " );
823         }
824         else
825         {
826             aSQL.appendAscii( " ( 0 = 1 ) " );
827         }
828 
829         ::rtl::OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
830 		if ( sGroupBy.getLength() )
831 			aSQL.append( sGroupBy );
832 
833         ::rtl::OUString sSQL( aSQL.makeStringAndClear() );
834         // normalize the statement so that it doesn't contain any application-level features anymore
835         ::rtl::OUString sError;
836         const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
837         DBG_ASSERT( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
838         if ( pStatementTree.get() )
839             if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
840                 break;
841 
842 		Reference< XResultSetMetaData > xResultSetMeta;
843         Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
844         try
845         {
846             xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
847 		    xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
848             xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
849         }
850         catch( const Exception& ) { }
851 
852         try
853         {
854             if ( !xResultSetMeta.is() )
855             {
856                 xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
857                 Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
858                 try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
859                 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
860 		        xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
861                 xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
862             }
863         }
864         catch( const Exception& )
865         {
866             //@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
867             // access returns a different order of column names when executing select * from
868             // and asking the columns from the metadata.
869             Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
870             Reference< XIndexAccess > xPara = getParameters();
871             for(sal_Int32 i = 1;i <= xPara->getCount();++i)
872                 xParameters->setNull(i,DataType::VARCHAR);
873             xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
874             xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
875         }
876 
877         if ( aSelectColumns->get().empty() )
878         {
879             // This is a valid case. If we can syntactically parse the query, but not semantically
880             // (e.g. because it is based on a table we do not know), then there will be no SelectColumns
881             aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
882             break;
883         }
884 
885         const ::comphelper::UStringMixEqual aCaseCompare( bCase );
886 		const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
887         typedef ::std::set< size_t > SizeTSet;
888         SizeTSet aUsedSelectColumns;
889         ::connectivity::parse::OParseColumn::StringMap aColumnNames;
890 
891 		sal_Int32 nCount = xResultSetMeta->getColumnCount();
892         OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
893 		for(sal_Int32 i=1;i<=nCount;++i)
894 		{
895             ::rtl::OUString sColumnName = xResultSetMeta->getColumnName(i);
896             ::rtl::OUString sColumnLabel;
897             if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
898             {
899                 Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
900                 xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
901             }
902             else
903 			    sColumnLabel = xResultSetMeta->getColumnLabel(i);
904             sal_Bool bFound = sal_False;
905 			OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
906             size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
907 			if ( aFind != aSelectColumns->get().end() )
908 			{
909                 if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
910 				{	// we found a column name which exists twice
911 					// so we start after the first found
912 					do
913 					{
914 						aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
915                         nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
916 					}
917 					while   (   ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
918                                 &&  ( aFind != aSelectColumns->get().end() )
919                             );
920 				}
921 				if ( aFind != aSelectColumns->get().end() )
922 				{
923 					(*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
924 					aUsedSelectColumns.insert( nFoundSelectColumnPos );
925 					aNames.push_back(sColumnName);
926                     bFound = sal_True;
927 				}
928 			}
929 
930             if ( bFound )
931                 continue;
932 
933 			OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
934                 aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
935 
936             if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
937             {
938                 aSelectColumns->get().push_back(
939                     ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
940                 );
941                 OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
942             }
943             else if ( aRealFind == aSelectColumns->get().end() )
944 			{
945                 // we can now only look if we found it under the realname propertery
946                 // here we have to make the assumption that the position is correct
947 				OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
948 				Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
949 				if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
950                     continue;
951 
952 				::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
953                 pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))));
954 				pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction")))));
955 
956                 ::rtl::OUString sRealName;
957                 xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
958                 ::std::vector< ::rtl::OUString>::iterator aFindName;
959 				if ( !sColumnName.getLength() )
960 					xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
961 
962 
963                 aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
964                 sal_Int32 j = 0;
965                 while ( aFindName != aNames.end() )
966                 {
967                     sColumnName += ::rtl::OUString::valueOf(++j);
968                     aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
969                 }
970 
971                 pColumn->setName(sColumnName);
972 				pColumn->setRealName(sRealName);
973 				pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
974 
975 				(aSelectColumns->get())[i-1] = pColumn;
976 			}
977             else
978                 continue;
979 
980             aUsedSelectColumns.insert( (size_t)(i - 1) );
981             aNames.push_back( sColumnName );
982 		}
983 	}
984 	catch(const Exception&)
985 	{
986 	}
987 
988     } while ( false );
989 
990     if ( aNames.empty() )
991         m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
992     else
993         m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
994 
995 	return m_aCurrentColumns[SelectColumns];
996 }
997 // -------------------------------------------------------------------------
998 sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
999 									::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1000 {
1001     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
1002 	// Runde Klammern um den Ausdruck
1003 	if (pCondition->count() == 3 &&
1004 		SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
1005 		SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
1006 	{
1007 		return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
1008 	}
1009 	// oder Verknuepfung
1010 	// a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1011 	else if (SQL_ISRULE(pCondition,search_condition))
1012 	{
1013 		sal_Bool bResult = sal_True;
1014 		for (int i = 0; bResult && i < 3; i+=2)
1015 		{
1016 			// Ist das erste Element wieder eine OR-Verknuepfung?
1017 			// Dann rekursiv absteigen ...
1018 			//if (!i && SQL_ISRULE(pCondition->getChild(i),search_condition))
1019 			if (SQL_ISRULE(pCondition->getChild(i),search_condition))
1020 				bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
1021 			else
1022 			{
1023 				rFilters.push_back( ::std::vector < PropertyValue >());
1024 				bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1025 			}
1026 		}
1027 		return bResult;
1028 	}
1029 	else
1030 	{
1031 		rFilters.push_back(::std::vector < PropertyValue >());
1032 		return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
1033 	}
1034 }
1035 
1036 //--------------------------------------------------------------------------------------------------
1037 sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
1038     OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
1039 {
1040     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
1041 	// Runde Klammern
1042 	if (SQL_ISRULE(pCondition,boolean_primary))
1043 	{
1044 		// this should not occur
1045 		DBG_ERROR("boolean_primary in And-Criteria");
1046 		return sal_False;
1047 	}
1048 	// Das erste Element ist (wieder) eine AND-Verknuepfung
1049 	else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
1050 	{
1051 		return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
1052 			   setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
1053 	}
1054 	else if (SQL_ISRULE(pCondition, comparison_predicate))
1055 	{
1056 		return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
1057 	}
1058 	else if (SQL_ISRULE(pCondition,like_predicate) ||
1059 			 SQL_ISRULE(pCondition,test_for_null) ||
1060 			 SQL_ISRULE(pCondition,in_predicate) ||
1061 			 SQL_ISRULE(pCondition,all_or_any_predicate) ||
1062 			 SQL_ISRULE(pCondition,between_predicate))
1063 	{
1064 		if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1065 		{
1066 			PropertyValue aItem;
1067 			::rtl::OUString aValue;
1068 			::rtl::OUString aColumnName;
1069 
1070 
1071 			//	pCondition->parseNodeToStr(aValue,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1072 			pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
1073 			//	pCondition->getChild(0)->parseNodeToStr(aColumnName,m_xMetaData, xFormatter, m_aLocale,static_cast<sal_Char>(m_sDecimalSep.toChar()));
1074 			pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
1075 
1076 			// don't display the column name
1077 			aValue = aValue.copy(aColumnName.getLength());
1078 			aValue = aValue.trim();
1079 
1080 			aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1081 			aItem.Value <<= aValue;
1082 			aItem.Handle = 0; // just to know that this is not one the known ones
1083 			if ( SQL_ISRULE(pCondition,like_predicate) )
1084 			{
1085                 if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
1086 					aItem.Handle = SQLFilterOperator::NOT_LIKE;
1087 				else
1088 					aItem.Handle = SQLFilterOperator::LIKE;
1089 			}
1090 			else if (SQL_ISRULE(pCondition,test_for_null))
1091 			{
1092 				if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
1093 					aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
1094 				else
1095 					aItem.Handle = SQLFilterOperator::SQLNULL;
1096 			}
1097 			else if (SQL_ISRULE(pCondition,in_predicate))
1098 			{
1099                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
1100 			}
1101 			else if (SQL_ISRULE(pCondition,all_or_any_predicate))
1102 			{
1103                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
1104 			}
1105 			else if (SQL_ISRULE(pCondition,between_predicate))
1106 			{
1107                 OSL_ENSURE( false, "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
1108 			}
1109 
1110 			rFilter.push_back(aItem);
1111 		}
1112 		else
1113 			return sal_False;
1114 	}
1115 	else if (SQL_ISRULE(pCondition,existence_test) ||
1116 			 SQL_ISRULE(pCondition,unique_test))
1117 	{
1118 		// this couldn't be handled here, too complex
1119 		// as we need a field name
1120 		return sal_False;
1121 	}
1122 	else
1123 		return sal_False;
1124 
1125 	return sal_True;
1126 }
1127 // -----------------------------------------------------------------------------
1128 sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
1129 {
1130     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
1131 	sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
1132 	switch (_pPredicate->getNodeType())
1133 	{
1134 		case SQL_NODE_EQUAL:
1135 			nPredicate = SQLFilterOperator::EQUAL;
1136 			break;
1137 		case SQL_NODE_NOTEQUAL:
1138 			nPredicate = SQLFilterOperator::NOT_EQUAL;
1139 			break;
1140 		case SQL_NODE_LESS:
1141 			nPredicate = SQLFilterOperator::LESS;
1142 			break;
1143 		case SQL_NODE_LESSEQ:
1144 			nPredicate = SQLFilterOperator::LESS_EQUAL;
1145 			break;
1146 		case SQL_NODE_GREAT:
1147 			nPredicate = SQLFilterOperator::GREATER;
1148 			break;
1149 		case SQL_NODE_GREATEQ:
1150 			nPredicate = SQLFilterOperator::GREATER_EQUAL;
1151 			break;
1152 		default:
1153 			OSL_ENSURE(0,"Wrong NodeType!");
1154 	}
1155 	return nPredicate;
1156 }
1157 //------------------------------------------------------------------------------
1158 sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
1159 										    ::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
1160 {
1161     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
1162 	DBG_ASSERT(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
1163 	if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
1164 		SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1165 	{
1166 		PropertyValue aItem;
1167 		::rtl::OUString aValue;
1168 		sal_uInt32 nPos;
1169 		if (SQL_ISRULE(pCondition->getChild(0), column_ref))
1170 		{
1171 			nPos = 0;
1172 			sal_uInt32 i=1;
1173 
1174 			aItem.Handle = getPredicateType(pCondition->getChild(i));
1175 			// don't display the equal
1176 			if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1177 				i++;
1178 
1179 			// go forward
1180 			for (;i < pCondition->count();i++)
1181 				pCondition->getChild(i)->parseNodeToPredicateStr(
1182                     aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
1183 		}
1184 		else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
1185 		{
1186 			nPos = pCondition->count()-1;
1187 
1188 			sal_Int32 i = pCondition->count() - 2;
1189 			switch (pCondition->getChild(i)->getNodeType())
1190 			{
1191 				case SQL_NODE_EQUAL:
1192 					// don't display the equal
1193 					i--;
1194 					aItem.Handle = SQLFilterOperator::EQUAL;
1195 					break;
1196 				case SQL_NODE_NOTEQUAL:
1197 					i--;
1198 					aItem.Handle = SQLFilterOperator::NOT_EQUAL;
1199 					break;
1200 				case SQL_NODE_LESS:
1201 					// take the opposite as we change the order
1202 					i--;
1203 					aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">="));
1204 					aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
1205 					break;
1206 				case SQL_NODE_LESSEQ:
1207 					// take the opposite as we change the order
1208 					i--;
1209 					aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">"));
1210 					aItem.Handle = SQLFilterOperator::GREATER;
1211 					break;
1212 				case SQL_NODE_GREAT:
1213 					// take the opposite as we change the order
1214 					i--;
1215 					aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<="));
1216 					aItem.Handle = SQLFilterOperator::LESS_EQUAL;
1217 					break;
1218 				case SQL_NODE_GREATEQ:
1219 					// take the opposite as we change the order
1220 					i--;
1221 					aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<"));
1222 					aItem.Handle = SQLFilterOperator::LESS;
1223 					break;
1224                 default:
1225                     break;
1226 			}
1227 
1228 			// go backward
1229 			for (; i >= 0; i--)
1230 				pCondition->getChild(i)->parseNodeToPredicateStr(
1231                     aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1232 		}
1233 		else
1234 			return sal_False;
1235 
1236 		aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
1237 		aItem.Value <<= aValue;
1238 		rFilter.push_back(aItem);
1239 	}
1240 	else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
1241 			 SQL_ISRULE(pCondition->getChild(0), general_set_fct))
1242 	{
1243 		PropertyValue aItem;
1244 		::rtl::OUString aValue;
1245 		::rtl::OUString aColumnName;
1246 
1247 		pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1248 		pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
1249 
1250 		aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
1251 		aItem.Value <<= aValue;
1252 		aItem.Handle = getPredicateType(pCondition->getChild(1));
1253 		rFilter.push_back(aItem);
1254 	}
1255 	else // kann sich nur um einen Expr. Ausdruck handeln
1256 	{
1257 		PropertyValue aItem;
1258 		::rtl::OUString aName, aValue;
1259 
1260 		OSQLParseNode *pLhs = pCondition->getChild(0);
1261 		OSQLParseNode *pRhs = pCondition->getChild(2);
1262 
1263 		// Feldnamen
1264 		sal_uInt16 i;
1265 		for (i=0;i< pLhs->count();i++)
1266 			 pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1267 
1268 		// Kriterium
1269 		aItem.Handle = getPredicateType(pCondition->getChild(1));
1270 		aValue		 = pCondition->getChild(1)->getTokenValue();
1271 		for(i=0;i< pRhs->count();i++)
1272 			pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
1273 
1274 		aItem.Name = aName;
1275 		aItem.Value <<= aValue;
1276 		rFilter.push_back(aItem);
1277 	}
1278 	return sal_True;
1279 }
1280 // functions for analysing SQL
1281 //--------------------------------------------------------------------------------------------------
1282 ::rtl::OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
1283 {
1284     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
1285 	::rtl::OUString aTableRange, aColumnName;
1286 	_rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
1287 	return aColumnName;
1288 }
1289 //------------------------------------------------------------------------------
1290 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getFilter(  ) throw(RuntimeException)
1291 {
1292     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
1293 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1294 	::osl::MutexGuard aGuard( m_aMutex );
1295 	return getSQLPart(Where,m_aAdditiveIterator,sal_False);
1296 }
1297 // -------------------------------------------------------------------------
1298 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getOrder(  ) throw(RuntimeException)
1299 {
1300     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
1301 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1302 	::osl::MutexGuard aGuard( m_aMutex );
1303 	return getSQLPart(Order,m_aAdditiveIterator,sal_False);
1304 }
1305 // -------------------------------------------------------------------------
1306 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getGroup(  ) throw (RuntimeException)
1307 {
1308     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
1309 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1310 	::osl::MutexGuard aGuard( m_aMutex );
1311 	return getSQLPart(Group,m_aAdditiveIterator,sal_False);
1312 }
1313 // -----------------------------------------------------------------------------
1314 ::rtl::OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException)
1315 {
1316     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
1317 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1318 	::osl::MutexGuard aGuard( m_aMutex );
1319 	return getSQLPart(Having,m_aAdditiveIterator,sal_False);
1320 }
1321 // -----------------------------------------------------------------------------
1322 ::rtl::OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
1323 {
1324     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
1325 	::rtl::OUString sReturn;
1326 	if(m_pTables && m_pTables->getCount() > 1)
1327 	{
1328 		::rtl::OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
1329 		column->getPropertyValue(PROPERTY_CATALOGNAME)	>>= aCatalog;
1330 		column->getPropertyValue(PROPERTY_SCHEMANAME)	>>= aSchema;
1331 		column->getPropertyValue(PROPERTY_TABLENAME)	>>= aTable;
1332 		column->getPropertyValue(PROPERTY_NAME)			>>= aColumnName;
1333 
1334 		Sequence< ::rtl::OUString> aNames(m_pTables->getElementNames());
1335 		const ::rtl::OUString* pBegin	= aNames.getConstArray();
1336 		const ::rtl::OUString* pEnd		= pBegin + aNames.getLength();
1337 
1338 		if(!aTable.getLength())
1339 		{ // we don't found a table name, now we must search every table for this column
1340 			for(;pBegin != pEnd;++pBegin)
1341 			{
1342 				Reference<XColumnsSupplier> xColumnsSupp;
1343 				m_pTables->getByName(*pBegin) >>= xColumnsSupp;
1344 
1345 				if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
1346 				{
1347 //					Reference<XPropertySet> xTableProp(xColumnsSupp,UNO_QUERY);
1348 //					xTableProp->getPropertyValue(PROPERTY_CATALOGNAME)	>>= aCatalog;
1349 //					xTableProp->getPropertyValue(PROPERTY_SCHEMANAME)	>>= aSchema;
1350 //					xTableProp->getPropertyValue(PROPERTY_NAME)			>>= aTable;
1351 					aTable = *pBegin;
1352 					break;
1353 				}
1354 			}
1355 		}
1356 		else
1357 		{
1358 			aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
1359 
1360 			// first check if this is the table we want to or has it a tablealias
1361 
1362 			if(!m_pTables->hasByName(aComposedName))
1363 			{
1364                 ::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
1365 				::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1366 				for(;pBegin != pEnd;++pBegin)
1367 				{
1368 					Reference<XPropertySet> xTableProp;
1369 					m_pTables->getByName(*pBegin) >>= xTableProp;
1370 					OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
1371 					if(xTableProp.is())
1372 					{
1373 						::rtl::OUString aCatalog2,aSchema2,aTable2;
1374 						xTableProp->getPropertyValue(PROPERTY_CATALOGNAME)	>>= aCatalog2;
1375 						xTableProp->getPropertyValue(PROPERTY_SCHEMANAME)	>>= aSchema2;
1376 						xTableProp->getPropertyValue(PROPERTY_NAME)			>>= aTable2;
1377 						if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
1378 						{
1379 							aCatalog	= aCatalog2;
1380 							aSchema		= aSchema2;
1381 							aTable		= aTable2;
1382 							break;
1383 						}
1384 					}
1385 				}
1386 			}
1387 		}
1388 		if(pBegin != pEnd)
1389 		{
1390 			sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1391 			sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("."));
1392 		}
1393 	}
1394 	return sReturn;
1395 }
1396 // -----------------------------------------------------------------------------
1397 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters(  ) throw(RuntimeException)
1398 {
1399     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
1400 	// now set the Parameters
1401 	if ( !m_aCurrentColumns[ParameterColumns] )
1402 	{
1403 		::vos::ORef< OSQLColumns> aCols = m_aSqlIterator.getParameters();
1404 		::std::vector< ::rtl::OUString> aNames;
1405         OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
1406 		for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
1407 			aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1408 		m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1409 	}
1410 
1411 	return m_aCurrentColumns[ParameterColumns];
1412 }
1413 // -----------------------------------------------------------------------------
1414 void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
1415 {
1416     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
1417     OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
1418 	if ( pColumns != NULL )
1419 	{
1420 		pColumns->disposing();
1421 		m_aColumnsCollection.push_back( pColumns );
1422 		m_aCurrentColumns[ _eType ] = NULL;
1423 	}
1424 }
1425 // -----------------------------------------------------------------------------
1426 void OSingleSelectQueryComposer::clearCurrentCollections()
1427 {
1428     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
1429 	::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
1430 	::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
1431 	for (;aIter != aEnd;++aIter)
1432 	{
1433 		if ( *aIter )
1434 		{
1435 			(*aIter)->disposing();
1436 			m_aColumnsCollection.push_back(*aIter);
1437 			*aIter = NULL;
1438 		}
1439 	}
1440 
1441 	if(m_pTables)
1442 	{
1443 		m_pTables->disposing();
1444 		m_aTablesCollection.push_back(m_pTables);
1445 		m_pTables = NULL;
1446 	}
1447 }
1448 // -----------------------------------------------------------------------------
1449 Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
1450     const ::vos::ORef< OSQLColumns >& _rCols )
1451 {
1452     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
1453 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1454 
1455 	::osl::MutexGuard aGuard( m_aMutex );
1456 	// now set the group columns
1457 	if ( !m_aCurrentColumns[_eType] )
1458 	{
1459 		::std::vector< ::rtl::OUString> aNames;
1460         OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
1461 		for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
1462 			aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
1463 		m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
1464 	}
1465 
1466 	return m_aCurrentColumns[_eType];
1467 }
1468 // -----------------------------------------------------------------------------
1469 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns(  ) throw(RuntimeException)
1470 {
1471     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
1472 	return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
1473 }
1474 // -------------------------------------------------------------------------
1475 Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns(  ) throw(RuntimeException)
1476 {
1477     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
1478 	return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
1479 }
1480 // -----------------------------------------------------------------------------
1481 ::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution(  ) throw (SQLException, RuntimeException)
1482 {
1483     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
1484 	::osl::MutexGuard aGuard( m_aMutex );
1485 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1486 
1487     ::rtl::OUString sSqlStatement( getQuery() );
1488 
1489     const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
1490     if ( pStatementNode )
1491     {
1492         SQLException aError;
1493         if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
1494             throw SQLException( aError );
1495     }
1496 
1497     return sSqlStatement;
1498 }
1499 // -----------------------------------------------------------------------------
1500 ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
1501 {
1502     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
1503 	::rtl::OUString sResult;
1504 
1505     const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
1506 	if ( pNode )
1507 		pNode->parseNodeToStr( sResult, m_xConnection );
1508 
1509 	return sResult;
1510 }
1511 // -----------------------------------------------------------------------------
1512 namespace
1513 {
1514 	::rtl::OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,const OPredicateInputController& i_aPredicateInputController,const Reference< XNameAccess >& i_xSelectColumns)
1515 	{
1516 		::rtl::OUStringBuffer sRet;
1517 		const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
1518 		const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
1519 		while ( pOrIter != pOrEnd )
1520 		{
1521 			if ( pOrIter->getLength() )
1522 			{
1523 				sRet.append(L_BRACKET);
1524 				const PropertyValue* pAndIter = pOrIter->getConstArray();
1525 				const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
1526 				while ( pAndIter != pAndEnd )
1527 				{
1528 					sRet.append(pAndIter->Name);
1529 					::rtl::OUString sValue;
1530 					pAndIter->Value >>= sValue;
1531                     if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(pAndIter->Name) )
1532                     {
1533                         Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(pAndIter->Name),UNO_QUERY);
1534                         sValue = i_aPredicateInputController.getPredicateValue(sValue,xColumn,sal_True);
1535                     }
1536                     else
1537                     {
1538                         sValue = i_aPredicateInputController.getPredicateValue(pAndIter->Name,sValue,sal_True);
1539                     }
1540 					lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
1541 					++pAndIter;
1542 					if ( pAndIter != pAndEnd )
1543 						sRet.append(STR_AND);
1544 				}
1545 				sRet.append(R_BRACKET);
1546 			}
1547 			++pOrIter;
1548 			if ( pOrIter != pOrEnd && sRet.getLength() )
1549 				sRet.append(STR_OR);
1550 		}
1551 		return sRet.makeStringAndClear();
1552 	}
1553 }
1554 // -----------------------------------------------------------------------------
1555 void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException)
1556 {
1557     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
1558     OPredicateInputController aPredicateInput(m_aContext.getLegacyServiceFactory(),m_xConnection);
1559 	setFilter(lcl_getCondition(filter,aPredicateInput,getColumns()));
1560 }
1561 // -----------------------------------------------------------------------------
1562 void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException)
1563 {
1564     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
1565     OPredicateInputController aPredicateInput(m_aContext.getLegacyServiceFactory(),m_xConnection);
1566 	setHavingClause(lcl_getCondition(filter,aPredicateInput,getColumns()));
1567 }
1568 // -----------------------------------------------------------------------------
1569 void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,::rtl::OUString>& _aSetFunctor,sal_Int32 filterOperator)
1570 {
1571     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
1572 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1573 
1574 	if ( !column.is()
1575 		|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
1576 		|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
1577         || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
1578 		throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
1579 
1580 	sal_Int32 nType = 0;
1581 	column->getPropertyValue(PROPERTY_TYPE) >>= nType;
1582 	sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
1583 	if(nSearchable == ColumnSearch::NONE)
1584 		throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
1585 
1586 	::osl::MutexGuard aGuard( m_aMutex );
1587 
1588 	::rtl::OUString aName;
1589 	column->getPropertyValue(PROPERTY_NAME) >>= aName;
1590 
1591 	Any aValue;
1592 	column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
1593 
1594 	::rtl::OUStringBuffer aSQL;
1595 	const ::rtl::OUString aQuote	= m_xMetaData->getIdentifierQuoteString();
1596     getColumns();
1597 
1598 	if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
1599 	{
1600 		Reference<XPropertySet> xColumn;
1601 		m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
1602 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1603 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1604 		OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))),"Property AggregateFunctionnot available!");
1605 
1606 		::rtl::OUString sRealName,sTableName;
1607 		xColumn->getPropertyValue(PROPERTY_REALNAME)	>>= sRealName;
1608 		xColumn->getPropertyValue(PROPERTY_TABLENAME)	>>= sTableName;
1609 		if(sTableName.indexOf('.',0) != -1)
1610 		{
1611 			::rtl::OUString aCatlog,aSchema,aTable;
1612 			::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
1613 			sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
1614 		}
1615 		else
1616 			sTableName = ::dbtools::quoteName(aQuote,sTableName);
1617 
1618 		if ( !::comphelper::getBOOL(xColumn->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function")))) )
1619 		{
1620 			aSQL =  sTableName;
1621 			aSQL.appendAscii( "." );
1622 			aSQL.append( ::dbtools::quoteName( aQuote, sRealName ) );
1623 		}
1624 		else
1625 			aSQL = sRealName;
1626 
1627 	}
1628 	else
1629     {
1630 		aSQL = getTableAlias( column );
1631         aSQL.append( ::dbtools::quoteName( aQuote, aName ) );
1632     }
1633 
1634 
1635 	if ( aValue.hasValue() )
1636 	{
1637 		if(  !m_xTypeConverter.is() )
1638             m_aContext.createComponent( "com.sun.star.script.Converter", m_xTypeConverter );
1639 		OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
1640 
1641         if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
1642         {
1643             ::rtl::OUString sEmpty;
1644             lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
1645         }
1646 
1647 		switch(nType)
1648 		{
1649 			case DataType::VARCHAR:
1650 			case DataType::CHAR:
1651 			case DataType::LONGVARCHAR:
1652 				aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1653 				break;
1654 			case DataType::CLOB:
1655 				{
1656 					Reference< XClob > xClob(aValue,UNO_QUERY);
1657 					if ( xClob.is() )
1658 					{
1659 						const ::sal_Int64 nLength = xClob->length();
1660 						if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
1661 						{
1662 							aSQL.appendAscii("'");
1663 							aSQL.append( xClob->getSubString(1,(sal_Int32)nLength) );
1664 							aSQL.appendAscii("'");
1665 						}
1666 					}
1667 					else
1668 					{
1669 						aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1670 					}
1671 				}
1672 				break;
1673 			case DataType::VARBINARY:
1674 			case DataType::BINARY:
1675 			case DataType::LONGVARBINARY:
1676 				{
1677 					Sequence<sal_Int8> aSeq;
1678 					if(aValue >>= aSeq)
1679 					{
1680 						if(nSearchable == ColumnSearch::CHAR)
1681 						{
1682                             aSQL.appendAscii( "\'" );
1683 						}
1684                         aSQL.appendAscii( "0x" );
1685 						const sal_Int8* pBegin	= aSeq.getConstArray();
1686 						const sal_Int8* pEnd	= pBegin + aSeq.getLength();
1687 						for(;pBegin != pEnd;++pBegin)
1688 						{
1689 							aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
1690 						}
1691 						if(nSearchable == ColumnSearch::CHAR)
1692 							aSQL.appendAscii( "\'" );
1693 					}
1694 					else
1695 						throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
1696 				}
1697 				break;
1698 			case DataType::BIT:
1699             case DataType::BOOLEAN:
1700 				{
1701 					sal_Bool bValue = sal_False;
1702 					m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
1703 
1704                     ::rtl::OUString sColumnExp = aSQL.makeStringAndClear();
1705                     getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
1706 				}
1707                 break;
1708 			default:
1709 				aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
1710                 break;
1711 		}
1712 	}
1713 	else
1714     {
1715         sal_Int32 nFilterOp = filterOperator;
1716         if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
1717             nFilterOp = SQLFilterOperator::SQLNULL;
1718         ::rtl::OUString sEmpty;
1719         lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
1720     }
1721 
1722 	// filter anhaengen
1723 	// select ohne where und order by aufbauen
1724 	::rtl::OUString sFilter = getFilter();
1725 
1726 	if ( sFilter.getLength() && aSQL.getLength() )
1727 	{
1728 		::rtl::OUString sTemp(L_BRACKET);
1729 		sTemp += sFilter;
1730 		sTemp += R_BRACKET;
1731 		sTemp += andCriteria ? STR_AND : STR_OR;
1732 		sFilter = sTemp;
1733 	}
1734 	sFilter += aSQL.makeStringAndClear();
1735 
1736 	// add the filter and the sort order
1737 	_aSetFunctor(this,sFilter);
1738 }
1739 // -----------------------------------------------------------------------------
1740 Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
1741 {
1742     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
1743 	::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
1744 
1745 	MutexGuard aGuard(m_aMutex);
1746 
1747 	Sequence< Sequence< PropertyValue > > aFilterSeq;
1748 	::rtl::OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
1749 
1750 	if ( sFilter.getLength() != 0 )
1751 	{
1752 		::rtl::OUString aSql(m_aPureSelectSQL);
1753 		// build a temporary parse node
1754 		const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
1755 
1756 		aSql += STR_WHERE;
1757 		aSql += sFilter;
1758 
1759 		::rtl::OUString aErrorMsg;
1760 		::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
1761 		if ( pSqlParseNode.get() )
1762 		{
1763 			m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
1764 			// normalize the filter
1765 			OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
1766 
1767 			OSQLParseNode* pCondition = pWhereNode->getChild(1);
1768         #if OSL_DEBUG_LEVEL > 0
1769             ::rtl::OUString sCondition;
1770             pCondition->parseNodeToStr( sCondition, m_xConnection );
1771         #endif
1772 			OSQLParseNode::negateSearchCondition(pCondition);
1773 
1774 			pCondition = pWhereNode->getChild(1);
1775         #if OSL_DEBUG_LEVEL > 0
1776             sCondition = ::rtl::OUString();
1777             pCondition->parseNodeToStr( sCondition, m_xConnection );
1778         #endif
1779 			OSQLParseNode::disjunctiveNormalForm(pCondition);
1780 
1781 			pCondition = pWhereNode->getChild(1);
1782         #if OSL_DEBUG_LEVEL > 0
1783             sCondition = ::rtl::OUString();
1784             pCondition->parseNodeToStr( sCondition, m_xConnection );
1785         #endif
1786 			OSQLParseNode::absorptions(pCondition);
1787 
1788 			pCondition = pWhereNode->getChild(1);
1789         #if OSL_DEBUG_LEVEL > 0
1790             sCondition = ::rtl::OUString();
1791             pCondition->parseNodeToStr( sCondition, m_xConnection );
1792         #endif
1793 			if ( pCondition )
1794 			{
1795 				::std::vector< ::std::vector < PropertyValue > > aFilters;
1796                 Reference< XNumberFormatter > xFormatter;
1797                 m_aContext.createComponent( "com.sun.star.util.NumberFormatter", xFormatter );
1798 				xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
1799 
1800 				if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
1801 				{
1802 					aFilterSeq.realloc(aFilters.size());
1803 					Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
1804 					::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
1805 					::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
1806 					for ( ; i != aEnd ; ++i)
1807 					{
1808 						const ::std::vector < PropertyValue >& rProperties = *i;
1809 						pFilters->realloc(rProperties.size());
1810 						PropertyValue* pFilter = pFilters->getArray();
1811 						::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
1812 						::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
1813 						for ( ; j != aEnd2 ; ++j)
1814 						{
1815 							*pFilter = *j;
1816 							++pFilter;
1817 						}
1818 						++pFilters;
1819 					}
1820 				}
1821 			}
1822 			// restore
1823 			m_aAdditiveIterator.setParseTree(pTempNode);
1824 		}
1825 	}
1826 	return aFilterSeq;
1827 }
1828 // -----------------------------------------------------------------------------
1829 ::rtl::OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
1830 {
1831     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
1832 	::rtl::OUString sKeyword;
1833 	switch(_ePart)
1834 	{
1835 		default:
1836             OSL_ENSURE( 0, "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
1837             // no break, fallback to WHERE
1838 		case Where:
1839 			sKeyword = STR_WHERE;
1840 			break;
1841 		case Group:
1842 			sKeyword = STR_GROUP_BY;
1843 			break;
1844 		case Having:
1845 			sKeyword = STR_HAVING;
1846 			break;
1847 		case Order:
1848 			sKeyword = STR_ORDER_BY;
1849 			break;
1850 	}
1851 	return sKeyword;
1852 }
1853 
1854 // -----------------------------------------------------------------------------
1855 ::rtl::OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
1856 {
1857     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
1858 	TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
1859 	::rtl::OUString sKeyword( getKeyword( _ePart ) );
1860 	switch(_ePart)
1861 	{
1862 		case Where:
1863 			F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
1864 			break;
1865 		case Group:
1866 			F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
1867 			break;
1868 		case Having:
1869 			F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
1870 			break;
1871 		case Order:
1872 			F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
1873 			break;
1874 		default:
1875 			OSL_ENSURE(0,"Invalid enum value!");
1876 	}
1877 
1878 	::rtl::OUString sRet = getStatementPart( F_tmp, _rIterator );
1879 	if ( _bWithKeyword && sRet.getLength() )
1880 		sRet = sKeyword + sRet;
1881 	return sRet;
1882 }
1883 // -----------------------------------------------------------------------------
1884