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