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 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
31 #include "QueryDesignView.hxx"
32 #endif
33 #ifndef DBAUI_QUERYTABLEVIEW_HXX
34 #include "QueryTableView.hxx"
35 #endif
36 #ifndef DBAUI_QUERY_TABLEWINDOW_HXX
37 #include "QTableWindow.hxx"
38 #endif
39 #ifndef _SV_TOOLBOX_HXX
40 #include <vcl/toolbox.hxx>
41 #endif
42 #ifndef DBAUI_QUERYCONTROLLER_HXX
43 #include "querycontroller.hxx"
44 #endif
45 #ifndef _SV_SPLIT_HXX
46 #include <vcl/split.hxx>
47 #endif
48 #ifndef _UNDO_HXX
49 #include <svl/undo.hxx>
50 #endif
51 #ifndef TOOLS_DIAGNOSE_EX_H
52 #include <tools/diagnose_ex.h>
53 #endif
54 #ifndef DBAUI_QYDLGTAB_HXX
55 #include "adtabdlg.hxx"
56 #endif
57 #ifndef _SV_SVAPP_HXX
58 #include <vcl/svapp.hxx>
59 #endif
60 #ifndef _SV_COMBOBOX_HXX
61 #include <vcl/combobox.hxx>
62 #endif
63 #ifndef _SV_MSGBOX_HXX
64 #include <vcl/msgbox.hxx>
65 #endif
66 #ifndef DBACCESS_UI_BROWSER_ID_HXX
67 #include "browserids.hxx"
68 #endif
69 #ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX
70 #include "SelectionBrowseBox.hxx"
71 #endif
72 #ifndef _DBU_QRY_HRC_
73 #include "dbu_qry.hrc"
74 #endif
75 #ifndef _UTL_CONFIGMGR_HXX_
76 #include <unotools/configmgr.hxx>
77 #endif
78 #ifndef _COMPHELPER_TYPES_HXX_
79 #include <comphelper/types.hxx>
80 #endif
81 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
82 #include <connectivity/dbtools.hxx>
83 #endif
84 #ifndef _DBHELPER_DBEXCEPTION_HXX_
85 #include <connectivity/dbexception.hxx>
86 #endif
87 #ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_
88 #include <com/sun/star/i18n/XLocaleData.hpp>
89 #endif
90 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
91 #include <com/sun/star/sdbc/DataType.hpp>
92 #endif
93 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
94 #include <com/sun/star/container/XNameAccess.hpp>
95 #endif
96 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
97 #include <com/sun/star/sdbc/ColumnValue.hpp>
98 #endif
99 #ifndef _CONNECTIVITY_PCOLUMN_HXX_
100 #include <connectivity/PColumn.hxx>
101 #endif
102 #ifndef DBAUI_QUERYTABLECONNECTION_HXX
103 #include "QTableConnection.hxx"
104 #endif
105 #ifndef DBAUI_CONNECTIONLINE_HXX
106 #include "ConnectionLine.hxx"
107 #endif
108 #ifndef DBAUI_CONNECTIONLINEDATA_HXX
109 #include "ConnectionLineData.hxx"
110 #endif
111 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX
112 #include "QTableConnectionData.hxx"
113 #endif
114 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
115 #include "dbustrings.hrc"
116 #endif
117 #ifndef _COMPHELPER_EXTRACT_HXX_
118 #include <comphelper/extract.hxx>
119 #endif
120 #ifndef DBAUI_TOOLS_HXX
121 #include "UITools.hxx"
122 #endif
123 #ifndef DBAUI_QUERYCONTAINERWINDOW_HXX
124 #include "querycontainerwindow.hxx"
125 #endif
126 #ifndef DBAUI_QUERYTABLEVIEW_HXX
127 #include "QueryTableView.hxx"
128 #endif
129 #ifndef _DBAUI_SQLMESSAGE_HXX_
130 #include "sqlmessage.hxx"
131 #endif
132 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
133 #include <unotools/syslocale.hxx>
134 #endif
135 
136 using namespace ::dbaui;
137 using namespace ::utl;
138 using namespace ::connectivity;
139 using namespace ::dbtools;
140 using namespace ::com::sun::star::uno;
141 using namespace ::com::sun::star::lang;
142 using namespace ::com::sun::star::i18n;
143 using namespace ::com::sun::star::sdbc;
144 using namespace ::com::sun::star::beans;
145 using namespace ::com::sun::star::container;
146 
147 #define SQL_ISRULEOR2(pParseNode, e1,e2) 	((pParseNode)->isRule() && (\
148 											(pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
149 											(pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
150 
151 // here we define our functions used in the anonymous namespace to get our header file smaller
152 // please look at the book LargeScale C++ to know why
153 namespace
154 {
155 	static const ::rtl::OUString C_AND = ::rtl::OUString::createFromAscii(" AND ");
156 	static const ::rtl::OUString C_OR  = ::rtl::OUString::createFromAscii(" OR ");
157 
158 	// forward declarations
159 	sal_Bool InsertJoin(	const OQueryDesignView* _pView,
160 							const ::connectivity::OSQLParseNode *pNode);
161 
162 	SqlParseError InstallFields(OQueryDesignView* _pView,
163 								const ::connectivity::OSQLParseNode* pNode,
164 								OJoinTableView::OTableWindowMap* pTabList );
165 
166 	SqlParseError GetGroupCriteria(	OQueryDesignView* _pView,
167 									OSelectionBrowseBox* _pSelectionBrw,
168 									const ::connectivity::OSQLParseNode* pSelectRoot );
169 
170 	SqlParseError GetHavingCriteria(OQueryDesignView* _pView,
171 									OSelectionBrowseBox* _pSelectionBrw,
172 									const ::connectivity::OSQLParseNode* pSelectRoot,
173 									sal_uInt16& rLevel );
174 
175 	SqlParseError GetOrderCriteria(	OQueryDesignView* _pView,
176 									OSelectionBrowseBox* _pSelectionBrw,
177 									const ::connectivity::OSQLParseNode* pParseRoot );
178 
179 	SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
180 									OSelectionBrowseBox* _pSelectionBrw,
181 									const ::connectivity::OSQLParseNode * pCondition,
182 									const sal_uInt16 nLevel,
183 									sal_Bool bHaving,
184                                     bool _bAddOrOnOneLine);
185 
186 	//------------------------------------------------------------------------------
187 	::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote)
188 	{
189 		::rtl::OUString sRet;
190 		if ( _bQuote && _sAliasName.getLength() )
191 		{
192 			sRet = ::dbtools::quoteName(_sQuote,_sAliasName);
193 			const static ::rtl::OUString sTableSeparater('.');
194 			sRet += sTableSeparater;
195 		}
196 		return sRet;
197 	}
198     //------------------------------------------------------------------------------
199     ::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef)
200     {
201         Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
202         ::rtl::OUString sTableRange;
203         if ( _pTableRef )
204         {
205             sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef);
206             if ( !sTableRange.getLength() )
207                 _pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False);
208         }
209         return sTableRange;
210     }
211     //------------------------------------------------------------------------------
212     void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false)
213     {
214         OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
215 		OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true));
216 
217 		if ( !pConn )
218 		{
219 			OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData();
220             TTableConnectionData::value_type aInfoData(pInfoData);
221 			pInfoData->InitFromDrag(_aDragLeft, _aDragRight);
222 			pInfoData->SetJoinType(_eJoinType);
223 
224             if ( _bNatural )
225             {
226                 aInfoData->ResetConnLines();
227                 pInfoData->setNatural(_bNatural);
228                 try
229                 {
230                     Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns());
231                     Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames();
232                     const ::rtl::OUString* pIter = aSeq.getConstArray();
233                     const ::rtl::OUString* pEnd	  = pIter + aSeq.getLength();
234                     for(;pIter != pEnd;++pIter)
235                     {
236                         if ( xReferencedTableColumns->hasByName(*pIter) )
237                             aInfoData->AppendConnLine(*pIter,*pIter);
238                     }
239                 }
240                 catch( const Exception& )
241                 {
242                     DBG_UNHANDLED_EXCEPTION();
243                 }
244             }
245 
246 			OQueryTableConnection aInfo(pTableView, aInfoData);
247 			// da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt,
248 			// ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer
249 			pTableView->NotifyTabConnection( aInfo );
250 		}
251 		else
252 		{
253 			::rtl::OUString aSourceFieldName(_aDragLeft->GetField());
254 			::rtl::OUString aDestFieldName(_aDragRight->GetField());
255 			// the connection could point on the other side
256 			if(pConn->GetSourceWin() == _aDragRight->GetTabWindow())
257 			{
258 				::rtl::OUString aTmp(aSourceFieldName);
259 				aSourceFieldName = aDestFieldName;
260 				aDestFieldName = aTmp;
261 			}
262 			pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName);
263 			pConn->UpdateLineList();
264 			// Modified-Flag
265 			//	SetModified();
266 			// und neu zeichnen
267 			pConn->RecalcLines();
268 				// fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben,
269 				// ihr BoundingRect zu ermitteln
270 			pConn->InvalidateConnection();
271 		}
272     }
273 	//------------------------------------------------------------------------------
274 	::rtl::OUString ParseCondition(	OQueryController& rController
275 									,const ::connectivity::OSQLParseNode* pCondition
276 									,const ::rtl::OUString _sDecimal
277 									,const ::com::sun::star::lang::Locale& _rLocale
278 									,sal_uInt32 _nStartIndex)
279 	{
280 		::rtl::OUString	aCondition;
281 		Reference< XConnection> xConnection = rController.getConnection();
282 		if ( xConnection.is() )
283 		{
284 			sal_uInt32 nCount = pCondition->count();
285 			for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i)
286 				pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
287 								xConnection,
288 								rController.getNumberFormatter(),
289 								_rLocale,
290 								static_cast<sal_Char>(_sDecimal.toChar()),
291 								&rController.getParser().getContext());
292 		}
293 		return aCondition;
294 	}
295 	//------------------------------------------------------------------------------
296 	SqlParseError FillOuterJoins(OQueryDesignView* _pView,
297 								const ::connectivity::OSQLParseNode* pTableRefList)
298 	{
299 		SqlParseError eErrorCode = eOk;
300 		sal_uInt32 nCount = pTableRefList->count();
301 		sal_Bool bError = sal_False;
302 		for (sal_uInt32 i=0; !bError && i < nCount; ++i)
303 		{
304 			const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i);
305 			const ::connectivity::OSQLParseNode* pJoinNode = NULL;
306 
307 			if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) )
308 				pJoinNode = pParseNode;
309 			else if(	SQL_ISRULE(pParseNode,table_ref)
310 					&&	pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
311 				pJoinNode = pParseNode->getChild(2);
312 
313 			if ( pJoinNode )
314 			{
315 				if ( !InsertJoin(_pView,pJoinNode) )
316 					bError = sal_True;
317 			}
318 		}
319 		// check if error occured
320 		if ( bError )
321 			eErrorCode = eIllegalJoin;
322 
323 		return eErrorCode;
324 	}
325 	// -----------------------------------------------------------------------------
326 
327 	/** FillDragInfo fills the field description out of the table
328 	*/
329 	//------------------------------------------------------------------------------
330 	SqlParseError FillDragInfo(	const OQueryDesignView* _pView,
331 							const ::connectivity::OSQLParseNode* pColumnRef,
332 							OTableFieldDescRef& _rDragInfo)
333 	{
334 		SqlParseError eErrorCode = eOk;
335 
336 		sal_Bool bErg = sal_False;
337 
338 		::rtl::OUString aTableRange,aColumnName;
339 		sal_uInt16 nCntAccount;
340 		::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
341 		rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
342 
343 		if ( aTableRange.getLength() )
344 		{
345 			OQueryTableWindow*	pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange );
346 			bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) );
347 		}
348 		if ( !bErg )
349         {
350 			bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount);
351             if ( !bErg )
352                 bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo);
353         }
354 		if ( !bErg )
355 		{
356 			eErrorCode = eColumnNotFound;
357 			String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND));
358 			sError.SearchAndReplaceAscii("$name$",aColumnName);
359 			_pView->getController().appendError( sError );
360 
361 			try
362 			{
363 				Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData();
364                 if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() )
365                     _pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) );
366 			}
367 			catch(Exception&)
368 			{
369 			}
370 		}
371 
372 		return eErrorCode;
373 	}
374 	//------------------------------------------------------------------------------
375 	::rtl::OUString BuildJoinCriteria(	const Reference< XConnection>& _xConnection,
376 										OConnectionLineDataVec* pLineDataList,
377 										OQueryTableConnectionData* pData)
378 	{
379 		::rtl::OUStringBuffer aCondition;
380 		if ( _xConnection.is() )
381         {
382 		    OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
383             OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
384 		    try
385 		    {
386 			    const Reference< XDatabaseMetaData >  xMetaData = _xConnection->getMetaData();
387 			    const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
388                 const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = "));
389 
390 			    for(;aIter != aEnd;++aIter)
391 			    {
392 				    OConnectionLineDataRef pLineData = *aIter;
393 				    if(aCondition.getLength())
394 					    aCondition.append(C_AND);
395 				    aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote));
396 				    aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) ));
397 				    aCondition.append(sEqual);
398 				    aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote));
399 				    aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) ));
400 			    }
401 		    }
402 		    catch(SQLException&)
403 		    {
404 			    OSL_ASSERT(!"Failure while building Join criteria!");
405 		    }
406         }
407 
408 		return aCondition.makeStringAndClear();
409 	}
410 	//------------------------------------------------------------------------------
411 	/** JoinCycle looks for a join cycle and append it to the string
412 		@param	_xConnection	the connection
413 		@param	_pEntryConn		the table connection which holds the data
414 		@param	_pEntryTabTo	the corresponding table window
415 		@param	_rJoin			the String which will contain the resulting string
416 	*/
417 	void JoinCycle(	const Reference< XConnection>& _xConnection,
418 					OQueryTableConnection* _pEntryConn,
419 					const OQueryTableWindow* _pEntryTabTo,
420 					::rtl::OUString& _rJoin )
421 	{
422 		OSL_ENSURE(_pEntryConn,"TableConnection can not be null!");
423 
424 		OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get());
425 		if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() )
426 		{
427 			sal_Bool bBrace = sal_False;
428 			if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1))
429 			{
430 				bBrace = sal_True;
431 				_rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' '));
432 			}
433 			(_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData);
434 			if(bBrace)
435 				_rJoin += ::rtl::OUString(')');
436 			_pEntryConn->SetVisited(sal_True);
437 		}
438 	}
439 	//------------------------------------------------------------------------------
440 	::rtl::OUString BuildTable(	const Reference< XConnection>& _xConnection,
441 								const OQueryTableWindow* pEntryTab,
442                                 bool _bForce = false
443 								)
444 	{
445 		::rtl::OUString aDBName(pEntryTab->GetComposedName());
446 
447 		//	Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
448 		if( _xConnection.is() )
449 		{
450 			try
451 			{
452 				Reference< XDatabaseMetaData >  xMetaData = _xConnection->getMetaData();
453 
454                 ::rtl::OUString sCatalog, sSchema, sTable;
455                 ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
456 				::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable );
457 
458 				::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
459 				if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName )
460 				{
461                     aTableListStr += ::rtl::OUString::createFromAscii(" ");
462                     if ( generateAsBeforeTableAlias( _xConnection ) )
463                         aTableListStr += ::rtl::OUString::createFromAscii("AS ");
464 					aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() );
465 				}
466 				aDBName = aTableListStr;
467 			}
468 			catch(const SQLException&)
469 			{
470                 DBG_UNHANDLED_EXCEPTION();
471 			}
472 		}
473 		return aDBName;
474 	}
475 	//------------------------------------------------------------------------------
476 	::rtl::OUString BuildJoin(	const Reference< XConnection>& _xConnection,
477 								const ::rtl::OUString& rLh,
478 								const ::rtl::OUString& rRh,
479 								OQueryTableConnectionData* pData)
480 	{
481 
482 		String aErg(rLh);
483         if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN )
484             aErg.AppendAscii(" NATURAL ");
485 		switch(pData->GetJoinType())
486 		{
487 			case LEFT_JOIN:
488 				aErg.AppendAscii(" LEFT OUTER ");
489 				break;
490 			case RIGHT_JOIN:
491 				aErg.AppendAscii(" RIGHT OUTER ");
492 				break;
493             case CROSS_JOIN:
494                 OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
495 				aErg.AppendAscii(" CROSS ");
496 				break;
497 			case INNER_JOIN:
498                 OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
499 				aErg.AppendAscii(" INNER ");
500 				break;
501 			default:
502 				aErg.AppendAscii(" FULL OUTER ");
503 				break;
504 		}
505 		aErg.AppendAscii("JOIN ");
506 		aErg += String(rRh);
507         if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() )
508         {
509 		    aErg.AppendAscii(" ON ");
510 		    aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData));
511         }
512 
513 		return aErg;
514 	}
515 	//------------------------------------------------------------------------------
516 	::rtl::OUString BuildJoin(	const Reference< XConnection>& _xConnection,
517 								OQueryTableWindow* pLh,
518 								OQueryTableWindow* pRh,
519 								OQueryTableConnectionData* pData
520 								)
521 	{
522         bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural();
523 		return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData);
524 	}
525 	//------------------------------------------------------------------------------
526 	::rtl::OUString BuildJoin(	const Reference< XConnection>& _xConnection,
527 								const ::rtl::OUString &rLh,
528 								OQueryTableWindow* pRh,
529 								OQueryTableConnectionData* pData
530 								)
531 	{
532 		return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData);
533 	}
534 	//------------------------------------------------------------------------------
535 	::rtl::OUString BuildJoin(	const Reference< XConnection>& _xConnection,
536 								OQueryTableWindow* pLh,
537 								const ::rtl::OUString &rRh,
538 								OQueryTableConnectionData* pData
539 								)
540 	{
541 		return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData);
542 	}
543 	//------------------------------------------------------------------------------
544 	void GetNextJoin(	const Reference< XConnection>& _xConnection,
545 						OQueryTableConnection* pEntryConn,
546 						OQueryTableWindow* pEntryTabTo,
547 						::rtl::OUString &aJoin)
548 	{
549 		OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
550         if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
551 			return;
552 
553 		//	Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
554 
555 		if(!aJoin.getLength())
556 		{
557 			OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
558 			aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData);
559 		}
560 		else if(pEntryTabTo == pEntryConn->GetDestWin())
561 		{
562 			aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData);
563 		}
564 		else if(pEntryTabTo == pEntryConn->GetSourceWin())
565 		{
566 			aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData);
567 		}
568 
569 		pEntryConn->SetVisited(sal_True);
570 
571 		// first search for the "to" window
572 		const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections();
573 		::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin();
574         ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end();
575 		for(;aIter != aEnd;++aIter)
576 		{
577 			OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
578 			if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo))
579 			{
580 				OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
581 				// exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
582 				JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
583 				if(!pNext->IsVisited())
584 					GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
585 			}
586 		}
587 
588 		// when nothing found found look for the "from" window
589 		if(aIter == aEnd)
590 		{
591 			OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
592 			aIter = pConnections->begin();
593 			for(;aIter != aEnd;++aIter)
594 			{
595 				OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
596 				if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom))
597 				{
598 					OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
599 					// exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
600 					JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
601 					if(!pNext->IsVisited())
602 						GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
603 				}
604 			}
605 		}
606 	}
607 	//------------------------------------------------------------------------------
608 	SqlParseError InsertJoinConnection(	const OQueryDesignView* _pView,
609 									const ::connectivity::OSQLParseNode *pNode,
610 									const EJoinType& _eJoinType,
611                                     const ::connectivity::OSQLParseNode *pLeftTable,
612                                     const ::connectivity::OSQLParseNode *pRightTable)
613 	{
614 		SqlParseError eErrorCode = eOk;
615 		if (pNode->count() == 3 &&	// Ausdruck is geklammert
616 			SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
617 			SQL_ISPUNCTUATION(pNode->getChild(2),")"))
618 		{
619 			eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType,pLeftTable,pRightTable);
620 		}
621 		else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term)	&&			// AND/OR-Verknuepfung:
622 				 pNode->count() == 3)
623 		{
624 			// nur AND Verkn�pfung zulassen
625 			if (!SQL_ISTOKEN(pNode->getChild(1),AND))
626 				eErrorCode = eIllegalJoinCondition;
627 			else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType,pLeftTable,pRightTable)) )
628 					eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType,pLeftTable,pRightTable);
629 		}
630 		else if (SQL_ISRULE(pNode,comparison_predicate))
631 		{
632 			// only the comparison of columns is allowed
633 			DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree");
634 			if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
635 				  SQL_ISRULE(pNode->getChild(2),column_ref) &&
636 				   pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
637 			{
638 				String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE));
639 				_pView->getController().appendError( sError );
640 				return eIllegalJoin;
641 			}
642 
643 			OTableFieldDescRef aDragLeft  = new OTableFieldDesc();
644 			OTableFieldDescRef aDragRight = new OTableFieldDesc();
645 			if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) ||
646 				eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight)))
647 				return eErrorCode;
648 
649             if ( pLeftTable )
650             {
651                 OQueryTableWindow*	pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pLeftTable->getByRule(OSQLParseNode::table_ref) ));
652                 // OQueryTableWindow*	pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTable->getByRule(OSQLParseNode::table_ref) ));
653                 if ( pLeftWindow == aDragLeft->GetTabWindow() )
654                     insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
655                 else
656                     insertConnection(_pView,_eJoinType,aDragRight,aDragLeft);
657             }
658             else
659                 insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
660 		}
661 		else
662 			eErrorCode = eIllegalJoin;
663 		return eErrorCode;
664 	}
665 	//------------------------------------------------------------------------------
666 	sal_Bool GetInnerJoinCriteria(	const OQueryDesignView* _pView,
667 									const ::connectivity::OSQLParseNode *pCondition)
668 	{
669 		return InsertJoinConnection(_pView,pCondition, INNER_JOIN,NULL,NULL) != eOk;
670 	}
671 	//------------------------------------------------------------------------------
672 	::rtl::OUString GenerateSelectList(	const OQueryDesignView* _pView,
673 										OTableFields&	_rFieldList,
674 										sal_Bool bAlias)
675 	{
676         Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
677 		if ( !xConnection.is() )
678 			return ::rtl::OUString();
679 
680 		::rtl::OUStringBuffer aTmpStr,aFieldListStr;
681 
682 		sal_Bool bAsterix = sal_False;
683 		int nVis = 0;
684 		OTableFields::iterator aIter = _rFieldList.begin();
685         OTableFields::iterator aEnd = _rFieldList.end();
686 		for(;aIter != aEnd;++aIter)
687 		{
688 			OTableFieldDescRef pEntryField = *aIter;
689 			if ( pEntryField->IsVisible() )
690 			{
691 				if ( pEntryField->GetField().toChar() == '*' )
692 					bAsterix = sal_True;
693 				++nVis;
694 			}
695 		}
696 		if(nVis == 1)
697 			bAsterix = sal_False;
698 
699 		try
700 		{
701 			const Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
702 			const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
703 
704 			OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
705 
706 			const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", "));
707             const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS "));
708 
709 			aIter = _rFieldList.begin();
710 		    for(;aIter != aEnd;++aIter)
711 			{
712 				OTableFieldDescRef pEntryField = *aIter;
713 				::rtl::OUString rFieldName = pEntryField->GetField();
714 				if ( rFieldName.getLength() && pEntryField->IsVisible() )
715 				{
716 					aTmpStr = ::rtl::OUString();
717 					const ::rtl::OUString rAlias = pEntryField->GetAlias();
718 					const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias();
719 
720 					aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote));
721 
722 					// if we have a none numeric field, the table alias could be in the name
723 					// otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
724 					if  ( !pEntryField->isOtherFunction() )
725 					{
726 						// we have to look if we have alias.* here but before we have to check if the column doesn't already exist
727 						String sTemp = rFieldName;
728 						OTableFieldDescRef	aInfo = new OTableFieldDesc();
729 						OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin();
730                         OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end();
731 						sal_Bool bFound = sal_False;
732 						for(;!bFound && tableIter != tableEnd ;++tableIter)
733 						{
734 							OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second);
735 
736                             bFound = pTabWin->ExistsField( rFieldName, aInfo );
737 							if ( bFound )
738 								rFieldName = aInfo->GetField();
739 						}
740 						if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) )
741 						{
742 							OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!");
743 							aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName));
744 						}
745 						else
746 							aTmpStr.append(rFieldName);
747 					}
748 					else
749 						aTmpStr.append(rFieldName);
750 
751 					if  ( pEntryField->isAggreateFunction() )
752 					{
753 						DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
754 						::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction());
755 						aTmpStr2.appendAscii("(");
756 						aTmpStr2.append(aTmpStr.makeStringAndClear());
757 						aTmpStr2.appendAscii(")");
758 						aTmpStr = aTmpStr2;
759 					}
760 
761 					if (rFieldAlias.getLength()							&&
762 						(rFieldName.toChar() != '*'						||
763 						pEntryField->isNumericOrAggreateFunction()		||
764 						pEntryField->isOtherFunction()))
765 					{
766 						aTmpStr.append(s_sAs);
767 						aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias));
768 					}
769 					aFieldListStr.append(aTmpStr.makeStringAndClear());
770 					aFieldListStr.append(sFieldSeparator);
771 				}
772 			}
773 			if(aFieldListStr.getLength())
774 				aFieldListStr.setLength(aFieldListStr.getLength()-2);
775 		}
776 		catch(SQLException&)
777 		{
778 			OSL_ASSERT(!"Failure while building select list!");
779 		}
780 		return aFieldListStr.makeStringAndClear();
781 	}
782 	//------------------------------------------------------------------------------
783 	sal_Bool GenerateCriterias(	OQueryDesignView* _pView,
784 								::rtl::OUStringBuffer& rRetStr,
785 								::rtl::OUStringBuffer& rHavingStr,
786 								OTableFields& _rFieldList,
787 								sal_Bool bMulti )
788 	{
789 		// * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
790 		sal_Bool bCritsOnAsterikWarning = sal_False;		// ** TMFS **
791 
792 		::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/;
793 		// Zeilenweise werden die Ausdr"ucke mit AND verknuepft
794 		sal_uInt16 nMaxCriteria = 0;
795 		OTableFields::iterator aIter = _rFieldList.begin();
796 		OTableFields::iterator aEnd = _rFieldList.end();
797 		for(;aIter != aEnd;++aIter)
798 		{
799 			nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size());
800 		}
801 		Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
802 		if(!xConnection.is())
803 			return sal_False;
804 		try
805 		{
806 			const Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
807 			const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
808 			const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext();
809 
810 			for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++)
811 			{
812 				aHavingStr = aWhereStr = ::rtl::OUString();
813 
814 				for(aIter = _rFieldList.begin();aIter != aEnd;++aIter)
815 				{
816 					OTableFieldDescRef	pEntryField = *aIter;
817 					aFieldName = pEntryField->GetField();
818 
819 					if (!aFieldName.getLength())
820 						continue;
821 					aCriteria = pEntryField->GetCriteria( i );
822 					if ( aCriteria.getLength() )
823 					{
824 						// * is not allowed to contain any filter, only when used in combination an aggregate function
825 						if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() )
826 						{
827 							// only show the messagebox the first time
828 							if (!bCritsOnAsterikWarning)
829 								ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute();
830 							bCritsOnAsterikWarning = sal_True;
831 							continue;
832 						}
833 						aWork = ::rtl::OUString();
834 
835 
836 						aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
837 
838 						if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') )
839 							aWork += aFieldName;
840 						else
841 							aWork += ::dbtools::quoteName(aQuote, aFieldName);
842 
843 						if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() )
844 						{
845 							if (!aHavingStr.getLength())			// noch keine Kriterien
846 								aHavingStr += ::rtl::OUString('(');			// Klammern
847 							else
848 								aHavingStr += C_AND;
849 
850 							if ( pEntryField->isAggreateFunction() )
851 							{
852 								OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!");
853 								aHavingStr += pEntryField->GetFunction();
854 								aHavingStr += ::rtl::OUString('(');			// Klammern
855 								aHavingStr += aWork;
856 								aHavingStr += ::rtl::OUString(')');			// Klammern
857 							}
858 							else
859 								aHavingStr += aWork;
860 
861 							::rtl::OUString aTmp = aCriteria;
862 							::rtl::OUString aErrorMsg;
863 							Reference<XPropertySet> xColumn;
864                             ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
865 							if (pParseNode.get())
866 							{
867 								if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
868 									pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
869 								::rtl::OUString sHavingStr = aHavingStr;
870 
871 								sal_uInt32 nCount = pParseNode->count();
872 								for( sal_uInt32 node = 1 ; node < nCount ; ++node)
873 									pParseNode->getChild(node)->parseNodeToStr(	sHavingStr,
874 																xConnection,
875 																&rContext,
876 																sal_False,
877 																!pEntryField->isOtherFunction());
878 								aHavingStr = sHavingStr;
879 							}
880 							else
881 								aHavingStr += aCriteria;
882 						}
883 						else
884 						{
885 							if ( !aWhereStr.getLength() )			// noch keine Kriterien
886 								aWhereStr += ::rtl::OUString('(');			// Klammern
887 							else
888 								aWhereStr += C_AND;
889 
890 							aWhereStr += ::rtl::OUString(' ');
891 							// aCriteria could have some german numbers so I have to be sure here
892 							::rtl::OUString aTmp = aCriteria;
893 							::rtl::OUString aErrorMsg;
894 							Reference<XPropertySet> xColumn;
895 							::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
896 							if (pParseNode.get())
897 							{
898 								if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
899 									pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
900 								::rtl::OUString aWhere = aWhereStr;
901 								pParseNode->parseNodeToStr(	aWhere,
902 															xConnection,
903 															&rContext,
904 															sal_False,
905 															!pEntryField->isOtherFunction() );
906 								aWhereStr = aWhere;
907 							}
908 							else
909 							{
910 								aWhereStr += aWork;
911 								aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
912 								aWhereStr += aCriteria;
913 							}
914 						}
915 					}
916 					// nur einmal f�r jedes Feld
917 					else if ( !i && pEntryField->isCondition() )
918 					{
919 						if (!aWhereStr.getLength())			// noch keine Kriterien
920 							aWhereStr += ::rtl::OUString('(');			// Klammern
921 						else
922 							aWhereStr += C_AND;
923 						aWhereStr += pEntryField->GetField();
924 					}
925 				}
926 				if (aWhereStr.getLength())
927 				{
928 					aWhereStr += ::rtl::OUString(')');						// Klammern zu fuer 'AND' Zweig
929 					if (rRetStr.getLength())							// schon Feldbedingungen ?
930 						rRetStr.append(C_OR);
931 					else										// Klammern auf fuer 'OR' Zweig
932 						rRetStr.append(sal_Unicode('('));
933 					rRetStr.append(aWhereStr);
934 				}
935 				if (aHavingStr.getLength())
936 				{
937 					aHavingStr += ::rtl::OUString(')');						// Klammern zu fuer 'AND' Zweig
938 					if (rHavingStr.getLength())							// schon Feldbedingungen ?
939 						rHavingStr.append(C_OR);
940 					else										// Klammern auf fuer 'OR' Zweig
941 						rHavingStr.append(sal_Unicode('('));
942 					rHavingStr.append(aHavingStr);
943 				}
944 			}
945 
946 			if (rRetStr.getLength())
947 				rRetStr.append(sal_Unicode(')'));								// Klammern zu fuer 'OR' Zweig
948 			if (rHavingStr.getLength())
949 				rHavingStr.append(sal_Unicode(')'));								// Klammern zu fuer 'OR' Zweig
950 		}
951 		catch(SQLException&)
952 		{
953 			OSL_ASSERT(!"Failure while building where clause!");
954 		}
955 		return sal_True;
956 	}
957 	//------------------------------------------------------------------------------
958 	SqlParseError GenerateOrder(	OQueryDesignView* _pView,
959 									OTableFields& _rFieldList,
960 									sal_Bool bMulti,
961 									::rtl::OUString& _rsRet)
962 	{
963         const OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
964 		Reference< XConnection> xConnection = rController.getConnection();
965 		if ( !xConnection.is() )
966 			return eNoConnection;
967 
968 		SqlParseError eErrorCode = eOk;
969 
970 		::rtl::OUString aColumnName;
971 		::rtl::OUString aWorkStr;
972 		try
973 		{
974             const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy();
975 			Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
976 			::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
977 			// * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
978 			sal_Bool bCritsOnAsterikWarning = sal_False;		// ** TMFS **
979 			OTableFields::iterator aIter = _rFieldList.begin();
980 			OTableFields::iterator aEnd = _rFieldList.end();
981 		    for(;aIter != aEnd;++aIter)
982 			{
983 				OTableFieldDescRef	pEntryField = *aIter;
984 				EOrderDir eOrder = pEntryField->GetOrderDir();
985 
986 				// nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen
987 				// sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt
988 				if ( eOrder != ORDER_NONE )
989 				{
990 					aColumnName = pEntryField->GetField();
991 					if(aColumnName.toChar() == '*')
992 					{
993 						// die entsprechende MessageBox nur beim ersten mal anzeigen
994 						if (!bCritsOnAsterikWarning)
995 							ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute();
996 						bCritsOnAsterikWarning = sal_True;
997 						continue;
998 					}
999 
1000 					if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() )
1001 					{
1002 						aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias());
1003 					}
1004 					else if ( pEntryField->isNumericOrAggreateFunction() )
1005 					{
1006 						DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
1007 						aWorkStr += pEntryField->GetFunction();
1008 						aWorkStr +=  ::rtl::OUString('(');
1009 						aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1010 						// only quote column name when we don't have a numeric
1011 						if ( pEntryField->isNumeric() )
1012 							aWorkStr += aColumnName;
1013 						else
1014 							aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
1015 
1016 						aWorkStr +=  ::rtl::OUString(')');
1017 					}
1018                     else if ( pEntryField->isOtherFunction() )
1019                     {
1020                         aWorkStr += aColumnName;
1021                     }
1022 					else
1023 					{
1024 						aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1025 						aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
1026 					}
1027 					aWorkStr += ::rtl::OUString(' ');
1028 					aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (sal_uInt16)eOrder );
1029 					aWorkStr += ::rtl::OUString(',');
1030 				}
1031 			}
1032 
1033 			{
1034 				String sTemp(aWorkStr);
1035 				sTemp.EraseTrailingChars( ',' );
1036 				aWorkStr = sTemp;
1037 			}
1038 
1039 			if ( aWorkStr.getLength() )
1040 			{
1041 				const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy();
1042 				String sToken(aWorkStr);
1043 				if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') )
1044 					eErrorCode = eStatementTooLong;
1045 				else
1046 				{
1047 					_rsRet = ::rtl::OUString::createFromAscii(" ORDER BY ");
1048 					_rsRet += aWorkStr;
1049 				}
1050 			}
1051 		}
1052 		catch(SQLException&)
1053 		{
1054 			OSL_ASSERT(!"Failure while building group by!");
1055 		}
1056 
1057 		return eErrorCode;
1058 	}
1059 
1060 	//------------------------------------------------------------------------------
1061 	void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection,
1062 									::rtl::OUString& _rJoinCrit,
1063 									const ::std::vector<OTableConnection*>* _pConnList)
1064 	{
1065 		::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin();
1066         ::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end();
1067 		for(;aIter != aEnd;++aIter)
1068 		{
1069 			const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter);
1070 			OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
1071             if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
1072 			{
1073 				if(_rJoinCrit.getLength())
1074 					_rJoinCrit += C_AND;
1075 				_rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData);
1076 			}
1077 		}
1078 	}
1079 	//------------------------------------------------------------------------------
1080 	void searchAndAppendName(const Reference< XConnection>& _xConnection,
1081 							 const OQueryTableWindow* _pTableWindow,
1082 							 ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames,
1083 							 ::rtl::OUString& _rsTableListStr
1084 							 )
1085 	{
1086 		::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow));
1087 
1088 		if(_rTableNames.find(sTabName) == _rTableNames.end())
1089 		{
1090 			_rTableNames[sTabName] = sal_True;
1091 			_rsTableListStr += sTabName;
1092 			_rsTableListStr += ::rtl::OUString(',');
1093 		}
1094 	}
1095 	//------------------------------------------------------------------------------
1096 	::rtl::OUString GenerateFromClause(	const Reference< XConnection>& _xConnection,
1097 										const OQueryTableView::OTableWindowMap*	pTabList,
1098 										const ::std::vector<OTableConnection*>*	pConnList
1099 										)
1100 	{
1101 
1102 		::rtl::OUString aTableListStr;
1103 		// wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt
1104 		::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames;
1105 
1106 		// generate outer join clause in from
1107 		if(!pConnList->empty())
1108 		{
1109 			::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin();
1110             ::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end();
1111             ::std::map<OTableWindow*,sal_Int32> aConnectionCount;
1112 			for(;aIter != aEnd;++aIter)
1113             {
1114 				static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False);
1115                 if ( aConnectionCount.find((*aIter)->GetSourceWin()) == aConnectionCount.end() )
1116                     aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetSourceWin(),0));
1117                 else
1118                     aConnectionCount[(*aIter)->GetSourceWin()]++;
1119                 if ( aConnectionCount.find((*aIter)->GetDestWin()) == aConnectionCount.end() )
1120                     aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetDestWin(),0));
1121                 else
1122                     aConnectionCount[(*aIter)->GetDestWin()]++;
1123             }
1124             ::std::multimap<sal_Int32 , OTableWindow*> aMulti;
1125             ::std::map<OTableWindow*,sal_Int32>::iterator aCountIter = aConnectionCount.begin();
1126             ::std::map<OTableWindow*,sal_Int32>::iterator aCountEnd = aConnectionCount.end();
1127             for(;aCountIter != aCountEnd;++aCountIter)
1128             {
1129                 aMulti.insert(::std::multimap<sal_Int32 , OTableWindow*>::value_type(aCountIter->second,aCountIter->first));
1130             }
1131 
1132             const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE );
1133             ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aRIter = aMulti.rbegin();
1134             ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aREnd = aMulti.rend();
1135             for(;aRIter != aREnd;++aRIter)
1136             {
1137                 ::std::vector<OTableConnection*>::const_iterator aConIter = aRIter->second->getTableView()->getTableConnections(aRIter->second);
1138                 for(;aConIter != aEnd;++aConIter)
1139                 {
1140                     OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aConIter);
1141 				    if(!pEntryConn->IsVisited() && pEntryConn->GetSourceWin() == aRIter->second )
1142 				    {
1143 					    ::rtl::OUString aJoin;
1144 					    GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin);
1145 
1146 					    if(aJoin.getLength())
1147 					    {
1148 						    // insert tables into table list to avoid double entries
1149 						    OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
1150 						    OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin());
1151 
1152 						    ::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom));
1153 						    if(aTableNames.find(sTabName) == aTableNames.end())
1154 							    aTableNames[sTabName] = sal_True;
1155 						    sTabName = BuildTable(_xConnection,pEntryTabTo);
1156 						    if(aTableNames.find(sTabName) == aTableNames.end())
1157 							    aTableNames[sTabName] = sal_True;
1158 
1159                             ::rtl::OUString aStr;
1160                             switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType())
1161 		                    {
1162 			                    case LEFT_JOIN:
1163 			                    case RIGHT_JOIN:
1164                                 case FULL_JOIN:
1165                                     {
1166 						                // create outer join
1167 						                if ( bUseEscape )
1168 							                aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ "));
1169 						                aStr += aJoin;
1170 						                if ( bUseEscape )
1171 							                aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }"));
1172                                     }
1173                                     break;
1174                                 default:
1175                                     aStr += aJoin;
1176                                     break;
1177                             }
1178 						    aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
1179 						    aTableListStr += aStr;
1180 					    }
1181 				    }
1182 			    }
1183             }
1184 
1185 			// and now all inner joins
1186 			aIter = pConnList->begin();
1187 			for(;aIter != aEnd;++aIter)
1188 			{
1189 				OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
1190 				if(!pEntryConn->IsVisited())
1191 				{
1192 					searchAndAppendName(_xConnection,
1193 										static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()),
1194 										aTableNames,
1195 										aTableListStr);
1196 
1197 					searchAndAppendName(_xConnection,
1198 										static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
1199 										aTableNames,
1200 										aTableListStr);
1201 				}
1202 			}
1203 		}
1204 		// all tables that haven't a connection to anyone
1205 		OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin();
1206         OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end();
1207 		for(;aTabIter != aTabEnd;++aTabIter)
1208 		{
1209 			const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second);
1210 			if(!pEntryTab->ExistsAConn())
1211 			{
1212 				aTableListStr += BuildTable(_xConnection,pEntryTab);
1213 				aTableListStr += ::rtl::OUString(',');
1214 			}
1215 		}
1216 
1217 		if(aTableListStr.getLength())
1218 			aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() );
1219 		return aTableListStr;
1220 	}
1221 	//------------------------------------------------------------------------------
1222 	::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti )
1223 	{
1224         OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1225 		const Reference< XConnection> xConnection = rController.getConnection();
1226 		if(!xConnection.is())
1227 			return ::rtl::OUString();
1228 
1229         ::std::map< rtl::OUString,bool> aGroupByNames;
1230 
1231 		::rtl::OUString aGroupByStr;
1232 		try
1233 		{
1234 			const Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
1235 			const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
1236 
1237 			OTableFields::iterator aIter = _rFieldList.begin();
1238 			OTableFields::iterator aEnd = _rFieldList.end();
1239 		    for(;aIter != aEnd;++aIter)
1240 			{
1241 				OTableFieldDescRef	pEntryField = *aIter;
1242 				if ( pEntryField->IsGroupBy() )
1243 				{
1244 					DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-(");
1245 					::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1246 
1247 					// only quote the field name when it isn't calculated
1248 					if ( pEntryField->isNoneFunction() )
1249                     {
1250 						sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField());
1251                     }
1252 					else
1253                     {
1254                         ::rtl::OUString aTmp = pEntryField->GetField();
1255 						::rtl::OUString aErrorMsg;
1256 						Reference<XPropertySet> xColumn;
1257                         ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
1258 						if (pParseNode.get())
1259 						{
1260 							::rtl::OUString sGroupBy;
1261 							pParseNode->getChild(0)->parseNodeToStr(	sGroupBy,
1262 														xConnection,
1263 														&rController.getParser().getContext(),
1264 														sal_False,
1265 														!pEntryField->isOtherFunction());
1266 							sGroupByPart += sGroupBy;
1267 						}
1268 						else
1269 							sGroupByPart += pEntryField->GetField();
1270                     }
1271                     if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() )
1272                     {
1273                         aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true));
1274                         aGroupByStr += sGroupByPart;
1275 					    aGroupByStr += ::rtl::OUString(',');
1276                     }
1277 				}
1278 			}
1279 			if ( aGroupByStr.getLength() )
1280 			{
1281 				aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') );
1282 				::rtl::OUString aGroupByStr2 = ::rtl::OUString::createFromAscii(" GROUP BY ");
1283 				aGroupByStr2 += aGroupByStr;
1284 				aGroupByStr = aGroupByStr2;
1285 			}
1286 		}
1287 		catch(SQLException&)
1288 		{
1289 			OSL_ASSERT(!"Failure while building group by!");
1290 		}
1291 		return aGroupByStr;
1292 	}
1293 	// -----------------------------------------------------------------------------
1294 	SqlParseError GetORCriteria(OQueryDesignView* _pView,
1295 								OSelectionBrowseBox* _pSelectionBrw,
1296 								const ::connectivity::OSQLParseNode * pCondition,
1297 								sal_uInt16& nLevel ,
1298 								sal_Bool bHaving = sal_False,
1299                                 bool bAddOrOnOneLine = false);
1300 	// -----------------------------------------------------------------------------
1301 	SqlParseError GetSelectionCriteria(	OQueryDesignView* _pView,
1302 										OSelectionBrowseBox* _pSelectionBrw,
1303 										const ::connectivity::OSQLParseNode* pNode,
1304 										sal_uInt16& rLevel )
1305 	{
1306 		if (!SQL_ISRULE(pNode, select_statement))
1307 			return eNoSelectStatement;
1308 
1309 		// nyi: mehr Pruefung auf korrekte Struktur!
1310 		pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL;
1311 		// no where clause found
1312 		if (!pNode || pNode->isLeaf())
1313 			return eOk;
1314 
1315 		// Naechster freier Satz ...
1316 		SqlParseError eErrorCode = eOk;
1317 		::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
1318 		if ( pCondition ) // no where clause
1319 		{
1320 			// now we have to chech the other conditions
1321 			// first make the logical easier
1322 			::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
1323 			::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1);
1324 
1325 			::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
1326 			pNodeTmp = pNode->getChild(1);
1327 			::connectivity::OSQLParseNode::absorptions(pNodeTmp);
1328 			pNodeTmp = pNode->getChild(1);
1329             // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079
1330             OSQLParseNode::compress(pNodeTmp);
1331             pNodeTmp = pNode->getChild(1);
1332 
1333 			// first extract the inner joins conditions
1334 			GetInnerJoinCriteria(_pView,pNodeTmp);
1335 			// now simplify again, join are checked in ComparisonPredicate
1336 			::connectivity::OSQLParseNode::absorptions(pNodeTmp);
1337 			pNodeTmp = pNode->getChild(1);
1338 
1339 			// it could happen that pCondition is not more valid
1340 			eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel);
1341 		}
1342 		return eErrorCode;
1343 	}
1344 	//------------------------------------------------------------------------------
1345 	SqlParseError GetANDCriteria(	OQueryDesignView* _pView,
1346 									OSelectionBrowseBox* _pSelectionBrw,
1347 									const  ::connectivity::OSQLParseNode * pCondition,
1348 									sal_uInt16& nLevel,
1349 									sal_Bool bHaving,
1350                                     bool bAddOrOnOneLine);
1351 	//------------------------------------------------------------------------------
1352 	SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
1353 							OSelectionBrowseBox* _pSelectionBrw,
1354 							const ::connectivity::OSQLParseNode * pCondition,
1355 							const sal_uInt16 nLevel,
1356 							sal_Bool bHaving,
1357                             bool bAddOrOnOneLine);
1358 	//------------------------------------------------------------------------------
1359 	SqlParseError GetORCriteria(OQueryDesignView* _pView,
1360 								OSelectionBrowseBox* _pSelectionBrw,
1361 								const ::connectivity::OSQLParseNode * pCondition,
1362 								sal_uInt16& nLevel ,
1363 								sal_Bool bHaving,
1364                                 bool bAddOrOnOneLine)
1365 	{
1366 		SqlParseError eErrorCode = eOk;
1367 
1368 		// Runde Klammern um den Ausdruck
1369 		if (pCondition->count() == 3 &&
1370 			SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
1371 			SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
1372 		{
1373 			eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine);
1374 		}
1375 		// oder Verknuepfung
1376 		// a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1377 		else if (SQL_ISRULE(pCondition,search_condition))
1378 		{
1379 			for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2)
1380 			{
1381                 const  ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i);
1382 				if ( SQL_ISRULE(pChild,search_condition) )
1383 					eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine);
1384 				else
1385 				{
1386                     eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, nLevel,bHaving, i == 0 ? false : bAddOrOnOneLine);
1387 					if ( !bAddOrOnOneLine)
1388 						nLevel++;
1389 				}
1390 			}
1391 		}
1392 		else
1393 			eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine );
1394 
1395 		return eErrorCode;
1396 	}
1397     //--------------------------------------------------------------------------------------------------
1398     bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef)
1399     {
1400         bool bRet = true;
1401         ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef;
1402         for (int i = 0; i < 3 && bRet; i+=2)
1403 		{
1404             const  ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i);
1405             if ( SQL_ISRULE(pChild,search_condition) )
1406                 bRet = CheckOrCriteria(pChild,pFirstColumnRef);
1407             else
1408             {
1409                 // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
1410                 ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref);
1411                 if ( pFirstColumnRef && pSecondColumnRef )
1412                     bRet = *pFirstColumnRef == *pSecondColumnRef;
1413                 else if ( !pFirstColumnRef )
1414                     pFirstColumnRef = pSecondColumnRef;
1415             }
1416         }
1417         return bRet;
1418     }
1419 	//--------------------------------------------------------------------------------------------------
1420 	SqlParseError GetANDCriteria(	OQueryDesignView* _pView,
1421 									OSelectionBrowseBox* _pSelectionBrw,
1422 									const  ::connectivity::OSQLParseNode * pCondition,
1423 									sal_uInt16& nLevel,
1424 									sal_Bool bHaving,
1425                                     bool bAddOrOnOneLine)
1426 	{
1427 		const ::com::sun::star::lang::Locale	aLocale = _pView->getLocale();
1428 		const ::rtl::OUString sDecimal = _pView->getDecimalSeparator();
1429 
1430 		// ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen
1431 		OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1432 		SqlParseError eErrorCode = eOk;
1433 
1434 		// Runde Klammern
1435 		if (SQL_ISRULE(pCondition,boolean_primary))
1436 		{
1437             // check if we have to put the or criteria on one line.
1438 			const  ::connectivity::OSQLParseNode* pSearchCondition = pCondition->getChild(1);
1439             bool bMustAddOrOnOneLine = CheckOrCriteria(pSearchCondition,NULL);
1440 			if ( SQL_ISRULE( pSearchCondition, search_condition) ) // we have a or
1441 			{
1442 				_pSelectionBrw->DuplicateConditionLevel( nLevel);
1443 				eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(0), nLevel,bHaving,bMustAddOrOnOneLine );
1444 				++nLevel;
1445 				eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(2), nLevel,bHaving,bMustAddOrOnOneLine );
1446 			}
1447 			else
1448 				eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition, nLevel,bHaving,bMustAddOrOnOneLine );
1449 		}
1450 		// Das erste Element ist (wieder) eine AND-Verknuepfung
1451 		else if ( SQL_ISRULE(pCondition,boolean_term) )
1452 		{
1453             OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term");
1454 			eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine );
1455 			if ( eErrorCode == eOk )
1456 				eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine );
1457 		}
1458 		else if (SQL_ISRULE( pCondition, comparison_predicate))
1459 		{
1460 			eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine);
1461 		}
1462 		else if( SQL_ISRULE(pCondition,like_predicate) )
1463 		{
1464             const  ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0);
1465 			if (SQL_ISRULE(pValueExp, column_ref ) )
1466 			{
1467 				::rtl::OUString aColumnName;
1468 				::rtl::OUString	aCondition;
1469 				Reference< XConnection> xConnection = rController.getConnection();
1470 				if ( xConnection.is() )
1471 				{
1472 					Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
1473 					// the international doesn't matter I have a string
1474 					pCondition->parseNodeToPredicateStr(aCondition,
1475 														xConnection,
1476 														rController.getNumberFormatter(),
1477 														aLocale,
1478 														static_cast<sal_Char>(sDecimal.toChar()),
1479 														&rController.getParser().getContext());
1480 
1481 					pValueExp->parseNodeToPredicateStr(	aColumnName,
1482 														xConnection,
1483 														rController.getNumberFormatter(),
1484 														aLocale,
1485 														static_cast<sal_Char>(sDecimal.toChar()),
1486 														&rController.getParser().getContext());
1487 
1488 					// don't display the column name
1489 					aCondition = aCondition.copy(aColumnName.getLength());
1490 					aCondition = aCondition.trim();
1491 				}
1492 
1493 				OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1494 				if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) ))
1495                 {
1496                     if ( bHaving )
1497 					    aDragLeft->SetGroupBy(sal_True);
1498 					_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1499                 }
1500 			}
1501             else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec)	        ||
1502 							SQL_ISRULEOR2(pValueExp,position_exp,extract_exp)	||
1503 							SQL_ISRULEOR2(pValueExp,fold,char_substring_fct)	||
1504 							SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct))
1505 		    {
1506 			    AddFunctionCondition(	_pView,
1507 									    _pSelectionBrw,
1508 									    pCondition,
1509 									    nLevel,
1510 									    bHaving,
1511                                         bAddOrOnOneLine);
1512 		    }
1513 			else
1514 			{
1515 				eErrorCode = eNoColumnInLike;
1516 				String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN));
1517 				_pView->getController().appendError( sError );
1518 			}
1519 		}
1520 		else if(	SQL_ISRULEOR2(pCondition,test_for_null,in_predicate)
1521 				||	SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate))
1522 		{
1523 			if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
1524 			{
1525 				AddFunctionCondition(	_pView,
1526 										_pSelectionBrw,
1527 										pCondition,
1528 										nLevel,
1529 										bHaving,
1530                                         bAddOrOnOneLine);
1531 			}
1532 			else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) )
1533 			{
1534 				// parse condition
1535 				::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
1536 				OTableFieldDescRef	aDragLeft = new OTableFieldDesc();
1537 				if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) )
1538                 {
1539                     if ( bHaving )
1540 					    aDragLeft->SetGroupBy(sal_True);
1541 					_pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
1542                 }
1543 			}
1544 			else
1545 			{
1546 				// Funktions-Bedingung parsen
1547 				::rtl::OUString	sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
1548 				Reference< XConnection> xConnection = rController.getConnection();
1549 				Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
1550 					// the international doesn't matter I have a string
1551 				::rtl::OUString sName;
1552 				pCondition->getChild(0)->parseNodeToPredicateStr(sName,
1553 													xConnection,
1554 													rController.getNumberFormatter(),
1555 													aLocale,
1556 													static_cast<sal_Char>(sDecimal.toChar()),
1557 													&rController.getParser().getContext());
1558 
1559 				OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1560 				aDragLeft->SetField(sName);
1561 				aDragLeft->SetFunctionType(FKT_OTHER);
1562 
1563 				if ( bHaving )
1564 					aDragLeft->SetGroupBy(sal_True);
1565 				_pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
1566 			}
1567 		}
1568 		else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) )
1569 		{
1570 			// Funktions-Bedingung parsen
1571 			::rtl::OUString	aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0);
1572 
1573 			OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1574 			aDragLeft->SetField(aCondition);
1575 			aDragLeft->SetFunctionType(FKT_CONDITION);
1576 
1577 			eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).isValid() ? eOk : eTooManyColumns;
1578 		}
1579 		else //! TODO not supported yet
1580 			eErrorCode = eStatementTooComplex;
1581 		// Fehler einfach weiterreichen.
1582 		return eErrorCode;
1583 	}
1584 	//------------------------------------------------------------------------------
1585 	SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
1586 							OSelectionBrowseBox* _pSelectionBrw,
1587 							const ::connectivity::OSQLParseNode * pCondition,
1588 							const sal_uInt16 nLevel,
1589 							sal_Bool bHaving,
1590                             bool bAddOrOnOneLine)
1591 	{
1592 		SqlParseError eErrorCode = eOk;
1593 		OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1594 
1595         OSQLParseNode* pFunction = pCondition->getChild(0);
1596 
1597         OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec)	        ||
1598 							SQL_ISRULEOR2(pFunction,position_exp,extract_exp)	||
1599 							SQL_ISRULEOR2(pFunction,fold,char_substring_fct)	||
1600 							SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!");
1601 		::rtl::OUString	aCondition;
1602 		OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1603 
1604 		::rtl::OUString aColumnName;
1605 		Reference< XConnection> xConnection = rController.getConnection();
1606 		if(xConnection.is())
1607 		{
1608 			Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
1609 			pCondition->parseNodeToPredicateStr(aCondition,
1610 												xConnection,
1611 												rController.getNumberFormatter(),
1612 												_pView->getLocale(),
1613 												static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1614 												&rController.getParser().getContext());
1615 
1616             pFunction->parseNodeToStr(	aColumnName,
1617 										xConnection,
1618 										&rController.getParser().getContext(),
1619 										sal_True,
1620 										sal_True); // quote is to true because we need quoted elements inside the function
1621             // i75557
1622 			//pFunction->parseNodeToPredicateStr(aColumnName,
1623 			//									xConnection,
1624 			//									rController.getNumberFormatter(),
1625 			//									_pView->getLocale(),
1626 			//									static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1627 			//									&rController.getParser().getContext());
1628 			// don't display the column name
1629 			aCondition = aCondition.copy(aColumnName.getLength());
1630 			aCondition = aCondition.trim();
1631 			if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign
1632 				aCondition = aCondition.copy(1);
1633 
1634 
1635 			if ( SQL_ISRULE(pFunction, general_set_fct ) )
1636 			{
1637 				sal_Int32 nFunctionType = FKT_AGGREGATE;
1638 				OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2);
1639 				if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' )
1640 				{
1641 					OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
1642 					OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
1643                     OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end();
1644 					for(;aIter != aTabEnd;++aIter)
1645 					{
1646 						OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
1647 						if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aDragLeft ))
1648 						{
1649 							aDragLeft->SetAlias(String());
1650 							aDragLeft->SetTable(String());
1651 							break;
1652 						}
1653 					}
1654 				}
1655 				else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft))
1656 						&& SQL_ISRULE(pParamNode,num_value_exp) )
1657 				{
1658 					::rtl::OUString sParameterValue;
1659 					pParamNode->parseNodeToStr(	sParameterValue,
1660 												xConnection,
1661 												&rController.getParser().getContext());
1662 					nFunctionType |= FKT_NUMERIC;
1663 					aDragLeft->SetField(sParameterValue);
1664 					eErrorCode = eOk;
1665 				}
1666 				aDragLeft->SetFunctionType(nFunctionType);
1667 				if ( bHaving )
1668 					aDragLeft->SetGroupBy(sal_True);
1669 				sal_Int32 nIndex = 0;
1670 				aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex));
1671 			}
1672 			else
1673 			{
1674 				// bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben
1675 				aDragLeft->SetField(aColumnName);
1676 				if(bHaving)
1677 					aDragLeft->SetGroupBy(sal_True);
1678 				aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
1679 			}
1680 			_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1681 		}
1682 
1683 		return eErrorCode;
1684 	}
1685 	//------------------------------------------------------------------------------
1686 	SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
1687 							OSelectionBrowseBox* _pSelectionBrw,
1688 							const ::connectivity::OSQLParseNode * pCondition,
1689 							const sal_uInt16 nLevel,
1690 							sal_Bool bHaving
1691                             ,bool bAddOrOnOneLine)
1692 	{
1693 		SqlParseError eErrorCode = eOk;
1694 		OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1695 
1696 		DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate");
1697 		if ( SQL_ISRULE(pCondition->getChild(0), column_ref )
1698 			|| SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) )
1699 		{
1700 			::rtl::OUString	aCondition;
1701 			OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1702 
1703 			if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
1704 			{
1705 				OTableFieldDescRef aDragRight = new OTableFieldDesc();
1706 				if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ||
1707 					eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight)))
1708 					return eErrorCode;
1709 
1710                 OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>(
1711                                                     _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()),
1712 																					   static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()),
1713                                                                                        true));
1714 				if ( pConn )
1715 				{
1716 					OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList();
1717 					OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
1718                     OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
1719 					for(;aIter != aEnd;++aIter)
1720 					{
1721 						if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() ||
1722 						   (*aIter)->GetDestFieldName() == aDragLeft->GetField() )
1723 							break;
1724 					}
1725 					if(aIter != aEnd)
1726 						return eOk;
1727 				}
1728 			}
1729 
1730 			sal_uInt32 nPos = 0;
1731 			if(SQL_ISRULE(pCondition->getChild(0), column_ref ))
1732 			{
1733 				nPos = 0;
1734 				sal_uInt32 i=1;
1735 
1736 				// don't display the equal
1737 				if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1738 					i++;
1739 
1740 				// Bedingung parsen
1741 				aCondition = ParseCondition(rController
1742 											,pCondition
1743 											,_pView->getDecimalSeparator()
1744 											,_pView->getLocale()
1745 											,i);
1746 			}
1747 			else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
1748 			{
1749 				nPos = pCondition->count()-1;
1750 
1751 				sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2);
1752 				switch (pCondition->getChild(i)->getNodeType())
1753 				{
1754 					case SQL_NODE_EQUAL:
1755 						// don't display the equal
1756 						i--;
1757 						break;
1758 					case SQL_NODE_LESS:
1759 						// take the opposite as we change the order
1760 						i--;
1761 						aCondition = aCondition + ::rtl::OUString::createFromAscii(">");
1762 						break;
1763 					case SQL_NODE_LESSEQ:
1764 						// take the opposite as we change the order
1765 						i--;
1766 						aCondition = aCondition + ::rtl::OUString::createFromAscii(">=");
1767 						break;
1768 					case SQL_NODE_GREAT:
1769 						// take the opposite as we change the order
1770 						i--;
1771 						aCondition = aCondition + ::rtl::OUString::createFromAscii("<");
1772 						break;
1773 					case SQL_NODE_GREATEQ:
1774 						// take the opposite as we change the order
1775 						i--;
1776 						aCondition = aCondition + ::rtl::OUString::createFromAscii("<=");
1777 						break;
1778                     default:
1779                         break;
1780 				}
1781 
1782 				// go backward
1783 				Reference< XConnection> xConnection = rController.getConnection();
1784 				if(xConnection.is())
1785 				{
1786 					Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
1787 					for (; i >= 0; i--)
1788 						pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
1789 												xConnection,
1790 												rController.getNumberFormatter(),
1791 												_pView->getLocale(),
1792 												static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1793 												&rController.getParser().getContext());
1794 				}
1795 			}
1796 			// else ???
1797 
1798 
1799 			if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft)))
1800 			{
1801 				if(bHaving)
1802 					aDragLeft->SetGroupBy(sal_True);
1803 				_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1804 			}
1805 		}
1806 		else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
1807 		{
1808 			AddFunctionCondition(	_pView,
1809 									_pSelectionBrw,
1810 									pCondition,
1811 									nLevel,
1812 									bHaving,
1813                                     bAddOrOnOneLine);
1814 		}
1815 		else // kann sich nur um einen Expr. Ausdruck handeln
1816 		{
1817 			::rtl::OUString aName,aCondition;
1818 
1819 			::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0);
1820 			::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2);
1821 			// Feldnamen
1822 			Reference< XConnection> xConnection = rController.getConnection();
1823 			if(xConnection.is())
1824 			{
1825 				pLhs->parseNodeToStr(aName,
1826 									 xConnection,
1827 									 &rController.getParser().getContext(),
1828 									 sal_True);
1829 				// Kriterium
1830 				aCondition = pCondition->getChild(1)->getTokenValue();
1831 				pRhs->parseNodeToPredicateStr(aCondition,
1832 															xConnection,
1833 															rController.getNumberFormatter(),
1834 															_pView->getLocale(),
1835 															static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1836 															&rController.getParser().getContext());
1837 			}
1838 
1839 			OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1840 			aDragLeft->SetField(aName);
1841 			aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
1842 			// und anh"angen
1843 			_pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1844 		}
1845 		return eErrorCode;
1846 	}
1847 
1848     //------------------------------------------------------------------------------
1849     namespace
1850     {
1851         OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo )
1852         {
1853 			OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin();
1854             OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end();
1855 			for ( ; aIter != aEnd; ++aIter )
1856 			{
1857 				OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second );
1858 				if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) )
1859 					return pTabWin;
1860 			}
1861             return NULL;
1862         }
1863     }
1864 
1865     //------------------------------------------------------------------------------
1866 	void InsertColumnRef(const OQueryDesignView* _pView,
1867 						const ::connectivity::OSQLParseNode * pColumnRef,
1868 						::rtl::OUString& aColumnName,
1869 						const ::rtl::OUString& aColumnAlias,
1870 						::rtl::OUString& aTableRange,
1871 						OTableFieldDescRef& _raInfo,
1872 						OJoinTableView::OTableWindowMap* pTabList)
1873 	{
1874 
1875 		// Tabellennamen zusammen setzen
1876 		::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
1877 		rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
1878 
1879 		sal_Bool bFound(sal_False);
1880 		DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein");
1881 		if (!aTableRange.getLength())
1882 		{
1883 			// SELECT column, ...
1884             bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo );
1885 			if ( bFound && ( aColumnName.toChar() != '*' ) )
1886 				_raInfo->SetFieldAlias(aColumnAlias);
1887 		}
1888 		else
1889 		{
1890 			// SELECT range.column, ...
1891 			OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange);
1892 
1893 			if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo))
1894 			{
1895 				if(aColumnName.toChar() != '*')
1896 					_raInfo->SetFieldAlias(aColumnAlias);
1897 				bFound = sal_True;
1898 			}
1899 		}
1900 		if (!bFound)
1901 		{
1902 			_raInfo->SetTable(::rtl::OUString());
1903 			_raInfo->SetAlias(::rtl::OUString());
1904 			_raInfo->SetField(aColumnName);
1905 			_raInfo->SetFieldAlias(aColumnAlias);	// nyi : hier ein fortlaufendes Expr_1, Expr_2 ...
1906 			_raInfo->SetFunctionType(FKT_OTHER);
1907 		}
1908 	}
1909 	//-----------------------------------------------------------------------------
1910 	sal_Bool checkJoinConditions(	const OQueryDesignView* _pView,
1911 									const ::connectivity::OSQLParseNode* _pNode )
1912 	{
1913 		const ::connectivity::OSQLParseNode* pJoinNode = NULL;
1914 		sal_Bool bRet = sal_True;
1915 		if (SQL_ISRULE(_pNode,qualified_join))
1916 			pJoinNode = _pNode;
1917         else if (SQL_ISRULE(_pNode,table_ref)
1918                 &&  _pNode->count() == 3
1919                 &&  SQL_ISPUNCTUATION(_pNode->getChild(0),"(")
1920                 &&  SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')'
1921 			pJoinNode = _pNode->getChild(1);
1922 		else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column
1923 			bRet = sal_False;
1924 
1925 		if (pJoinNode && !InsertJoin(_pView,pJoinNode))
1926 			bRet = sal_False;
1927 		return bRet;
1928 	}
1929 	//-----------------------------------------------------------------------------
1930 	sal_Bool InsertJoin(const OQueryDesignView* _pView,
1931 						const ::connectivity::OSQLParseNode *pNode)
1932 	{
1933 		DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ),
1934 			"OQueryDesignView::InsertJoin: Fehler im Parse Tree");
1935 
1936         if (SQL_ISRULE(pNode,joined_table))
1937             return InsertJoin(_pView,pNode->getChild(1));
1938 
1939 		// first check the left and right side
1940         const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref
1941         if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) )
1942             pRightTableRef = pNode->getChild(4); // table_ref
1943 
1944 		if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef))
1945 			return sal_False;
1946 
1947 		// named column join wird sp�ter vieleicht noch implementiert
1948 		// SQL_ISRULE(pNode->getChild(4),named_columns_join)
1949         EJoinType eJoinType = INNER_JOIN;
1950         bool bNatural = false;
1951 		if ( SQL_ISRULE(pNode, qualified_join) )
1952 		{
1953 			::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type
1954             if ( SQL_ISTOKEN(pJoinType,NATURAL) )
1955             {
1956                 bNatural = true;
1957                 pJoinType = pNode->getChild(2);
1958             }
1959 
1960 			if (SQL_ISRULE(pJoinType,join_type) && (!pJoinType->count() || SQL_ISTOKEN(pJoinType->getChild(0),INNER)))
1961 			{
1962 				eJoinType = INNER_JOIN;
1963 			}
1964 			else
1965 			{
1966 				if (SQL_ISRULE(pJoinType,join_type))	   // eine Ebene tiefer
1967 					pJoinType = pJoinType->getChild(0);
1968 
1969 				if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT))
1970 					eJoinType = LEFT_JOIN;
1971 				else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT))
1972 					eJoinType = RIGHT_JOIN;
1973 				else
1974 					eJoinType = FULL_JOIN;
1975 			}
1976             if ( SQL_ISRULE(pNode->getChild(4),join_condition) )
1977             {
1978 			    if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType,pNode->getChild(0),pRightTableRef) != eOk )
1979 				    return sal_False;
1980             }
1981 		}
1982         else if ( SQL_ISRULE(pNode, cross_union) )
1983         {
1984             eJoinType = CROSS_JOIN;
1985             pRightTableRef = pNode->getChild(pNode->count() - 1);
1986         }
1987         else
1988 			return sal_False;
1989 
1990         if ( eJoinType == CROSS_JOIN || bNatural )
1991         {
1992 
1993             OQueryTableWindow*	pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) );
1994             OQueryTableWindow*	pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) );
1995             OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!");
1996             if ( !pLeftWindow || !pRightWindow )
1997                 return sal_False;
1998 
1999             OTableFieldDescRef aDragLeft  = new OTableFieldDesc();
2000             aDragLeft->SetTabWindow(pLeftWindow);
2001             aDragLeft->SetTable(pLeftWindow->GetTableName());
2002             aDragLeft->SetAlias(pLeftWindow->GetAliasName());
2003 
2004 			OTableFieldDescRef aDragRight = new OTableFieldDesc();
2005             aDragRight->SetTabWindow(pRightWindow);
2006             aDragRight->SetTable(pRightWindow->GetTableName());
2007             aDragRight->SetAlias(pRightWindow->GetAliasName());
2008 
2009             insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural);
2010         }
2011 
2012 
2013 		return sal_True;
2014 	}
2015 	//------------------------------------------------------------------------------
2016 	void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
2017 	{
2018 		// now we have to insert the fields which aren't in the statement
2019 		OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2020 		OTableFields& rUnUsedFields = rController.getUnUsedFields();
2021         OTableFields::iterator aEnd = rUnUsedFields.end();
2022 		for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter)
2023 			if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).isValid())
2024 				(*aIter) = NULL;
2025 		OTableFields().swap( rUnUsedFields );
2026 	}
2027 
2028 	//------------------------------------------------------------------------------
2029 	SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
2030 	{
2031 		SqlParseError eErrorCode = eOk;
2032 
2033 		OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2034 
2035 		_pSelectionBrw->PreFill();
2036 		_pSelectionBrw->SetReadOnly(rController.isReadOnly());
2037 		_pSelectionBrw->Fill();
2038 
2039 
2040 		::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator();
2041 		const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree();
2042 
2043         do
2044         {
2045             if ( !pParseTree )
2046             {
2047 			    // now we have to insert the fields which aren't in the statement
2048 			    insertUnUsedFields(_pView,_pSelectionBrw);
2049                 break;
2050             }
2051 
2052             if ( !rController.isEsacpeProcessing() ) // not allowed in this mode
2053             {
2054 			    eErrorCode = eNativeMode;
2055                 break;
2056             }
2057 
2058 			if ( !( SQL_ISRULE( pParseTree, select_statement ) ) )
2059             {
2060 				eErrorCode = eNoSelectStatement;
2061                 break;
2062             }
2063 
2064             const OSQLParseNode* pTableExp = pParseTree->getChild(3);
2065             if ( pTableExp->getChild(6)->count() > 0 || pTableExp->getChild(7)->count() > 0 || pTableExp->getChild(8)->count() > 0)
2066             {
2067 				eErrorCode = eStatementTooComplex;
2068                 break;
2069             }
2070 
2071 			Reference< XConnection> xConnection = rController.getConnection();
2072 			if ( !xConnection.is() )
2073             {
2074                 DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" );
2075                 break;
2076             }
2077 
2078 			const OSQLTables& aMap = aIterator.getTables();
2079 			::comphelper::UStringMixLess aTmp(aMap.key_comp());
2080 			::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() );
2081 
2082 			Reference< XDatabaseMetaData >  xMetaData = xConnection->getMetaData();
2083 			try
2084 			{
2085 			    sal_Int32 nMax = xMetaData->getMaxTablesInSelect();
2086                 if ( nMax && nMax < (sal_Int32)aMap.size() )
2087                 {
2088 					eErrorCode = eTooManyTables;
2089                     break;
2090                 }
2091 
2092 				::rtl::OUString sComposedName;
2093 				::rtl::OUString aQualifierName;
2094 				::rtl::OUString sAlias;
2095 
2096 				OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
2097                 pTableView->clearLayoutInformation();
2098 				OSQLTables::const_iterator aIter = aMap.begin();
2099                 OSQLTables::const_iterator aEnd = aMap.end();
2100 				for(;aIter != aEnd;++aIter)
2101 				{
2102 					OSQLTable xTable = aIter->second;
2103                     Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW );
2104 
2105 					sAlias = aIter->first;
2106 
2107                     // check whether this is a query
2108                     Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo();
2109                     bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND );
2110 
2111                     if ( bIsQuery )
2112                         OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName );
2113                     else
2114                     {
2115                         sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false );
2116 
2117                         // if the alias is the complete (composed) table, then shorten it
2118                         if ( aKeyComp( sComposedName, aIter->first ) )
2119 					    {
2120 						    ::rtl::OUString sCatalog, sSchema, sTable;
2121 						    ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
2122 						    sAlias = sTable;
2123 					    }
2124                     }
2125 
2126                     // find the existent window for this alias
2127 					OQueryTableWindow* pExistentWin	= pTableView->FindTable( sAlias );
2128 					if ( !pExistentWin )
2129 					{
2130 						pTableView->AddTabWin( sComposedName, sAlias, sal_False );  // don't create data here
2131 					}
2132 					else
2133 					{
2134 						// there already exists a window for this alias ....
2135 						if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) )
2136 							// ... but for another complete table name -> new window
2137 							pTableView->AddTabWin(sComposedName, sAlias);
2138 					}
2139 				}
2140 
2141 				// now delete the data for which we haven't any tablewindow
2142 				OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap());
2143 				OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin();
2144                 OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end();
2145 				for(;aIterTableMap != aIterTableEnd;++aIterTableMap)
2146 				{
2147 					if(aMap.find(aIterTableMap->second->GetComposedName())	== aMap.end() &&
2148 						aMap.find(aIterTableMap->first)						== aMap.end())
2149 						pTableView->RemoveTabWin(aIterTableMap->second);
2150 				}
2151 
2152 				if ( eOk == (eErrorCode = FillOuterJoins(_pView,pTableExp->getChild(0)->getChild(1))) )
2153 				{
2154 					// check if we have a distinct statement
2155 					if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT))
2156 					{
2157 						rController.setDistinct(sal_True);
2158 						rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES);
2159 					}
2160 					if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk )
2161 					{
2162 						// GetSelectionCriteria must be called before GetHavingCriteria
2163 						sal_uInt16 nLevel=0;
2164 
2165 						if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
2166 						{
2167 							if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) )
2168 							{
2169 								if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
2170 								{
2171 									if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) )
2172 										insertUnUsedFields(_pView,_pSelectionBrw);
2173 								}
2174 							}
2175 						}
2176 					}
2177 				}
2178 			}
2179 			catch(SQLException&)
2180 			{
2181 				OSL_ASSERT(!"getMaxTablesInSelect!");
2182 			}
2183 		}
2184         while ( false );
2185 
2186 		// Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt
2187 		rController.ClearUndoManager();
2188 		_pSelectionBrw->Invalidate();
2189 		return eErrorCode;
2190 	}
2191 	//------------------------------------------------------------------------------
2192 	/** fillSelectSubList
2193 		@return
2194 			<TRUE/> when columns could be inserted otherwise <FALSE/>
2195 	*/
2196 	//------------------------------------------------------------------------------
2197 	SqlParseError fillSelectSubList(	OQueryDesignView* _pView,
2198 								OJoinTableView::OTableWindowMap* _pTabList)
2199 	{
2200 		SqlParseError eErrorCode = eOk;
2201 		sal_Bool bFirstField = sal_True;
2202 		::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*"));
2203 		OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin();
2204         OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end();
2205 		for(;aIter != aEnd && eOk == eErrorCode ;++aIter)
2206 		{
2207 			OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
2208             OTableFieldDescRef	aInfo = new OTableFieldDesc();
2209 			if (pTabWin->ExistsField( sAsterix, aInfo ))
2210 			{
2211 				eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2212 				bFirstField = sal_False;
2213 			}
2214 		}
2215 		return eErrorCode;
2216 	}
2217 	//------------------------------------------------------------------------------
2218 	SqlParseError InstallFields(OQueryDesignView* _pView,
2219 								const ::connectivity::OSQLParseNode* pNode,
2220 								OJoinTableView::OTableWindowMap* pTabList )
2221 	{
2222 		if( pNode==0 || !SQL_ISRULE(pNode,select_statement))
2223 			return eNoSelectStatement;
2224 
2225 		::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2); // selection
2226 		sal_Bool bFirstField = sal_True;	// bei der Initialisierung mu� auf alle Faelle das erste Feld neu aktiviert werden
2227 
2228 		SqlParseError eErrorCode = eOk;
2229 
2230 		if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") )
2231 		{
2232 			// SELECT * ...
2233 			eErrorCode = fillSelectSubList(_pView,pTabList);
2234 		}
2235 		else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) )
2236 		{
2237 			// SELECT column, ...
2238 			OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2239 			Reference< XConnection> xConnection = rController.getConnection();
2240 
2241 			::rtl::OUString aColumnName,aTableRange;
2242 			for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i)
2243 			{
2244 				::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i);
2245 
2246                 do {
2247 
2248                 if ( SQL_ISRULE(pColumnRef,select_sublist) )
2249 				{
2250 					 eErrorCode = fillSelectSubList(_pView,pTabList);
2251                      break;
2252 				}
2253 
2254                 if ( SQL_ISRULE(pColumnRef,derived_column) )
2255 				{
2256 					::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein
2257 					pColumnRef = pColumnRef->getChild(0);
2258 					OTableFieldDescRef aInfo = new OTableFieldDesc();
2259 
2260 					if (	pColumnRef->count() == 3 &&
2261 							SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
2262 							SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
2263 						)
2264 						pColumnRef = pColumnRef->getChild(1);
2265 
2266 					if (SQL_ISRULE(pColumnRef,column_ref))
2267 					{
2268 						InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
2269 						eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2270 						bFirstField = sal_False;
2271 					}
2272 					else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec)	||
2273 							SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp)		||
2274 							SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct)		||
2275 							SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct))
2276 					{
2277 						::rtl::OUString aColumns;
2278                         pColumnRef->parseNodeToPredicateStr(aColumns,
2279 												            xConnection,
2280 												            rController.getNumberFormatter(),
2281 												            _pView->getLocale(),
2282 												            static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
2283 												            &rController.getParser().getContext());
2284 						//pColumnRef->parseNodeToStr(	aColumns,
2285 						//							xConnection,
2286 						//							&rController.getParser().getContext(),
2287 						//							sal_True,
2288 						//							sal_True); // quote is to true because we need quoted elements inside the function
2289 
2290 						sal_Int32 nFunctionType = FKT_NONE;
2291 						::connectivity::OSQLParseNode* pParamRef = NULL;
2292 						sal_Int32 nColumnRefPos = pColumnRef->count() - 2;
2293 						if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() )
2294 							pParamRef = pColumnRef->getChild(nColumnRefPos);
2295 
2296 						if (	SQL_ISRULE(pColumnRef,general_set_fct)
2297 							&&	SQL_ISRULE(pParamRef,column_ref) )
2298 						{
2299 							// Parameter auf Columnref pr"ufen
2300 							InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
2301 						}
2302 						else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
2303 						{
2304 							if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' )
2305 							{
2306 								OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
2307                                 OJoinTableView::OTableWindowMap::iterator aEnd  = pTabList->end();
2308 								for(;aIter != aEnd;++aIter)
2309 								{
2310 									OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
2311 									if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aInfo ))
2312 									{
2313 										aInfo->SetAlias(String());
2314 										aInfo->SetTable(String());
2315 										break;
2316 									}
2317 								}
2318 							}
2319 							else
2320 							{
2321 								::rtl::OUString sFieldName = aColumns;
2322 								if ( pParamRef )
2323 								{	// we got an aggregate function but without column name inside
2324 									// so we set the whole argument of the function as field name
2325 									nFunctionType |= FKT_NUMERIC;
2326 									sFieldName = ::rtl::OUString();
2327 									pParamRef->parseNodeToStr(	sFieldName,
2328 														xConnection,
2329 														&rController.getParser().getContext(),
2330 														sal_True,
2331 														sal_True); // quote is to true because we need quoted elements inside the function
2332 								}
2333 								aInfo->SetDataType(DataType::DOUBLE);
2334 								aInfo->SetFieldType(TAB_NORMAL_FIELD);
2335 								aInfo->SetField(sFieldName);
2336 							}
2337 							aInfo->SetTabWindow(NULL);
2338 							aInfo->SetFieldAlias(aColumnAlias);
2339 						}
2340 						else
2341 						{
2342                             _pView->fillFunctionInfo(pColumnRef,aColumns,aInfo);
2343 							aInfo->SetFieldAlias(aColumnAlias);
2344 						}
2345 
2346 						if ( SQL_ISRULE(pColumnRef,general_set_fct) )
2347 						{
2348 							aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE);
2349 							String aCol(aColumns);
2350 							aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' '));
2351 						}
2352 						else
2353 							aInfo->SetFunctionType(nFunctionType|FKT_OTHER);
2354 
2355 						eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2356 						bFirstField = sal_False;
2357 					}
2358 					else //if(SQL_ISRULE(pColumnRef,num_value_exp)	|| SQL_ISRULE(pColumnRef,term))
2359 					{
2360 						::rtl::OUString aColumns;
2361 						pColumnRef->parseNodeToStr(	aColumns,
2362 													xConnection,
2363 													&rController.getParser().getContext(),
2364 													sal_True,
2365 													sal_True); // quote is to true because we need quoted elements inside the function
2366 
2367                         aInfo->SetTabWindow( NULL );
2368 
2369                         // since we support queries in queries, the thingie might belong to an existing "table"
2370                         OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo );
2371                         if ( pExistingTable )
2372                         {
2373                             aInfo->SetTabWindow( pExistingTable );
2374 					        aInfo->SetTable( pExistingTable->GetTableName() );
2375 					        aInfo->SetAlias( pExistingTable->GetAliasName() );
2376                         }
2377 
2378                         aInfo->SetDataType(DataType::DOUBLE);
2379 						aInfo->SetFieldType(TAB_NORMAL_FIELD);
2380 						aInfo->SetField(aColumns);
2381 						aInfo->SetFieldAlias(aColumnAlias);
2382 						aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
2383 
2384 						eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2385 						bFirstField = sal_False;
2386 					}
2387 
2388                     break;
2389 				}
2390 
2391                 DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" );
2392 
2393                 } while ( false );
2394 			}
2395 		}
2396 		else
2397 			eErrorCode = eStatementTooComplex;
2398 
2399 		return eErrorCode;
2400 	}
2401 	//------------------------------------------------------------------------------
2402 	SqlParseError GetOrderCriteria(	OQueryDesignView* _pView,
2403 							OSelectionBrowseBox* _pSelectionBrw,
2404 							const ::connectivity::OSQLParseNode* pParseRoot )
2405 	{
2406 		SqlParseError eErrorCode = eOk;
2407 		if (!pParseRoot->getChild(3)->getChild(4)->isLeaf())
2408 		{
2409 			::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2);
2410 			::connectivity::OSQLParseNode* pParamRef = NULL;
2411 
2412             OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2413 			EOrderDir eOrderDir;
2414 			OTableFieldDescRef aDragLeft = new OTableFieldDesc();
2415 			for( sal_uInt32 i=0 ; i<pNode->count() ; i++ )
2416 			{
2417 				eOrderDir = ORDER_ASC;
2418 				::connectivity::OSQLParseNode*	pChild = pNode->getChild( i );
2419 
2420 				if (SQL_ISTOKEN( pChild->getChild(1), DESC ) )
2421 					eOrderDir = ORDER_DESC;
2422 
2423                 ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0);
2424 
2425 				if(SQL_ISRULE(pArgument,column_ref))
2426 				{
2427 					if( eOk == FillDragInfo(_pView,pArgument,aDragLeft))
2428 						_pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i);
2429 					else // it could be a alias name for a field
2430 					{
2431 						::rtl::OUString aTableRange,aColumnName;
2432 						::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator();
2433 						rParseIter.getColumnRange( pArgument, aColumnName, aTableRange );
2434 
2435 						OTableFields& aList = rController.getTableFieldDesc();
2436 						OTableFields::iterator aIter = aList.begin();
2437                         OTableFields::iterator aEnd = aList.end();
2438 						for(;aIter != aEnd;++aIter)
2439 						{
2440 							OTableFieldDescRef pEntry = *aIter;
2441 							if(pEntry.isValid() && pEntry->GetFieldAlias() == aColumnName)
2442 								pEntry->SetOrderDir( eOrderDir );
2443 						}
2444 					}
2445 				}
2446 				else if(SQL_ISRULE(pArgument, general_set_fct ) &&
2447 						SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
2448 						eOk == FillDragInfo(_pView,pParamRef,aDragLeft))
2449 					_pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
2450                 else if( SQL_ISRULE(pArgument, set_fct_spec ) )
2451                 {
2452 
2453 		            Reference< XConnection> xConnection = rController.getConnection();
2454 		            if(xConnection.is())
2455 		            {
2456                         ::rtl::OUString sCondition;
2457 			            pArgument->parseNodeToPredicateStr(sCondition,
2458 												            xConnection,
2459 												            rController.getNumberFormatter(),
2460 												            _pView->getLocale(),
2461 												            static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
2462 												            &rController.getParser().getContext());
2463                         _pView->fillFunctionInfo(pArgument,sCondition,aDragLeft);
2464                         aDragLeft->SetFunctionType(FKT_OTHER);
2465                         aDragLeft->SetOrderDir(eOrderDir);
2466                         aDragLeft->SetVisible(sal_False);
2467                         _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
2468                     }
2469                     else
2470                         eErrorCode = eColumnNotFound;
2471                 }
2472 				else
2473 					eErrorCode = eColumnNotFound;
2474 			}
2475 		}
2476 		return eErrorCode;
2477 	}
2478 	//------------------------------------------------------------------------------
2479 	SqlParseError GetHavingCriteria(	OQueryDesignView* _pView,
2480 							OSelectionBrowseBox* _pSelectionBrw,
2481 							const ::connectivity::OSQLParseNode* pSelectRoot,
2482 							sal_uInt16& rLevel )
2483 	{
2484 		SqlParseError eErrorCode = eOk;
2485 		if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf())
2486 			eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True);
2487 		return eErrorCode;
2488 	}
2489 	//------------------------------------------------------------------------------
2490 	SqlParseError GetGroupCriteria(	OQueryDesignView* _pView,
2491 							OSelectionBrowseBox* _pSelectionBrw,
2492 							const ::connectivity::OSQLParseNode* pSelectRoot )
2493 	{
2494 		SqlParseError eErrorCode = eOk;
2495 		if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause
2496 		{
2497             OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2498 			::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2);
2499 
2500 			for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i )
2501 			{
2502                 OTableFieldDescRef aDragInfo = new OTableFieldDesc();
2503                 ::connectivity::OSQLParseNode* pParamRef = NULL;
2504 				::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i );
2505 				if(SQL_ISRULE(pArgument,column_ref))
2506 				{
2507 					if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) )
2508 					{
2509 						aDragInfo->SetGroupBy(sal_True);
2510 						_pSelectionBrw->AddGroupBy(aDragInfo,i);
2511 					}
2512 				}
2513                 else if(SQL_ISRULE(pArgument, general_set_fct ) &&
2514 						SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
2515 						eOk == FillDragInfo(_pView,pParamRef,aDragInfo))
2516                 {
2517                     aDragInfo->SetGroupBy(sal_True);
2518 					_pSelectionBrw->AddGroupBy( aDragInfo, i );
2519                 }
2520                 else if( SQL_ISRULE(pArgument, set_fct_spec ) )
2521                 {
2522 		            Reference< XConnection> xConnection = rController.getConnection();
2523 		            if(xConnection.is())
2524 		            {
2525                         ::rtl::OUString sGroupByExpression;
2526 			            pArgument->parseNodeToStr(	sGroupByExpression,
2527 													xConnection,
2528 													&rController.getParser().getContext(),
2529 													sal_True,
2530 													sal_True); // quote is to true because we need quoted elements inside the function
2531                         _pView->fillFunctionInfo(pArgument,sGroupByExpression,aDragInfo);
2532                         aDragInfo->SetFunctionType(FKT_OTHER);
2533                         aDragInfo->SetGroupBy(sal_True);
2534                         aDragInfo->SetVisible(sal_False);
2535                         _pSelectionBrw->AddGroupBy( aDragInfo, i );
2536                     }
2537                     else
2538                         eErrorCode = eColumnNotFound;
2539                 }
2540 			}
2541 		}
2542 		return eErrorCode;
2543 	}
2544 
2545     //------------------------------------------------------------------------------
2546 	String getParseErrorMessage( SqlParseError _eErrorCode )
2547 	{
2548 		sal_uInt16 nResId;
2549 		switch(_eErrorCode)
2550 		{
2551 			case eIllegalJoin:
2552 				nResId = STR_QRY_ILLEGAL_JOIN;
2553 				break;
2554 			case eStatementTooLong:
2555 				nResId = STR_QRY_TOO_LONG_STATEMENT;
2556 				break;
2557 			case eNoConnection:
2558 				nResId = STR_QRY_SYNTAX;
2559 				break;
2560 			case eNoSelectStatement:
2561 				nResId = STR_QRY_NOSELECT;
2562 				break;
2563 			case eColumnInLikeNotFound:
2564 				nResId = STR_QRY_SYNTAX;
2565 				break;
2566 			case eNoColumnInLike:
2567 				nResId = STR_QRY_SYNTAX;
2568 				break;
2569 			case eColumnNotFound:
2570 				nResId = STR_QRY_SYNTAX;
2571 				break;
2572 			case eNativeMode:
2573 				nResId = STR_QRY_NATIVE;
2574 				break;
2575 			case eTooManyTables:
2576 				nResId = STR_QRY_TOO_MANY_TABLES;
2577 				break;
2578 			case eTooManyConditions:
2579 				nResId = STR_QRY_TOOMANYCOND;
2580 				break;
2581 			case eTooManyColumns:
2582 				nResId = STR_QRY_TOO_MANY_COLUMNS;
2583 				break;
2584 			case eStatementTooComplex:
2585 				nResId = STR_QRY_TOOCOMPLEX;
2586 				break;
2587 			default:
2588 				nResId = STR_QRY_SYNTAX;
2589 				break;
2590 		}
2591 		;
2592         return String( ModuleRes( nResId ) );
2593 	}
2594 
2595 	//------------------------------------------------------------------------------
2596 	//------------------------------------------------------------------------------
2597 }
2598 // end of anonymouse namespace
2599 DBG_NAME(OQueryDesignView)
2600 
2601 OQueryDesignView::OQueryDesignView(	OQueryContainerWindow* _pParent,
2602 									OQueryController& _rController,
2603 									const Reference< XMultiServiceFactory >& _rFactory)
2604 	:OQueryView( _pParent, _rController, _rFactory )
2605 	,m_aSplitter( this )
2606 	,m_eChildFocus(NONE)
2607 	,m_bInKeyEvent(sal_False)
2608 	,m_bInSplitHandler( sal_False )
2609 {
2610     DBG_CTOR(OQueryDesignView,NULL);
2611 
2612 	try
2613 	{
2614 		SvtSysLocale aSysLocale;
2615 		m_aLocale = aSysLocale.GetLocaleData().getLocale();
2616 		m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep();
2617 	}
2618 	catch(Exception&)
2619 	{
2620 	}
2621 
2622 	m_pSelectionBox = new OSelectionBrowseBox(this);
2623 
2624 	setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows());
2625 	m_pSelectionBox->Show();
2626 	// Splitter einrichten
2627 	m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl));
2628 	m_aSplitter.Show();
2629 
2630 }
2631 // -----------------------------------------------------------------------------
2632 OQueryDesignView::~OQueryDesignView()
2633 {
2634 	if ( m_pTableView )
2635 		::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
2636 	::std::auto_ptr<Window> aTemp(m_pSelectionBox);
2637 	m_pSelectionBox = NULL;
2638 
2639     DBG_DTOR(OQueryDesignView,NULL);
2640 }
2641 //------------------------------------------------------------------------------
2642 IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ )
2643 {
2644 	if (!getController().isReadOnly())
2645 	{
2646 		m_bInSplitHandler = sal_True;
2647 		m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) );
2648 		static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel());
2649 		static_cast<OQueryController&>(getController()).setModified( sal_True );
2650 		Resize();
2651 		m_bInSplitHandler = sal_True;
2652 	}
2653 	return 0L;
2654 }
2655 // -------------------------------------------------------------------------
2656 void OQueryDesignView::Construct()
2657 {
2658 	m_pTableView = new OQueryTableView(m_pScrollWindow,this);
2659 	::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow));
2660 	OQueryView::Construct();
2661 }
2662 // -----------------------------------------------------------------------------
2663 void OQueryDesignView::initialize()
2664 {
2665 	if(static_cast<OQueryController&>(getController()).getSplitPos() != -1)
2666 	{
2667 		m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) );
2668 		m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos());
2669 	}
2670 	m_pSelectionBox->initialize();
2671 	reset();
2672 }
2673 // -------------------------------------------------------------------------
2674 void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground)
2675 {
2676 	Point aPlaygroundPos( _rPlayground.TopLeft() );
2677 	Size aPlaygroundSize( _rPlayground.GetSize() );
2678 
2679 	// calc the split pos, and forward it to the controller
2680 	sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos();
2681 	if ( 0 != aPlaygroundSize.Height() )
2682 	{
2683 		if	(	( -1 == nSplitPos )
2684 			||	( nSplitPos >= aPlaygroundSize.Height() )
2685 			)
2686 		{
2687 			// let the selection browse box determine an optimal size
2688 			Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
2689 			nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height();
2690 			// still an invalid size?
2691 			if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() )
2692 				nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6);
2693 
2694 			static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos);
2695 		}
2696 
2697 		if ( !m_bInSplitHandler )
2698 		{	// the resize is triggered by something else than the split handler
2699 			// our main focus is to try to preserve the size of the selectionbrowse box
2700 			Size aSelBoxSize = m_pSelectionBox->GetSizePixel();
2701 			if ( aSelBoxSize.Height() )
2702 			{
2703 				// keep the size of the sel box constant
2704 				nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height();
2705 
2706 				// and if the box is smaller than the optimal size, try to do something about it
2707 				Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
2708 				if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() )
2709 				{
2710 					nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height();
2711 				}
2712 
2713 				static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos );
2714 			}
2715 		}
2716 	}
2717 
2718 	// normalize the split pos
2719 	Point	aSplitPos		= Point( _rPlayground.Left(), nSplitPos );
2720 	Size	aSplitSize		= Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() );
2721 
2722 	if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() ))
2723 		aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height();
2724 
2725 	if( aSplitPos.Y() <= aPlaygroundPos.Y() )
2726 		aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2);
2727 
2728 	// position the table
2729 	Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y());
2730 	m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize);
2731 
2732 	// position the selection browse box
2733 	Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() );
2734 	m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() ));
2735 
2736 	// set the size of the splitter
2737 	m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize );
2738 	m_aSplitter.SetDragRectPixel( _rPlayground );
2739 
2740 	// just for completeness: there is no space left, we occupied it all ...
2741 	_rPlayground.SetPos( _rPlayground.BottomRight() );
2742 	_rPlayground.SetSize( Size( 0, 0 ) );
2743 }
2744 // -----------------------------------------------------------------------------
2745 void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly)
2746 {
2747 	m_pSelectionBox->SetReadOnly(_bReadOnly);
2748 }
2749 // -----------------------------------------------------------------------------
2750 void OQueryDesignView::clear()
2751 {
2752 	m_pSelectionBox->ClearAll(); // clear the whole selection
2753 	m_pTableView->ClearAll();
2754 }
2755 // -----------------------------------------------------------------------------
2756 void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/)
2757 {
2758 }
2759 // -----------------------------------------------------------------------------
2760 void OQueryDesignView::copy()
2761 {
2762 	if( m_eChildFocus == SELECTION)
2763 		m_pSelectionBox->copy();
2764 }
2765 // -----------------------------------------------------------------------------
2766 sal_Bool OQueryDesignView::isCutAllowed()
2767 {
2768 	sal_Bool bAllowed = sal_False;
2769 	if ( SELECTION == m_eChildFocus )
2770 		bAllowed = m_pSelectionBox->isCutAllowed();
2771 	return bAllowed;
2772 }
2773 // -----------------------------------------------------------------------------
2774 sal_Bool OQueryDesignView::isPasteAllowed()
2775 {
2776 	sal_Bool bAllowed = sal_False;
2777 	if ( SELECTION == m_eChildFocus )
2778 		bAllowed = m_pSelectionBox->isPasteAllowed();
2779 	return bAllowed;
2780 }
2781 // -----------------------------------------------------------------------------
2782 sal_Bool OQueryDesignView::isCopyAllowed()
2783 {
2784 	sal_Bool bAllowed = sal_False;
2785 	if ( SELECTION == m_eChildFocus )
2786 		bAllowed = m_pSelectionBox->isCopyAllowed();
2787 	return bAllowed;
2788 }
2789 // -----------------------------------------------------------------------------
2790 void OQueryDesignView::stopTimer()
2791 {
2792 	m_pSelectionBox->stopTimer();
2793 }
2794 // -----------------------------------------------------------------------------
2795 void OQueryDesignView::startTimer()
2796 {
2797 	m_pSelectionBox->startTimer();
2798 }
2799 // -----------------------------------------------------------------------------
2800 void OQueryDesignView::cut()
2801 {
2802 	if( m_eChildFocus == SELECTION)
2803 	{
2804 		m_pSelectionBox->cut();
2805 		static_cast<OQueryController&>(getController()).setModified(sal_True);
2806 	}
2807 }
2808 // -----------------------------------------------------------------------------
2809 void OQueryDesignView::paste()
2810 {
2811 	if( m_eChildFocus == SELECTION)
2812 	{
2813 		m_pSelectionBox->paste();
2814 		static_cast<OQueryController&>(getController()).setModified(sal_True);
2815 	}
2816 }
2817 // -----------------------------------------------------------------------------
2818 void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName)
2819 {
2820 	// Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde
2821 	DeleteFields(rAliasName);
2822 	static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE);	// view nochmal bescheid sagen
2823 }
2824 //------------------------------------------------------------------------------
2825 void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName )
2826 {
2827 	m_pSelectionBox->DeleteFields( rAliasName );
2828 }
2829 // -----------------------------------------------------------------------------
2830 bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo)  const
2831 {
2832     return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo);
2833 }
2834 // -----------------------------------------------------------------------------
2835 SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate)
2836 {
2837 	return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).isValid() ? eOk : eTooManyColumns;
2838 }
2839 // -----------------------------------------------------------------------------
2840 sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const
2841 {
2842     static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15;
2843     sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos);
2844     if ( !nWidth )
2845         nWidth = s_nDefaultWidth;
2846 	return nWidth;
2847 }
2848 //------------------------------------------------------------------------------
2849 void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList)
2850 {
2851 	DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !");
2852 	pFieldList->Clear();
2853 
2854 	sal_Bool bAllTables = sAliasName.getLength() == 0;
2855 
2856 	OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap();
2857 	::rtl::OUString strCurrentPrefix;
2858 	::std::vector< ::rtl::OUString> aFields;
2859 	OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin();
2860     OJoinTableView::OTableWindowMap::iterator aEnd  = pTabWins->end();
2861     for(;aIter != aEnd;++aIter)
2862 	{
2863 		OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second);
2864 		if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName))
2865 		{
2866 			strCurrentPrefix = pCurrentWin->GetAliasName();
2867 			strCurrentPrefix += ::rtl::OUString('.');
2868 
2869 			pCurrentWin->EnumValidFields(aFields);
2870 
2871 			::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin();
2872             ::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end();
2873 			for(;aStrIter != aStrEnd;++aStrIter)
2874 			{
2875 				if (bAllTables || aStrIter->toChar() == '*')
2876 					pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter);
2877 				else
2878 					pFieldList->InsertEntry(*aStrIter);
2879 			}
2880 
2881 			if (!bAllTables)
2882 				// das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig
2883 				// (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt)
2884 				break;
2885 		}
2886 	}
2887 }
2888 // -----------------------------------------------------------------------------
2889 long OQueryDesignView::PreNotify(NotifyEvent& rNEvt)
2890 {
2891 	switch (rNEvt.GetType())
2892 	{
2893 		case EVENT_GETFOCUS:
2894 #if OSL_DEBUG_LEVEL > 0
2895 			{
2896 				Window* pFocus = Application::GetFocusWindow();
2897                 (void)pFocus;
2898 			}
2899 #endif
2900 
2901 			if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() )
2902 				m_eChildFocus = SELECTION;
2903 			else
2904 				m_eChildFocus = TABLEVIEW;
2905 			break;
2906 	}
2907 
2908 	return OQueryView::PreNotify(rNEvt);
2909 }
2910 //------------------------------------------------------------------------------
2911 
2912 
2913 // -----------------------------------------------------------------------------
2914 // check if the statement is correct when not returning false
2915 sal_Bool OQueryDesignView::checkStatement()
2916 {
2917 	sal_Bool bRet = sal_True;
2918 	if ( m_pSelectionBox )
2919 		bRet = m_pSelectionBox->Save(); // a error occured so we return no
2920 	return bRet;
2921 }
2922 //-------------------------------------------------------------------------------
2923 ::rtl::OUString OQueryDesignView::getStatement()
2924 {
2925 	OQueryController& rController = static_cast<OQueryController&>(getController());
2926 	m_rController.clearError();
2927 	// used for fields which aren't any longer in the statement
2928 	OTableFields& rUnUsedFields = rController.getUnUsedFields();
2929 	OTableFields().swap( rUnUsedFields );
2930 
2931 	// create the select columns
2932 	sal_uInt32 nFieldcount = 0;
2933 	OTableFields& rFieldList = rController.getTableFieldDesc();
2934 	OTableFields::iterator aIter = rFieldList.begin();
2935     OTableFields::iterator aEnd = rFieldList.end();
2936 	for(;aIter != aEnd;++aIter)
2937 	{
2938 		OTableFieldDescRef pEntryField = *aIter;
2939 		if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() )
2940 			++nFieldcount;
2941 		else if (pEntryField->GetField().getLength()			&&
2942 				!pEntryField->HasCriteria()					&&
2943 				pEntryField->isNoneFunction()				&&
2944 				pEntryField->GetOrderDir() == ORDER_NONE	&&
2945                 !pEntryField->IsGroupBy()                   &&
2946 				!pEntryField->GetFunction().getLength() )
2947 			rUnUsedFields.push_back(pEntryField);
2948 	}
2949 	if ( !nFieldcount )	// keine Felder sichtbar also zur"uck
2950 	{
2951 		rUnUsedFields = rFieldList;
2952 		return ::rtl::OUString();
2953 	}
2954 
2955 	OQueryTableView::OTableWindowMap* pTabList   = m_pTableView->GetTabWinMap();
2956 	sal_uInt32 nTabcount		= pTabList->size();
2957 
2958 	::rtl::OUString	aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1));
2959 	if( !aFieldListStr.getLength() )
2960 		return ::rtl::OUString();
2961 	// Ausnahmebehandlung, wenn keine Felder angegeben worden sind
2962 	// Dann darf die Tabpage nicht gewechselt werden
2963 	// Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt
2964 	// und eine Errormeldung erzeugt
2965 	// ----------------- Tabellenliste aufbauen ----------------------
2966 
2967 	const ::std::vector<OTableConnection*>*	pConnList = m_pTableView->getTableConnections();
2968 	Reference< XConnection> xConnection = rController.getConnection();
2969 	::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList));
2970 	DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !");
2971 	// wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits
2972 	// eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder
2973 	// existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher)
2974 	::rtl::OUStringBuffer aHavingStr,aCriteriaListStr;
2975 	// ----------------- Kriterien aufbauen ----------------------
2976 	if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1))
2977 		return ::rtl::OUString();
2978 
2979 	::rtl::OUString aJoinCrit;
2980 	GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList);
2981 	if(aJoinCrit.getLength())
2982 	{
2983 		::rtl::OUString aTmp = ::rtl::OUString::createFromAscii("( ");
2984 		aTmp += aJoinCrit;
2985 		aTmp += ::rtl::OUString::createFromAscii(" )");
2986 		if(aCriteriaListStr.getLength())
2987 		{
2988 			aTmp += C_AND;
2989 			aTmp += aCriteriaListStr.makeStringAndClear();
2990 		}
2991 		aCriteriaListStr = aTmp;
2992 	}
2993 	// ----------------- Statement aufbauen ----------------------
2994 	::rtl::OUStringBuffer aSqlCmd(::rtl::OUString::createFromAscii("SELECT "));
2995 	if(static_cast<OQueryController&>(getController()).isDistinct())
2996 		aSqlCmd.append(::rtl::OUString::createFromAscii(" DISTINCT "));
2997 	aSqlCmd.append(aFieldListStr);
2998 	aSqlCmd.append(::rtl::OUString::createFromAscii(" FROM "));
2999 	aSqlCmd.append(aTableListStr);
3000 
3001 	if (aCriteriaListStr.getLength())
3002 	{
3003 		aSqlCmd.append(::rtl::OUString::createFromAscii(" WHERE "));
3004 		aSqlCmd.append(aCriteriaListStr.makeStringAndClear());
3005 	}
3006 	// ----------------- GroupBy aufbauen und Anh"angen ------------
3007 	Reference<XDatabaseMetaData> xMeta;
3008 	if ( xConnection.is() )
3009 		xMeta = xConnection->getMetaData();
3010 	sal_Bool bUseAlias = nTabcount > 1;
3011 	if ( xMeta.is() )
3012 		bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated();
3013 
3014 	aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias));
3015 	// ----------------- having Anh"angen ------------
3016 	if(aHavingStr.getLength())
3017 	{
3018 		aSqlCmd.append(::rtl::OUString::createFromAscii(" HAVING "));
3019 		aSqlCmd.append(aHavingStr.makeStringAndClear());
3020 	}
3021 	// ----------------- Sortierung aufbauen und Anh"angen ------------
3022 	::rtl::OUString sOrder;
3023 	SqlParseError eErrorCode = eOk;
3024 	if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk)
3025 		aSqlCmd.append(sOrder);
3026 	else
3027 	{
3028 		if ( !m_rController.hasError() )
3029             m_rController.appendError( getParseErrorMessage( eErrorCode ) );
3030 
3031         m_rController.displayError();
3032 	}
3033 
3034     ::rtl::OUString sSQL = aSqlCmd.makeStringAndClear();
3035     if ( xConnection.is() )
3036     {
3037         ::connectivity::OSQLParser& rParser( rController.getParser() );
3038         ::rtl::OUString sErrorMessage;
3039         ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) );
3040         if ( pParseNode.get() )
3041         {
3042             OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1);
3043             if ( pNode->count() > 1 )
3044             {
3045 		        ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
3046 		        if ( pCondition ) // no where clause
3047                 {
3048                     OSQLParseNode::compress(pCondition);
3049                     ::rtl::OUString sTemp;
3050                     pParseNode->parseNodeToStr(sTemp,xConnection);
3051                     sSQL = sTemp;
3052                 }
3053             }
3054         }
3055     }
3056 	return sSQL;
3057 }
3058 // -----------------------------------------------------------------------------
3059 // -----------------------------------------------------------------------------
3060 void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable)
3061 {
3062 	sal_uInt16 nRow;
3063 	switch (_nSlotId)
3064 	{
3065 		case SID_QUERY_VIEW_FUNCTIONS:
3066 			nRow = BROW_FUNCTION_ROW;
3067 			break;
3068 		case SID_QUERY_VIEW_TABLES:
3069 			nRow = BROW_TABLE_ROW;
3070 			break;
3071 		case SID_QUERY_VIEW_ALIASES:
3072 			nRow = BROW_COLUMNALIAS_ROW;
3073 			break;
3074 		default:
3075 			// ????????????
3076 			nRow = 0;
3077 			break;
3078 	}
3079 	m_pSelectionBox->SetRowVisible(nRow,_bEnable);
3080 	m_pSelectionBox->Invalidate();
3081 }
3082 // -----------------------------------------------------------------------------
3083 sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId)
3084 {
3085 	sal_uInt16 nRow;
3086 	switch (_nSlotId)
3087 	{
3088 		case SID_QUERY_VIEW_FUNCTIONS:
3089 			nRow = BROW_FUNCTION_ROW;
3090 			break;
3091 		case SID_QUERY_VIEW_TABLES:
3092 			nRow = BROW_TABLE_ROW;
3093 			break;
3094 		case SID_QUERY_VIEW_ALIASES:
3095 			nRow = BROW_COLUMNALIAS_ROW;
3096 			break;
3097 		default:
3098 			// ?????????
3099 			nRow = 0;
3100 			break;
3101 	}
3102 	return m_pSelectionBox->IsRowVisible(nRow);
3103 }
3104 // -----------------------------------------------------------------------------
3105 void OQueryDesignView::SaveUIConfig()
3106 {
3107 	OQueryController& rCtrl = static_cast<OQueryController&>(getController());
3108 	rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() );
3109 	//	rCtrl.SaveTabFieldsWidth( m_pSelectionBox );
3110 	rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() );
3111     if ( m_aSplitter.GetSplitPosPixel() != 0 )
3112 	    rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() );
3113 }
3114 // -----------------------------------------------------------------------------
3115 OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry,
3116 														   const String& _sCriteria,
3117 														   ::rtl::OUString& _rsErrorMessage,
3118 														   Reference<XPropertySet>& _rxColumn) const
3119 {
3120 	OSL_ENSURE(pEntry.isValid(),"Entry is null!");
3121 	if(!pEntry.isValid())
3122 		return NULL;
3123 	Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection();
3124 	if(!xConnection.is())
3125 		return NULL;
3126 
3127 	::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() );
3128 	OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow());
3129 
3130 	String sTest(_sCriteria);
3131 	// special handling for functions
3132 	if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) )
3133 	{
3134 		// we have a function here so we have to distinguish the type of return value
3135 		String sFunction;
3136 		if ( pEntry->isNumericOrAggreateFunction() )
3137 			sFunction = pEntry->GetFunction();
3138 
3139         if ( !sFunction.Len() )
3140 			sFunction = pEntry->GetField();
3141 
3142 		if(sFunction.GetTokenCount('(') > 1)
3143 			sFunction = sFunction.GetToken(0,'('); // this should be the name of the function
3144 
3145 		sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext());
3146 		if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) )
3147 		{
3148 			// first try the international version
3149 			::rtl::OUString sSql;
3150 			sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * "));
3151 			sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE "));
3152 			sSql += pEntry->GetField();
3153 			sSql += _sCriteria;
3154             ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) );
3155 			nType = DataType::DOUBLE;
3156 			if ( pParseNode.get() )
3157 			{
3158 				OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
3159 				if ( pColumnRef )
3160 				{
3161 					OTableFieldDescRef aField = new OTableFieldDesc();
3162 					if ( eOk == FillDragInfo(this,pColumnRef,aField) )
3163 					{
3164 						nType = aField->GetDataType();
3165 					}
3166 				}
3167 			}
3168 		}
3169 
3170 		Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
3171 		parse::OParseColumn* pColumn = new parse::OParseColumn(	pEntry->GetField(),
3172 																::rtl::OUString(),
3173 																::rtl::OUString(),
3174                                                                 ::rtl::OUString(),
3175 																ColumnValue::NULLABLE_UNKNOWN,
3176 																0,
3177 																0,
3178 																nType,
3179 																sal_False,
3180 																sal_False,
3181 																xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
3182 		_rxColumn = pColumn;
3183 		pColumn->setFunction(sal_True);
3184 		pColumn->setRealName(pEntry->GetField());
3185 	}
3186 	else
3187 	{
3188 		if (pWin)
3189 		{
3190 			Reference<XNameAccess> xColumns = pWin->GetOriginalColumns();
3191 			if (xColumns.is() && xColumns->hasByName(pEntry->GetField()))
3192 				xColumns->getByName(pEntry->GetField()) >>= _rxColumn;
3193 		}
3194 	}
3195 
3196 	OSQLParseNode* pParseNode = rParser.predicateTree(	_rsErrorMessage,
3197 														sTest,
3198 														static_cast<OQueryController&>(getController()).getNumberFormatter(),
3199 														_rxColumn);
3200 	return pParseNode;
3201 }
3202 // -----------------------------------------------------------------------------
3203 void OQueryDesignView::GetFocus()
3204 {
3205 	OQueryView::GetFocus();
3206 	if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() )
3207 	{
3208 		// first we have to deactivate the current cell to refill when nescessary
3209 		m_pSelectionBox->DeactivateCell();
3210 		m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId());
3211 		m_pSelectionBox->GrabFocus();
3212 	}
3213 }
3214 // -----------------------------------------------------------------------------
3215 void OQueryDesignView::reset()
3216 {
3217 	m_pTableView->ClearAll();
3218 	m_pTableView->ReSync();
3219 }
3220 // -----------------------------------------------------------------------------
3221 void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows)
3222 {
3223 	m_pSelectionBox->SetNoneVisbleRow(_nRows);
3224 }
3225 
3226 // -----------------------------------------------------------------------------
3227 void OQueryDesignView::initByFieldDescriptions( const Sequence< PropertyValue >& i_rFieldDescriptions )
3228 {
3229 	OQueryController& rController = static_cast< OQueryController& >( getController() );
3230 
3231 	m_pSelectionBox->PreFill();
3232 	m_pSelectionBox->SetReadOnly( rController.isReadOnly() );
3233 	m_pSelectionBox->Fill();
3234 
3235     for (   const PropertyValue* field = i_rFieldDescriptions.getConstArray();
3236             field != i_rFieldDescriptions.getConstArray() + i_rFieldDescriptions.getLength();
3237             ++field
3238         )
3239     {
3240         ::vos::ORef< OTableFieldDesc > pField( new OTableFieldDesc() );
3241         pField->Load( *field, true );
3242         InsertField( pField, sal_True, sal_False );
3243     }
3244 
3245     rController.ClearUndoManager();
3246 	m_pSelectionBox->Invalidate();
3247 }
3248 
3249 // -----------------------------------------------------------------------------
3250 bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo )
3251 {
3252 	SqlParseError eErrorCode = eNativeMode;
3253 	m_rController.clearError();
3254 
3255     try
3256     {
3257         eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox );
3258 
3259         if ( eErrorCode != eOk )
3260 	    {
3261 	        if ( !m_rController.hasError() )
3262                 m_rController.appendError( getParseErrorMessage( eErrorCode ) );
3263 
3264             if ( _pErrorInfo )
3265             {
3266                 *_pErrorInfo = m_rController.getError();
3267             }
3268             else
3269             {
3270                 m_rController.displayError();
3271             }
3272 	    }
3273     }
3274     catch ( const Exception& )
3275     {
3276         DBG_UNHANDLED_EXCEPTION();
3277     }
3278 	return eErrorCode == eOk;
3279 }
3280 //------------------------------------------------------------------------------
3281 void OQueryDesignView::fillFunctionInfo(  const ::connectivity::OSQLParseNode* pNode
3282                                         ,const ::rtl::OUString& sFunctionTerm
3283                                         ,OTableFieldDescRef& aInfo)
3284 {
3285     // get the type out of the funtion name
3286     OQueryController& rController = static_cast<OQueryController&>(getController());
3287 	sal_Int32 nDataType = DataType::DOUBLE;
3288 	::rtl::OUString sFieldName = sFunctionTerm;
3289 	OSQLParseNode* pFunctionName = pNode->getChild(0);
3290 	if ( !SQL_ISPUNCTUATION(pFunctionName,"{") )
3291 	{
3292 		if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) )
3293 			pFunctionName = pFunctionName->getChild(0);
3294 
3295 		::rtl::OUString sFunctionName = pFunctionName->getTokenValue();
3296 		if ( !sFunctionName.getLength() )
3297 			sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8);
3298 
3299 		nDataType = OSQLParser::getFunctionReturnType(
3300 							sFunctionName
3301 							,&rController.getParser().getContext());
3302 	}
3303 	aInfo->SetDataType(nDataType);
3304 	aInfo->SetFieldType(TAB_NORMAL_FIELD);
3305 	aInfo->SetField(sFieldName);
3306 	aInfo->SetTabWindow(NULL);
3307 }
3308 // -----------------------------------------------------------------------------
3309