merge the formfield patch from ooo-build
[ooovba.git] / dbaccess / source / ui / querydesign / QueryDesignView.cxx
blob2c926e9af330acf223e85e770b0081ee67c0b0ac
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: QueryDesignView.cxx,v $
10 * $Revision: 1.96.8.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dbaccess.hxx"
33 #ifndef DBAUI_QUERYDESIGNVIEW_HXX
34 #include "QueryDesignView.hxx"
35 #endif
36 #ifndef DBAUI_QUERYTABLEVIEW_HXX
37 #include "QueryTableView.hxx"
38 #endif
39 #ifndef DBAUI_QUERY_TABLEWINDOW_HXX
40 #include "QTableWindow.hxx"
41 #endif
42 #ifndef _SV_TOOLBOX_HXX
43 #include <vcl/toolbox.hxx>
44 #endif
45 #ifndef DBAUI_QUERYCONTROLLER_HXX
46 #include "querycontroller.hxx"
47 #endif
48 #ifndef _SV_SPLIT_HXX
49 #include <vcl/split.hxx>
50 #endif
51 #ifndef _UNDO_HXX
52 #include <svtools/undo.hxx>
53 #endif
54 #ifndef TOOLS_DIAGNOSE_EX_H
55 #include <tools/diagnose_ex.h>
56 #endif
57 #ifndef DBAUI_QYDLGTAB_HXX
58 #include "adtabdlg.hxx"
59 #endif
60 #ifndef _SV_SVAPP_HXX
61 #include <vcl/svapp.hxx>
62 #endif
63 #ifndef _SV_COMBOBOX_HXX
64 #include <vcl/combobox.hxx>
65 #endif
66 #ifndef _SV_MSGBOX_HXX
67 #include <vcl/msgbox.hxx>
68 #endif
69 #ifndef DBACCESS_UI_BROWSER_ID_HXX
70 #include "browserids.hxx"
71 #endif
72 #ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX
73 #include "SelectionBrowseBox.hxx"
74 #endif
75 #ifndef _DBU_QRY_HRC_
76 #include "dbu_qry.hrc"
77 #endif
78 #ifndef _UTL_CONFIGMGR_HXX_
79 #include <unotools/configmgr.hxx>
80 #endif
81 #ifndef _COMPHELPER_TYPES_HXX_
82 #include <comphelper/types.hxx>
83 #endif
84 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
85 #include <connectivity/dbtools.hxx>
86 #endif
87 #ifndef _DBHELPER_DBEXCEPTION_HXX_
88 #include <connectivity/dbexception.hxx>
89 #endif
90 #ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_
91 #include <com/sun/star/i18n/XLocaleData.hpp>
92 #endif
93 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
94 #include <com/sun/star/sdbc/DataType.hpp>
95 #endif
96 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
97 #include <com/sun/star/container/XNameAccess.hpp>
98 #endif
99 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
100 #include <com/sun/star/sdbc/ColumnValue.hpp>
101 #endif
102 #ifndef _CONNECTIVITY_PCOLUMN_HXX_
103 #include <connectivity/PColumn.hxx>
104 #endif
105 #ifndef DBAUI_QUERYTABLECONNECTION_HXX
106 #include "QTableConnection.hxx"
107 #endif
108 #ifndef DBAUI_CONNECTIONLINE_HXX
109 #include "ConnectionLine.hxx"
110 #endif
111 #ifndef DBAUI_CONNECTIONLINEDATA_HXX
112 #include "ConnectionLineData.hxx"
113 #endif
114 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX
115 #include "QTableConnectionData.hxx"
116 #endif
117 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
118 #include "dbustrings.hrc"
119 #endif
120 #ifndef _COMPHELPER_EXTRACT_HXX_
121 #include <comphelper/extract.hxx>
122 #endif
123 #ifndef DBAUI_TOOLS_HXX
124 #include "UITools.hxx"
125 #endif
126 #ifndef DBAUI_QUERYCONTAINERWINDOW_HXX
127 #include "querycontainerwindow.hxx"
128 #endif
129 #ifndef DBAUI_QUERYTABLEVIEW_HXX
130 #include "QueryTableView.hxx"
131 #endif
132 #ifndef _DBAUI_SQLMESSAGE_HXX_
133 #include "sqlmessage.hxx"
134 #endif
135 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
136 #include <svtools/syslocale.hxx>
137 #endif
139 using namespace ::dbaui;
140 using namespace ::utl;
141 using namespace ::connectivity;
142 using namespace ::dbtools;
143 using namespace ::com::sun::star::uno;
144 using namespace ::com::sun::star::lang;
145 using namespace ::com::sun::star::i18n;
146 using namespace ::com::sun::star::sdbc;
147 using namespace ::com::sun::star::beans;
148 using namespace ::com::sun::star::container;
150 #define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\
151 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
152 (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
154 // here we define our functions used in the anonymous namespace to get our header file smaller
155 // please look at the book LargeScale C++ to know why
156 namespace
158 static const ::rtl::OUString C_AND = ::rtl::OUString::createFromAscii(" AND ");
159 static const ::rtl::OUString C_OR = ::rtl::OUString::createFromAscii(" OR ");
161 // forward declarations
162 sal_Bool InsertJoin( const OQueryDesignView* _pView,
163 const ::connectivity::OSQLParseNode *pNode);
165 SqlParseError InstallFields(OQueryDesignView* _pView,
166 const ::connectivity::OSQLParseNode* pNode,
167 OJoinTableView::OTableWindowMap* pTabList );
169 SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
170 OSelectionBrowseBox* _pSelectionBrw,
171 const ::connectivity::OSQLParseNode* pSelectRoot );
173 SqlParseError GetHavingCriteria(OQueryDesignView* _pView,
174 OSelectionBrowseBox* _pSelectionBrw,
175 const ::connectivity::OSQLParseNode* pSelectRoot,
176 sal_uInt16& rLevel );
178 SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
179 OSelectionBrowseBox* _pSelectionBrw,
180 const ::connectivity::OSQLParseNode* pParseRoot );
182 SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
183 OSelectionBrowseBox* _pSelectionBrw,
184 const ::connectivity::OSQLParseNode * pCondition,
185 const sal_uInt16 nLevel,
186 sal_Bool bHaving,
187 bool _bAddOrOnOneLine);
189 void fillFunctionInfo( OQueryDesignView* _pView
190 ,const ::connectivity::OSQLParseNode* pNode
191 ,const ::rtl::OUString& sFunctionTerm
192 ,OTableFieldDescRef& aInfo);
194 //------------------------------------------------------------------------------
195 ::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote)
197 ::rtl::OUString sRet;
198 if ( _bQuote && _sAliasName.getLength() )
200 sRet = ::dbtools::quoteName(_sQuote,_sAliasName);
201 const static ::rtl::OUString sTableSeparater('.');
202 sRet += sTableSeparater;
204 return sRet;
206 //------------------------------------------------------------------------------
207 ::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef)
209 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
210 ::rtl::OUString sTableRange;
211 if ( _pTableRef )
213 sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef);
214 if ( !sTableRange.getLength() )
215 _pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False);
217 return sTableRange;
219 //------------------------------------------------------------------------------
220 void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false)
222 OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
223 OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true));
225 if ( !pConn )
227 OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData();
228 TTableConnectionData::value_type aInfoData(pInfoData);
229 pInfoData->InitFromDrag(_aDragLeft, _aDragRight);
230 pInfoData->SetJoinType(_eJoinType);
232 if ( _bNatural )
234 aInfoData->ResetConnLines();
235 pInfoData->setNatural(_bNatural);
238 Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns());
239 Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames();
240 const ::rtl::OUString* pIter = aSeq.getConstArray();
241 const ::rtl::OUString* pEnd = pIter + aSeq.getLength();
242 for(;pIter != pEnd;++pIter)
244 if ( xReferencedTableColumns->hasByName(*pIter) )
245 aInfoData->AppendConnLine(*pIter,*pIter);
248 catch( const Exception& )
250 DBG_UNHANDLED_EXCEPTION();
254 OQueryTableConnection aInfo(pTableView, aInfoData);
255 // da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt,
256 // ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer
257 pTableView->NotifyTabConnection( aInfo );
259 else
261 ::rtl::OUString aSourceFieldName(_aDragLeft->GetField());
262 ::rtl::OUString aDestFieldName(_aDragRight->GetField());
263 // the connection could point on the other side
264 if(pConn->GetSourceWin() == _aDragRight->GetTabWindow())
266 ::rtl::OUString aTmp(aSourceFieldName);
267 aSourceFieldName = aDestFieldName;
268 aDestFieldName = aTmp;
270 pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName);
271 pConn->UpdateLineList();
272 // Modified-Flag
273 // SetModified();
274 // und neu zeichnen
275 pConn->RecalcLines();
276 // fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben,
277 // ihr BoundingRect zu ermitteln
278 pConn->InvalidateConnection();
281 //------------------------------------------------------------------------------
282 ::rtl::OUString ParseCondition( OQueryController& rController
283 ,const ::connectivity::OSQLParseNode* pCondition
284 ,const ::rtl::OUString _sDecimal
285 ,const ::com::sun::star::lang::Locale& _rLocale
286 ,sal_uInt32 _nStartIndex)
288 ::rtl::OUString aCondition;
289 Reference< XConnection> xConnection = rController.getConnection();
290 if ( xConnection.is() )
292 sal_uInt32 nCount = pCondition->count();
293 for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i)
294 pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
295 xConnection,
296 rController.getNumberFormatter(),
297 _rLocale,
298 static_cast<sal_Char>(_sDecimal.toChar()),
299 &rController.getParser().getContext());
301 return aCondition;
303 //------------------------------------------------------------------------------
304 SqlParseError FillOuterJoins(OQueryDesignView* _pView,
305 const ::connectivity::OSQLParseNode* pTableRefList)
307 SqlParseError eErrorCode = eOk;
308 sal_uInt32 nCount = pTableRefList->count();
309 sal_Bool bError = sal_False;
310 for (sal_uInt32 i=0; !bError && i < nCount; ++i)
312 const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i);
313 const ::connectivity::OSQLParseNode* pJoinNode = NULL;
315 if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) )
316 pJoinNode = pParseNode;
317 else if( SQL_ISRULE(pParseNode,table_ref)
318 && pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
319 pJoinNode = pParseNode->getChild(2);
321 if ( pJoinNode )
323 if ( !InsertJoin(_pView,pJoinNode) )
324 bError = sal_True;
327 // check if error occured
328 if ( bError )
329 eErrorCode = eIllegalJoin;
331 return eErrorCode;
333 //------------------------------------------------------------------------------
334 ::rtl::OUString QuoteField( const OQueryDesignView* _pView,const ::rtl::OUString& rValue, sal_Int32 aType )
336 ::rtl::OUString rNewValue;
337 switch (rValue.toChar())
339 case '?':
340 if (rValue.getLength() != 1)
341 break;
342 case '\'': // ::rtl::OUString Quotierung oder Datum
343 //case '#': // Datumsquotierung // jetengine
344 case ':': // Parameter
345 case '[': // Parameter
346 return rValue;
349 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
350 Reference< XDatabaseMetaData > xMetaData;
351 if(xConnection.is())
352 xMetaData = xConnection->getMetaData();
353 ::rtl::OUString aQuote;
356 if(xMetaData.is())
357 aQuote = xMetaData->getIdentifierQuoteString();
359 switch( aType )
361 case DataType::DATE:
362 case DataType::TIME:
363 case DataType::TIMESTAMP:
364 if (rValue.toChar() != '{') // nur quoten, wenn kein Access Datum
365 rNewValue = ::dbtools::quoteName(aQuote,rValue);
366 else
367 rNewValue = rValue;
368 break;
369 case DataType::CHAR:
370 case DataType::VARCHAR:
371 case DataType::LONGVARCHAR:
372 rNewValue = ::dbtools::quoteName(aQuote,rValue);
373 break;
374 case DataType::DECIMAL:
375 case DataType::NUMERIC:
376 case DataType::TINYINT:
377 case DataType::SMALLINT:
378 case DataType::INTEGER:
379 case DataType::BIGINT:
380 case DataType::REAL:
381 case DataType::DOUBLE:
382 case DataType::BINARY:
383 case DataType::VARBINARY:
384 case DataType::LONGVARBINARY:
385 rNewValue = rValue;
386 break;
387 case DataType::BIT:
388 case DataType::BOOLEAN:
390 if(xMetaData.is())
392 ::comphelper::UStringMixEqual bCase(xMetaData->supportsMixedCaseQuotedIdentifiers());
393 if (bCase(rValue, String(ModuleRes(STR_QUERY_TRUE))))
394 rNewValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TRUE"));
395 else if (bCase(rValue, String(ModuleRes(STR_QUERY_FALSE))))
396 rNewValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FALSE"));
397 else
398 rNewValue = rValue;
401 break;
402 default:
403 DBG_ERROR( "QuoteField: illegal type" );
404 break;
407 catch(SQLException&)
409 DBG_ERROR( "QuoteField: Exception" );
411 return rNewValue;
413 // -----------------------------------------------------------------------------
415 /** FillDragInfo fills the field description out of the table
417 //------------------------------------------------------------------------------
418 SqlParseError FillDragInfo( const OQueryDesignView* _pView,
419 const ::connectivity::OSQLParseNode* pColumnRef,
420 OTableFieldDescRef& _rDragInfo)
422 SqlParseError eErrorCode = eOk;
424 sal_Bool bErg = sal_False;
426 ::rtl::OUString aTableRange,aColumnName;
427 sal_uInt16 nCntAccount;
428 ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
429 rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
431 if ( aTableRange.getLength() )
433 OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange );
434 bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) );
436 if ( !bErg )
438 bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount);
439 if ( !bErg )
440 bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo);
442 if ( !bErg )
444 eErrorCode = eColumnNotFound;
445 String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND));
446 sError.SearchAndReplaceAscii("$name$",aColumnName);
447 _pView->getController().appendError( sError );
451 Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData();
452 if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() )
453 _pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) );
455 catch(Exception&)
460 return eErrorCode;
462 //------------------------------------------------------------------------------
463 ::rtl::OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection,
464 OConnectionLineDataVec* pLineDataList,
465 OQueryTableConnectionData* pData)
467 ::rtl::OUStringBuffer aCondition;
468 if ( _xConnection.is() )
470 OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
471 OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
474 const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
475 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
476 const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = "));
478 for(;aIter != aEnd;++aIter)
480 OConnectionLineDataRef pLineData = *aIter;
481 if(aCondition.getLength())
482 aCondition.append(C_AND);
483 aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote));
484 aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) ));
485 aCondition.append(sEqual);
486 aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote));
487 aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) ));
490 catch(SQLException&)
492 OSL_ASSERT(!"Failure while building Join criteria!");
496 return aCondition.makeStringAndClear();
498 //------------------------------------------------------------------------------
499 /** JoinCycle looks for a join cycle and append it to the string
500 @param _xConnection the connection
501 @param _pEntryConn the table connection which holds the data
502 @param _pEntryTabTo the corresponding table window
503 @param _rJoin the String which will contain the resulting string
505 void JoinCycle( const Reference< XConnection>& _xConnection,
506 OQueryTableConnection* _pEntryConn,
507 const OQueryTableWindow* _pEntryTabTo,
508 ::rtl::OUString& _rJoin )
510 OSL_ENSURE(_pEntryConn,"TableConnection can not be null!");
512 OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get());
513 if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() )
515 sal_Bool bBrace = sal_False;
516 if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1))
518 bBrace = sal_True;
519 _rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' '));
521 (_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData);
522 if(bBrace)
523 _rJoin += ::rtl::OUString(')');
524 _pEntryConn->SetVisited(sal_True);
527 //------------------------------------------------------------------------------
528 ::rtl::OUString BuildTable( const Reference< XConnection>& _xConnection,
529 const OQueryTableWindow* pEntryTab,
530 bool _bForce = false
533 ::rtl::OUString aDBName(pEntryTab->GetComposedName());
535 // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
536 if( _xConnection.is() )
540 Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
542 ::rtl::OUString sCatalog, sSchema, sTable;
543 ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
544 ::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable );
546 ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
547 if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName )
549 aTableListStr += ::rtl::OUString::createFromAscii(" ");
550 if ( generateAsBeforeTableAlias( _xConnection ) )
551 aTableListStr += ::rtl::OUString::createFromAscii("AS ");
552 aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() );
554 aDBName = aTableListStr;
556 catch(const SQLException&)
558 DBG_UNHANDLED_EXCEPTION();
561 return aDBName;
563 //------------------------------------------------------------------------------
564 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
565 const ::rtl::OUString& rLh,
566 const ::rtl::OUString& rRh,
567 OQueryTableConnectionData* pData)
570 String aErg(rLh);
571 if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN )
572 aErg.AppendAscii(" NATURAL ");
573 switch(pData->GetJoinType())
575 case LEFT_JOIN:
576 aErg.AppendAscii(" LEFT OUTER ");
577 break;
578 case RIGHT_JOIN:
579 aErg.AppendAscii(" RIGHT OUTER ");
580 break;
581 case CROSS_JOIN:
582 OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
583 aErg.AppendAscii(" CROSS ");
584 break;
585 case INNER_JOIN:
586 OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
587 aErg.AppendAscii(" INNER ");
588 break;
589 default:
590 aErg.AppendAscii(" FULL OUTER ");
591 break;
593 aErg.AppendAscii("JOIN ");
594 aErg += String(rRh);
595 if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() )
597 aErg.AppendAscii(" ON ");
598 aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData));
601 return aErg;
603 //------------------------------------------------------------------------------
604 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
605 OQueryTableWindow* pLh,
606 OQueryTableWindow* pRh,
607 OQueryTableConnectionData* pData
610 bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural();
611 return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData);
613 //------------------------------------------------------------------------------
614 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
615 const ::rtl::OUString &rLh,
616 OQueryTableWindow* pRh,
617 OQueryTableConnectionData* pData
620 return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData);
622 //------------------------------------------------------------------------------
623 ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
624 OQueryTableWindow* pLh,
625 const ::rtl::OUString &rRh,
626 OQueryTableConnectionData* pData
629 return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData);
631 //------------------------------------------------------------------------------
632 void GetNextJoin( const Reference< XConnection>& _xConnection,
633 OQueryTableConnection* pEntryConn,
634 OQueryTableWindow* pEntryTabTo,
635 ::rtl::OUString &aJoin)
637 OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
638 if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
639 return;
641 // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
643 if(!aJoin.getLength())
645 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
646 aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData);
648 else if(pEntryTabTo == pEntryConn->GetDestWin())
650 aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData);
652 else if(pEntryTabTo == pEntryConn->GetSourceWin())
654 aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData);
657 pEntryConn->SetVisited(sal_True);
659 // first search for the "to" window
660 const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections();
661 ::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin();
662 ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end();
663 for(;aIter != aEnd;++aIter)
665 OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
666 if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo))
668 OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
669 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
670 JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
671 if(!pNext->IsVisited())
672 GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
676 // when nothing found found look for the "from" window
677 if(aIter == aEnd)
679 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
680 aIter = pConnections->begin();
681 for(;aIter != aEnd;++aIter)
683 OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
684 if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom))
686 OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
687 // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
688 JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
689 if(!pNext->IsVisited())
690 GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
695 //------------------------------------------------------------------------------
696 SqlParseError InsertJoinConnection( const OQueryDesignView* _pView,
697 const ::connectivity::OSQLParseNode *pNode,
698 const EJoinType& _eJoinType)
700 SqlParseError eErrorCode = eOk;
701 if (pNode->count() == 3 && // Ausdruck is geklammert
702 SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
703 SQL_ISPUNCTUATION(pNode->getChild(2),")"))
705 eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType);
707 else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-Verknuepfung:
708 pNode->count() == 3)
710 // nur AND Verknüpfung zulassen
711 if (!SQL_ISTOKEN(pNode->getChild(1),AND))
712 eErrorCode = eIllegalJoinCondition;
713 else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType)) )
714 eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType);
716 else if (SQL_ISRULE(pNode,comparison_predicate))
718 // only the comparison of columns is allowed
719 DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree");
720 if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
721 SQL_ISRULE(pNode->getChild(2),column_ref) &&
722 pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
724 String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE));
725 _pView->getController().appendError( sError );
726 return eIllegalJoin;
729 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
730 OTableFieldDescRef aDragRight = new OTableFieldDesc();
731 if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) ||
732 eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight)))
733 return eErrorCode;
735 insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
737 else
738 eErrorCode = eIllegalJoin;
739 return eErrorCode;
741 //------------------------------------------------------------------------------
742 sal_Bool GetInnerJoinCriteria( const OQueryDesignView* _pView,
743 const ::connectivity::OSQLParseNode *pCondition)
745 return InsertJoinConnection(_pView,pCondition, INNER_JOIN) != eOk;
747 //------------------------------------------------------------------------------
748 ::rtl::OUString GenerateSelectList( const OQueryDesignView* _pView,
749 OTableFields& _rFieldList,
750 sal_Bool bAlias)
752 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
753 if ( !xConnection.is() )
754 return ::rtl::OUString();
756 ::rtl::OUStringBuffer aTmpStr,aFieldListStr;
758 sal_Bool bAsterix = sal_False;
759 int nVis = 0;
760 OTableFields::iterator aIter = _rFieldList.begin();
761 OTableFields::iterator aEnd = _rFieldList.end();
762 for(;aIter != aEnd;++aIter)
764 OTableFieldDescRef pEntryField = *aIter;
765 if ( pEntryField->IsVisible() )
767 if ( pEntryField->GetField().toChar() == '*' )
768 bAsterix = sal_True;
769 ++nVis;
772 if(nVis == 1)
773 bAsterix = sal_False;
777 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
778 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
780 OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
782 const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", "));
783 const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS "));
785 aIter = _rFieldList.begin();
786 for(;aIter != aEnd;++aIter)
788 OTableFieldDescRef pEntryField = *aIter;
789 ::rtl::OUString rFieldName = pEntryField->GetField();
790 if ( rFieldName.getLength() && pEntryField->IsVisible() )
792 aTmpStr = ::rtl::OUString();
793 const ::rtl::OUString rAlias = pEntryField->GetAlias();
794 const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias();
796 aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote));
798 // if we have a none numeric field, the table alias could be in the name
799 // otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
800 if ( !pEntryField->isNumeric() )
802 // we have to look if we have alias.* here but before we have to check if the column doesn't already exist
803 String sTemp = rFieldName;
804 OTableFieldDescRef aInfo = new OTableFieldDesc();
805 OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin();
806 OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end();
807 sal_Bool bFound = sal_False;
808 for(;!bFound && tableIter != tableEnd ;++tableIter)
810 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second);
812 bFound = pTabWin->ExistsField( rFieldName, aInfo );
813 if ( bFound )
814 rFieldName = aInfo->GetField();
816 if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) )
818 OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!");
819 aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName));
821 else
822 aTmpStr.append(rFieldName);
824 else
825 aTmpStr.append(rFieldName);
827 if ( pEntryField->isAggreateFunction() )
829 DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
830 ::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction());
831 aTmpStr2.appendAscii("(");
832 aTmpStr2.append(aTmpStr.makeStringAndClear());
833 aTmpStr2.appendAscii(")");
834 aTmpStr = aTmpStr2;
837 if (rFieldAlias.getLength() &&
838 (rFieldName.toChar() != '*' ||
839 pEntryField->isNumericOrAggreateFunction() ||
840 pEntryField->isOtherFunction()))
842 aTmpStr.append(s_sAs);
843 aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias));
845 aFieldListStr.append(aTmpStr.makeStringAndClear());
846 aFieldListStr.append(sFieldSeparator);
849 if(aFieldListStr.getLength())
850 aFieldListStr.setLength(aFieldListStr.getLength()-2);
852 catch(SQLException&)
854 OSL_ASSERT(!"Failure while building select list!");
856 return aFieldListStr.makeStringAndClear();
858 //------------------------------------------------------------------------------
859 sal_Bool GenerateCriterias( OQueryDesignView* _pView,
860 ::rtl::OUStringBuffer& rRetStr,
861 ::rtl::OUStringBuffer& rHavingStr,
862 OTableFields& _rFieldList,
863 sal_Bool bMulti )
865 // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
866 sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
868 ::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/;
869 // Zeilenweise werden die Ausdr"ucke mit AND verknuepft
870 sal_uInt16 nMaxCriteria = 0;
871 OTableFields::iterator aIter = _rFieldList.begin();
872 OTableFields::iterator aEnd = _rFieldList.end();
873 for(;aIter != aEnd;++aIter)
875 nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size());
877 Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
878 if(!xConnection.is())
879 return FALSE;
882 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
883 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
884 const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext();
886 for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++)
888 aHavingStr = aWhereStr = ::rtl::OUString();
890 for(aIter = _rFieldList.begin();aIter != aEnd;++aIter)
892 OTableFieldDescRef pEntryField = *aIter;
893 aFieldName = pEntryField->GetField();
895 if (!aFieldName.getLength())
896 continue;
897 aCriteria = pEntryField->GetCriteria( i );
898 if ( aCriteria.getLength() )
900 // * is not allowed to contain any filter, only when used in combination an aggregate function
901 if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() )
903 // only show the messagebox the first time
904 if (!bCritsOnAsterikWarning)
905 ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute();
906 bCritsOnAsterikWarning = sal_True;
907 continue;
909 aWork = ::rtl::OUString();
912 aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
914 if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') )
915 aWork += aFieldName;
916 else
917 aWork += ::dbtools::quoteName(aQuote, aFieldName);
919 if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() )
921 if (!aHavingStr.getLength()) // noch keine Kriterien
922 aHavingStr += ::rtl::OUString('('); // Klammern
923 else
924 aHavingStr += C_AND;
926 if ( pEntryField->isAggreateFunction() )
928 OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!");
929 aHavingStr += pEntryField->GetFunction();
930 aHavingStr += ::rtl::OUString('('); // Klammern
931 aHavingStr += aWork;
932 aHavingStr += ::rtl::OUString(')'); // Klammern
934 else
935 aHavingStr += aWork;
937 ::rtl::OUString aTmp = aCriteria;
938 ::rtl::OUString aErrorMsg;
939 Reference<XPropertySet> xColumn;
940 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
941 if (pParseNode.get())
943 if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
944 pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
945 ::rtl::OUString sHavingStr = aHavingStr;
947 sal_uInt32 nCount = pParseNode->count();
948 for( sal_uInt32 node = 1 ; node < nCount ; ++node)
949 pParseNode->getChild(node)->parseNodeToStr( sHavingStr,
950 xConnection,
951 &rContext,
952 sal_False,
953 !pEntryField->isOtherFunction());
954 aHavingStr = sHavingStr;
956 else
957 aHavingStr += aCriteria;
959 else
961 if ( !aWhereStr.getLength() ) // noch keine Kriterien
962 aWhereStr += ::rtl::OUString('('); // Klammern
963 else
964 aWhereStr += C_AND;
966 aWhereStr += ::rtl::OUString(' ');
967 // aCriteria could have some german numbers so I have to be sure here
968 ::rtl::OUString aTmp = aCriteria;
969 ::rtl::OUString aErrorMsg;
970 Reference<XPropertySet> xColumn;
971 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
972 if (pParseNode.get())
974 if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
975 pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
976 ::rtl::OUString aWhere = aWhereStr;
977 pParseNode->parseNodeToStr( aWhere,
978 xConnection,
979 &rContext,
980 sal_False,
981 !pEntryField->isOtherFunction() );
982 aWhereStr = aWhere;
984 else
986 aWhereStr += aWork;
987 aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
988 aWhereStr += aCriteria;
992 // nur einmal für jedes Feld
993 else if ( !i && pEntryField->isCondition() )
995 if (!aWhereStr.getLength()) // noch keine Kriterien
996 aWhereStr += ::rtl::OUString('('); // Klammern
997 else
998 aWhereStr += C_AND;
999 aWhereStr += pEntryField->GetField();
1002 if (aWhereStr.getLength())
1004 aWhereStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
1005 if (rRetStr.getLength()) // schon Feldbedingungen ?
1006 rRetStr.append(C_OR);
1007 else // Klammern auf fuer 'OR' Zweig
1008 rRetStr.append(sal_Unicode('('));
1009 rRetStr.append(aWhereStr);
1011 if (aHavingStr.getLength())
1013 aHavingStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
1014 if (rHavingStr.getLength()) // schon Feldbedingungen ?
1015 rHavingStr.append(C_OR);
1016 else // Klammern auf fuer 'OR' Zweig
1017 rHavingStr.append(sal_Unicode('('));
1018 rHavingStr.append(aHavingStr);
1022 if (rRetStr.getLength())
1023 rRetStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
1024 if (rHavingStr.getLength())
1025 rHavingStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
1027 catch(SQLException&)
1029 OSL_ASSERT(!"Failure while building where clause!");
1031 return sal_True;
1033 //------------------------------------------------------------------------------
1034 SqlParseError GenerateOrder( OQueryDesignView* _pView,
1035 OTableFields& _rFieldList,
1036 sal_Bool bMulti,
1037 ::rtl::OUString& _rsRet)
1039 const OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1040 Reference< XConnection> xConnection = rController.getConnection();
1041 if ( !xConnection.is() )
1042 return eNoConnection;
1044 SqlParseError eErrorCode = eOk;
1046 ::rtl::OUString aColumnName;
1047 ::rtl::OUString aWorkStr;
1050 const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy();
1051 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
1052 ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
1053 // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
1054 sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
1055 OTableFields::iterator aIter = _rFieldList.begin();
1056 OTableFields::iterator aEnd = _rFieldList.end();
1057 for(;aIter != aEnd;++aIter)
1059 OTableFieldDescRef pEntryField = *aIter;
1060 EOrderDir eOrder = pEntryField->GetOrderDir();
1062 // nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen
1063 // sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt
1064 if ( eOrder != ORDER_NONE )
1066 aColumnName = pEntryField->GetField();
1067 if(aColumnName.toChar() == '*')
1069 // die entsprechende MessageBox nur beim ersten mal anzeigen
1070 if (!bCritsOnAsterikWarning)
1071 ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute();
1072 bCritsOnAsterikWarning = sal_True;
1073 continue;
1076 if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() )
1078 aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias());
1080 else if ( pEntryField->isNumericOrAggreateFunction() )
1082 DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
1083 aWorkStr += pEntryField->GetFunction();
1084 aWorkStr += ::rtl::OUString('(');
1085 aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1086 // only quote column name when we don't have a numeric
1087 if ( pEntryField->isNumeric() )
1088 aWorkStr += aColumnName;
1089 else
1090 aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
1092 aWorkStr += ::rtl::OUString(')');
1094 else if ( pEntryField->isOtherFunction() )
1096 aWorkStr += aColumnName;
1098 else
1100 aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1101 aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
1103 aWorkStr += ::rtl::OUString(' ');
1104 aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (USHORT)eOrder );
1105 aWorkStr += ::rtl::OUString(',');
1110 String sTemp(aWorkStr);
1111 sTemp.EraseTrailingChars( ',' );
1112 aWorkStr = sTemp;
1115 if ( aWorkStr.getLength() )
1117 const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy();
1118 String sToken(aWorkStr);
1119 if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') )
1120 eErrorCode = eStatementTooLong;
1121 else
1123 _rsRet = ::rtl::OUString::createFromAscii(" ORDER BY ");
1124 _rsRet += aWorkStr;
1128 catch(SQLException&)
1130 OSL_ASSERT(!"Failure while building group by!");
1133 return eErrorCode;
1136 //------------------------------------------------------------------------------
1137 void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection,
1138 ::rtl::OUString& _rJoinCrit,
1139 const ::std::vector<OTableConnection*>* _pConnList)
1141 ::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin();
1142 ::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end();
1143 for(;aIter != aEnd;++aIter)
1145 const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter);
1146 OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
1147 if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
1149 if(_rJoinCrit.getLength())
1150 _rJoinCrit += C_AND;
1151 _rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData);
1155 //------------------------------------------------------------------------------
1156 void searchAndAppendName(const Reference< XConnection>& _xConnection,
1157 const OQueryTableWindow* _pTableWindow,
1158 ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames,
1159 ::rtl::OUString& _rsTableListStr
1162 ::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow));
1164 if(_rTableNames.find(sTabName) == _rTableNames.end())
1166 _rTableNames[sTabName] = sal_True;
1167 _rsTableListStr += sTabName;
1168 _rsTableListStr += ::rtl::OUString(',');
1171 //------------------------------------------------------------------------------
1172 ::rtl::OUString GenerateFromClause( const Reference< XConnection>& _xConnection,
1173 const OQueryTableView::OTableWindowMap* pTabList,
1174 const ::std::vector<OTableConnection*>* pConnList
1178 ::rtl::OUString aTableListStr;
1179 // wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt
1180 ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames;
1182 // generate outer join clause in from
1183 if(!pConnList->empty())
1185 ::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin();
1186 ::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end();
1187 for(;aIter != aEnd;++aIter)
1188 static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False);
1190 aIter = pConnList->begin();
1191 const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE );
1192 for(;aIter != aEnd;++aIter)
1194 OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
1195 if(!pEntryConn->IsVisited())
1197 ::rtl::OUString aJoin;
1198 GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin);
1200 if(aJoin.getLength())
1202 // insert tables into table list to avoid double entries
1203 OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
1204 OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin());
1206 ::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom));
1207 if(aTableNames.find(sTabName) == aTableNames.end())
1208 aTableNames[sTabName] = sal_True;
1209 sTabName = BuildTable(_xConnection,pEntryTabTo);
1210 if(aTableNames.find(sTabName) == aTableNames.end())
1211 aTableNames[sTabName] = sal_True;
1213 ::rtl::OUString aStr;
1214 switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType())
1216 case LEFT_JOIN:
1217 case RIGHT_JOIN:
1218 case FULL_JOIN:
1220 // create outer join
1221 if ( bUseEscape )
1222 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ "));
1223 aStr += aJoin;
1224 if ( bUseEscape )
1225 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }"));
1227 break;
1228 default:
1229 aStr += aJoin;
1230 break;
1232 aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
1233 aTableListStr += aStr;
1238 // and now all inner joins
1239 aIter = pConnList->begin();
1240 for(;aIter != aEnd;++aIter)
1242 OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
1243 if(!pEntryConn->IsVisited())
1245 searchAndAppendName(_xConnection,
1246 static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()),
1247 aTableNames,
1248 aTableListStr);
1250 searchAndAppendName(_xConnection,
1251 static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
1252 aTableNames,
1253 aTableListStr);
1257 // all tables that haven't a connection to anyone
1258 OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin();
1259 OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end();
1260 for(;aTabIter != aTabEnd;++aTabIter)
1262 const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second);
1263 if(!pEntryTab->ExistsAConn())
1265 aTableListStr += BuildTable(_xConnection,pEntryTab);
1266 aTableListStr += ::rtl::OUString(',');
1270 if(aTableListStr.getLength())
1271 aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() );
1272 return aTableListStr;
1274 //------------------------------------------------------------------------------
1275 ::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti )
1277 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1278 const Reference< XConnection> xConnection = rController.getConnection();
1279 if(!xConnection.is())
1280 return ::rtl::OUString();
1282 ::std::map< rtl::OUString,bool> aGroupByNames;
1284 ::rtl::OUString aGroupByStr;
1287 const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
1288 const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
1290 OTableFields::iterator aIter = _rFieldList.begin();
1291 OTableFields::iterator aEnd = _rFieldList.end();
1292 for(;aIter != aEnd;++aIter)
1294 OTableFieldDescRef pEntryField = *aIter;
1295 if ( pEntryField->IsGroupBy() )
1297 DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-(");
1298 ::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
1300 // only quote the field name when it isn't calculated
1301 if ( pEntryField->isNoneFunction() )
1303 sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField());
1305 else
1307 ::rtl::OUString aTmp = pEntryField->GetField();
1308 ::rtl::OUString aErrorMsg;
1309 Reference<XPropertySet> xColumn;
1310 ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
1311 if (pParseNode.get())
1313 ::rtl::OUString sGroupBy;
1314 pParseNode->parseNodeToStr( sGroupBy,
1315 xConnection,
1316 &rController.getParser().getContext(),
1317 sal_False,
1318 !pEntryField->isOtherFunction());
1319 sGroupByPart += sGroupBy;
1321 else
1322 sGroupByPart += pEntryField->GetField();
1324 if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() )
1326 aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true));
1327 aGroupByStr += sGroupByPart;
1328 aGroupByStr += ::rtl::OUString(',');
1332 if ( aGroupByStr.getLength() )
1334 aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') );
1335 ::rtl::OUString aGroupByStr2 = ::rtl::OUString::createFromAscii(" GROUP BY ");
1336 aGroupByStr2 += aGroupByStr;
1337 aGroupByStr = aGroupByStr2;
1340 catch(SQLException&)
1342 OSL_ASSERT(!"Failure while building group by!");
1344 return aGroupByStr;
1346 // -----------------------------------------------------------------------------
1347 SqlParseError GetORCriteria(OQueryDesignView* _pView,
1348 OSelectionBrowseBox* _pSelectionBrw,
1349 const ::connectivity::OSQLParseNode * pCondition,
1350 sal_uInt16& nLevel ,
1351 sal_Bool bHaving = sal_False,
1352 bool bAddOrOnOneLine = false);
1353 // -----------------------------------------------------------------------------
1354 SqlParseError GetSelectionCriteria( OQueryDesignView* _pView,
1355 OSelectionBrowseBox* _pSelectionBrw,
1356 const ::connectivity::OSQLParseNode* pNode,
1357 sal_uInt16& rLevel )
1359 if (!SQL_ISRULE(pNode, select_statement))
1360 return eNoSelectStatement;
1362 // nyi: mehr Pruefung auf korrekte Struktur!
1363 pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL;
1364 // no where clause found
1365 if (!pNode || pNode->isLeaf())
1366 return eOk;
1368 // Naechster freier Satz ...
1369 SqlParseError eErrorCode = eOk;
1370 ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
1371 if ( pCondition ) // no where clause
1373 // now we have to chech the other conditions
1374 // first make the logical easier
1375 ::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
1376 ::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1);
1378 ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
1379 pNodeTmp = pNode->getChild(1);
1380 ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
1381 pNodeTmp = pNode->getChild(1);
1382 // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079
1383 OSQLParseNode::compress(pNodeTmp);
1384 pNodeTmp = pNode->getChild(1);
1386 // first extract the inner joins conditions
1387 GetInnerJoinCriteria(_pView,pNodeTmp);
1389 // it could happen that pCondition is not more valid
1390 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel);
1392 return eErrorCode;
1394 //------------------------------------------------------------------------------
1395 SqlParseError GetANDCriteria( OQueryDesignView* _pView,
1396 OSelectionBrowseBox* _pSelectionBrw,
1397 const ::connectivity::OSQLParseNode * pCondition,
1398 const sal_uInt16 nLevel,
1399 sal_Bool bHaving,
1400 bool bAddOrOnOneLine);
1401 //------------------------------------------------------------------------------
1402 SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
1403 OSelectionBrowseBox* _pSelectionBrw,
1404 const ::connectivity::OSQLParseNode * pCondition,
1405 const sal_uInt16 nLevel,
1406 sal_Bool bHaving,
1407 bool bAddOrOnOneLine);
1408 //------------------------------------------------------------------------------
1409 SqlParseError GetORCriteria(OQueryDesignView* _pView,
1410 OSelectionBrowseBox* _pSelectionBrw,
1411 const ::connectivity::OSQLParseNode * pCondition,
1412 sal_uInt16& nLevel ,
1413 sal_Bool bHaving,
1414 bool bAddOrOnOneLine)
1416 SqlParseError eErrorCode = eOk;
1418 // Runde Klammern um den Ausdruck
1419 if (pCondition->count() == 3 &&
1420 SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
1421 SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
1423 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine);
1425 // oder Verknuepfung
1426 // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
1427 else if (SQL_ISRULE(pCondition,search_condition))
1429 for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2)
1431 const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i);
1432 if ( SQL_ISRULE(pChild,search_condition) )
1433 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine);
1434 else
1435 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, bAddOrOnOneLine ? nLevel : nLevel++,bHaving, i == 0 ? false : bAddOrOnOneLine);
1438 else
1439 eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine );
1441 return eErrorCode;
1443 //--------------------------------------------------------------------------------------------------
1444 bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef)
1446 bool bRet = true;
1447 ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef;
1448 for (int i = 0; i < 3 && bRet; i+=2)
1450 const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i);
1451 if ( SQL_ISRULE(pChild,search_condition) )
1452 bRet = CheckOrCriteria(pChild,pFirstColumnRef);
1453 else
1455 // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
1456 ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref);
1457 if ( pFirstColumnRef && pSecondColumnRef )
1458 bRet = *pFirstColumnRef == *pSecondColumnRef;
1459 else if ( !pFirstColumnRef )
1460 pFirstColumnRef = pSecondColumnRef;
1463 return bRet;
1465 //--------------------------------------------------------------------------------------------------
1466 SqlParseError GetANDCriteria( OQueryDesignView* _pView,
1467 OSelectionBrowseBox* _pSelectionBrw,
1468 const ::connectivity::OSQLParseNode * pCondition,
1469 const sal_uInt16 nLevel,
1470 sal_Bool bHaving,
1471 bool bAddOrOnOneLine)
1473 const ::com::sun::star::lang::Locale aLocale = _pView->getLocale();
1474 const ::rtl::OUString sDecimal = _pView->getDecimalSeparator();
1476 // ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen
1477 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1478 SqlParseError eErrorCode = eOk;
1480 // Runde Klammern
1481 if (SQL_ISRULE(pCondition,boolean_primary))
1483 sal_uInt16 nLevel2 = nLevel;
1484 // check if we have to put the or criteria on one line.
1485 bool bMustAddOrOnOneLine = CheckOrCriteria(pCondition->getChild(1),NULL);
1486 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1), nLevel2,bHaving,bMustAddOrOnOneLine );
1488 // Das erste Element ist (wieder) eine AND-Verknuepfung
1489 else if ( SQL_ISRULE(pCondition,boolean_term) )
1491 OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term");
1492 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine );
1493 if ( eErrorCode == eOk )
1494 eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine );
1496 else if (SQL_ISRULE( pCondition, comparison_predicate))
1498 eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine);
1500 else if( SQL_ISRULE(pCondition,like_predicate) )
1502 const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0);
1503 if (SQL_ISRULE(pValueExp, column_ref ) )
1505 ::rtl::OUString aColumnName;
1506 ::rtl::OUString aCondition;
1507 Reference< XConnection> xConnection = rController.getConnection();
1508 if ( xConnection.is() )
1510 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
1511 // the international doesn't matter I have a string
1512 pCondition->parseNodeToPredicateStr(aCondition,
1513 xConnection,
1514 rController.getNumberFormatter(),
1515 aLocale,
1516 static_cast<sal_Char>(sDecimal.toChar()),
1517 &rController.getParser().getContext());
1519 pValueExp->parseNodeToPredicateStr( aColumnName,
1520 xConnection,
1521 rController.getNumberFormatter(),
1522 aLocale,
1523 static_cast<sal_Char>(sDecimal.toChar()),
1524 &rController.getParser().getContext());
1526 // don't display the column name
1527 aCondition = aCondition.copy(aColumnName.getLength());
1528 aCondition = aCondition.trim();
1531 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1532 if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) ))
1534 if ( bHaving )
1535 aDragLeft->SetGroupBy(sal_True);
1536 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1539 else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec) ||
1540 SQL_ISRULEOR2(pValueExp,position_exp,extract_exp) ||
1541 SQL_ISRULEOR2(pValueExp,fold,char_substring_fct) ||
1542 SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct))
1544 AddFunctionCondition( _pView,
1545 _pSelectionBrw,
1546 pCondition,
1547 nLevel,
1548 bHaving,
1549 bAddOrOnOneLine);
1551 else
1553 eErrorCode = eNoColumnInLike;
1554 String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN));
1555 _pView->getController().appendError( sError );
1558 else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate)
1559 || SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate))
1561 if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
1563 AddFunctionCondition( _pView,
1564 _pSelectionBrw,
1565 pCondition,
1566 nLevel,
1567 bHaving,
1568 bAddOrOnOneLine);
1570 else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) )
1572 // parse condition
1573 ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
1574 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1575 if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) )
1577 if ( bHaving )
1578 aDragLeft->SetGroupBy(sal_True);
1579 _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
1583 else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) )
1586 // Funktions-Bedingung parsen
1587 ::rtl::OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0);
1589 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1590 aDragLeft->SetField(aCondition);
1591 aDragLeft->SetFunctionType(FKT_CONDITION);
1593 eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).isValid() ? eOk : eTooManyColumns;
1595 else //! TODO not supported yet
1596 eErrorCode = eStatementTooComplex;
1597 // Fehler einfach weiterreichen.
1598 return eErrorCode;
1600 //------------------------------------------------------------------------------
1601 SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
1602 OSelectionBrowseBox* _pSelectionBrw,
1603 const ::connectivity::OSQLParseNode * pCondition,
1604 const sal_uInt16 nLevel,
1605 sal_Bool bHaving,
1606 bool bAddOrOnOneLine)
1608 SqlParseError eErrorCode = eOk;
1609 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1611 OSQLParseNode* pFunction = pCondition->getChild(0);
1613 OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec) ||
1614 SQL_ISRULEOR2(pFunction,position_exp,extract_exp) ||
1615 SQL_ISRULEOR2(pFunction,fold,char_substring_fct) ||
1616 SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!");
1617 ::rtl::OUString aCondition;
1618 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1620 ::rtl::OUString aColumnName;
1621 Reference< XConnection> xConnection = rController.getConnection();
1622 if(xConnection.is())
1624 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
1625 pCondition->parseNodeToPredicateStr(aCondition,
1626 xConnection,
1627 rController.getNumberFormatter(),
1628 _pView->getLocale(),
1629 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1630 &rController.getParser().getContext());
1632 pFunction->parseNodeToStr( aColumnName,
1633 xConnection,
1634 &rController.getParser().getContext(),
1635 sal_True,
1636 sal_True); // quote is to true because we need quoted elements inside the function
1637 // i75557
1638 //pFunction->parseNodeToPredicateStr(aColumnName,
1639 // xConnection,
1640 // rController.getNumberFormatter(),
1641 // _pView->getLocale(),
1642 // static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1643 // &rController.getParser().getContext());
1644 // don't display the column name
1645 aCondition = aCondition.copy(aColumnName.getLength());
1646 aCondition = aCondition.trim();
1647 if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign
1648 aCondition = aCondition.copy(1);
1651 if ( SQL_ISRULE(pFunction, general_set_fct ) )
1653 sal_Int32 nFunctionType = FKT_AGGREGATE;
1654 OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2);
1655 if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' )
1657 OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
1658 OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
1659 OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end();
1660 for(;aIter != aTabEnd;++aIter)
1662 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
1663 if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aDragLeft ))
1665 aDragLeft->SetAlias(String());
1666 aDragLeft->SetTable(String());
1667 break;
1671 else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft))
1672 && SQL_ISRULE(pParamNode,num_value_exp) )
1674 ::rtl::OUString sParameterValue;
1675 pParamNode->parseNodeToStr( sParameterValue,
1676 xConnection,
1677 &rController.getParser().getContext());
1678 nFunctionType |= FKT_NUMERIC;
1679 aDragLeft->SetField(sParameterValue);
1680 eErrorCode = eOk;
1682 aDragLeft->SetFunctionType(nFunctionType);
1683 if ( bHaving )
1684 aDragLeft->SetGroupBy(sal_True);
1685 sal_Int32 nIndex = 0;
1686 aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex));
1688 else
1690 // bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben
1691 aDragLeft->SetField(aColumnName);
1692 if(bHaving)
1693 aDragLeft->SetGroupBy(sal_True);
1694 aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
1696 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1699 return eErrorCode;
1701 //------------------------------------------------------------------------------
1702 SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
1703 OSelectionBrowseBox* _pSelectionBrw,
1704 const ::connectivity::OSQLParseNode * pCondition,
1705 const sal_uInt16 nLevel,
1706 sal_Bool bHaving
1707 ,bool bAddOrOnOneLine)
1709 SqlParseError eErrorCode = eOk;
1710 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
1712 DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate");
1713 if ( SQL_ISRULE(pCondition->getChild(0), column_ref )
1714 || SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) )
1716 ::rtl::OUString aCondition;
1717 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1719 if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
1721 OTableFieldDescRef aDragRight = new OTableFieldDesc();
1722 if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ||
1723 eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight)))
1724 return eErrorCode;
1726 OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>(
1727 _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()),
1728 static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()),
1729 true));
1730 if ( pConn )
1732 OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList();
1733 OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
1734 OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
1735 for(;aIter != aEnd;++aIter)
1737 if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() ||
1738 (*aIter)->GetDestFieldName() == aDragLeft->GetField() )
1739 break;
1741 if(aIter != aEnd)
1742 return eOk;
1746 sal_uInt32 nPos = 0;
1747 if(SQL_ISRULE(pCondition->getChild(0), column_ref ))
1749 nPos = 0;
1750 sal_uInt32 i=1;
1752 // don't display the equal
1753 if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
1754 i++;
1756 // Bedingung parsen
1757 aCondition = ParseCondition(rController
1758 ,pCondition
1759 ,_pView->getDecimalSeparator()
1760 ,_pView->getLocale()
1761 ,i);
1763 else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
1765 nPos = pCondition->count()-1;
1767 sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2);
1768 switch (pCondition->getChild(i)->getNodeType())
1770 case SQL_NODE_EQUAL:
1771 // don't display the equal
1772 i--;
1773 break;
1774 case SQL_NODE_LESS:
1775 // take the opposite as we change the order
1776 i--;
1777 aCondition = aCondition + ::rtl::OUString::createFromAscii(">");
1778 break;
1779 case SQL_NODE_LESSEQ:
1780 // take the opposite as we change the order
1781 i--;
1782 aCondition = aCondition + ::rtl::OUString::createFromAscii(">=");
1783 break;
1784 case SQL_NODE_GREAT:
1785 // take the opposite as we change the order
1786 i--;
1787 aCondition = aCondition + ::rtl::OUString::createFromAscii("<");
1788 break;
1789 case SQL_NODE_GREATEQ:
1790 // take the opposite as we change the order
1791 i--;
1792 aCondition = aCondition + ::rtl::OUString::createFromAscii("<=");
1793 break;
1794 default:
1795 break;
1798 // go backward
1799 Reference< XConnection> xConnection = rController.getConnection();
1800 if(xConnection.is())
1802 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
1803 for (; i >= 0; i--)
1804 pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
1805 xConnection,
1806 rController.getNumberFormatter(),
1807 _pView->getLocale(),
1808 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1809 &rController.getParser().getContext());
1812 // else ???
1815 if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft)))
1817 if(bHaving)
1818 aDragLeft->SetGroupBy(sal_True);
1819 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1822 else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
1824 AddFunctionCondition( _pView,
1825 _pSelectionBrw,
1826 pCondition,
1827 nLevel,
1828 bHaving,
1829 bAddOrOnOneLine);
1831 else // kann sich nur um einen Expr. Ausdruck handeln
1833 ::rtl::OUString aName,aCondition;
1835 ::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0);
1836 ::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2);
1837 // Feldnamen
1838 Reference< XConnection> xConnection = rController.getConnection();
1839 if(xConnection.is())
1841 pLhs->parseNodeToStr(aName,
1842 xConnection,
1843 &rController.getParser().getContext(),
1844 sal_True);
1845 // Kriterium
1846 aCondition = pCondition->getChild(1)->getTokenValue();
1847 pRhs->parseNodeToPredicateStr(aCondition,
1848 xConnection,
1849 rController.getNumberFormatter(),
1850 _pView->getLocale(),
1851 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
1852 &rController.getParser().getContext());
1855 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
1856 aDragLeft->SetField(aName);
1857 aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
1858 // und anh"angen
1859 _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
1861 return eErrorCode;
1864 //------------------------------------------------------------------------------
1865 namespace
1867 OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo )
1869 OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin();
1870 OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end();
1871 for ( ; aIter != aEnd; ++aIter )
1873 OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second );
1874 if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) )
1875 return pTabWin;
1877 return NULL;
1881 //------------------------------------------------------------------------------
1882 void InsertColumnRef(const OQueryDesignView* _pView,
1883 const ::connectivity::OSQLParseNode * pColumnRef,
1884 ::rtl::OUString& aColumnName,
1885 const ::rtl::OUString& aColumnAlias,
1886 ::rtl::OUString& aTableRange,
1887 OTableFieldDescRef& _raInfo,
1888 OJoinTableView::OTableWindowMap* pTabList)
1891 // Tabellennamen zusammen setzen
1892 ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
1893 rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
1895 sal_Bool bFound(sal_False);
1896 DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein");
1897 if (!aTableRange.getLength())
1899 // SELECT column, ...
1900 bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo );
1901 if ( bFound && ( aColumnName.toChar() != '*' ) )
1902 _raInfo->SetFieldAlias(aColumnAlias);
1904 else
1906 // SELECT range.column, ...
1907 OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange);
1909 if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo))
1911 if(aColumnName.toChar() != '*')
1912 _raInfo->SetFieldAlias(aColumnAlias);
1913 bFound = sal_True;
1916 if (!bFound)
1918 _raInfo->SetTable(::rtl::OUString());
1919 _raInfo->SetAlias(::rtl::OUString());
1920 _raInfo->SetField(aColumnName);
1921 _raInfo->SetFieldAlias(aColumnAlias); // nyi : hier ein fortlaufendes Expr_1, Expr_2 ...
1922 _raInfo->SetFunctionType(FKT_OTHER);
1925 //-----------------------------------------------------------------------------
1926 sal_Bool checkJoinConditions( const OQueryDesignView* _pView,
1927 const ::connectivity::OSQLParseNode* _pNode )
1929 const ::connectivity::OSQLParseNode* pJoinNode = NULL;
1930 sal_Bool bRet = sal_True;
1931 if (SQL_ISRULE(_pNode,qualified_join))
1932 pJoinNode = _pNode;
1933 else if (SQL_ISRULE(_pNode,table_ref)
1934 && _pNode->count() == 3
1935 && SQL_ISPUNCTUATION(_pNode->getChild(0),"(")
1936 && SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')'
1937 pJoinNode = _pNode->getChild(1);
1938 else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column
1939 bRet = sal_False;
1941 if (pJoinNode && !InsertJoin(_pView,pJoinNode))
1942 bRet = sal_False;
1943 return bRet;
1945 //-----------------------------------------------------------------------------
1946 sal_Bool InsertJoin(const OQueryDesignView* _pView,
1947 const ::connectivity::OSQLParseNode *pNode)
1949 DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ),
1950 "OQueryDesignView::InsertJoin: Fehler im Parse Tree");
1952 if (SQL_ISRULE(pNode,joined_table))
1953 return InsertJoin(_pView,pNode->getChild(1));
1955 // first check the left and right side
1956 const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref
1957 if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) )
1958 pRightTableRef = pNode->getChild(4); // table_ref
1960 if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef))
1961 return sal_False;
1963 // named column join wird später vieleicht noch implementiert
1964 // SQL_ISRULE(pNode->getChild(4),named_columns_join)
1965 EJoinType eJoinType = INNER_JOIN;
1966 bool bNatural = false;
1967 if ( SQL_ISRULE(pNode, qualified_join) )
1969 ::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type
1970 if ( SQL_ISTOKEN(pJoinType,NATURAL) )
1972 bNatural = true;
1973 pJoinType = pNode->getChild(2);
1976 if (SQL_ISRULE(pJoinType,join_type) && SQL_ISTOKEN(pJoinType->getChild(0),INNER))
1978 eJoinType = INNER_JOIN;
1980 else
1982 if (SQL_ISRULE(pJoinType,join_type)) // eine Ebene tiefer
1983 pJoinType = pJoinType->getChild(0);
1985 if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT))
1986 eJoinType = LEFT_JOIN;
1987 else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT))
1988 eJoinType = RIGHT_JOIN;
1989 else
1990 eJoinType = FULL_JOIN;
1992 if ( SQL_ISRULE(pNode->getChild(4),join_condition) )
1994 if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType) != eOk )
1995 return sal_False;
1998 else if ( SQL_ISRULE(pNode, cross_union) )
2000 eJoinType = CROSS_JOIN;
2001 pRightTableRef = pNode->getChild(pNode->count() - 1);
2003 else
2004 return sal_False;
2006 if ( eJoinType == CROSS_JOIN || bNatural )
2009 OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) );
2010 OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) );
2011 OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!");
2012 if ( !pLeftWindow || !pRightWindow )
2013 return sal_False;
2015 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
2016 aDragLeft->SetTabWindow(pLeftWindow);
2017 aDragLeft->SetTable(pLeftWindow->GetTableName());
2018 aDragLeft->SetAlias(pLeftWindow->GetAliasName());
2020 OTableFieldDescRef aDragRight = new OTableFieldDesc();
2021 aDragRight->SetTabWindow(pRightWindow);
2022 aDragRight->SetTable(pRightWindow->GetTableName());
2023 aDragRight->SetAlias(pRightWindow->GetAliasName());
2025 insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural);
2029 return sal_True;
2031 //------------------------------------------------------------------------------
2032 void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
2034 // now we have to insert the fields which aren't in the statement
2035 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2036 OTableFields& rUnUsedFields = rController.getUnUsedFields();
2037 OTableFields::iterator aEnd = rUnUsedFields.end();
2038 for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter)
2039 if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).isValid())
2040 (*aIter) = NULL;
2041 OTableFields().swap( rUnUsedFields );
2043 //------------------------------------------------------------------------------
2044 SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
2046 SqlParseError eErrorCode = eOk;
2048 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2050 _pSelectionBrw->PreFill();
2051 _pSelectionBrw->SetReadOnly(rController.isReadOnly());
2052 _pSelectionBrw->Fill();
2055 ::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator();
2056 const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree();
2060 if ( !pParseTree )
2062 // now we have to insert the fields which aren't in the statement
2063 insertUnUsedFields(_pView,_pSelectionBrw);
2064 break;
2067 if ( !rController.isEsacpeProcessing() ) // not allowed in this mode
2069 eErrorCode = eNativeMode;
2070 break;
2073 if ( !( SQL_ISRULE( pParseTree, select_statement ) ) )
2075 eErrorCode = eNoSelectStatement;
2076 break;
2079 Reference< XConnection> xConnection = rController.getConnection();
2080 if ( !xConnection.is() )
2082 DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" );
2083 break;
2086 const OSQLTables& aMap = aIterator.getTables();
2087 ::comphelper::UStringMixLess aTmp(aMap.key_comp());
2088 ::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() );
2090 Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
2093 sal_Int32 nMax = xMetaData->getMaxTablesInSelect();
2094 if ( nMax && nMax < (sal_Int32)aMap.size() )
2096 eErrorCode = eTooManyTables;
2097 break;
2100 ::rtl::OUString sComposedName;
2101 ::rtl::OUString aQualifierName;
2102 ::rtl::OUString sAlias;
2104 OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
2105 pTableView->clearLayoutInformation();
2106 OSQLTables::const_iterator aIter = aMap.begin();
2107 OSQLTables::const_iterator aEnd = aMap.end();
2108 for(;aIter != aEnd;++aIter)
2110 OSQLTable xTable = aIter->second;
2111 Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW );
2113 sAlias = aIter->first;
2115 // check whether this is a query
2116 Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo();
2117 bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND );
2119 if ( bIsQuery )
2120 OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName );
2121 else
2123 sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false );
2125 // if the alias is the complete (composed) table, then shorten it
2126 if ( aKeyComp( sComposedName, aIter->first ) )
2128 ::rtl::OUString sCatalog, sSchema, sTable;
2129 ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
2130 sAlias = sTable;
2134 // find the existent window for this alias
2135 OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias );
2136 if ( !pExistentWin )
2138 pTableView->AddTabWin( sComposedName, sAlias, sal_False ); // don't create data here
2140 else
2142 // there already exists a window for this alias ....
2143 if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) )
2144 // ... but for another complete table name -> new window
2145 pTableView->AddTabWin(sComposedName, sAlias);
2149 // now delete the data for which we haven't any tablewindow
2150 OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap());
2151 OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin();
2152 OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end();
2153 for(;aIterTableMap != aIterTableEnd;++aIterTableMap)
2155 if(aMap.find(aIterTableMap->second->GetComposedName()) == aMap.end() &&
2156 aMap.find(aIterTableMap->first) == aMap.end())
2157 pTableView->RemoveTabWin(aIterTableMap->second);
2160 if ( eOk == (eErrorCode = FillOuterJoins(_pView,pParseTree->getChild(3)->getChild(0)->getChild(1))) )
2162 // check if we have a distinct statement
2163 if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT))
2165 rController.setDistinct(sal_True);
2166 rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES);
2168 if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk )
2170 // GetSelectionCriteria must be called before GetHavingCriteria
2171 sal_uInt16 nLevel=0;
2173 if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
2175 if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) )
2177 if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
2179 if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) )
2180 insertUnUsedFields(_pView,_pSelectionBrw);
2187 catch(SQLException&)
2189 OSL_ASSERT(!"getMaxTablesInSelect!");
2192 while ( false );
2194 // Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt
2195 rController.getUndoMgr()->Clear();
2196 _pSelectionBrw->Invalidate();
2197 return eErrorCode;
2199 //------------------------------------------------------------------------------
2200 /** fillSelectSubList
2201 @return
2202 <TRUE/> when columns could be inserted otherwise <FALSE/>
2204 //------------------------------------------------------------------------------
2205 SqlParseError fillSelectSubList( OQueryDesignView* _pView,
2206 OJoinTableView::OTableWindowMap* _pTabList)
2208 SqlParseError eErrorCode = eOk;
2209 sal_Bool bFirstField = sal_True;
2210 ::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*"));
2211 OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin();
2212 OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end();
2213 for(;aIter != aEnd && eOk == eErrorCode ;++aIter)
2215 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
2216 OTableFieldDescRef aInfo = new OTableFieldDesc();
2217 if (pTabWin->ExistsField( sAsterix, aInfo ))
2219 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2220 bFirstField = sal_False;
2223 return eErrorCode;
2225 //------------------------------------------------------------------------------
2226 void fillFunctionInfo( OQueryDesignView* _pView
2227 ,const ::connectivity::OSQLParseNode* pNode
2228 ,const ::rtl::OUString& sFunctionTerm
2229 ,OTableFieldDescRef& aInfo)
2231 // get the type out of the funtion name
2232 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2233 sal_Int32 nDataType = DataType::DOUBLE;
2234 ::rtl::OUString sFieldName = sFunctionTerm;
2235 OSQLParseNode* pFunctionName = pNode->getChild(0);
2236 if ( !SQL_ISPUNCTUATION(pFunctionName,"{") )
2238 if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) )
2239 pFunctionName = pFunctionName->getChild(0);
2241 ::rtl::OUString sFunctionName = pFunctionName->getTokenValue();
2242 if ( !sFunctionName.getLength() )
2243 sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8);
2245 nDataType = OSQLParser::getFunctionReturnType(
2246 sFunctionName
2247 ,&rController.getParser().getContext());
2249 aInfo->SetDataType(nDataType);
2250 aInfo->SetFieldType(TAB_NORMAL_FIELD);
2251 aInfo->SetField(sFieldName);
2252 aInfo->SetTabWindow(NULL);
2254 //------------------------------------------------------------------------------
2255 SqlParseError InstallFields(OQueryDesignView* _pView,
2256 const ::connectivity::OSQLParseNode* pNode,
2257 OJoinTableView::OTableWindowMap* pTabList )
2259 if( pNode==0 || !SQL_ISRULE(pNode,select_statement))
2260 return eNoSelectStatement;
2262 ::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2);
2263 sal_Bool bFirstField = sal_True; // bei der Initialisierung muß auf alle Faelle das erste Feld neu aktiviert werden
2265 SqlParseError eErrorCode = eOk;
2267 if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") )
2269 // SELECT * ...
2270 eErrorCode = fillSelectSubList(_pView,pTabList);
2272 else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) )
2274 // SELECT column, ...
2275 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2276 Reference< XConnection> xConnection = rController.getConnection();
2278 ::rtl::OUString aColumnName,aTableRange;
2279 for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i)
2281 ::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i);
2283 do {
2285 if ( SQL_ISRULE(pColumnRef,select_sublist) )
2287 eErrorCode = fillSelectSubList(_pView,pTabList);
2288 break;
2291 if ( SQL_ISRULE(pColumnRef,derived_column) )
2293 if ( !xConnection.is() )
2294 break;
2296 ::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein
2297 pColumnRef = pColumnRef->getChild(0);
2298 OTableFieldDescRef aInfo = new OTableFieldDesc();
2300 if ( pColumnRef->count() == 3 &&
2301 SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
2302 SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
2304 pColumnRef = pColumnRef->getChild(1);
2306 if (SQL_ISRULE(pColumnRef,column_ref))
2308 InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
2309 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2310 bFirstField = sal_False;
2312 else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec) ||
2313 SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) ||
2314 SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) ||
2315 SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct))
2317 ::rtl::OUString aColumns;
2318 pColumnRef->parseNodeToStr( aColumns,
2319 xConnection,
2320 &rController.getParser().getContext(),
2321 sal_True,
2322 sal_True); // quote is to true because we need quoted elements inside the function
2324 sal_Int32 nFunctionType = FKT_NONE;
2325 ::connectivity::OSQLParseNode* pParamRef = NULL;
2326 sal_Int32 nColumnRefPos = pColumnRef->count() - 2;
2327 if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() )
2328 pParamRef = pColumnRef->getChild(nColumnRefPos);
2330 if ( SQL_ISRULE(pColumnRef,general_set_fct)
2331 && SQL_ISRULE(pParamRef,column_ref) )
2333 // Parameter auf Columnref pr"ufen
2334 InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
2336 else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
2338 if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' )
2340 OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
2341 OJoinTableView::OTableWindowMap::iterator aEnd = pTabList->end();
2342 for(;aIter != aEnd;++aIter)
2344 OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
2345 if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aInfo ))
2347 aInfo->SetAlias(String());
2348 aInfo->SetTable(String());
2349 break;
2353 else
2355 ::rtl::OUString sFieldName = aColumns;
2356 if ( pParamRef )
2357 { // we got an aggregate function but without column name inside
2358 // so we set the whole argument of the function as field name
2359 nFunctionType |= FKT_NUMERIC;
2360 sFieldName = ::rtl::OUString();
2361 pParamRef->parseNodeToStr( sFieldName,
2362 xConnection,
2363 &rController.getParser().getContext(),
2364 sal_True,
2365 sal_True); // quote is to true because we need quoted elements inside the function
2367 aInfo->SetDataType(DataType::DOUBLE);
2368 aInfo->SetFieldType(TAB_NORMAL_FIELD);
2369 aInfo->SetField(sFieldName);
2371 aInfo->SetTabWindow(NULL);
2372 aInfo->SetFieldAlias(aColumnAlias);
2374 else
2376 fillFunctionInfo(_pView,pColumnRef,aColumns,aInfo);
2377 aInfo->SetFieldAlias(aColumnAlias);
2380 if ( SQL_ISRULE(pColumnRef,general_set_fct) )
2382 aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE);
2383 String aCol(aColumns);
2384 aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' '));
2386 else
2387 aInfo->SetFunctionType(nFunctionType|FKT_OTHER);
2389 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2390 bFirstField = sal_False;
2392 else //if(SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))
2394 ::rtl::OUString aColumns;
2395 pColumnRef->parseNodeToStr( aColumns,
2396 xConnection,
2397 &rController.getParser().getContext(),
2398 sal_True,
2399 sal_True); // quote is to true because we need quoted elements inside the function
2401 aInfo->SetTabWindow( NULL );
2403 // since we support queries in queries, the thingie might belong to an existing "table"
2404 OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo );
2405 if ( pExistingTable )
2407 aInfo->SetTabWindow( pExistingTable );
2408 aInfo->SetTable( pExistingTable->GetTableName() );
2409 aInfo->SetAlias( pExistingTable->GetAliasName() );
2412 aInfo->SetDataType(DataType::DOUBLE);
2413 aInfo->SetFieldType(TAB_NORMAL_FIELD);
2414 aInfo->SetField(aColumns);
2415 aInfo->SetFieldAlias(aColumnAlias);
2416 aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
2418 eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
2419 bFirstField = sal_False;
2422 break;
2425 DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" );
2427 } while ( false );
2430 else
2431 eErrorCode = eStatementTooComplex;
2433 return eErrorCode;
2435 //------------------------------------------------------------------------------
2436 SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
2437 OSelectionBrowseBox* _pSelectionBrw,
2438 const ::connectivity::OSQLParseNode* pParseRoot )
2440 SqlParseError eErrorCode = eOk;
2441 if (!pParseRoot->getChild(3)->getChild(4)->isLeaf())
2443 ::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2);
2444 ::connectivity::OSQLParseNode* pParamRef = NULL;
2446 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2447 EOrderDir eOrderDir;
2448 OTableFieldDescRef aDragLeft = new OTableFieldDesc();
2449 for( sal_uInt32 i=0 ; i<pNode->count() ; i++ )
2451 eOrderDir = ORDER_ASC;
2452 ::connectivity::OSQLParseNode* pChild = pNode->getChild( i );
2454 if (SQL_ISTOKEN( pChild->getChild(1), DESC ) )
2455 eOrderDir = ORDER_DESC;
2457 ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0);
2459 if(SQL_ISRULE(pArgument,column_ref))
2461 if( eOk == FillDragInfo(_pView,pArgument,aDragLeft))
2462 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i);
2463 else // it could be a alias name for a field
2465 ::rtl::OUString aTableRange,aColumnName;
2466 ::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator();
2467 rParseIter.getColumnRange( pArgument, aColumnName, aTableRange );
2469 OTableFields& aList = rController.getTableFieldDesc();
2470 OTableFields::iterator aIter = aList.begin();
2471 OTableFields::iterator aEnd = aList.end();
2472 for(;aIter != aEnd;++aIter)
2474 OTableFieldDescRef pEntry = *aIter;
2475 if(pEntry.isValid() && pEntry->GetFieldAlias() == aColumnName)
2476 pEntry->SetOrderDir( eOrderDir );
2480 else if(SQL_ISRULE(pArgument, general_set_fct ) &&
2481 SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
2482 eOk == FillDragInfo(_pView,pParamRef,aDragLeft))
2483 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
2484 else if( SQL_ISRULE(pArgument, set_fct_spec ) )
2487 Reference< XConnection> xConnection = rController.getConnection();
2488 if(xConnection.is())
2490 ::rtl::OUString sCondition;
2491 pArgument->parseNodeToPredicateStr(sCondition,
2492 xConnection,
2493 rController.getNumberFormatter(),
2494 _pView->getLocale(),
2495 static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
2496 &rController.getParser().getContext());
2497 fillFunctionInfo(_pView,pArgument,sCondition,aDragLeft);
2498 aDragLeft->SetFunctionType(FKT_OTHER);
2499 aDragLeft->SetOrderDir(eOrderDir);
2500 aDragLeft->SetVisible(sal_False);
2501 _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
2503 else
2504 eErrorCode = eColumnNotFound;
2506 else
2507 eErrorCode = eColumnNotFound;
2510 return eErrorCode;
2512 //------------------------------------------------------------------------------
2513 SqlParseError GetHavingCriteria( OQueryDesignView* _pView,
2514 OSelectionBrowseBox* _pSelectionBrw,
2515 const ::connectivity::OSQLParseNode* pSelectRoot,
2516 sal_uInt16& rLevel )
2518 SqlParseError eErrorCode = eOk;
2519 if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf())
2520 eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True);
2521 return eErrorCode;
2523 //------------------------------------------------------------------------------
2524 SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
2525 OSelectionBrowseBox* _pSelectionBrw,
2526 const ::connectivity::OSQLParseNode* pSelectRoot )
2528 SqlParseError eErrorCode = eOk;
2529 if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf())
2531 OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
2532 ::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2);
2533 OTableFieldDescRef aDragInfo = new OTableFieldDesc();
2534 for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i )
2536 ::connectivity::OSQLParseNode* pParamRef = NULL;
2537 ::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i );
2538 if(SQL_ISRULE(pArgument,column_ref))
2540 if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) )
2542 aDragInfo->SetGroupBy(sal_True);
2543 _pSelectionBrw->AddGroupBy(aDragInfo,i);
2546 else if(SQL_ISRULE(pArgument, general_set_fct ) &&
2547 SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
2548 eOk == FillDragInfo(_pView,pParamRef,aDragInfo))
2550 aDragInfo->SetGroupBy(sal_True);
2551 _pSelectionBrw->AddGroupBy( aDragInfo, i );
2553 else if( SQL_ISRULE(pArgument, set_fct_spec ) )
2555 Reference< XConnection> xConnection = rController.getConnection();
2556 if(xConnection.is())
2558 ::rtl::OUString sGroupByExpression;
2559 pArgument->parseNodeToStr( sGroupByExpression,
2560 xConnection,
2561 &rController.getParser().getContext(),
2562 sal_True,
2563 sal_True); // quote is to true because we need quoted elements inside the function
2564 fillFunctionInfo(_pView,pArgument,sGroupByExpression,aDragInfo);
2565 aDragInfo->SetFunctionType(FKT_OTHER);
2566 aDragInfo->SetGroupBy(sal_True);
2567 aDragInfo->SetVisible(sal_False);
2568 _pSelectionBrw->AddGroupBy( aDragInfo, i );
2570 else
2571 eErrorCode = eColumnNotFound;
2575 return eErrorCode;
2578 //------------------------------------------------------------------------------
2579 String getParseErrorMessage( SqlParseError _eErrorCode )
2581 USHORT nResId;
2582 switch(_eErrorCode)
2584 case eIllegalJoin:
2585 nResId = STR_QRY_ILLEGAL_JOIN;
2586 break;
2587 case eStatementTooLong:
2588 nResId = STR_QRY_TOO_LONG_STATEMENT;
2589 break;
2590 case eNoConnection:
2591 nResId = STR_QRY_SYNTAX;
2592 break;
2593 case eNoSelectStatement:
2594 nResId = STR_QRY_NOSELECT;
2595 break;
2596 case eColumnInLikeNotFound:
2597 nResId = STR_QRY_SYNTAX;
2598 break;
2599 case eNoColumnInLike:
2600 nResId = STR_QRY_SYNTAX;
2601 break;
2602 case eColumnNotFound:
2603 nResId = STR_QRY_SYNTAX;
2604 break;
2605 case eNativeMode:
2606 nResId = STR_QRY_NATIVE;
2607 break;
2608 case eTooManyTables:
2609 nResId = STR_QRY_TOO_MANY_TABLES;
2610 break;
2611 case eTooManyConditions:
2612 nResId = STR_QRY_TOOMANYCOND;
2613 break;
2614 case eTooManyColumns:
2615 nResId = STR_QRY_TOO_MANY_COLUMNS;
2616 break;
2617 case eStatementTooComplex:
2618 nResId = STR_QRY_TOOCOMPLEX;
2619 break;
2620 default:
2621 nResId = STR_QRY_SYNTAX;
2622 break;
2625 return String( ModuleRes( nResId ) );
2628 //------------------------------------------------------------------------------
2629 //------------------------------------------------------------------------------
2631 // end of anonymouse namespace
2632 DBG_NAME(OQueryDesignView)
2634 OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent,
2635 OQueryController& _rController,
2636 const Reference< XMultiServiceFactory >& _rFactory)
2637 :OQueryView( _pParent, _rController, _rFactory )
2638 ,m_aSplitter( this )
2639 ,m_eChildFocus(NONE)
2640 ,m_bInKeyEvent(sal_False)
2641 ,m_bInSplitHandler( sal_False )
2643 DBG_CTOR(OQueryDesignView,NULL);
2647 SvtSysLocale aSysLocale;
2648 m_aLocale = aSysLocale.GetLocaleData().getLocale();
2649 m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep();
2651 catch(Exception&)
2655 m_pSelectionBox = new OSelectionBrowseBox(this);
2657 setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows());
2658 m_pSelectionBox->Show();
2659 // Splitter einrichten
2660 m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl));
2661 m_aSplitter.Show();
2664 // -----------------------------------------------------------------------------
2665 OQueryDesignView::~OQueryDesignView()
2667 if ( m_pTableView )
2668 ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
2669 ::std::auto_ptr<Window> aTemp(m_pSelectionBox);
2670 m_pSelectionBox = NULL;
2672 DBG_DTOR(OQueryDesignView,NULL);
2674 //------------------------------------------------------------------------------
2675 IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ )
2677 if (!getController().isReadOnly())
2679 m_bInSplitHandler = sal_True;
2680 m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) );
2681 static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel());
2682 static_cast<OQueryController&>(getController()).setModified();
2683 Resize();
2684 m_bInSplitHandler = sal_True;
2686 return 0L;
2688 // -------------------------------------------------------------------------
2689 void OQueryDesignView::Construct()
2691 m_pTableView = new OQueryTableView(m_pScrollWindow,this);
2692 ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow));
2693 OQueryView::Construct();
2695 // -----------------------------------------------------------------------------
2696 void OQueryDesignView::initialize()
2698 if(static_cast<OQueryController&>(getController()).getSplitPos() != -1)
2700 m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) );
2701 m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos());
2703 m_pSelectionBox->initialize();
2704 reset();
2706 // -------------------------------------------------------------------------
2707 void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground)
2709 Point aPlaygroundPos( _rPlayground.TopLeft() );
2710 Size aPlaygroundSize( _rPlayground.GetSize() );
2712 // calc the split pos, and forward it to the controller
2713 sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos();
2714 if ( 0 != aPlaygroundSize.Height() )
2716 if ( ( -1 == nSplitPos )
2717 || ( nSplitPos >= aPlaygroundSize.Height() )
2720 // let the selection browse box determine an optimal size
2721 Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
2722 nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height();
2723 // still an invalid size?
2724 if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() )
2725 nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6);
2727 static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos);
2730 if ( !m_bInSplitHandler )
2731 { // the resize is triggered by something else than the split handler
2732 // our main focus is to try to preserve the size of the selectionbrowse box
2733 Size aSelBoxSize = m_pSelectionBox->GetSizePixel();
2734 if ( aSelBoxSize.Height() )
2736 // keep the size of the sel box constant
2737 nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height();
2739 // and if the box is smaller than the optimal size, try to do something about it
2740 Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
2741 if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() )
2743 nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height();
2746 static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos );
2751 // normalize the split pos
2752 Point aSplitPos = Point( _rPlayground.Left(), nSplitPos );
2753 Size aSplitSize = Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() );
2755 if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() ))
2756 aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height();
2758 if( aSplitPos.Y() <= aPlaygroundPos.Y() )
2759 aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2);
2761 // position the table
2762 Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y());
2763 m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize);
2765 // position the selection browse box
2766 Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() );
2767 m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() ));
2769 // set the size of the splitter
2770 m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize );
2771 m_aSplitter.SetDragRectPixel( _rPlayground );
2773 // just for completeness: there is no space left, we occupied it all ...
2774 _rPlayground.SetPos( _rPlayground.BottomRight() );
2775 _rPlayground.SetSize( Size( 0, 0 ) );
2777 // -----------------------------------------------------------------------------
2778 void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly)
2780 m_pSelectionBox->SetReadOnly(_bReadOnly);
2782 // -----------------------------------------------------------------------------
2783 void OQueryDesignView::clear()
2785 m_pSelectionBox->ClearAll(); // clear the whole selection
2786 m_pTableView->ClearAll();
2788 // -----------------------------------------------------------------------------
2789 void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/)
2792 // -----------------------------------------------------------------------------
2793 void OQueryDesignView::copy()
2795 if( m_eChildFocus == SELECTION)
2796 m_pSelectionBox->copy();
2798 // -----------------------------------------------------------------------------
2799 sal_Bool OQueryDesignView::isCutAllowed()
2801 sal_Bool bAllowed = sal_False;
2802 if ( SELECTION == m_eChildFocus )
2803 bAllowed = m_pSelectionBox->isCutAllowed();
2804 return bAllowed;
2806 // -----------------------------------------------------------------------------
2807 sal_Bool OQueryDesignView::isPasteAllowed()
2809 sal_Bool bAllowed = sal_False;
2810 if ( SELECTION == m_eChildFocus )
2811 bAllowed = m_pSelectionBox->isPasteAllowed();
2812 return bAllowed;
2814 // -----------------------------------------------------------------------------
2815 sal_Bool OQueryDesignView::isCopyAllowed()
2817 sal_Bool bAllowed = sal_False;
2818 if ( SELECTION == m_eChildFocus )
2819 bAllowed = m_pSelectionBox->isCopyAllowed();
2820 return bAllowed;
2822 // -----------------------------------------------------------------------------
2823 void OQueryDesignView::stopTimer()
2825 m_pSelectionBox->stopTimer();
2827 // -----------------------------------------------------------------------------
2828 void OQueryDesignView::startTimer()
2830 m_pSelectionBox->startTimer();
2832 // -----------------------------------------------------------------------------
2833 void OQueryDesignView::cut()
2835 if( m_eChildFocus == SELECTION)
2837 m_pSelectionBox->cut();
2838 static_cast<OQueryController&>(getController()).setModified(sal_True);
2841 // -----------------------------------------------------------------------------
2842 void OQueryDesignView::paste()
2844 if( m_eChildFocus == SELECTION)
2846 m_pSelectionBox->paste();
2847 static_cast<OQueryController&>(getController()).setModified(sal_True);
2850 // -----------------------------------------------------------------------------
2851 void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName)
2853 // Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde
2854 DeleteFields(rAliasName);
2855 static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // view nochmal bescheid sagen
2857 //------------------------------------------------------------------------------
2858 void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName )
2860 m_pSelectionBox->DeleteFields( rAliasName );
2862 // -----------------------------------------------------------------------------
2863 bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const
2865 return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo);
2867 // -----------------------------------------------------------------------------
2868 SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate)
2870 return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).isValid() ? eOk : eTooManyColumns;
2872 // -----------------------------------------------------------------------------
2873 sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const
2875 static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15;
2876 sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos);
2877 if ( !nWidth )
2878 nWidth = s_nDefaultWidth;
2879 return nWidth;
2881 //------------------------------------------------------------------------------
2882 void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList)
2884 DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !");
2885 pFieldList->Clear();
2887 sal_Bool bAllTables = sAliasName.getLength() == 0;
2889 OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap();
2890 ::rtl::OUString strCurrentPrefix;
2891 ::std::vector< ::rtl::OUString> aFields;
2892 OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin();
2893 OJoinTableView::OTableWindowMap::iterator aEnd = pTabWins->end();
2894 for(;aIter != aEnd;++aIter)
2896 OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second);
2897 if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName))
2899 strCurrentPrefix = pCurrentWin->GetAliasName();
2900 strCurrentPrefix += ::rtl::OUString('.');
2902 pCurrentWin->EnumValidFields(aFields);
2904 ::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin();
2905 ::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end();
2906 for(;aStrIter != aStrEnd;++aStrIter)
2908 if (bAllTables || aStrIter->toChar() == '*')
2909 pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter);
2910 else
2911 pFieldList->InsertEntry(*aStrIter);
2914 if (!bAllTables)
2915 // das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig
2916 // (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt)
2917 break;
2921 // -----------------------------------------------------------------------------
2922 long OQueryDesignView::PreNotify(NotifyEvent& rNEvt)
2924 switch (rNEvt.GetType())
2926 case EVENT_GETFOCUS:
2927 #if OSL_DEBUG_LEVEL > 0
2929 Window* pFocus = Application::GetFocusWindow();
2930 (void)pFocus;
2932 #endif
2934 if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() )
2935 m_eChildFocus = SELECTION;
2936 else
2937 m_eChildFocus = TABLEVIEW;
2938 break;
2941 return OQueryView::PreNotify(rNEvt);
2943 //------------------------------------------------------------------------------
2946 // -----------------------------------------------------------------------------
2947 // check if the statement is correct when not returning false
2948 sal_Bool OQueryDesignView::checkStatement()
2950 sal_Bool bRet = sal_True;
2951 if ( m_pSelectionBox )
2952 bRet = m_pSelectionBox->Save(); // a error occured so we return no
2953 return bRet;
2955 //-------------------------------------------------------------------------------
2956 ::rtl::OUString OQueryDesignView::getStatement()
2958 OQueryController& rController = static_cast<OQueryController&>(getController());
2959 m_rController.clearError();
2960 // used for fields which aren't any longer in the statement
2961 OTableFields& rUnUsedFields = rController.getUnUsedFields();
2962 OTableFields().swap( rUnUsedFields );
2964 // create the select columns
2965 sal_uInt32 nFieldcount = 0;
2966 OTableFields& rFieldList = rController.getTableFieldDesc();
2967 OTableFields::iterator aIter = rFieldList.begin();
2968 OTableFields::iterator aEnd = rFieldList.end();
2969 for(;aIter != aEnd;++aIter)
2971 OTableFieldDescRef pEntryField = *aIter;
2972 if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() )
2973 ++nFieldcount;
2974 else if (pEntryField->GetField().getLength() &&
2975 !pEntryField->HasCriteria() &&
2976 pEntryField->isNoneFunction() &&
2977 pEntryField->GetOrderDir() == ORDER_NONE &&
2978 !pEntryField->IsGroupBy() &&
2979 !pEntryField->GetFunction().getLength() )
2980 rUnUsedFields.push_back(pEntryField);
2982 if ( !nFieldcount ) // keine Felder sichtbar also zur"uck
2984 rUnUsedFields = rFieldList;
2985 return ::rtl::OUString();
2988 OQueryTableView::OTableWindowMap* pTabList = m_pTableView->GetTabWinMap();
2989 sal_uInt32 nTabcount = pTabList->size();
2991 ::rtl::OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1));
2992 if( !aFieldListStr.getLength() )
2993 return ::rtl::OUString();
2994 // Ausnahmebehandlung, wenn keine Felder angegeben worden sind
2995 // Dann darf die Tabpage nicht gewechselt werden
2996 // Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt
2997 // und eine Errormeldung erzeugt
2998 // ----------------- Tabellenliste aufbauen ----------------------
3000 const ::std::vector<OTableConnection*>* pConnList = m_pTableView->getTableConnections();
3001 Reference< XConnection> xConnection = rController.getConnection();
3002 ::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList));
3003 DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !");
3004 // wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits
3005 // eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder
3006 // existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher)
3007 ::rtl::OUStringBuffer aHavingStr,aCriteriaListStr;
3008 // ----------------- Kriterien aufbauen ----------------------
3009 if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1))
3010 return ::rtl::OUString();
3012 ::rtl::OUString aJoinCrit;
3013 GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList);
3014 if(aJoinCrit.getLength())
3016 ::rtl::OUString aTmp = ::rtl::OUString::createFromAscii("( ");
3017 aTmp += aJoinCrit;
3018 aTmp += ::rtl::OUString::createFromAscii(" )");
3019 if(aCriteriaListStr.getLength())
3021 aTmp += C_AND;
3022 aTmp += aCriteriaListStr.makeStringAndClear();
3024 aCriteriaListStr = aTmp;
3026 // ----------------- Statement aufbauen ----------------------
3027 ::rtl::OUStringBuffer aSqlCmd(::rtl::OUString::createFromAscii("SELECT "));
3028 if(static_cast<OQueryController&>(getController()).isDistinct())
3029 aSqlCmd.append(::rtl::OUString::createFromAscii(" DISTINCT "));
3030 aSqlCmd.append(aFieldListStr);
3031 aSqlCmd.append(::rtl::OUString::createFromAscii(" FROM "));
3032 aSqlCmd.append(aTableListStr);
3034 if (aCriteriaListStr.getLength())
3036 aSqlCmd.append(::rtl::OUString::createFromAscii(" WHERE "));
3037 aSqlCmd.append(aCriteriaListStr.makeStringAndClear());
3039 // ----------------- GroupBy aufbauen und Anh"angen ------------
3040 Reference<XDatabaseMetaData> xMeta;
3041 if ( xConnection.is() )
3042 xMeta = xConnection->getMetaData();
3043 sal_Bool bUseAlias = nTabcount > 1;
3044 if ( xMeta.is() )
3045 bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated();
3047 aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias));
3048 // ----------------- having Anh"angen ------------
3049 if(aHavingStr.getLength())
3051 aSqlCmd.append(::rtl::OUString::createFromAscii(" HAVING "));
3052 aSqlCmd.append(aHavingStr.makeStringAndClear());
3054 // ----------------- Sortierung aufbauen und Anh"angen ------------
3055 ::rtl::OUString sOrder;
3056 SqlParseError eErrorCode = eOk;
3057 if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk)
3058 aSqlCmd.append(sOrder);
3059 else
3061 if ( !m_rController.hasError() )
3062 m_rController.appendError( getParseErrorMessage( eErrorCode ) );
3064 m_rController.displayError();
3067 ::rtl::OUString sSQL = aSqlCmd.makeStringAndClear();
3068 if ( xConnection.is() )
3070 ::connectivity::OSQLParser& rParser( rController.getParser() );
3071 ::rtl::OUString sErrorMessage;
3072 ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) );
3073 if ( pParseNode.get() )
3075 OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1);
3076 if ( pNode->count() > 1 )
3078 ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
3079 if ( pCondition ) // no where clause
3081 OSQLParseNode::compress(pCondition);
3082 ::rtl::OUString sTemp;
3083 pParseNode->parseNodeToStr(sTemp,xConnection);
3084 sSQL = sTemp;
3089 return sSQL;
3091 // -----------------------------------------------------------------------------
3092 // -----------------------------------------------------------------------------
3093 void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable)
3095 sal_uInt16 nRow;
3096 switch (_nSlotId)
3098 case SID_QUERY_VIEW_FUNCTIONS:
3099 nRow = BROW_FUNCTION_ROW;
3100 break;
3101 case SID_QUERY_VIEW_TABLES:
3102 nRow = BROW_TABLE_ROW;
3103 break;
3104 case SID_QUERY_VIEW_ALIASES:
3105 nRow = BROW_COLUMNALIAS_ROW;
3106 break;
3107 default:
3108 // ????????????
3109 nRow = 0;
3110 break;
3112 m_pSelectionBox->SetRowVisible(nRow,_bEnable);
3113 m_pSelectionBox->Invalidate();
3115 // -----------------------------------------------------------------------------
3116 sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId)
3118 sal_uInt16 nRow;
3119 switch (_nSlotId)
3121 case SID_QUERY_VIEW_FUNCTIONS:
3122 nRow = BROW_FUNCTION_ROW;
3123 break;
3124 case SID_QUERY_VIEW_TABLES:
3125 nRow = BROW_TABLE_ROW;
3126 break;
3127 case SID_QUERY_VIEW_ALIASES:
3128 nRow = BROW_COLUMNALIAS_ROW;
3129 break;
3130 default:
3131 // ?????????
3132 nRow = 0;
3133 break;
3135 return m_pSelectionBox->IsRowVisible(nRow);
3137 // -----------------------------------------------------------------------------
3138 void OQueryDesignView::SaveUIConfig()
3140 OQueryController& rCtrl = static_cast<OQueryController&>(getController());
3141 rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() );
3142 // rCtrl.SaveTabFieldsWidth( m_pSelectionBox );
3143 rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() );
3144 if ( m_aSplitter.GetSplitPosPixel() != 0 )
3145 rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() );
3147 // -----------------------------------------------------------------------------
3148 OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry,
3149 const String& _sCriteria,
3150 ::rtl::OUString& _rsErrorMessage,
3151 Reference<XPropertySet>& _rxColumn) const
3153 OSL_ENSURE(pEntry.isValid(),"Entry is null!");
3154 if(!pEntry.isValid())
3155 return NULL;
3156 Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection();
3157 if(!xConnection.is())
3158 return NULL;
3160 ::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() );
3161 OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow());
3163 String sTest(_sCriteria);
3164 // special handling for functions
3165 if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) )
3167 // we have a function here so we have to distinguish the type of return value
3168 String sFunction;
3169 if ( pEntry->isNumericOrAggreateFunction() )
3170 sFunction = pEntry->GetFunction();
3172 if ( !sFunction.Len() )
3173 sFunction = pEntry->GetField();
3175 if(sFunction.GetTokenCount('(') > 1)
3176 sFunction = sFunction.GetToken(0,'('); // this should be the name of the function
3178 sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext());
3179 if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) )
3181 // first try the international version
3182 ::rtl::OUString sSql;
3183 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * "));
3184 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE "));
3185 sSql += pEntry->GetField();
3186 sSql += _sCriteria;
3187 ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) );
3188 nType = DataType::DOUBLE;
3189 if ( pParseNode.get() )
3191 OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
3192 if ( pColumnRef )
3194 OTableFieldDescRef aField = new OTableFieldDesc();
3195 if ( eOk == FillDragInfo(this,pColumnRef,aField) )
3197 nType = aField->GetDataType();
3203 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
3204 parse::OParseColumn* pColumn = new parse::OParseColumn( pEntry->GetField(),
3205 ::rtl::OUString(),
3206 ::rtl::OUString(),
3207 ColumnValue::NULLABLE_UNKNOWN,
3210 nType,
3211 sal_False,
3212 sal_False,
3213 xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
3214 _rxColumn = pColumn;
3215 pColumn->setFunction(sal_True);
3216 pColumn->setRealName(pEntry->GetField());
3218 else
3220 if (pWin)
3222 Reference<XNameAccess> xColumns = pWin->GetOriginalColumns();
3223 if (xColumns.is() && xColumns->hasByName(pEntry->GetField()))
3224 xColumns->getByName(pEntry->GetField()) >>= _rxColumn;
3228 OSQLParseNode* pParseNode = rParser.predicateTree( _rsErrorMessage,
3229 sTest,
3230 static_cast<OQueryController&>(getController()).getNumberFormatter(),
3231 _rxColumn);
3232 return pParseNode;
3234 // -----------------------------------------------------------------------------
3235 void OQueryDesignView::GetFocus()
3237 OQueryView::GetFocus();
3238 if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() )
3240 // first we have to deactivate the current cell to refill when nescessary
3241 m_pSelectionBox->DeactivateCell();
3242 m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId());
3243 m_pSelectionBox->GrabFocus();
3246 // -----------------------------------------------------------------------------
3247 void OQueryDesignView::reset()
3249 m_pTableView->ClearAll();
3250 m_pTableView->ReSync();
3252 // -----------------------------------------------------------------------------
3253 void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows)
3255 m_pSelectionBox->SetNoneVisbleRow(_nRows);
3257 // -----------------------------------------------------------------------------
3258 bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo )
3260 SqlParseError eErrorCode = eNativeMode;
3261 m_rController.clearError();
3265 eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox );
3267 if ( eErrorCode != eOk )
3269 if ( !m_rController.hasError() )
3270 m_rController.appendError( getParseErrorMessage( eErrorCode ) );
3272 if ( _pErrorInfo )
3274 *_pErrorInfo = m_rController.getError();
3276 else
3278 m_rController.displayError();
3282 catch ( const Exception& )
3284 DBG_UNHANDLED_EXCEPTION();
3286 return eErrorCode == eOk;
3288 // -----------------------------------------------------------------------------