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