1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
36 #ifndef DBAUI_QUERYTABLEVIEW_HXX
37 #include "QueryTableView.hxx"
39 #ifndef DBAUI_QUERY_TABLEWINDOW_HXX
40 #include "QTableWindow.hxx"
42 #ifndef _SV_TOOLBOX_HXX
43 #include <vcl/toolbox.hxx>
45 #ifndef DBAUI_QUERYCONTROLLER_HXX
46 #include "querycontroller.hxx"
49 #include <vcl/split.hxx>
52 #include <svtools/undo.hxx>
54 #ifndef TOOLS_DIAGNOSE_EX_H
55 #include <tools/diagnose_ex.h>
57 #ifndef DBAUI_QYDLGTAB_HXX
58 #include "adtabdlg.hxx"
61 #include <vcl/svapp.hxx>
63 #ifndef _SV_COMBOBOX_HXX
64 #include <vcl/combobox.hxx>
66 #ifndef _SV_MSGBOX_HXX
67 #include <vcl/msgbox.hxx>
69 #ifndef DBACCESS_UI_BROWSER_ID_HXX
70 #include "browserids.hxx"
72 #ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX
73 #include "SelectionBrowseBox.hxx"
76 #include "dbu_qry.hrc"
78 #ifndef _UTL_CONFIGMGR_HXX_
79 #include <unotools/configmgr.hxx>
81 #ifndef _COMPHELPER_TYPES_HXX_
82 #include <comphelper/types.hxx>
84 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
85 #include <connectivity/dbtools.hxx>
87 #ifndef _DBHELPER_DBEXCEPTION_HXX_
88 #include <connectivity/dbexception.hxx>
90 #ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_
91 #include <com/sun/star/i18n/XLocaleData.hpp>
93 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
94 #include <com/sun/star/sdbc/DataType.hpp>
96 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
97 #include <com/sun/star/container/XNameAccess.hpp>
99 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
100 #include <com/sun/star/sdbc/ColumnValue.hpp>
102 #ifndef _CONNECTIVITY_PCOLUMN_HXX_
103 #include <connectivity/PColumn.hxx>
105 #ifndef DBAUI_QUERYTABLECONNECTION_HXX
106 #include "QTableConnection.hxx"
108 #ifndef DBAUI_CONNECTIONLINE_HXX
109 #include "ConnectionLine.hxx"
111 #ifndef DBAUI_CONNECTIONLINEDATA_HXX
112 #include "ConnectionLineData.hxx"
114 #ifndef DBAUI_QTABLECONNECTIONDATA_HXX
115 #include "QTableConnectionData.hxx"
117 #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
118 #include "dbustrings.hrc"
120 #ifndef _COMPHELPER_EXTRACT_HXX_
121 #include <comphelper/extract.hxx>
123 #ifndef DBAUI_TOOLS_HXX
124 #include "UITools.hxx"
126 #ifndef DBAUI_QUERYCONTAINERWINDOW_HXX
127 #include "querycontainerwindow.hxx"
129 #ifndef DBAUI_QUERYTABLEVIEW_HXX
130 #include "QueryTableView.hxx"
132 #ifndef _DBAUI_SQLMESSAGE_HXX_
133 #include "sqlmessage.hxx"
135 #ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
136 #include <svtools/syslocale.hxx>
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
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
,
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
;
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
;
213 sTableRange
= ::connectivity::OSQLParseNode::getTableRange(_pTableRef
);
214 if ( !sTableRange
.getLength() )
215 _pTableRef
->parseNodeToStr(sTableRange
,xConnection
,NULL
,sal_False
,sal_False
);
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));
227 OQueryTableConnectionData
* pInfoData
= new OQueryTableConnectionData();
228 TTableConnectionData::value_type
aInfoData(pInfoData
);
229 pInfoData
->InitFromDrag(_aDragLeft
, _aDragRight
);
230 pInfoData
->SetJoinType(_eJoinType
);
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
);
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();
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
,
296 rController
.getNumberFormatter(),
298 static_cast<sal_Char
>(_sDecimal
.toChar()),
299 &rController
.getParser().getContext());
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);
323 if ( !InsertJoin(_pView
,pJoinNode
) )
327 // check if error occured
329 eErrorCode
= eIllegalJoin
;
333 //------------------------------------------------------------------------------
334 ::rtl::OUString
QuoteField( const OQueryDesignView
* _pView
,const ::rtl::OUString
& rValue
, sal_Int32 aType
)
336 ::rtl::OUString rNewValue
;
337 switch (rValue
.toChar())
340 if (rValue
.getLength() != 1)
342 case '\'': // ::rtl::OUString Quotierung oder Datum
343 //case '#': // Datumsquotierung // jetengine
344 case ':': // Parameter
345 case '[': // Parameter
349 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(_pView
->getController()).getConnection();
350 Reference
< XDatabaseMetaData
> xMetaData
;
352 xMetaData
= xConnection
->getMetaData();
353 ::rtl::OUString aQuote
;
357 aQuote
= xMetaData
->getIdentifierQuoteString();
363 case DataType::TIMESTAMP
:
364 if (rValue
.toChar() != '{') // nur quoten, wenn kein Access Datum
365 rNewValue
= ::dbtools::quoteName(aQuote
,rValue
);
370 case DataType::VARCHAR
:
371 case DataType::LONGVARCHAR
:
372 rNewValue
= ::dbtools::quoteName(aQuote
,rValue
);
374 case DataType::DECIMAL
:
375 case DataType::NUMERIC
:
376 case DataType::TINYINT
:
377 case DataType::SMALLINT
:
378 case DataType::INTEGER
:
379 case DataType::BIGINT
:
381 case DataType::DOUBLE
:
382 case DataType::BINARY
:
383 case DataType::VARBINARY
:
384 case DataType::LONGVARBINARY
:
388 case DataType::BOOLEAN
:
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"));
403 DBG_ERROR( "QuoteField: illegal type" );
409 DBG_ERROR( "QuoteField: Exception" );
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
) );
438 bErg
= static_cast<OQueryTableView
*>(_pView
->getTableView())->FindTableFromField(aColumnName
, _rDragInfo
, nCntAccount
);
440 bErg
= _pView
->HasFieldByAliasName(aColumnName
, _rDragInfo
);
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
) ) );
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
) ));
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))
519 _rJoin
= _rJoin
.replaceAt(_rJoin
.getLength()-1,1,::rtl::OUString(' '));
521 (_rJoin
+= C_AND
) += BuildJoinCriteria(_xConnection
,pData
->GetConnLineDataList(),pData
);
523 _rJoin
+= ::rtl::OUString(')');
524 _pEntryConn
->SetVisited(sal_True
);
527 //------------------------------------------------------------------------------
528 ::rtl::OUString
BuildTable( const Reference
< XConnection
>& _xConnection
,
529 const OQueryTableWindow
* pEntryTab
,
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();
563 //------------------------------------------------------------------------------
564 ::rtl::OUString
BuildJoin( const Reference
< XConnection
>& _xConnection
,
565 const ::rtl::OUString
& rLh
,
566 const ::rtl::OUString
& rRh
,
567 OQueryTableConnectionData
* pData
)
571 if ( pData
->isNatural() && pData
->GetJoinType() != CROSS_JOIN
)
572 aErg
.AppendAscii(" NATURAL ");
573 switch(pData
->GetJoinType())
576 aErg
.AppendAscii(" LEFT OUTER ");
579 aErg
.AppendAscii(" RIGHT OUTER ");
582 OSL_ENSURE(!pData
->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
583 aErg
.AppendAscii(" CROSS ");
586 OSL_ENSURE(pData
->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
587 aErg
.AppendAscii(" INNER ");
590 aErg
.AppendAscii(" FULL OUTER ");
593 aErg
.AppendAscii("JOIN ");
595 if ( CROSS_JOIN
!= pData
->GetJoinType() && !pData
->isNatural() )
597 aErg
.AppendAscii(" ON ");
598 aErg
+= String(BuildJoinCriteria(_xConnection
,pData
->GetConnLineDataList(),pData
));
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() )
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
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:
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
);
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
)))
735 insertConnection(_pView
,_eJoinType
,aDragLeft
,aDragRight
);
738 eErrorCode
= eIllegalJoin
;
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
,
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
;
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() == '*' )
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
);
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
));
822 aTmpStr
.append(rFieldName
);
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(")");
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);
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
,
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())
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())
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
;
909 aWork
= ::rtl::OUString();
912 aWork
+= quoteTableAlias(bMulti
,pEntryField
->GetAlias(),aQuote
);
914 if ( (pEntryField
->GetFunctionType() & (FKT_OTHER
|FKT_NUMERIC
)) || (aFieldName
.toChar() == '*') )
917 aWork
+= ::dbtools::quoteName(aQuote
, aFieldName
);
919 if ( pEntryField
->isAggreateFunction() || pEntryField
->IsGroupBy() )
921 if (!aHavingStr
.getLength()) // noch keine Kriterien
922 aHavingStr
+= ::rtl::OUString('('); // Klammern
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
932 aHavingStr
+= ::rtl::OUString(')'); // Klammern
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
,
953 !pEntryField
->isOtherFunction());
954 aHavingStr
= sHavingStr
;
957 aHavingStr
+= aCriteria
;
961 if ( !aWhereStr
.getLength() ) // noch keine Kriterien
962 aWhereStr
+= ::rtl::OUString('('); // Klammern
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
,
981 !pEntryField
->isOtherFunction() );
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
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!");
1033 //------------------------------------------------------------------------------
1034 SqlParseError
GenerateOrder( OQueryDesignView
* _pView
,
1035 OTableFields
& _rFieldList
,
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
;
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
;
1090 aWorkStr
+= ::dbtools::quoteName(aQuote
, aColumnName
);
1092 aWorkStr
+= ::rtl::OUString(')');
1094 else if ( pEntryField
->isOtherFunction() )
1096 aWorkStr
+= aColumnName
;
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( ',' );
1115 if ( aWorkStr
.getLength() )
1117 const sal_Int32 nMaxOrder
= xMetaData
->getMaxColumnsInOrderBy();
1118 String
sToken(aWorkStr
);
1119 if ( nMaxOrder
&& nMaxOrder
< sToken
.GetTokenCount(',') )
1120 eErrorCode
= eStatementTooLong
;
1123 _rsRet
= ::rtl::OUString::createFromAscii(" ORDER BY ");
1128 catch(SQLException
&)
1130 OSL_ASSERT(!"Failure while building group by!");
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())
1220 // create outer join
1222 aStr
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ "));
1225 aStr
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }"));
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()),
1250 searchAndAppendName(_xConnection
,
1251 static_cast<OQueryTableWindow
*>(pEntryConn
->GetDestWin()),
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());
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
,
1316 &rController
.getParser().getContext(),
1318 !pEntryField
->isOtherFunction());
1319 sGroupByPart
+= sGroupBy
;
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!");
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())
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
);
1394 //------------------------------------------------------------------------------
1395 SqlParseError
GetANDCriteria( OQueryDesignView
* _pView
,
1396 OSelectionBrowseBox
* _pSelectionBrw
,
1397 const ::connectivity::OSQLParseNode
* pCondition
,
1398 const sal_uInt16 nLevel
,
1400 bool bAddOrOnOneLine
);
1401 //------------------------------------------------------------------------------
1402 SqlParseError
ComparisonPredicate(OQueryDesignView
* _pView
,
1403 OSelectionBrowseBox
* _pSelectionBrw
,
1404 const ::connectivity::OSQLParseNode
* pCondition
,
1405 const sal_uInt16 nLevel
,
1407 bool bAddOrOnOneLine
);
1408 //------------------------------------------------------------------------------
1409 SqlParseError
GetORCriteria(OQueryDesignView
* _pView
,
1410 OSelectionBrowseBox
* _pSelectionBrw
,
1411 const ::connectivity::OSQLParseNode
* pCondition
,
1412 sal_uInt16
& nLevel
,
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
);
1435 eErrorCode
= GetANDCriteria(_pView
,_pSelectionBrw
,pChild
, bAddOrOnOneLine
? nLevel
: nLevel
++,bHaving
, i
== 0 ? false : bAddOrOnOneLine
);
1439 eErrorCode
= GetANDCriteria( _pView
,_pSelectionBrw
,pCondition
, nLevel
, bHaving
,bAddOrOnOneLine
);
1443 //--------------------------------------------------------------------------------------------------
1444 bool CheckOrCriteria(const ::connectivity::OSQLParseNode
* _pCondition
,::connectivity::OSQLParseNode
* _pFirstColumnRef
)
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
);
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
;
1465 //--------------------------------------------------------------------------------------------------
1466 SqlParseError
GetANDCriteria( OQueryDesignView
* _pView
,
1467 OSelectionBrowseBox
* _pSelectionBrw
,
1468 const ::connectivity::OSQLParseNode
* pCondition
,
1469 const sal_uInt16 nLevel
,
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
;
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
,
1514 rController
.getNumberFormatter(),
1516 static_cast<sal_Char
>(sDecimal
.toChar()),
1517 &rController
.getParser().getContext());
1519 pValueExp
->parseNodeToPredicateStr( aColumnName
,
1521 rController
.getNumberFormatter(),
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
) ))
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
,
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
,
1570 else if ( SQL_ISRULE(pCondition
->getChild(0), column_ref
) )
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
)) )
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.
1600 //------------------------------------------------------------------------------
1601 SqlParseError
AddFunctionCondition(OQueryDesignView
* _pView
,
1602 OSelectionBrowseBox
* _pSelectionBrw
,
1603 const ::connectivity::OSQLParseNode
* pCondition
,
1604 const sal_uInt16 nLevel
,
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
,
1627 rController
.getNumberFormatter(),
1628 _pView
->getLocale(),
1629 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
1630 &rController
.getParser().getContext());
1632 pFunction
->parseNodeToStr( aColumnName
,
1634 &rController
.getParser().getContext(),
1636 sal_True
); // quote is to true because we need quoted elements inside the function
1638 //pFunction->parseNodeToPredicateStr(aColumnName,
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());
1671 else if( eOk
!= ( eErrorCode
= FillDragInfo(_pView
,pParamNode
,aDragLeft
))
1672 && SQL_ISRULE(pParamNode
,num_value_exp
) )
1674 ::rtl::OUString sParameterValue
;
1675 pParamNode
->parseNodeToStr( sParameterValue
,
1677 &rController
.getParser().getContext());
1678 nFunctionType
|= FKT_NUMERIC
;
1679 aDragLeft
->SetField(sParameterValue
);
1682 aDragLeft
->SetFunctionType(nFunctionType
);
1684 aDragLeft
->SetGroupBy(sal_True
);
1685 sal_Int32 nIndex
= 0;
1686 aDragLeft
->SetFunction(aColumnName
.getToken(0,'(',nIndex
));
1690 // bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben
1691 aDragLeft
->SetField(aColumnName
);
1693 aDragLeft
->SetGroupBy(sal_True
);
1694 aDragLeft
->SetFunctionType(FKT_OTHER
|FKT_NUMERIC
);
1696 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1701 //------------------------------------------------------------------------------
1702 SqlParseError
ComparisonPredicate(OQueryDesignView
* _pView
,
1703 OSelectionBrowseBox
* _pSelectionBrw
,
1704 const ::connectivity::OSQLParseNode
* pCondition
,
1705 const sal_uInt16 nLevel
,
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
)))
1726 OQueryTableConnection
* pConn
= static_cast<OQueryTableConnection
*>(
1727 _pView
->getTableView()->GetTabConn(static_cast<OQueryTableWindow
*>(aDragLeft
->GetTabWindow()),
1728 static_cast<OQueryTableWindow
*>(aDragRight
->GetTabWindow()),
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() )
1746 sal_uInt32 nPos
= 0;
1747 if(SQL_ISRULE(pCondition
->getChild(0), column_ref
))
1752 // don't display the equal
1753 if (pCondition
->getChild(i
)->getNodeType() == SQL_NODE_EQUAL
)
1757 aCondition
= ParseCondition(rController
1759 ,_pView
->getDecimalSeparator()
1760 ,_pView
->getLocale()
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
1775 // take the opposite as we change the order
1777 aCondition
= aCondition
+ ::rtl::OUString::createFromAscii(">");
1779 case SQL_NODE_LESSEQ
:
1780 // take the opposite as we change the order
1782 aCondition
= aCondition
+ ::rtl::OUString::createFromAscii(">=");
1784 case SQL_NODE_GREAT
:
1785 // take the opposite as we change the order
1787 aCondition
= aCondition
+ ::rtl::OUString::createFromAscii("<");
1789 case SQL_NODE_GREATEQ
:
1790 // take the opposite as we change the order
1792 aCondition
= aCondition
+ ::rtl::OUString::createFromAscii("<=");
1799 Reference
< XConnection
> xConnection
= rController
.getConnection();
1800 if(xConnection
.is())
1802 Reference
< XDatabaseMetaData
> xMetaData
= xConnection
->getMetaData();
1804 pCondition
->getChild(i
)->parseNodeToPredicateStr(aCondition
,
1806 rController
.getNumberFormatter(),
1807 _pView
->getLocale(),
1808 static_cast<sal_Char
>(_pView
->getDecimalSeparator().toChar()),
1809 &rController
.getParser().getContext());
1815 if( eOk
== ( eErrorCode
= FillDragInfo(_pView
,pCondition
->getChild(nPos
),aDragLeft
)))
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
,
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);
1838 Reference
< XConnection
> xConnection
= rController
.getConnection();
1839 if(xConnection
.is())
1841 pLhs
->parseNodeToStr(aName
,
1843 &rController
.getParser().getContext(),
1846 aCondition
= pCondition
->getChild(1)->getTokenValue();
1847 pRhs
->parseNodeToPredicateStr(aCondition
,
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
);
1859 _pSelectionBrw
->AddCondition(aDragLeft
, aCondition
, nLevel
,bAddOrOnOneLine
);
1864 //------------------------------------------------------------------------------
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
) )
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
);
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
);
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
))
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
1941 if (pJoinNode
&& !InsertJoin(_pView
,pJoinNode
))
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
))
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
) )
1973 pJoinType
= pNode
->getChild(2);
1976 if (SQL_ISRULE(pJoinType
,join_type
) && SQL_ISTOKEN(pJoinType
->getChild(0),INNER
))
1978 eJoinType
= INNER_JOIN
;
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
;
1990 eJoinType
= FULL_JOIN
;
1992 if ( SQL_ISRULE(pNode
->getChild(4),join_condition
) )
1994 if ( InsertJoinConnection(_pView
,pNode
->getChild(4)->getChild(1), eJoinType
) != eOk
)
1998 else if ( SQL_ISRULE(pNode
, cross_union
) )
2000 eJoinType
= CROSS_JOIN
;
2001 pRightTableRef
= pNode
->getChild(pNode
->count() - 1);
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
)
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
);
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())
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();
2062 // now we have to insert the fields which aren't in the statement
2063 insertUnUsedFields(_pView
,_pSelectionBrw
);
2067 if ( !rController
.isEsacpeProcessing() ) // not allowed in this mode
2069 eErrorCode
= eNativeMode
;
2073 if ( !( SQL_ISRULE( pParseTree
, select_statement
) ) )
2075 eErrorCode
= eNoSelectStatement
;
2079 Reference
< XConnection
> xConnection
= rController
.getConnection();
2080 if ( !xConnection
.is() )
2082 DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" );
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
;
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
);
2120 OSL_VERIFY( xTableProps
->getPropertyValue( PROPERTY_NAME
) >>= sComposedName
);
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
);
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
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!");
2194 // Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt
2195 rController
.getUndoMgr()->Clear();
2196 _pSelectionBrw
->Invalidate();
2199 //------------------------------------------------------------------------------
2200 /** fillSelectSubList
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
;
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(
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),"*") )
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
);
2285 if ( SQL_ISRULE(pColumnRef
,select_sublist
) )
2287 eErrorCode
= fillSelectSubList(_pView
,pTabList
);
2291 if ( SQL_ISRULE(pColumnRef
,derived_column
) )
2293 if ( !xConnection
.is() )
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
,
2320 &rController
.getParser().getContext(),
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());
2355 ::rtl::OUString sFieldName
= aColumns
;
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
,
2363 &rController
.getParser().getContext(),
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
);
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(' '));
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
,
2397 &rController
.getParser().getContext(),
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
;
2425 DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" );
2431 eErrorCode
= eStatementTooComplex
;
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
,
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
);
2504 eErrorCode
= eColumnNotFound
;
2507 eErrorCode
= eColumnNotFound
;
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
);
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
,
2561 &rController
.getParser().getContext(),
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
);
2571 eErrorCode
= eColumnNotFound
;
2578 //------------------------------------------------------------------------------
2579 String
getParseErrorMessage( SqlParseError _eErrorCode
)
2585 nResId
= STR_QRY_ILLEGAL_JOIN
;
2587 case eStatementTooLong
:
2588 nResId
= STR_QRY_TOO_LONG_STATEMENT
;
2591 nResId
= STR_QRY_SYNTAX
;
2593 case eNoSelectStatement
:
2594 nResId
= STR_QRY_NOSELECT
;
2596 case eColumnInLikeNotFound
:
2597 nResId
= STR_QRY_SYNTAX
;
2599 case eNoColumnInLike
:
2600 nResId
= STR_QRY_SYNTAX
;
2602 case eColumnNotFound
:
2603 nResId
= STR_QRY_SYNTAX
;
2606 nResId
= STR_QRY_NATIVE
;
2608 case eTooManyTables
:
2609 nResId
= STR_QRY_TOO_MANY_TABLES
;
2611 case eTooManyConditions
:
2612 nResId
= STR_QRY_TOOMANYCOND
;
2614 case eTooManyColumns
:
2615 nResId
= STR_QRY_TOO_MANY_COLUMNS
;
2617 case eStatementTooComplex
:
2618 nResId
= STR_QRY_TOOCOMPLEX
;
2621 nResId
= STR_QRY_SYNTAX
;
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();
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
));
2664 // -----------------------------------------------------------------------------
2665 OQueryDesignView::~OQueryDesignView()
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();
2684 m_bInSplitHandler
= sal_True
;
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();
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();
2806 // -----------------------------------------------------------------------------
2807 sal_Bool
OQueryDesignView::isPasteAllowed()
2809 sal_Bool bAllowed
= sal_False
;
2810 if ( SELECTION
== m_eChildFocus
)
2811 bAllowed
= m_pSelectionBox
->isPasteAllowed();
2814 // -----------------------------------------------------------------------------
2815 sal_Bool
OQueryDesignView::isCopyAllowed()
2817 sal_Bool bAllowed
= sal_False
;
2818 if ( SELECTION
== m_eChildFocus
)
2819 bAllowed
= m_pSelectionBox
->isCopyAllowed();
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
);
2878 nWidth
= s_nDefaultWidth
;
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
);
2911 pFieldList
->InsertEntry(*aStrIter
);
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)
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();
2934 if ( m_pSelectionBox
&& m_pSelectionBox
->HasChildPathFocus() )
2935 m_eChildFocus
= SELECTION
;
2937 m_eChildFocus
= TABLEVIEW
;
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
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() )
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("( ");
3018 aTmp
+= ::rtl::OUString::createFromAscii(" )");
3019 if(aCriteriaListStr
.getLength())
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;
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
);
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
);
3091 // -----------------------------------------------------------------------------
3092 // -----------------------------------------------------------------------------
3093 void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId
,sal_Bool _bEnable
)
3098 case SID_QUERY_VIEW_FUNCTIONS
:
3099 nRow
= BROW_FUNCTION_ROW
;
3101 case SID_QUERY_VIEW_TABLES
:
3102 nRow
= BROW_TABLE_ROW
;
3104 case SID_QUERY_VIEW_ALIASES
:
3105 nRow
= BROW_COLUMNALIAS_ROW
;
3112 m_pSelectionBox
->SetRowVisible(nRow
,_bEnable
);
3113 m_pSelectionBox
->Invalidate();
3115 // -----------------------------------------------------------------------------
3116 sal_Bool
OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId
)
3121 case SID_QUERY_VIEW_FUNCTIONS
:
3122 nRow
= BROW_FUNCTION_ROW
;
3124 case SID_QUERY_VIEW_TABLES
:
3125 nRow
= BROW_TABLE_ROW
;
3127 case SID_QUERY_VIEW_ALIASES
:
3128 nRow
= BROW_COLUMNALIAS_ROW
;
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())
3156 Reference
< XConnection
> xConnection
= static_cast<OQueryController
&>(getController()).getConnection();
3157 if(!xConnection
.is())
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
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();
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
);
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(),
3207 ColumnValue::NULLABLE_UNKNOWN
,
3213 xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers());
3214 _rxColumn
= pColumn
;
3215 pColumn
->setFunction(sal_True
);
3216 pColumn
->setRealName(pEntry
->GetField());
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
,
3230 static_cast<OQueryController
&>(getController()).getNumberFormatter(),
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
) );
3274 *_pErrorInfo
= m_rController
.getError();
3278 m_rController
.displayError();
3282 catch ( const Exception
& )
3284 DBG_UNHANDLED_EXCEPTION();
3286 return eErrorCode
== eOk
;
3288 // -----------------------------------------------------------------------------