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