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