summaryrefslogtreecommitdiff
path: root/dbaccess/source/ui/querydesign/QueryDesignView.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/ui/querydesign/QueryDesignView.cxx')
-rw-r--r--dbaccess/source/ui/querydesign/QueryDesignView.cxx3300
1 files changed, 3300 insertions, 0 deletions
diff --git a/dbaccess/source/ui/querydesign/QueryDesignView.cxx b/dbaccess/source/ui/querydesign/QueryDesignView.cxx
new file mode 100644
index 000000000000..0eb7c09f29e9
--- /dev/null
+++ b/dbaccess/source/ui/querydesign/QueryDesignView.cxx
@@ -0,0 +1,3300 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_dbaccess.hxx"
+#ifndef DBAUI_QUERYDESIGNVIEW_HXX
+#include "QueryDesignView.hxx"
+#endif
+#ifndef DBAUI_QUERYTABLEVIEW_HXX
+#include "QueryTableView.hxx"
+#endif
+#ifndef DBAUI_QUERY_TABLEWINDOW_HXX
+#include "QTableWindow.hxx"
+#endif
+#ifndef _SV_TOOLBOX_HXX
+#include <vcl/toolbox.hxx>
+#endif
+#ifndef DBAUI_QUERYCONTROLLER_HXX
+#include "querycontroller.hxx"
+#endif
+#ifndef _SV_SPLIT_HXX
+#include <vcl/split.hxx>
+#endif
+#ifndef _UNDO_HXX
+#include <svl/undo.hxx>
+#endif
+#ifndef TOOLS_DIAGNOSE_EX_H
+#include <tools/diagnose_ex.h>
+#endif
+#ifndef DBAUI_QYDLGTAB_HXX
+#include "adtabdlg.hxx"
+#endif
+#ifndef _SV_SVAPP_HXX
+#include <vcl/svapp.hxx>
+#endif
+#ifndef _SV_COMBOBOX_HXX
+#include <vcl/combobox.hxx>
+#endif
+#ifndef _SV_MSGBOX_HXX
+#include <vcl/msgbox.hxx>
+#endif
+#ifndef DBACCESS_UI_BROWSER_ID_HXX
+#include "browserids.hxx"
+#endif
+#ifndef DBAUI_QUERYDESIGN_OSELECTIONBROWSEBOX_HXX
+#include "SelectionBrowseBox.hxx"
+#endif
+#ifndef _DBU_QRY_HRC_
+#include "dbu_qry.hrc"
+#endif
+#ifndef _UTL_CONFIGMGR_HXX_
+#include <unotools/configmgr.hxx>
+#endif
+#ifndef _COMPHELPER_TYPES_HXX_
+#include <comphelper/types.hxx>
+#endif
+#ifndef _CONNECTIVITY_DBTOOLS_HXX_
+#include <connectivity/dbtools.hxx>
+#endif
+#ifndef _DBHELPER_DBEXCEPTION_HXX_
+#include <connectivity/dbexception.hxx>
+#endif
+#ifndef _COM_SUN_STAR_I18N_XLOCALEDATA_HPP_
+#include <com/sun/star/i18n/XLocaleData.hpp>
+#endif
+#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
+#include <com/sun/star/sdbc/DataType.hpp>
+#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
+#include <com/sun/star/container/XNameAccess.hpp>
+#endif
+#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
+#include <com/sun/star/sdbc/ColumnValue.hpp>
+#endif
+#ifndef _CONNECTIVITY_PCOLUMN_HXX_
+#include <connectivity/PColumn.hxx>
+#endif
+#ifndef DBAUI_QUERYTABLECONNECTION_HXX
+#include "QTableConnection.hxx"
+#endif
+#ifndef DBAUI_CONNECTIONLINE_HXX
+#include "ConnectionLine.hxx"
+#endif
+#ifndef DBAUI_CONNECTIONLINEDATA_HXX
+#include "ConnectionLineData.hxx"
+#endif
+#ifndef DBAUI_QTABLECONNECTIONDATA_HXX
+#include "QTableConnectionData.hxx"
+#endif
+#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
+#include "dbustrings.hrc"
+#endif
+#ifndef _COMPHELPER_EXTRACT_HXX_
+#include <comphelper/extract.hxx>
+#endif
+#ifndef DBAUI_TOOLS_HXX
+#include "UITools.hxx"
+#endif
+#ifndef DBAUI_QUERYCONTAINERWINDOW_HXX
+#include "querycontainerwindow.hxx"
+#endif
+#ifndef DBAUI_QUERYTABLEVIEW_HXX
+#include "QueryTableView.hxx"
+#endif
+#ifndef _DBAUI_SQLMESSAGE_HXX_
+#include "sqlmessage.hxx"
+#endif
+#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
+#include <unotools/syslocale.hxx>
+#endif
+
+using namespace ::dbaui;
+using namespace ::utl;
+using namespace ::connectivity;
+using namespace ::dbtools;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+
+#define SQL_ISRULEOR2(pParseNode, e1,e2) ((pParseNode)->isRule() && (\
+ (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e1) || \
+ (pParseNode)->getRuleID() == OSQLParser::RuleID(OSQLParseNode::e2)))
+
+// here we define our functions used in the anonymous namespace to get our header file smaller
+// please look at the book LargeScale C++ to know why
+namespace
+{
+ static const ::rtl::OUString C_AND = ::rtl::OUString::createFromAscii(" AND ");
+ static const ::rtl::OUString C_OR = ::rtl::OUString::createFromAscii(" OR ");
+
+ // forward declarations
+ sal_Bool InsertJoin( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode);
+
+ SqlParseError InstallFields(OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pNode,
+ OJoinTableView::OTableWindowMap* pTabList );
+
+ SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot );
+
+ SqlParseError GetHavingCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot,
+ sal_uInt16& rLevel );
+
+ SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pParseRoot );
+
+ SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ sal_Bool bHaving,
+ bool _bAddOrOnOneLine);
+
+ //------------------------------------------------------------------------------
+ ::rtl::OUString quoteTableAlias(sal_Bool _bQuote, const ::rtl::OUString& _sAliasName, const ::rtl::OUString& _sQuote)
+ {
+ ::rtl::OUString sRet;
+ if ( _bQuote && _sAliasName.getLength() )
+ {
+ sRet = ::dbtools::quoteName(_sQuote,_sAliasName);
+ const static ::rtl::OUString sTableSeparater('.');
+ sRet += sTableSeparater;
+ }
+ return sRet;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString getTableRange(const OQueryDesignView* _pView,const ::connectivity::OSQLParseNode* _pTableRef)
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ ::rtl::OUString sTableRange;
+ if ( _pTableRef )
+ {
+ sTableRange = ::connectivity::OSQLParseNode::getTableRange(_pTableRef);
+ if ( !sTableRange.getLength() )
+ _pTableRef->parseNodeToStr(sTableRange,xConnection,NULL,sal_False,sal_False);
+ }
+ return sTableRange;
+ }
+ //------------------------------------------------------------------------------
+ void insertConnection(const OQueryDesignView* _pView,const EJoinType& _eJoinType,OTableFieldDescRef _aDragLeft,OTableFieldDescRef _aDragRight,bool _bNatural = false)
+ {
+ OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
+ OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>( pTableView->GetTabConn(static_cast<OTableWindow*>(_aDragLeft->GetTabWindow()),static_cast<OTableWindow*>(_aDragRight->GetTabWindow()),true));
+
+ if ( !pConn )
+ {
+ OQueryTableConnectionData* pInfoData = new OQueryTableConnectionData();
+ TTableConnectionData::value_type aInfoData(pInfoData);
+ pInfoData->InitFromDrag(_aDragLeft, _aDragRight);
+ pInfoData->SetJoinType(_eJoinType);
+
+ if ( _bNatural )
+ {
+ aInfoData->ResetConnLines();
+ pInfoData->setNatural(_bNatural);
+ try
+ {
+ Reference<XNameAccess> xReferencedTableColumns(aInfoData->getReferencedTable()->getColumns());
+ Sequence< ::rtl::OUString> aSeq = aInfoData->getReferencingTable()->getColumns()->getElementNames();
+ const ::rtl::OUString* pIter = aSeq.getConstArray();
+ const ::rtl::OUString* pEnd = pIter + aSeq.getLength();
+ for(;pIter != pEnd;++pIter)
+ {
+ if ( xReferencedTableColumns->hasByName(*pIter) )
+ aInfoData->AppendConnLine(*pIter,*pIter);
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+
+ OQueryTableConnection aInfo(pTableView, aInfoData);
+ // da ein OQueryTableConnection-Objekt nie den Besitz der uebergebenen Daten uebernimmt, sondern sich nur den Zeiger merkt,
+ // ist dieser Zeiger auf eine lokale Variable hier unkritisch, denn aInfoData und aInfo haben die selbe Lebensdauer
+ pTableView->NotifyTabConnection( aInfo );
+ }
+ else
+ {
+ ::rtl::OUString aSourceFieldName(_aDragLeft->GetField());
+ ::rtl::OUString aDestFieldName(_aDragRight->GetField());
+ // the connection could point on the other side
+ if(pConn->GetSourceWin() == _aDragRight->GetTabWindow())
+ {
+ ::rtl::OUString aTmp(aSourceFieldName);
+ aSourceFieldName = aDestFieldName;
+ aDestFieldName = aTmp;
+ }
+ pConn->GetData()->AppendConnLine( aSourceFieldName,aDestFieldName);
+ pConn->UpdateLineList();
+ // Modified-Flag
+ // SetModified();
+ // und neu zeichnen
+ pConn->RecalcLines();
+ // fuer das unten folgende Invalidate muss ich dieser neuen Connection erst mal die Moeglichkeit geben,
+ // ihr BoundingRect zu ermitteln
+ pConn->InvalidateConnection();
+ }
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString ParseCondition( OQueryController& rController
+ ,const ::connectivity::OSQLParseNode* pCondition
+ ,const ::rtl::OUString _sDecimal
+ ,const ::com::sun::star::lang::Locale& _rLocale
+ ,sal_uInt32 _nStartIndex)
+ {
+ ::rtl::OUString aCondition;
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( xConnection.is() )
+ {
+ sal_uInt32 nCount = pCondition->count();
+ for(sal_uInt32 i = _nStartIndex ; i < nCount ; ++i)
+ pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _rLocale,
+ static_cast<sal_Char>(_sDecimal.toChar()),
+ &rController.getParser().getContext());
+ }
+ return aCondition;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError FillOuterJoins(OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pTableRefList)
+ {
+ SqlParseError eErrorCode = eOk;
+ sal_uInt32 nCount = pTableRefList->count();
+ sal_Bool bError = sal_False;
+ for (sal_uInt32 i=0; !bError && i < nCount; ++i)
+ {
+ const ::connectivity::OSQLParseNode* pParseNode = pTableRefList->getChild(i);
+ const ::connectivity::OSQLParseNode* pJoinNode = NULL;
+
+ if ( SQL_ISRULE( pParseNode, qualified_join ) || SQL_ISRULE( pParseNode, joined_table ) || SQL_ISRULE( pParseNode, cross_union ) )
+ pJoinNode = pParseNode;
+ else if( SQL_ISRULE(pParseNode,table_ref)
+ && pParseNode->count() == 4 ) // '{' SQL_TOKEN_OJ joined_table '}'
+ pJoinNode = pParseNode->getChild(2);
+
+ if ( pJoinNode )
+ {
+ if ( !InsertJoin(_pView,pJoinNode) )
+ bError = sal_True;
+ }
+ }
+ // check if error occured
+ if ( bError )
+ eErrorCode = eIllegalJoin;
+
+ return eErrorCode;
+ }
+ // -----------------------------------------------------------------------------
+
+ /** FillDragInfo fills the field description out of the table
+ */
+ //------------------------------------------------------------------------------
+ SqlParseError FillDragInfo( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pColumnRef,
+ OTableFieldDescRef& _rDragInfo)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ sal_Bool bErg = sal_False;
+
+ ::rtl::OUString aTableRange,aColumnName;
+ sal_uInt16 nCntAccount;
+ ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
+ rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
+
+ if ( aTableRange.getLength() )
+ {
+ OQueryTableWindow* pSTW = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( aTableRange );
+ bErg = (pSTW && pSTW->ExistsField( aColumnName, _rDragInfo ) );
+ }
+ if ( !bErg )
+ {
+ bErg = static_cast<OQueryTableView*>(_pView->getTableView())->FindTableFromField(aColumnName, _rDragInfo, nCntAccount);
+ if ( !bErg )
+ bErg = _pView->HasFieldByAliasName(aColumnName, _rDragInfo);
+ }
+ if ( !bErg )
+ {
+ eErrorCode = eColumnNotFound;
+ String sError(ModuleRes(STR_QRY_COLUMN_NOT_FOUND));
+ sError.SearchAndReplaceAscii("$name$",aColumnName);
+ _pView->getController().appendError( sError );
+
+ try
+ {
+ Reference<XDatabaseMetaData> xMeta = _pView->getController().getConnection()->getMetaData();
+ if ( xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() )
+ _pView->getController().appendError( String( ModuleRes( STR_QRY_CHECK_CASESENSITIVE ) ) );
+ }
+ catch(Exception&)
+ {
+ }
+ }
+
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildJoinCriteria( const Reference< XConnection>& _xConnection,
+ OConnectionLineDataVec* pLineDataList,
+ OQueryTableConnectionData* pData)
+ {
+ ::rtl::OUStringBuffer aCondition;
+ if ( _xConnection.is() )
+ {
+ OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
+ OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
+ const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+ const ::rtl::OUString sEqual(RTL_CONSTASCII_USTRINGPARAM(" = "));
+
+ for(;aIter != aEnd;++aIter)
+ {
+ OConnectionLineDataRef pLineData = *aIter;
+ if(aCondition.getLength())
+ aCondition.append(C_AND);
+ aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_FROM),aQuote));
+ aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_FROM) ));
+ aCondition.append(sEqual);
+ aCondition.append(quoteTableAlias(sal_True,pData->GetAliasName(JTCS_TO),aQuote));
+ aCondition.append(::dbtools::quoteName(aQuote, pLineData->GetFieldName(JTCS_TO) ));
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"Failure while building Join criteria!");
+ }
+ }
+
+ return aCondition.makeStringAndClear();
+ }
+ //------------------------------------------------------------------------------
+ /** JoinCycle looks for a join cycle and append it to the string
+ @param _xConnection the connection
+ @param _pEntryConn the table connection which holds the data
+ @param _pEntryTabTo the corresponding table window
+ @param _rJoin the String which will contain the resulting string
+ */
+ void JoinCycle( const Reference< XConnection>& _xConnection,
+ OQueryTableConnection* _pEntryConn,
+ const OQueryTableWindow* _pEntryTabTo,
+ ::rtl::OUString& _rJoin )
+ {
+ OSL_ENSURE(_pEntryConn,"TableConnection can not be null!");
+
+ OQueryTableConnectionData* pData = static_cast< OQueryTableConnectionData*>(_pEntryConn->GetData().get());
+ if ( pData->GetJoinType() != INNER_JOIN && _pEntryTabTo->ExistsAVisitedConn() )
+ {
+ sal_Bool bBrace = sal_False;
+ if(_rJoin.getLength() && _rJoin.lastIndexOf(')') == (_rJoin.getLength()-1))
+ {
+ bBrace = sal_True;
+ _rJoin = _rJoin.replaceAt(_rJoin.getLength()-1,1,::rtl::OUString(' '));
+ }
+ (_rJoin += C_AND) += BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData);
+ if(bBrace)
+ _rJoin += ::rtl::OUString(')');
+ _pEntryConn->SetVisited(sal_True);
+ }
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildTable( const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* pEntryTab,
+ bool _bForce = false
+ )
+ {
+ ::rtl::OUString aDBName(pEntryTab->GetComposedName());
+
+ // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ if( _xConnection.is() )
+ {
+ try
+ {
+ Reference< XDatabaseMetaData > xMetaData = _xConnection->getMetaData();
+
+ ::rtl::OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( xMetaData, aDBName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
+ ::rtl::OUString aTableListStr = ::dbtools::composeTableNameForSelect( _xConnection, sCatalog, sSchema, sTable );
+
+ ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+ if ( _bForce || isAppendTableAliasEnabled( _xConnection ) || pEntryTab->GetAliasName() != aDBName )
+ {
+ aTableListStr += ::rtl::OUString::createFromAscii(" ");
+ if ( generateAsBeforeTableAlias( _xConnection ) )
+ aTableListStr += ::rtl::OUString::createFromAscii("AS ");
+ aTableListStr += ::dbtools::quoteName( aQuote, pEntryTab->GetAliasName() );
+ }
+ aDBName = aTableListStr;
+ }
+ catch(const SQLException&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ }
+ return aDBName;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const ::rtl::OUString& rLh,
+ const ::rtl::OUString& rRh,
+ OQueryTableConnectionData* pData)
+ {
+
+ String aErg(rLh);
+ if ( pData->isNatural() && pData->GetJoinType() != CROSS_JOIN )
+ aErg.AppendAscii(" NATURAL ");
+ switch(pData->GetJoinType())
+ {
+ case LEFT_JOIN:
+ aErg.AppendAscii(" LEFT OUTER ");
+ break;
+ case RIGHT_JOIN:
+ aErg.AppendAscii(" RIGHT OUTER ");
+ break;
+ case CROSS_JOIN:
+ OSL_ENSURE(!pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
+ aErg.AppendAscii(" CROSS ");
+ break;
+ case INNER_JOIN:
+ OSL_ENSURE(pData->isNatural(),"OQueryDesignView::BuildJoin: This should not happen!");
+ aErg.AppendAscii(" INNER ");
+ break;
+ default:
+ aErg.AppendAscii(" FULL OUTER ");
+ break;
+ }
+ aErg.AppendAscii("JOIN ");
+ aErg += String(rRh);
+ if ( CROSS_JOIN != pData->GetJoinType() && !pData->isNatural() )
+ {
+ aErg.AppendAscii(" ON ");
+ aErg += String(BuildJoinCriteria(_xConnection,pData->GetConnLineDataList(),pData));
+ }
+
+ return aErg;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ OQueryTableWindow* pLh,
+ OQueryTableWindow* pRh,
+ OQueryTableConnectionData* pData
+ )
+ {
+ bool bForce = pData->GetJoinType() == CROSS_JOIN || pData->isNatural();
+ return BuildJoin(_xConnection,BuildTable(_xConnection,pLh,bForce),BuildTable(_xConnection,pRh,bForce),pData);
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ const ::rtl::OUString &rLh,
+ OQueryTableWindow* pRh,
+ OQueryTableConnectionData* pData
+ )
+ {
+ return BuildJoin(_xConnection,rLh,BuildTable(_xConnection,pRh),pData);
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString BuildJoin( const Reference< XConnection>& _xConnection,
+ OQueryTableWindow* pLh,
+ const ::rtl::OUString &rRh,
+ OQueryTableConnectionData* pData
+ )
+ {
+ return BuildJoin(_xConnection,BuildTable(_xConnection,pLh),rRh,pData);
+ }
+ //------------------------------------------------------------------------------
+ void GetNextJoin( const Reference< XConnection>& _xConnection,
+ OQueryTableConnection* pEntryConn,
+ OQueryTableWindow* pEntryTabTo,
+ ::rtl::OUString &aJoin)
+ {
+ OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
+ if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
+ return;
+
+ // Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+
+ if(!aJoin.getLength())
+ {
+ OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ aJoin = BuildJoin(_xConnection,pEntryTabFrom,pEntryTabTo,pEntryConnData);
+ }
+ else if(pEntryTabTo == pEntryConn->GetDestWin())
+ {
+ aJoin = BuildJoin(_xConnection,aJoin,pEntryTabTo,pEntryConnData);
+ }
+ else if(pEntryTabTo == pEntryConn->GetSourceWin())
+ {
+ aJoin = BuildJoin(_xConnection,pEntryTabTo,aJoin,pEntryConnData);
+ }
+
+ pEntryConn->SetVisited(sal_True);
+
+ // first search for the "to" window
+ const ::std::vector<OTableConnection*>* pConnections = pEntryConn->GetParent()->getTableConnections();
+ ::std::vector<OTableConnection*>::const_iterator aIter = pConnections->begin();
+ ::std::vector<OTableConnection*>::const_iterator aEnd = pConnections->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
+ if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabTo || pNext->GetDestWin() == pEntryTabTo))
+ {
+ OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabTo ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
+ // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
+ JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
+ if(!pNext->IsVisited())
+ GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
+ }
+ }
+
+ // when nothing found found look for the "from" window
+ if(aIter == aEnd)
+ {
+ OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ aIter = pConnections->begin();
+ for(;aIter != aEnd;++aIter)
+ {
+ OQueryTableConnection* pNext = static_cast<OQueryTableConnection*>(*aIter);
+ if(!pNext->IsVisited() && (pNext->GetSourceWin() == pEntryTabFrom || pNext->GetDestWin() == pEntryTabFrom))
+ {
+ OQueryTableWindow* pEntryTab = pNext->GetSourceWin() == pEntryTabFrom ? static_cast<OQueryTableWindow*>(pNext->GetDestWin()) : static_cast<OQueryTableWindow*>(pNext->GetSourceWin());
+ // exists there a connection to a OQueryTableWindow that holds a connection that has been already visited
+ JoinCycle(_xConnection,pNext,pEntryTab,aJoin);
+ if(!pNext->IsVisited())
+ GetNextJoin(_xConnection,pNext,pEntryTab,aJoin);
+ }
+ }
+ }
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError InsertJoinConnection( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode,
+ const EJoinType& _eJoinType,
+ const ::connectivity::OSQLParseNode *pLeftTable,
+ const ::connectivity::OSQLParseNode *pRightTable)
+ {
+ SqlParseError eErrorCode = eOk;
+ if (pNode->count() == 3 && // Ausdruck is geklammert
+ SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pNode->getChild(2),")"))
+ {
+ eErrorCode = InsertJoinConnection(_pView,pNode->getChild(1), _eJoinType,pLeftTable,pRightTable);
+ }
+ else if (SQL_ISRULEOR2(pNode,search_condition,boolean_term) && // AND/OR-Verknuepfung:
+ pNode->count() == 3)
+ {
+ // nur AND Verknüpfung zulassen
+ if (!SQL_ISTOKEN(pNode->getChild(1),AND))
+ eErrorCode = eIllegalJoinCondition;
+ else if ( eOk == (eErrorCode = InsertJoinConnection(_pView,pNode->getChild(0), _eJoinType,pLeftTable,pRightTable)) )
+ eErrorCode = InsertJoinConnection(_pView,pNode->getChild(2), _eJoinType,pLeftTable,pRightTable);
+ }
+ else if (SQL_ISRULE(pNode,comparison_predicate))
+ {
+ // only the comparison of columns is allowed
+ DBG_ASSERT(pNode->count() == 3,"OQueryDesignView::InsertJoinConnection: Fehler im Parse Tree");
+ if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
+ SQL_ISRULE(pNode->getChild(2),column_ref) &&
+ pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
+ {
+ String sError(ModuleRes(STR_QRY_JOIN_COLUMN_COMPARE));
+ _pView->getController().appendError( sError );
+ return eIllegalJoin;
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ if ( eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(0),aDragLeft)) ||
+ eOk != ( eErrorCode = FillDragInfo(_pView,pNode->getChild(2),aDragRight)))
+ return eErrorCode;
+
+ if ( pLeftTable )
+ {
+ OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pLeftTable->getByRule(OSQLParseNode::table_ref) ));
+ // OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTable->getByRule(OSQLParseNode::table_ref) ));
+ if ( pLeftWindow == aDragLeft->GetTabWindow() )
+ insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
+ else
+ insertConnection(_pView,_eJoinType,aDragRight,aDragLeft);
+ }
+ else
+ insertConnection(_pView,_eJoinType,aDragLeft,aDragRight);
+ }
+ else
+ eErrorCode = eIllegalJoin;
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ sal_Bool GetInnerJoinCriteria( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pCondition)
+ {
+ return InsertJoinConnection(_pView,pCondition, INNER_JOIN,NULL,NULL) != eOk;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString GenerateSelectList( const OQueryDesignView* _pView,
+ OTableFields& _rFieldList,
+ sal_Bool bAlias)
+ {
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ if ( !xConnection.is() )
+ return ::rtl::OUString();
+
+ ::rtl::OUStringBuffer aTmpStr,aFieldListStr;
+
+ sal_Bool bAsterix = sal_False;
+ int nVis = 0;
+ OTableFields::iterator aIter = _rFieldList.begin();
+ OTableFields::iterator aEnd = _rFieldList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ if ( pEntryField->IsVisible() )
+ {
+ if ( pEntryField->GetField().toChar() == '*' )
+ bAsterix = sal_True;
+ ++nVis;
+ }
+ }
+ if(nVis == 1)
+ bAsterix = sal_False;
+
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+
+ OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
+
+ const static ::rtl::OUString sFieldSeparator(RTL_CONSTASCII_USTRINGPARAM(", "));
+ const static ::rtl::OUString s_sAs(RTL_CONSTASCII_USTRINGPARAM(" AS "));
+
+ aIter = _rFieldList.begin();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ ::rtl::OUString rFieldName = pEntryField->GetField();
+ if ( rFieldName.getLength() && pEntryField->IsVisible() )
+ {
+ aTmpStr = ::rtl::OUString();
+ const ::rtl::OUString rAlias = pEntryField->GetAlias();
+ const ::rtl::OUString rFieldAlias = pEntryField->GetFieldAlias();
+
+ aTmpStr.append(quoteTableAlias((bAlias || bAsterix),rAlias,aQuote));
+
+ // if we have a none numeric field, the table alias could be in the name
+ // otherwise we are not allowed to do this (e.g. 0.1 * PRICE )
+ if ( !pEntryField->isOtherFunction() )
+ {
+ // we have to look if we have alias.* here but before we have to check if the column doesn't already exist
+ String sTemp = rFieldName;
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+ OJoinTableView::OTableWindowMap::iterator tableIter = pTabList->begin();
+ OJoinTableView::OTableWindowMap::iterator tableEnd = pTabList->end();
+ sal_Bool bFound = sal_False;
+ for(;!bFound && tableIter != tableEnd ;++tableIter)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(tableIter->second);
+
+ bFound = pTabWin->ExistsField( rFieldName, aInfo );
+ if ( bFound )
+ rFieldName = aInfo->GetField();
+ }
+ if ( ( rFieldName.toChar() != '*' ) && ( rFieldName.indexOf( aQuote ) == -1 ) )
+ {
+ OSL_ENSURE(pEntryField->GetTable().getLength(),"No table field name!");
+ aTmpStr.append(::dbtools::quoteName(aQuote, rFieldName));
+ }
+ else
+ aTmpStr.append(rFieldName);
+ }
+ else
+ aTmpStr.append(rFieldName);
+
+ if ( pEntryField->isAggreateFunction() )
+ {
+ DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
+ ::rtl::OUStringBuffer aTmpStr2( pEntryField->GetFunction());
+ aTmpStr2.appendAscii("(");
+ aTmpStr2.append(aTmpStr.makeStringAndClear());
+ aTmpStr2.appendAscii(")");
+ aTmpStr = aTmpStr2;
+ }
+
+ if (rFieldAlias.getLength() &&
+ (rFieldName.toChar() != '*' ||
+ pEntryField->isNumericOrAggreateFunction() ||
+ pEntryField->isOtherFunction()))
+ {
+ aTmpStr.append(s_sAs);
+ aTmpStr.append(::dbtools::quoteName(aQuote, rFieldAlias));
+ }
+ aFieldListStr.append(aTmpStr.makeStringAndClear());
+ aFieldListStr.append(sFieldSeparator);
+ }
+ }
+ if(aFieldListStr.getLength())
+ aFieldListStr.setLength(aFieldListStr.getLength()-2);
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"Failure while building select list!");
+ }
+ return aFieldListStr.makeStringAndClear();
+ }
+ //------------------------------------------------------------------------------
+ sal_Bool GenerateCriterias( OQueryDesignView* _pView,
+ ::rtl::OUStringBuffer& rRetStr,
+ ::rtl::OUStringBuffer& rHavingStr,
+ OTableFields& _rFieldList,
+ sal_Bool bMulti )
+ {
+ // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
+ sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
+
+ ::rtl::OUString aFieldName,aCriteria,aWhereStr,aHavingStr,aWork/*,aOrderStr*/;
+ // Zeilenweise werden die Ausdr"ucke mit AND verknuepft
+ sal_uInt16 nMaxCriteria = 0;
+ OTableFields::iterator aIter = _rFieldList.begin();
+ OTableFields::iterator aEnd = _rFieldList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ nMaxCriteria = ::std::max<sal_uInt16>(nMaxCriteria,(sal_uInt16)(*aIter)->GetCriteria().size());
+ }
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(_pView->getController()).getConnection();
+ if(!xConnection.is())
+ return FALSE;
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+ const IParseContext& rContext = static_cast<OQueryController&>(_pView->getController()).getParser().getContext();
+
+ for (sal_uInt16 i=0 ; i < nMaxCriteria ; i++)
+ {
+ aHavingStr = aWhereStr = ::rtl::OUString();
+
+ for(aIter = _rFieldList.begin();aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ aFieldName = pEntryField->GetField();
+
+ if (!aFieldName.getLength())
+ continue;
+ aCriteria = pEntryField->GetCriteria( i );
+ if ( aCriteria.getLength() )
+ {
+ // * is not allowed to contain any filter, only when used in combination an aggregate function
+ if ( aFieldName.toChar() == '*' && pEntryField->isNoneFunction() )
+ {
+ // only show the messagebox the first time
+ if (!bCritsOnAsterikWarning)
+ ErrorBox(_pView, ModuleRes( ERR_QRY_CRITERIA_ON_ASTERISK)).Execute();
+ bCritsOnAsterikWarning = sal_True;
+ continue;
+ }
+ aWork = ::rtl::OUString();
+
+
+ aWork += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
+
+ if ( (pEntryField->GetFunctionType() & (FKT_OTHER|FKT_NUMERIC)) || (aFieldName.toChar() == '*') )
+ aWork += aFieldName;
+ else
+ aWork += ::dbtools::quoteName(aQuote, aFieldName);
+
+ if ( pEntryField->isAggreateFunction() || pEntryField->IsGroupBy() )
+ {
+ if (!aHavingStr.getLength()) // noch keine Kriterien
+ aHavingStr += ::rtl::OUString('('); // Klammern
+ else
+ aHavingStr += C_AND;
+
+ if ( pEntryField->isAggreateFunction() )
+ {
+ OSL_ENSURE(pEntryField->GetFunction().getLength(),"No function name for aggregate given!");
+ aHavingStr += pEntryField->GetFunction();
+ aHavingStr += ::rtl::OUString('('); // Klammern
+ aHavingStr += aWork;
+ aHavingStr += ::rtl::OUString(')'); // Klammern
+ }
+ else
+ aHavingStr += aWork;
+
+ ::rtl::OUString aTmp = aCriteria;
+ ::rtl::OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
+ if (pParseNode.get())
+ {
+ if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
+ pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
+ ::rtl::OUString sHavingStr = aHavingStr;
+
+ sal_uInt32 nCount = pParseNode->count();
+ for( sal_uInt32 node = 1 ; node < nCount ; ++node)
+ pParseNode->getChild(node)->parseNodeToStr( sHavingStr,
+ xConnection,
+ &rContext,
+ sal_False,
+ !pEntryField->isOtherFunction());
+ aHavingStr = sHavingStr;
+ }
+ else
+ aHavingStr += aCriteria;
+ }
+ else
+ {
+ if ( !aWhereStr.getLength() ) // noch keine Kriterien
+ aWhereStr += ::rtl::OUString('('); // Klammern
+ else
+ aWhereStr += C_AND;
+
+ aWhereStr += ::rtl::OUString(' ');
+ // aCriteria could have some german numbers so I have to be sure here
+ ::rtl::OUString aTmp = aCriteria;
+ ::rtl::OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode( _pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
+ if (pParseNode.get())
+ {
+ if (bMulti && !(pEntryField->isOtherFunction() || (aFieldName.toChar() == '*')))
+ pParseNode->replaceNodeValue(pEntryField->GetAlias(),aFieldName);
+ ::rtl::OUString aWhere = aWhereStr;
+ pParseNode->parseNodeToStr( aWhere,
+ xConnection,
+ &rContext,
+ sal_False,
+ !pEntryField->isOtherFunction() );
+ aWhereStr = aWhere;
+ }
+ else
+ {
+ aWhereStr += aWork;
+ aWhereStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("="));
+ aWhereStr += aCriteria;
+ }
+ }
+ }
+ // nur einmal für jedes Feld
+ else if ( !i && pEntryField->isCondition() )
+ {
+ if (!aWhereStr.getLength()) // noch keine Kriterien
+ aWhereStr += ::rtl::OUString('('); // Klammern
+ else
+ aWhereStr += C_AND;
+ aWhereStr += pEntryField->GetField();
+ }
+ }
+ if (aWhereStr.getLength())
+ {
+ aWhereStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
+ if (rRetStr.getLength()) // schon Feldbedingungen ?
+ rRetStr.append(C_OR);
+ else // Klammern auf fuer 'OR' Zweig
+ rRetStr.append(sal_Unicode('('));
+ rRetStr.append(aWhereStr);
+ }
+ if (aHavingStr.getLength())
+ {
+ aHavingStr += ::rtl::OUString(')'); // Klammern zu fuer 'AND' Zweig
+ if (rHavingStr.getLength()) // schon Feldbedingungen ?
+ rHavingStr.append(C_OR);
+ else // Klammern auf fuer 'OR' Zweig
+ rHavingStr.append(sal_Unicode('('));
+ rHavingStr.append(aHavingStr);
+ }
+ }
+
+ if (rRetStr.getLength())
+ rRetStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
+ if (rHavingStr.getLength())
+ rHavingStr.append(sal_Unicode(')')); // Klammern zu fuer 'OR' Zweig
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"Failure while building where clause!");
+ }
+ return sal_True;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError GenerateOrder( OQueryDesignView* _pView,
+ OTableFields& _rFieldList,
+ sal_Bool bMulti,
+ ::rtl::OUString& _rsRet)
+ {
+ const OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( !xConnection.is() )
+ return eNoConnection;
+
+ SqlParseError eErrorCode = eOk;
+
+ ::rtl::OUString aColumnName;
+ ::rtl::OUString aWorkStr;
+ try
+ {
+ const bool bColumnAliasInOrderBy = rController.getSdbMetaData().supportsColumnAliasInOrderBy();
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+ // * darf keine Filter enthalten : habe ich die entsprechende Warnung schon angezeigt ?
+ sal_Bool bCritsOnAsterikWarning = sal_False; // ** TMFS **
+ OTableFields::iterator aIter = _rFieldList.begin();
+ OTableFields::iterator aEnd = _rFieldList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ EOrderDir eOrder = pEntryField->GetOrderDir();
+
+ // nur wenn eine Sortierung und ein Tabellenname vorhanden ist-> erzeugen
+ // sonst werden die Expressions vom Order By im GenerateCriteria mit erzeugt
+ if ( eOrder != ORDER_NONE )
+ {
+ aColumnName = pEntryField->GetField();
+ if(aColumnName.toChar() == '*')
+ {
+ // die entsprechende MessageBox nur beim ersten mal anzeigen
+ if (!bCritsOnAsterikWarning)
+ ErrorBox(_pView, ModuleRes( ERR_QRY_ORDERBY_ON_ASTERISK)).Execute();
+ bCritsOnAsterikWarning = sal_True;
+ continue;
+ }
+
+ if ( bColumnAliasInOrderBy && pEntryField->GetFieldAlias().getLength() )
+ {
+ aWorkStr += ::dbtools::quoteName(aQuote, pEntryField->GetFieldAlias());
+ }
+ else if ( pEntryField->isNumericOrAggreateFunction() )
+ {
+ DBG_ASSERT(pEntryField->GetFunction().getLength(),"Functionname darf hier nicht leer sein! ;-(");
+ aWorkStr += pEntryField->GetFunction();
+ aWorkStr += ::rtl::OUString('(');
+ aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
+ // only quote column name when we don't have a numeric
+ if ( pEntryField->isNumeric() )
+ aWorkStr += aColumnName;
+ else
+ aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
+
+ aWorkStr += ::rtl::OUString(')');
+ }
+ else if ( pEntryField->isOtherFunction() )
+ {
+ aWorkStr += aColumnName;
+ }
+ else
+ {
+ aWorkStr += quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
+ aWorkStr += ::dbtools::quoteName(aQuote, aColumnName);
+ }
+ aWorkStr += ::rtl::OUString(' ');
+ aWorkStr += String::CreateFromAscii( ";ASC;DESC" ).GetToken( (USHORT)eOrder );
+ aWorkStr += ::rtl::OUString(',');
+ }
+ }
+
+ {
+ String sTemp(aWorkStr);
+ sTemp.EraseTrailingChars( ',' );
+ aWorkStr = sTemp;
+ }
+
+ if ( aWorkStr.getLength() )
+ {
+ const sal_Int32 nMaxOrder = xMetaData->getMaxColumnsInOrderBy();
+ String sToken(aWorkStr);
+ if ( nMaxOrder && nMaxOrder < sToken.GetTokenCount(',') )
+ eErrorCode = eStatementTooLong;
+ else
+ {
+ _rsRet = ::rtl::OUString::createFromAscii(" ORDER BY ");
+ _rsRet += aWorkStr;
+ }
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"Failure while building group by!");
+ }
+
+ return eErrorCode;
+ }
+
+ //------------------------------------------------------------------------------
+ void GenerateInnerJoinCriterias(const Reference< XConnection>& _xConnection,
+ ::rtl::OUString& _rJoinCrit,
+ const ::std::vector<OTableConnection*>* _pConnList)
+ {
+ ::std::vector<OTableConnection*>::const_iterator aIter = _pConnList->begin();
+ ::std::vector<OTableConnection*>::const_iterator aEnd = _pConnList->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ const OQueryTableConnection* pEntryConn = static_cast<const OQueryTableConnection*>(*aIter);
+ OQueryTableConnectionData* pEntryConnData = static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get());
+ if ( pEntryConnData->GetJoinType() == INNER_JOIN && !pEntryConnData->isNatural() )
+ {
+ if(_rJoinCrit.getLength())
+ _rJoinCrit += C_AND;
+ _rJoinCrit += BuildJoinCriteria(_xConnection,pEntryConnData->GetConnLineDataList(),pEntryConnData);
+ }
+ }
+ }
+ //------------------------------------------------------------------------------
+ void searchAndAppendName(const Reference< XConnection>& _xConnection,
+ const OQueryTableWindow* _pTableWindow,
+ ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess>& _rTableNames,
+ ::rtl::OUString& _rsTableListStr
+ )
+ {
+ ::rtl::OUString sTabName(BuildTable(_xConnection,_pTableWindow));
+
+ if(_rTableNames.find(sTabName) == _rTableNames.end())
+ {
+ _rTableNames[sTabName] = sal_True;
+ _rsTableListStr += sTabName;
+ _rsTableListStr += ::rtl::OUString(',');
+ }
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString GenerateFromClause( const Reference< XConnection>& _xConnection,
+ const OQueryTableView::OTableWindowMap* pTabList,
+ const ::std::vector<OTableConnection*>* pConnList
+ )
+ {
+
+ ::rtl::OUString aTableListStr;
+ // wird gebraucht um sicher zustelllen das eine Tabelle nicht doppelt vorkommt
+ ::std::map< ::rtl::OUString,sal_Bool,::comphelper::UStringMixLess> aTableNames;
+
+ // generate outer join clause in from
+ if(!pConnList->empty())
+ {
+ ::std::vector<OTableConnection*>::const_iterator aIter = pConnList->begin();
+ ::std::vector<OTableConnection*>::const_iterator aEnd = pConnList->end();
+ ::std::map<OTableWindow*,sal_Int32> aConnectionCount;
+ for(;aIter != aEnd;++aIter)
+ {
+ static_cast<OQueryTableConnection*>(*aIter)->SetVisited(sal_False);
+ if ( aConnectionCount.find((*aIter)->GetSourceWin()) == aConnectionCount.end() )
+ aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetSourceWin(),0));
+ else
+ aConnectionCount[(*aIter)->GetSourceWin()]++;
+ if ( aConnectionCount.find((*aIter)->GetDestWin()) == aConnectionCount.end() )
+ aConnectionCount.insert(::std::map<OTableWindow*,sal_Int32>::value_type((*aIter)->GetDestWin(),0));
+ else
+ aConnectionCount[(*aIter)->GetDestWin()]++;
+ }
+ ::std::multimap<sal_Int32 , OTableWindow*> aMulti;
+ ::std::map<OTableWindow*,sal_Int32>::iterator aCountIter = aConnectionCount.begin();
+ ::std::map<OTableWindow*,sal_Int32>::iterator aCountEnd = aConnectionCount.end();
+ for(;aCountIter != aCountEnd;++aCountIter)
+ {
+ aMulti.insert(::std::multimap<sal_Int32 , OTableWindow*>::value_type(aCountIter->second,aCountIter->first));
+ }
+
+ const sal_Bool bUseEscape = ::dbtools::getBooleanDataSourceSetting( _xConnection, PROPERTY_OUTERJOINESCAPE );
+ ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aRIter = aMulti.rbegin();
+ ::std::multimap<sal_Int32 , OTableWindow*>::reverse_iterator aREnd = aMulti.rend();
+ for(;aRIter != aREnd;++aRIter)
+ {
+ ::std::vector<OTableConnection*>::const_iterator aConIter = aRIter->second->getTableView()->getTableConnections(aRIter->second);
+ for(;aConIter != aEnd;++aConIter)
+ {
+ OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aConIter);
+ if(!pEntryConn->IsVisited() && pEntryConn->GetSourceWin() == aRIter->second )
+ {
+ ::rtl::OUString aJoin;
+ GetNextJoin(_xConnection,pEntryConn,static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),aJoin);
+
+ if(aJoin.getLength())
+ {
+ // insert tables into table list to avoid double entries
+ OQueryTableWindow* pEntryTabFrom = static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin());
+ OQueryTableWindow* pEntryTabTo = static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin());
+
+ ::rtl::OUString sTabName(BuildTable(_xConnection,pEntryTabFrom));
+ if(aTableNames.find(sTabName) == aTableNames.end())
+ aTableNames[sTabName] = sal_True;
+ sTabName = BuildTable(_xConnection,pEntryTabTo);
+ if(aTableNames.find(sTabName) == aTableNames.end())
+ aTableNames[sTabName] = sal_True;
+
+ ::rtl::OUString aStr;
+ switch(static_cast<OQueryTableConnectionData*>(pEntryConn->GetData().get())->GetJoinType())
+ {
+ case LEFT_JOIN:
+ case RIGHT_JOIN:
+ case FULL_JOIN:
+ {
+ // create outer join
+ if ( bUseEscape )
+ aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("{ OJ "));
+ aStr += aJoin;
+ if ( bUseEscape )
+ aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" }"));
+ }
+ break;
+ default:
+ aStr += aJoin;
+ break;
+ }
+ aStr += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(","));
+ aTableListStr += aStr;
+ }
+ }
+ }
+ }
+
+ // and now all inner joins
+ aIter = pConnList->begin();
+ for(;aIter != aEnd;++aIter)
+ {
+ OQueryTableConnection* pEntryConn = static_cast<OQueryTableConnection*>(*aIter);
+ if(!pEntryConn->IsVisited())
+ {
+ searchAndAppendName(_xConnection,
+ static_cast<OQueryTableWindow*>(pEntryConn->GetSourceWin()),
+ aTableNames,
+ aTableListStr);
+
+ searchAndAppendName(_xConnection,
+ static_cast<OQueryTableWindow*>(pEntryConn->GetDestWin()),
+ aTableNames,
+ aTableListStr);
+ }
+ }
+ }
+ // all tables that haven't a connection to anyone
+ OQueryTableView::OTableWindowMap::const_iterator aTabIter = pTabList->begin();
+ OQueryTableView::OTableWindowMap::const_iterator aTabEnd = pTabList->end();
+ for(;aTabIter != aTabEnd;++aTabIter)
+ {
+ const OQueryTableWindow* pEntryTab = static_cast<const OQueryTableWindow*>(aTabIter->second);
+ if(!pEntryTab->ExistsAConn())
+ {
+ aTableListStr += BuildTable(_xConnection,pEntryTab);
+ aTableListStr += ::rtl::OUString(',');
+ }
+ }
+
+ if(aTableListStr.getLength())
+ aTableListStr = aTableListStr.replaceAt(aTableListStr.getLength()-1,1, ::rtl::OUString() );
+ return aTableListStr;
+ }
+ //------------------------------------------------------------------------------
+ ::rtl::OUString GenerateGroupBy(const OQueryDesignView* _pView,OTableFields& _rFieldList, sal_Bool bMulti )
+ {
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ const Reference< XConnection> xConnection = rController.getConnection();
+ if(!xConnection.is())
+ return ::rtl::OUString();
+
+ ::std::map< rtl::OUString,bool> aGroupByNames;
+
+ ::rtl::OUString aGroupByStr;
+ try
+ {
+ const Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ const ::rtl::OUString aQuote = xMetaData->getIdentifierQuoteString();
+
+ OTableFields::iterator aIter = _rFieldList.begin();
+ OTableFields::iterator aEnd = _rFieldList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ if ( pEntryField->IsGroupBy() )
+ {
+ DBG_ASSERT(pEntryField->GetField().getLength(),"Kein FieldName vorhanden!;-(");
+ ::rtl::OUString sGroupByPart = quoteTableAlias(bMulti,pEntryField->GetAlias(),aQuote);
+
+ // only quote the field name when it isn't calculated
+ if ( pEntryField->isNoneFunction() )
+ {
+ sGroupByPart += ::dbtools::quoteName(aQuote, pEntryField->GetField());
+ }
+ else
+ {
+ ::rtl::OUString aTmp = pEntryField->GetField();
+ ::rtl::OUString aErrorMsg;
+ Reference<XPropertySet> xColumn;
+ ::std::auto_ptr< ::connectivity::OSQLParseNode> pParseNode(_pView->getPredicateTreeFromEntry(pEntryField,aTmp,aErrorMsg,xColumn));
+ if (pParseNode.get())
+ {
+ ::rtl::OUString sGroupBy;
+ pParseNode->getChild(0)->parseNodeToStr( sGroupBy,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_False,
+ !pEntryField->isOtherFunction());
+ sGroupByPart += sGroupBy;
+ }
+ else
+ sGroupByPart += pEntryField->GetField();
+ }
+ if ( aGroupByNames.find(sGroupByPart) == aGroupByNames.end() )
+ {
+ aGroupByNames.insert(::std::map< rtl::OUString,bool>::value_type(sGroupByPart,true));
+ aGroupByStr += sGroupByPart;
+ aGroupByStr += ::rtl::OUString(',');
+ }
+ }
+ }
+ if ( aGroupByStr.getLength() )
+ {
+ aGroupByStr = aGroupByStr.replaceAt(aGroupByStr.getLength()-1,1, ::rtl::OUString(' ') );
+ ::rtl::OUString aGroupByStr2 = ::rtl::OUString::createFromAscii(" GROUP BY ");
+ aGroupByStr2 += aGroupByStr;
+ aGroupByStr = aGroupByStr2;
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"Failure while building group by!");
+ }
+ return aGroupByStr;
+ }
+ // -----------------------------------------------------------------------------
+ SqlParseError GetORCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel ,
+ sal_Bool bHaving = sal_False,
+ bool bAddOrOnOneLine = false);
+ // -----------------------------------------------------------------------------
+ SqlParseError GetSelectionCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pNode,
+ sal_uInt16& rLevel )
+ {
+ if (!SQL_ISRULE(pNode, select_statement))
+ return eNoSelectStatement;
+
+ // nyi: mehr Pruefung auf korrekte Struktur!
+ pNode = pNode ? pNode->getChild(3)->getChild(1) : NULL;
+ // no where clause found
+ if (!pNode || pNode->isLeaf())
+ return eOk;
+
+ // Naechster freier Satz ...
+ SqlParseError eErrorCode = eOk;
+ ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
+ if ( pCondition ) // no where clause
+ {
+ // now we have to chech the other conditions
+ // first make the logical easier
+ ::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
+ ::connectivity::OSQLParseNode *pNodeTmp = pNode->getChild(1);
+
+ ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+ ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+ // compress sort the criteria @see http://www.openoffice.org/issues/show_bug.cgi?id=24079
+ OSQLParseNode::compress(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+
+ // first extract the inner joins conditions
+ GetInnerJoinCriteria(_pView,pNodeTmp);
+ // now simplify again, join are checked in ComparisonPredicate
+ ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
+ pNodeTmp = pNode->getChild(1);
+
+ // it could happen that pCondition is not more valid
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pNodeTmp, rLevel);
+ }
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError GetANDCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel,
+ sal_Bool bHaving,
+ bool bAddOrOnOneLine);
+ //------------------------------------------------------------------------------
+ SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ sal_Bool bHaving,
+ bool bAddOrOnOneLine);
+ //------------------------------------------------------------------------------
+ SqlParseError GetORCriteria(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel ,
+ sal_Bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ // Runde Klammern um den Ausdruck
+ if (pCondition->count() == 3 &&
+ SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
+ {
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pCondition->getChild(1),nLevel,bHaving,bAddOrOnOneLine);
+ }
+ // oder Verknuepfung
+ // a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
+ else if (SQL_ISRULE(pCondition,search_condition))
+ {
+ for (int i = 0; i < 3 && eErrorCode == eOk ; i+=2)
+ {
+ const ::connectivity::OSQLParseNode* pChild = pCondition->getChild(i);
+ if ( SQL_ISRULE(pChild,search_condition) )
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pChild,nLevel,bHaving,bAddOrOnOneLine);
+ else
+ {
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pChild, nLevel,bHaving, i == 0 ? false : bAddOrOnOneLine);
+ if ( !bAddOrOnOneLine)
+ nLevel++;
+ }
+ }
+ }
+ else
+ eErrorCode = GetANDCriteria( _pView,_pSelectionBrw,pCondition, nLevel, bHaving,bAddOrOnOneLine );
+
+ return eErrorCode;
+ }
+ //--------------------------------------------------------------------------------------------------
+ bool CheckOrCriteria(const ::connectivity::OSQLParseNode* _pCondition,::connectivity::OSQLParseNode* _pFirstColumnRef)
+ {
+ bool bRet = true;
+ ::connectivity::OSQLParseNode* pFirstColumnRef = _pFirstColumnRef;
+ for (int i = 0; i < 3 && bRet; i+=2)
+ {
+ const ::connectivity::OSQLParseNode* pChild = _pCondition->getChild(i);
+ if ( SQL_ISRULE(pChild,search_condition) )
+ bRet = CheckOrCriteria(pChild,pFirstColumnRef);
+ else
+ {
+ // this is a simple way to test columns are the same, may be we have to adjust this algo a little bit in future. :-)
+ ::connectivity::OSQLParseNode* pSecondColumnRef = pChild->getByRule(::connectivity::OSQLParseNode::column_ref);
+ if ( pFirstColumnRef && pSecondColumnRef )
+ bRet = *pFirstColumnRef == *pSecondColumnRef;
+ else if ( !pFirstColumnRef )
+ pFirstColumnRef = pSecondColumnRef;
+ }
+ }
+ return bRet;
+ }
+ //--------------------------------------------------------------------------------------------------
+ SqlParseError GetANDCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ sal_uInt16& nLevel,
+ sal_Bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ const ::com::sun::star::lang::Locale aLocale = _pView->getLocale();
+ const ::rtl::OUString sDecimal = _pView->getDecimalSeparator();
+
+ // ich werde ein paar Mal einen gecasteten Pointer auf meinen ::com::sun::star::sdbcx::Container brauchen
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ SqlParseError eErrorCode = eOk;
+
+ // Runde Klammern
+ if (SQL_ISRULE(pCondition,boolean_primary))
+ {
+ // check if we have to put the or criteria on one line.
+ const ::connectivity::OSQLParseNode* pSearchCondition = pCondition->getChild(1);
+ bool bMustAddOrOnOneLine = CheckOrCriteria(pSearchCondition,NULL);
+ if ( SQL_ISRULE( pSearchCondition, search_condition) ) // we have a or
+ {
+ _pSelectionBrw->DuplicateConditionLevel( nLevel);
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(0), nLevel,bHaving,bMustAddOrOnOneLine );
+ ++nLevel;
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition->getChild(2), nLevel,bHaving,bMustAddOrOnOneLine );
+ }
+ else
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSearchCondition, nLevel,bHaving,bMustAddOrOnOneLine );
+ }
+ // Das erste Element ist (wieder) eine AND-Verknuepfung
+ else if ( SQL_ISRULE(pCondition,boolean_term) )
+ {
+ OSL_ENSURE(pCondition->count() == 3,"Illegal definifiton of boolean_term");
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(0), nLevel,bHaving,bAddOrOnOneLine );
+ if ( eErrorCode == eOk )
+ eErrorCode = GetANDCriteria(_pView,_pSelectionBrw,pCondition->getChild(2), nLevel,bHaving,bAddOrOnOneLine );
+ }
+ else if (SQL_ISRULE( pCondition, comparison_predicate))
+ {
+ eErrorCode = ComparisonPredicate(_pView,_pSelectionBrw,pCondition,nLevel,bHaving,bAddOrOnOneLine);
+ }
+ else if( SQL_ISRULE(pCondition,like_predicate) )
+ {
+ const ::connectivity::OSQLParseNode* pValueExp = pCondition->getChild(0);
+ if (SQL_ISRULE(pValueExp, column_ref ) )
+ {
+ ::rtl::OUString aColumnName;
+ ::rtl::OUString aCondition;
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( xConnection.is() )
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ // the international doesn't matter I have a string
+ pCondition->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ static_cast<sal_Char>(sDecimal.toChar()),
+ &rController.getParser().getContext());
+
+ pValueExp->parseNodeToPredicateStr( aColumnName,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ static_cast<sal_Char>(sDecimal.toChar()),
+ &rController.getParser().getContext());
+
+ // don't display the column name
+ aCondition = aCondition.copy(aColumnName.getLength());
+ aCondition = aCondition.trim();
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ if ( eOk == ( eErrorCode = FillDragInfo(_pView,pValueExp,aDragLeft) ))
+ {
+ if ( bHaving )
+ aDragLeft->SetGroupBy(sal_True);
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if(SQL_ISRULEOR2(pValueExp,general_set_fct ,set_fct_spec) ||
+ SQL_ISRULEOR2(pValueExp,position_exp,extract_exp) ||
+ SQL_ISRULEOR2(pValueExp,fold,char_substring_fct) ||
+ SQL_ISRULEOR2(pValueExp,length_exp,char_value_fct))
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else
+ {
+ eErrorCode = eNoColumnInLike;
+ String sError(ModuleRes(STR_QRY_LIKE_LEFT_NO_COLUMN));
+ _pView->getController().appendError( sError );
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition,test_for_null,in_predicate)
+ || SQL_ISRULEOR2(pCondition,all_or_any_predicate,between_predicate))
+ {
+ if ( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) )
+ {
+ // parse condition
+ ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ if ( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) )
+ {
+ if ( bHaving )
+ aDragLeft->SetGroupBy(sal_True);
+ _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else
+ {
+ // Funktions-Bedingung parsen
+ ::rtl::OUString sCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,1);
+ Reference< XConnection> xConnection = rController.getConnection();
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ // the international doesn't matter I have a string
+ ::rtl::OUString sName;
+ pCondition->getChild(0)->parseNodeToPredicateStr(sName,
+ xConnection,
+ rController.getNumberFormatter(),
+ aLocale,
+ static_cast<sal_Char>(sDecimal.toChar()),
+ &rController.getParser().getContext());
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(sName);
+ aDragLeft->SetFunctionType(FKT_OTHER);
+
+ if ( bHaving )
+ aDragLeft->SetGroupBy(sal_True);
+ _pSelectionBrw->AddCondition(aDragLeft, sCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition,existence_test,unique_test) )
+ {
+ // Funktions-Bedingung parsen
+ ::rtl::OUString aCondition = ParseCondition(rController,pCondition,sDecimal,aLocale,0);
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(aCondition);
+ aDragLeft->SetFunctionType(FKT_CONDITION);
+
+ eErrorCode = _pSelectionBrw->InsertField(aDragLeft,BROWSER_INVALIDID,sal_False,sal_True).isValid() ? eOk : eTooManyColumns;
+ }
+ else //! TODO not supported yet
+ eErrorCode = eStatementTooComplex;
+ // Fehler einfach weiterreichen.
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError AddFunctionCondition(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ sal_Bool bHaving,
+ bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ OSQLParseNode* pFunction = pCondition->getChild(0);
+
+ OSL_ENSURE(SQL_ISRULEOR2(pFunction,general_set_fct ,set_fct_spec) ||
+ SQL_ISRULEOR2(pFunction,position_exp,extract_exp) ||
+ SQL_ISRULEOR2(pFunction,fold,char_substring_fct) ||
+ SQL_ISRULEOR2(pFunction,length_exp,char_value_fct),"Illegal call!");
+ ::rtl::OUString aCondition;
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+
+ ::rtl::OUString aColumnName;
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ pCondition->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ &rController.getParser().getContext());
+
+ pFunction->parseNodeToStr( aColumnName,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_True,
+ sal_True); // quote is to true because we need quoted elements inside the function
+ // i75557
+ //pFunction->parseNodeToPredicateStr(aColumnName,
+ // xConnection,
+ // rController.getNumberFormatter(),
+ // _pView->getLocale(),
+ // static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ // &rController.getParser().getContext());
+ // don't display the column name
+ aCondition = aCondition.copy(aColumnName.getLength());
+ aCondition = aCondition.trim();
+ if ( aCondition.indexOf('=',0) == 0 ) // ignore the equal sign
+ aCondition = aCondition.copy(1);
+
+
+ if ( SQL_ISRULE(pFunction, general_set_fct ) )
+ {
+ sal_Int32 nFunctionType = FKT_AGGREGATE;
+ OSQLParseNode* pParamNode = pFunction->getChild(pFunction->count()-2);
+ if ( pParamNode && pParamNode->getTokenValue().toChar() == '*' )
+ {
+ OJoinTableView::OTableWindowMap* pTabList = _pView->getTableView()->GetTabWinMap();
+ OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
+ OJoinTableView::OTableWindowMap::iterator aTabEnd = pTabList->end();
+ for(;aIter != aTabEnd;++aIter)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
+ if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aDragLeft ))
+ {
+ aDragLeft->SetAlias(String());
+ aDragLeft->SetTable(String());
+ break;
+ }
+ }
+ }
+ else if( eOk != ( eErrorCode = FillDragInfo(_pView,pParamNode,aDragLeft))
+ && SQL_ISRULE(pParamNode,num_value_exp) )
+ {
+ ::rtl::OUString sParameterValue;
+ pParamNode->parseNodeToStr( sParameterValue,
+ xConnection,
+ &rController.getParser().getContext());
+ nFunctionType |= FKT_NUMERIC;
+ aDragLeft->SetField(sParameterValue);
+ eErrorCode = eOk;
+ }
+ aDragLeft->SetFunctionType(nFunctionType);
+ if ( bHaving )
+ aDragLeft->SetGroupBy(sal_True);
+ sal_Int32 nIndex = 0;
+ aDragLeft->SetFunction(aColumnName.getToken(0,'(',nIndex));
+ }
+ else
+ {
+ // bei unbekannten Funktionen wird der gesamte Text in das Field gechrieben
+ aDragLeft->SetField(aColumnName);
+ if(bHaving)
+ aDragLeft->SetGroupBy(sal_True);
+ aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
+ }
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError ComparisonPredicate(OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode * pCondition,
+ const sal_uInt16 nLevel,
+ sal_Bool bHaving
+ ,bool bAddOrOnOneLine)
+ {
+ SqlParseError eErrorCode = eOk;
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ DBG_ASSERT(SQL_ISRULE( pCondition, comparison_predicate),"ComparisonPredicate: pCondition ist kein ComparisonPredicate");
+ if ( SQL_ISRULE(pCondition->getChild(0), column_ref )
+ || SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref) )
+ {
+ ::rtl::OUString aCondition;
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+
+ if ( SQL_ISRULE(pCondition->getChild(0), column_ref ) && SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
+ {
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ if (eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(0),aDragLeft)) ||
+ eOk != ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(2),aDragRight)))
+ return eErrorCode;
+
+ OQueryTableConnection* pConn = static_cast<OQueryTableConnection*>(
+ _pView->getTableView()->GetTabConn(static_cast<OQueryTableWindow*>(aDragLeft->GetTabWindow()),
+ static_cast<OQueryTableWindow*>(aDragRight->GetTabWindow()),
+ true));
+ if ( pConn )
+ {
+ OConnectionLineDataVec* pLineDataList = pConn->GetData()->GetConnLineDataList();
+ OConnectionLineDataVec::iterator aIter = pLineDataList->begin();
+ OConnectionLineDataVec::iterator aEnd = pLineDataList->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ if((*aIter)->GetSourceFieldName() == aDragLeft->GetField() ||
+ (*aIter)->GetDestFieldName() == aDragLeft->GetField() )
+ break;
+ }
+ if(aIter != aEnd)
+ return eOk;
+ }
+ }
+
+ sal_uInt32 nPos = 0;
+ if(SQL_ISRULE(pCondition->getChild(0), column_ref ))
+ {
+ nPos = 0;
+ sal_uInt32 i=1;
+
+ // don't display the equal
+ if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
+ i++;
+
+ // Bedingung parsen
+ aCondition = ParseCondition(rController
+ ,pCondition
+ ,_pView->getDecimalSeparator()
+ ,_pView->getLocale()
+ ,i);
+ }
+ else if( SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref ) )
+ {
+ nPos = pCondition->count()-1;
+
+ sal_Int32 i = static_cast<sal_Int32>(pCondition->count() - 2);
+ switch (pCondition->getChild(i)->getNodeType())
+ {
+ case SQL_NODE_EQUAL:
+ // don't display the equal
+ i--;
+ break;
+ case SQL_NODE_LESS:
+ // take the opposite as we change the order
+ i--;
+ aCondition = aCondition + ::rtl::OUString::createFromAscii(">");
+ break;
+ case SQL_NODE_LESSEQ:
+ // take the opposite as we change the order
+ i--;
+ aCondition = aCondition + ::rtl::OUString::createFromAscii(">=");
+ break;
+ case SQL_NODE_GREAT:
+ // take the opposite as we change the order
+ i--;
+ aCondition = aCondition + ::rtl::OUString::createFromAscii("<");
+ break;
+ case SQL_NODE_GREATEQ:
+ // take the opposite as we change the order
+ i--;
+ aCondition = aCondition + ::rtl::OUString::createFromAscii("<=");
+ break;
+ default:
+ break;
+ }
+
+ // go backward
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ for (; i >= 0; i--)
+ pCondition->getChild(i)->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ &rController.getParser().getContext());
+ }
+ }
+ // else ???
+
+
+ if( eOk == ( eErrorCode = FillDragInfo(_pView,pCondition->getChild(nPos),aDragLeft)))
+ {
+ if(bHaving)
+ aDragLeft->SetGroupBy(sal_True);
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ }
+ else if( SQL_ISRULEOR2(pCondition->getChild(0), set_fct_spec , general_set_fct ) )
+ {
+ AddFunctionCondition( _pView,
+ _pSelectionBrw,
+ pCondition,
+ nLevel,
+ bHaving,
+ bAddOrOnOneLine);
+ }
+ else // kann sich nur um einen Expr. Ausdruck handeln
+ {
+ ::rtl::OUString aName,aCondition;
+
+ ::connectivity::OSQLParseNode *pLhs = pCondition->getChild(0);
+ ::connectivity::OSQLParseNode *pRhs = pCondition->getChild(2);
+ // Feldnamen
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ pLhs->parseNodeToStr(aName,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_True);
+ // Kriterium
+ aCondition = pCondition->getChild(1)->getTokenValue();
+ pRhs->parseNodeToPredicateStr(aCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ &rController.getParser().getContext());
+ }
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetField(aName);
+ aDragLeft->SetFunctionType(FKT_OTHER|FKT_NUMERIC);
+ // und anh"angen
+ _pSelectionBrw->AddCondition(aDragLeft, aCondition, nLevel,bAddOrOnOneLine);
+ }
+ return eErrorCode;
+ }
+
+ //------------------------------------------------------------------------------
+ namespace
+ {
+ OQueryTableWindow* lcl_findColumnInTables( const ::rtl::OUString& _rColumName, const OJoinTableView::OTableWindowMap& _rTabList, OTableFieldDescRef& _rInfo )
+ {
+ OJoinTableView::OTableWindowMap::const_iterator aIter = _rTabList.begin();
+ OJoinTableView::OTableWindowMap::const_iterator aEnd = _rTabList.end();
+ for ( ; aIter != aEnd; ++aIter )
+ {
+ OQueryTableWindow* pTabWin = static_cast< OQueryTableWindow* >( aIter->second );
+ if ( pTabWin && pTabWin->ExistsField( _rColumName, _rInfo ) )
+ return pTabWin;
+ }
+ return NULL;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ void InsertColumnRef(const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode * pColumnRef,
+ ::rtl::OUString& aColumnName,
+ const ::rtl::OUString& aColumnAlias,
+ ::rtl::OUString& aTableRange,
+ OTableFieldDescRef& _raInfo,
+ OJoinTableView::OTableWindowMap* pTabList)
+ {
+
+ // Tabellennamen zusammen setzen
+ ::connectivity::OSQLParseTreeIterator& rParseIter = static_cast<OQueryController&>(_pView->getController()).getParseIterator();
+ rParseIter.getColumnRange( pColumnRef, aColumnName, aTableRange );
+
+ sal_Bool bFound(sal_False);
+ DBG_ASSERT(aColumnName.getLength(),"Columnname darf nicht leer sein");
+ if (!aTableRange.getLength())
+ {
+ // SELECT column, ...
+ bFound = NULL != lcl_findColumnInTables( aColumnName, *pTabList, _raInfo );
+ if ( bFound && ( aColumnName.toChar() != '*' ) )
+ _raInfo->SetFieldAlias(aColumnAlias);
+ }
+ else
+ {
+ // SELECT range.column, ...
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable(aTableRange);
+
+ if (pTabWin && pTabWin->ExistsField(aColumnName, _raInfo))
+ {
+ if(aColumnName.toChar() != '*')
+ _raInfo->SetFieldAlias(aColumnAlias);
+ bFound = sal_True;
+ }
+ }
+ if (!bFound)
+ {
+ _raInfo->SetTable(::rtl::OUString());
+ _raInfo->SetAlias(::rtl::OUString());
+ _raInfo->SetField(aColumnName);
+ _raInfo->SetFieldAlias(aColumnAlias); // nyi : hier ein fortlaufendes Expr_1, Expr_2 ...
+ _raInfo->SetFunctionType(FKT_OTHER);
+ }
+ }
+ //-----------------------------------------------------------------------------
+ sal_Bool checkJoinConditions( const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* _pNode )
+ {
+ const ::connectivity::OSQLParseNode* pJoinNode = NULL;
+ sal_Bool bRet = sal_True;
+ if (SQL_ISRULE(_pNode,qualified_join))
+ pJoinNode = _pNode;
+ else if (SQL_ISRULE(_pNode,table_ref)
+ && _pNode->count() == 3
+ && SQL_ISPUNCTUATION(_pNode->getChild(0),"(")
+ && SQL_ISPUNCTUATION(_pNode->getChild(2),")") ) // '(' joined_table ')'
+ pJoinNode = _pNode->getChild(1);
+ else if (! ( SQL_ISRULE(_pNode, table_ref) && _pNode->count() == 2) ) // table_node table_primary_as_range_column
+ bRet = sal_False;
+
+ if (pJoinNode && !InsertJoin(_pView,pJoinNode))
+ bRet = sal_False;
+ return bRet;
+ }
+ //-----------------------------------------------------------------------------
+ sal_Bool InsertJoin(const OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode *pNode)
+ {
+ DBG_ASSERT( SQL_ISRULE( pNode, qualified_join ) || SQL_ISRULE( pNode, joined_table ) || SQL_ISRULE( pNode, cross_union ),
+ "OQueryDesignView::InsertJoin: Fehler im Parse Tree");
+
+ if (SQL_ISRULE(pNode,joined_table))
+ return InsertJoin(_pView,pNode->getChild(1));
+
+ // first check the left and right side
+ const ::connectivity::OSQLParseNode* pRightTableRef = pNode->getChild(3); // table_ref
+ if ( SQL_ISRULE(pNode, qualified_join) && SQL_ISTOKEN(pNode->getChild(1),NATURAL) )
+ pRightTableRef = pNode->getChild(4); // table_ref
+
+ if ( !checkJoinConditions(_pView,pNode->getChild(0)) || !checkJoinConditions(_pView,pRightTableRef))
+ return sal_False;
+
+ // named column join wird später vieleicht noch implementiert
+ // SQL_ISRULE(pNode->getChild(4),named_columns_join)
+ EJoinType eJoinType = INNER_JOIN;
+ bool bNatural = false;
+ if ( SQL_ISRULE(pNode, qualified_join) )
+ {
+ ::connectivity::OSQLParseNode* pJoinType = pNode->getChild(1); // join_type
+ if ( SQL_ISTOKEN(pJoinType,NATURAL) )
+ {
+ bNatural = true;
+ pJoinType = pNode->getChild(2);
+ }
+
+ if (SQL_ISRULE(pJoinType,join_type) && SQL_ISTOKEN(pJoinType->getChild(0),INNER))
+ {
+ eJoinType = INNER_JOIN;
+ }
+ else
+ {
+ if (SQL_ISRULE(pJoinType,join_type)) // eine Ebene tiefer
+ pJoinType = pJoinType->getChild(0);
+
+ if (SQL_ISTOKEN(pJoinType->getChild(0),LEFT))
+ eJoinType = LEFT_JOIN;
+ else if(SQL_ISTOKEN(pJoinType->getChild(0),RIGHT))
+ eJoinType = RIGHT_JOIN;
+ else
+ eJoinType = FULL_JOIN;
+ }
+ if ( SQL_ISRULE(pNode->getChild(4),join_condition) )
+ {
+ if ( InsertJoinConnection(_pView,pNode->getChild(4)->getChild(1), eJoinType,pNode->getChild(0),pRightTableRef) != eOk )
+ return sal_False;
+ }
+ }
+ else if ( SQL_ISRULE(pNode, cross_union) )
+ {
+ eJoinType = CROSS_JOIN;
+ pRightTableRef = pNode->getChild(pNode->count() - 1);
+ }
+ else
+ return sal_False;
+
+ if ( eJoinType == CROSS_JOIN || bNatural )
+ {
+
+ OQueryTableWindow* pLeftWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pNode->getChild(0)) );
+ OQueryTableWindow* pRightWindow = static_cast<OQueryTableView*>(_pView->getTableView())->FindTable( getTableRange(_pView,pRightTableRef) );
+ OSL_ENSURE(pLeftWindow && pRightWindow,"Table Windows could not be found!");
+ if ( !pLeftWindow || !pRightWindow )
+ return sal_False;
+
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ aDragLeft->SetTabWindow(pLeftWindow);
+ aDragLeft->SetTable(pLeftWindow->GetTableName());
+ aDragLeft->SetAlias(pLeftWindow->GetAliasName());
+
+ OTableFieldDescRef aDragRight = new OTableFieldDesc();
+ aDragRight->SetTabWindow(pRightWindow);
+ aDragRight->SetTable(pRightWindow->GetTableName());
+ aDragRight->SetAlias(pRightWindow->GetAliasName());
+
+ insertConnection(_pView,eJoinType,aDragLeft,aDragRight,bNatural);
+ }
+
+
+ return sal_True;
+ }
+ //------------------------------------------------------------------------------
+ void insertUnUsedFields(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
+ {
+ // now we have to insert the fields which aren't in the statement
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ OTableFields& rUnUsedFields = rController.getUnUsedFields();
+ OTableFields::iterator aEnd = rUnUsedFields.end();
+ for(OTableFields::iterator aIter = rUnUsedFields.begin();aIter != aEnd;++aIter)
+ if(_pSelectionBrw->InsertField(*aIter,BROWSER_INVALIDID,sal_False,sal_False).isValid())
+ (*aIter) = NULL;
+ OTableFields().swap( rUnUsedFields );
+ }
+
+ //------------------------------------------------------------------------------
+ SqlParseError InitFromParseNodeImpl(OQueryDesignView* _pView,OSelectionBrowseBox* _pSelectionBrw)
+ {
+ SqlParseError eErrorCode = eOk;
+
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+
+ _pSelectionBrw->PreFill();
+ _pSelectionBrw->SetReadOnly(rController.isReadOnly());
+ _pSelectionBrw->Fill();
+
+
+ ::connectivity::OSQLParseTreeIterator& aIterator = rController.getParseIterator();
+ const ::connectivity::OSQLParseNode* pParseTree = aIterator.getParseTree();
+
+ do
+ {
+ if ( !pParseTree )
+ {
+ // now we have to insert the fields which aren't in the statement
+ insertUnUsedFields(_pView,_pSelectionBrw);
+ break;
+ }
+
+ if ( !rController.isEsacpeProcessing() ) // not allowed in this mode
+ {
+ eErrorCode = eNativeMode;
+ break;
+ }
+
+ if ( !( SQL_ISRULE( pParseTree, select_statement ) ) )
+ {
+ eErrorCode = eNoSelectStatement;
+ break;
+ }
+
+ Reference< XConnection> xConnection = rController.getConnection();
+ if ( !xConnection.is() )
+ {
+ DBG_ERROR( "InitFromParseNodeImpl: no connection? no connection!" );
+ break;
+ }
+
+ const OSQLTables& aMap = aIterator.getTables();
+ ::comphelper::UStringMixLess aTmp(aMap.key_comp());
+ ::comphelper::UStringMixEqual aKeyComp( aTmp.isCaseSensitive() );
+
+ Reference< XDatabaseMetaData > xMetaData = xConnection->getMetaData();
+ try
+ {
+ sal_Int32 nMax = xMetaData->getMaxTablesInSelect();
+ if ( nMax && nMax < (sal_Int32)aMap.size() )
+ {
+ eErrorCode = eTooManyTables;
+ break;
+ }
+
+ ::rtl::OUString sComposedName;
+ ::rtl::OUString aQualifierName;
+ ::rtl::OUString sAlias;
+
+ OQueryTableView* pTableView = static_cast<OQueryTableView*>(_pView->getTableView());
+ pTableView->clearLayoutInformation();
+ OSQLTables::const_iterator aIter = aMap.begin();
+ OSQLTables::const_iterator aEnd = aMap.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OSQLTable xTable = aIter->second;
+ Reference< XPropertySet > xTableProps( xTable, UNO_QUERY_THROW );
+
+ sAlias = aIter->first;
+
+ // check whether this is a query
+ Reference< XPropertySetInfo > xPSI = xTableProps->getPropertySetInfo();
+ bool bIsQuery = xPSI.is() && xPSI->hasPropertyByName( PROPERTY_COMMAND );
+
+ if ( bIsQuery )
+ OSL_VERIFY( xTableProps->getPropertyValue( PROPERTY_NAME ) >>= sComposedName );
+ else
+ {
+ sComposedName = ::dbtools::composeTableName( xMetaData, xTableProps, ::dbtools::eInDataManipulation, false, false, false );
+
+ // if the alias is the complete (composed) table, then shorten it
+ if ( aKeyComp( sComposedName, aIter->first ) )
+ {
+ ::rtl::OUString sCatalog, sSchema, sTable;
+ ::dbtools::qualifiedNameComponents( xMetaData, sComposedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
+ sAlias = sTable;
+ }
+ }
+
+ // find the existent window for this alias
+ OQueryTableWindow* pExistentWin = pTableView->FindTable( sAlias );
+ if ( !pExistentWin )
+ {
+ pTableView->AddTabWin( sComposedName, sAlias, sal_False ); // don't create data here
+ }
+ else
+ {
+ // there already exists a window for this alias ....
+ if ( !aKeyComp( pExistentWin->GetData()->GetComposedName(), sComposedName ) )
+ // ... but for another complete table name -> new window
+ pTableView->AddTabWin(sComposedName, sAlias);
+ }
+ }
+
+ // now delete the data for which we haven't any tablewindow
+ OJoinTableView::OTableWindowMap aTableMap(*pTableView->GetTabWinMap());
+ OJoinTableView::OTableWindowMap::iterator aIterTableMap = aTableMap.begin();
+ OJoinTableView::OTableWindowMap::iterator aIterTableEnd = aTableMap.end();
+ for(;aIterTableMap != aIterTableEnd;++aIterTableMap)
+ {
+ if(aMap.find(aIterTableMap->second->GetComposedName()) == aMap.end() &&
+ aMap.find(aIterTableMap->first) == aMap.end())
+ pTableView->RemoveTabWin(aIterTableMap->second);
+ }
+
+ if ( eOk == (eErrorCode = FillOuterJoins(_pView,pParseTree->getChild(3)->getChild(0)->getChild(1))) )
+ {
+ // check if we have a distinct statement
+ if(SQL_ISTOKEN(pParseTree->getChild(1),DISTINCT))
+ {
+ rController.setDistinct(sal_True);
+ rController.InvalidateFeature(SID_QUERY_DISTINCT_VALUES);
+ }
+ if ( (eErrorCode = InstallFields(_pView,pParseTree, pTableView->GetTabWinMap())) == eOk )
+ {
+ // GetSelectionCriteria must be called before GetHavingCriteria
+ sal_uInt16 nLevel=0;
+
+ if ( eOk == (eErrorCode = GetSelectionCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
+ {
+ if ( eOk == (eErrorCode = GetGroupCriteria(_pView,_pSelectionBrw,pParseTree)) )
+ {
+ if ( eOk == (eErrorCode = GetHavingCriteria(_pView,_pSelectionBrw,pParseTree,nLevel)) )
+ {
+ if ( eOk == (eErrorCode = GetOrderCriteria(_pView,_pSelectionBrw,pParseTree)) )
+ insertUnUsedFields(_pView,_pSelectionBrw);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch(SQLException&)
+ {
+ OSL_ASSERT(!"getMaxTablesInSelect!");
+ }
+ }
+ while ( false );
+
+ // Durch das Neuerzeugen wurden wieder Undo-Actions in den Manager gestellt
+ rController.getUndoMgr()->Clear();
+ _pSelectionBrw->Invalidate();
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ /** fillSelectSubList
+ @return
+ <TRUE/> when columns could be inserted otherwise <FALSE/>
+ */
+ //------------------------------------------------------------------------------
+ SqlParseError fillSelectSubList( OQueryDesignView* _pView,
+ OJoinTableView::OTableWindowMap* _pTabList)
+ {
+ SqlParseError eErrorCode = eOk;
+ sal_Bool bFirstField = sal_True;
+ ::rtl::OUString sAsterix(RTL_CONSTASCII_USTRINGPARAM("*"));
+ OJoinTableView::OTableWindowMap::iterator aIter = _pTabList->begin();
+ OJoinTableView::OTableWindowMap::iterator aEnd = _pTabList->end();
+ for(;aIter != aEnd && eOk == eErrorCode ;++aIter)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+ if (pTabWin->ExistsField( sAsterix, aInfo ))
+ {
+ eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
+ bFirstField = sal_False;
+ }
+ }
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError InstallFields(OQueryDesignView* _pView,
+ const ::connectivity::OSQLParseNode* pNode,
+ OJoinTableView::OTableWindowMap* pTabList )
+ {
+ if( pNode==0 || !SQL_ISRULE(pNode,select_statement))
+ return eNoSelectStatement;
+
+ ::connectivity::OSQLParseNode* pParseTree = pNode->getChild(2); // selection
+ sal_Bool bFirstField = sal_True; // bei der Initialisierung muß auf alle Faelle das erste Feld neu aktiviert werden
+
+ SqlParseError eErrorCode = eOk;
+
+ if ( pParseTree->isRule() && SQL_ISPUNCTUATION(pParseTree->getChild(0),"*") )
+ {
+ // SELECT * ...
+ eErrorCode = fillSelectSubList(_pView,pTabList);
+ }
+ else if (SQL_ISRULE(pParseTree,scalar_exp_commalist) )
+ {
+ // SELECT column, ...
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ Reference< XConnection> xConnection = rController.getConnection();
+
+ ::rtl::OUString aColumnName,aTableRange;
+ for (sal_uInt32 i = 0; i < pParseTree->count() && eOk == eErrorCode ; ++i)
+ {
+ ::connectivity::OSQLParseNode * pColumnRef = pParseTree->getChild(i);
+
+ do {
+
+ if ( SQL_ISRULE(pColumnRef,select_sublist) )
+ {
+ eErrorCode = fillSelectSubList(_pView,pTabList);
+ break;
+ }
+
+ if ( SQL_ISRULE(pColumnRef,derived_column) )
+ {
+ ::rtl::OUString aColumnAlias(rController.getParseIterator().getColumnAlias(pColumnRef)); // kann leer sein
+ pColumnRef = pColumnRef->getChild(0);
+ OTableFieldDescRef aInfo = new OTableFieldDesc();
+
+ if ( pColumnRef->count() == 3 &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(0),"(") &&
+ SQL_ISPUNCTUATION(pColumnRef->getChild(2),")")
+ )
+ pColumnRef = pColumnRef->getChild(1);
+
+ if (SQL_ISRULE(pColumnRef,column_ref))
+ {
+ InsertColumnRef(_pView,pColumnRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
+ eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
+ bFirstField = sal_False;
+ }
+ else if(SQL_ISRULEOR2(pColumnRef,general_set_fct ,set_fct_spec) ||
+ SQL_ISRULEOR2(pColumnRef,position_exp,extract_exp) ||
+ SQL_ISRULEOR2(pColumnRef,fold,char_substring_fct) ||
+ SQL_ISRULEOR2(pColumnRef,length_exp,char_value_fct))
+ {
+ ::rtl::OUString aColumns;
+ pColumnRef->parseNodeToPredicateStr(aColumns,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ &rController.getParser().getContext());
+ //pColumnRef->parseNodeToStr( aColumns,
+ // xConnection,
+ // &rController.getParser().getContext(),
+ // sal_True,
+ // sal_True); // quote is to true because we need quoted elements inside the function
+
+ sal_Int32 nFunctionType = FKT_NONE;
+ ::connectivity::OSQLParseNode* pParamRef = NULL;
+ sal_Int32 nColumnRefPos = pColumnRef->count() - 2;
+ if ( nColumnRefPos >= 0 && static_cast<sal_uInt32>(nColumnRefPos) < pColumnRef->count() )
+ pParamRef = pColumnRef->getChild(nColumnRefPos);
+
+ if ( SQL_ISRULE(pColumnRef,general_set_fct)
+ && SQL_ISRULE(pParamRef,column_ref) )
+ {
+ // Parameter auf Columnref pr"ufen
+ InsertColumnRef(_pView,pParamRef,aColumnName,aColumnAlias,aTableRange,aInfo,pTabList);
+ }
+ else if ( SQL_ISRULE(pColumnRef,general_set_fct) )
+ {
+ if ( pParamRef && pParamRef->getTokenValue().toChar() == '*' )
+ {
+ OJoinTableView::OTableWindowMap::iterator aIter = pTabList->begin();
+ OJoinTableView::OTableWindowMap::iterator aEnd = pTabList->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OQueryTableWindow* pTabWin = static_cast<OQueryTableWindow*>(aIter->second);
+ if (pTabWin->ExistsField( ::rtl::OUString::createFromAscii("*"), aInfo ))
+ {
+ aInfo->SetAlias(String());
+ aInfo->SetTable(String());
+ break;
+ }
+ }
+ }
+ else
+ {
+ ::rtl::OUString sFieldName = aColumns;
+ if ( pParamRef )
+ { // we got an aggregate function but without column name inside
+ // so we set the whole argument of the function as field name
+ nFunctionType |= FKT_NUMERIC;
+ sFieldName = ::rtl::OUString();
+ pParamRef->parseNodeToStr( sFieldName,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_True,
+ sal_True); // quote is to true because we need quoted elements inside the function
+ }
+ aInfo->SetDataType(DataType::DOUBLE);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(sFieldName);
+ }
+ aInfo->SetTabWindow(NULL);
+ aInfo->SetFieldAlias(aColumnAlias);
+ }
+ else
+ {
+ _pView->fillFunctionInfo(pColumnRef,aColumns,aInfo);
+ aInfo->SetFieldAlias(aColumnAlias);
+ }
+
+ if ( SQL_ISRULE(pColumnRef,general_set_fct) )
+ {
+ aInfo->SetFunctionType(nFunctionType|FKT_AGGREGATE);
+ String aCol(aColumns);
+ aInfo->SetFunction(aCol.GetToken(0,'(').EraseTrailingChars(' '));
+ }
+ else
+ aInfo->SetFunctionType(nFunctionType|FKT_OTHER);
+
+ eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
+ bFirstField = sal_False;
+ }
+ else //if(SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))
+ {
+ ::rtl::OUString aColumns;
+ pColumnRef->parseNodeToStr( aColumns,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_True,
+ sal_True); // quote is to true because we need quoted elements inside the function
+
+ aInfo->SetTabWindow( NULL );
+
+ // since we support queries in queries, the thingie might belong to an existing "table"
+ OQueryTableWindow* pExistingTable = lcl_findColumnInTables( aColumns, *pTabList, aInfo );
+ if ( pExistingTable )
+ {
+ aInfo->SetTabWindow( pExistingTable );
+ aInfo->SetTable( pExistingTable->GetTableName() );
+ aInfo->SetAlias( pExistingTable->GetAliasName() );
+ }
+
+ aInfo->SetDataType(DataType::DOUBLE);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(aColumns);
+ aInfo->SetFieldAlias(aColumnAlias);
+ aInfo->SetFunctionType(FKT_NUMERIC | FKT_OTHER);
+
+ eErrorCode = _pView->InsertField(aInfo, sal_True, bFirstField);
+ bFirstField = sal_False;
+ }
+
+ break;
+ }
+
+ DBG_ERROR( "InstallFields: don't know how to interpret this parse node!" );
+
+ } while ( false );
+ }
+ }
+ else
+ eErrorCode = eStatementTooComplex;
+
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError GetOrderCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pParseRoot )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pParseRoot->getChild(3)->getChild(4)->isLeaf())
+ {
+ ::connectivity::OSQLParseNode* pNode = pParseRoot->getChild(3)->getChild(4)->getChild(2);
+ ::connectivity::OSQLParseNode* pParamRef = NULL;
+
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ EOrderDir eOrderDir;
+ OTableFieldDescRef aDragLeft = new OTableFieldDesc();
+ for( sal_uInt32 i=0 ; i<pNode->count() ; i++ )
+ {
+ eOrderDir = ORDER_ASC;
+ ::connectivity::OSQLParseNode* pChild = pNode->getChild( i );
+
+ if (SQL_ISTOKEN( pChild->getChild(1), DESC ) )
+ eOrderDir = ORDER_DESC;
+
+ ::connectivity::OSQLParseNode* pArgument = pChild->getChild(0);
+
+ if(SQL_ISRULE(pArgument,column_ref))
+ {
+ if( eOk == FillDragInfo(_pView,pArgument,aDragLeft))
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i);
+ else // it could be a alias name for a field
+ {
+ ::rtl::OUString aTableRange,aColumnName;
+ ::connectivity::OSQLParseTreeIterator& rParseIter = rController.getParseIterator();
+ rParseIter.getColumnRange( pArgument, aColumnName, aTableRange );
+
+ OTableFields& aList = rController.getTableFieldDesc();
+ OTableFields::iterator aIter = aList.begin();
+ OTableFields::iterator aEnd = aList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntry = *aIter;
+ if(pEntry.isValid() && pEntry->GetFieldAlias() == aColumnName)
+ pEntry->SetOrderDir( eOrderDir );
+ }
+ }
+ }
+ else if(SQL_ISRULE(pArgument, general_set_fct ) &&
+ SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
+ eOk == FillDragInfo(_pView,pParamRef,aDragLeft))
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
+ else if( SQL_ISRULE(pArgument, set_fct_spec ) )
+ {
+
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ ::rtl::OUString sCondition;
+ pArgument->parseNodeToPredicateStr(sCondition,
+ xConnection,
+ rController.getNumberFormatter(),
+ _pView->getLocale(),
+ static_cast<sal_Char>(_pView->getDecimalSeparator().toChar()),
+ &rController.getParser().getContext());
+ _pView->fillFunctionInfo(pArgument,sCondition,aDragLeft);
+ aDragLeft->SetFunctionType(FKT_OTHER);
+ aDragLeft->SetOrderDir(eOrderDir);
+ aDragLeft->SetVisible(sal_False);
+ _pSelectionBrw->AddOrder( aDragLeft, eOrderDir, i );
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ }
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError GetHavingCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot,
+ sal_uInt16& rLevel )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pSelectRoot->getChild(3)->getChild(3)->isLeaf())
+ eErrorCode = GetORCriteria(_pView,_pSelectionBrw,pSelectRoot->getChild(3)->getChild(3)->getChild(1),rLevel, sal_True);
+ return eErrorCode;
+ }
+ //------------------------------------------------------------------------------
+ SqlParseError GetGroupCriteria( OQueryDesignView* _pView,
+ OSelectionBrowseBox* _pSelectionBrw,
+ const ::connectivity::OSQLParseNode* pSelectRoot )
+ {
+ SqlParseError eErrorCode = eOk;
+ if (!pSelectRoot->getChild(3)->getChild(2)->isLeaf()) // opt_group_by_clause
+ {
+ OQueryController& rController = static_cast<OQueryController&>(_pView->getController());
+ ::connectivity::OSQLParseNode* pGroupBy = pSelectRoot->getChild(3)->getChild(2)->getChild(2);
+ OTableFieldDescRef aDragInfo = new OTableFieldDesc();
+ for( sal_uInt32 i=0 ; i < pGroupBy->count() && eOk == eErrorCode; ++i )
+ {
+ ::connectivity::OSQLParseNode* pParamRef = NULL;
+ ::connectivity::OSQLParseNode* pArgument = pGroupBy->getChild( i );
+ if(SQL_ISRULE(pArgument,column_ref))
+ {
+ if ( eOk == (eErrorCode = FillDragInfo(_pView,pArgument,aDragInfo)) )
+ {
+ aDragInfo->SetGroupBy(sal_True);
+ _pSelectionBrw->AddGroupBy(aDragInfo,i);
+ }
+ }
+ else if(SQL_ISRULE(pArgument, general_set_fct ) &&
+ SQL_ISRULE(pParamRef = pArgument->getChild(pArgument->count()-2),column_ref) &&
+ eOk == FillDragInfo(_pView,pParamRef,aDragInfo))
+ {
+ aDragInfo->SetGroupBy(sal_True);
+ _pSelectionBrw->AddGroupBy( aDragInfo, i );
+ }
+ else if( SQL_ISRULE(pArgument, set_fct_spec ) )
+ {
+ Reference< XConnection> xConnection = rController.getConnection();
+ if(xConnection.is())
+ {
+ ::rtl::OUString sGroupByExpression;
+ pArgument->parseNodeToStr( sGroupByExpression,
+ xConnection,
+ &rController.getParser().getContext(),
+ sal_True,
+ sal_True); // quote is to true because we need quoted elements inside the function
+ _pView->fillFunctionInfo(pArgument,sGroupByExpression,aDragInfo);
+ aDragInfo->SetFunctionType(FKT_OTHER);
+ aDragInfo->SetGroupBy(sal_True);
+ aDragInfo->SetVisible(sal_False);
+ _pSelectionBrw->AddGroupBy( aDragInfo, i );
+ }
+ else
+ eErrorCode = eColumnNotFound;
+ }
+ }
+ }
+ return eErrorCode;
+ }
+
+ //------------------------------------------------------------------------------
+ String getParseErrorMessage( SqlParseError _eErrorCode )
+ {
+ USHORT nResId;
+ switch(_eErrorCode)
+ {
+ case eIllegalJoin:
+ nResId = STR_QRY_ILLEGAL_JOIN;
+ break;
+ case eStatementTooLong:
+ nResId = STR_QRY_TOO_LONG_STATEMENT;
+ break;
+ case eNoConnection:
+ nResId = STR_QRY_SYNTAX;
+ break;
+ case eNoSelectStatement:
+ nResId = STR_QRY_NOSELECT;
+ break;
+ case eColumnInLikeNotFound:
+ nResId = STR_QRY_SYNTAX;
+ break;
+ case eNoColumnInLike:
+ nResId = STR_QRY_SYNTAX;
+ break;
+ case eColumnNotFound:
+ nResId = STR_QRY_SYNTAX;
+ break;
+ case eNativeMode:
+ nResId = STR_QRY_NATIVE;
+ break;
+ case eTooManyTables:
+ nResId = STR_QRY_TOO_MANY_TABLES;
+ break;
+ case eTooManyConditions:
+ nResId = STR_QRY_TOOMANYCOND;
+ break;
+ case eTooManyColumns:
+ nResId = STR_QRY_TOO_MANY_COLUMNS;
+ break;
+ case eStatementTooComplex:
+ nResId = STR_QRY_TOOCOMPLEX;
+ break;
+ default:
+ nResId = STR_QRY_SYNTAX;
+ break;
+ }
+ ;
+ return String( ModuleRes( nResId ) );
+ }
+
+ //------------------------------------------------------------------------------
+ //------------------------------------------------------------------------------
+}
+// end of anonymouse namespace
+DBG_NAME(OQueryDesignView)
+
+OQueryDesignView::OQueryDesignView( OQueryContainerWindow* _pParent,
+ OQueryController& _rController,
+ const Reference< XMultiServiceFactory >& _rFactory)
+ :OQueryView( _pParent, _rController, _rFactory )
+ ,m_aSplitter( this )
+ ,m_eChildFocus(NONE)
+ ,m_bInKeyEvent(sal_False)
+ ,m_bInSplitHandler( sal_False )
+{
+ DBG_CTOR(OQueryDesignView,NULL);
+
+ try
+ {
+ SvtSysLocale aSysLocale;
+ m_aLocale = aSysLocale.GetLocaleData().getLocale();
+ m_sDecimalSep = aSysLocale.GetLocaleData().getNumDecimalSep();
+ }
+ catch(Exception&)
+ {
+ }
+
+ m_pSelectionBox = new OSelectionBrowseBox(this);
+
+ setNoneVisbleRow(static_cast<OQueryController&>(getController()).getVisibleRows());
+ m_pSelectionBox->Show();
+ // Splitter einrichten
+ m_aSplitter.SetSplitHdl(LINK(this, OQueryDesignView,SplitHdl));
+ m_aSplitter.Show();
+
+}
+// -----------------------------------------------------------------------------
+OQueryDesignView::~OQueryDesignView()
+{
+ if ( m_pTableView )
+ ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::RemoveWindow));
+ ::std::auto_ptr<Window> aTemp(m_pSelectionBox);
+ m_pSelectionBox = NULL;
+
+ DBG_DTOR(OQueryDesignView,NULL);
+}
+//------------------------------------------------------------------------------
+IMPL_LINK( OQueryDesignView, SplitHdl, void*, /*p*/ )
+{
+ if (!getController().isReadOnly())
+ {
+ m_bInSplitHandler = sal_True;
+ m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),m_aSplitter.GetSplitPosPixel() ) );
+ static_cast<OQueryController&>(getController()).setSplitPos(m_aSplitter.GetSplitPosPixel());
+ static_cast<OQueryController&>(getController()).setModified( sal_True );
+ Resize();
+ m_bInSplitHandler = sal_True;
+ }
+ return 0L;
+}
+// -------------------------------------------------------------------------
+void OQueryDesignView::Construct()
+{
+ m_pTableView = new OQueryTableView(m_pScrollWindow,this);
+ ::dbaui::notifySystemWindow(this,m_pTableView,::comphelper::mem_fun(&TaskPaneList::AddWindow));
+ OQueryView::Construct();
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::initialize()
+{
+ if(static_cast<OQueryController&>(getController()).getSplitPos() != -1)
+ {
+ m_aSplitter.SetPosPixel( Point( m_aSplitter.GetPosPixel().X(),static_cast<OQueryController&>(getController()).getSplitPos() ) );
+ m_aSplitter.SetSplitPosPixel(static_cast<OQueryController&>(getController()).getSplitPos());
+ }
+ m_pSelectionBox->initialize();
+ reset();
+}
+// -------------------------------------------------------------------------
+void OQueryDesignView::resizeDocumentView(Rectangle& _rPlayground)
+{
+ Point aPlaygroundPos( _rPlayground.TopLeft() );
+ Size aPlaygroundSize( _rPlayground.GetSize() );
+
+ // calc the split pos, and forward it to the controller
+ sal_Int32 nSplitPos = static_cast<OQueryController&>(getController()).getSplitPos();
+ if ( 0 != aPlaygroundSize.Height() )
+ {
+ if ( ( -1 == nSplitPos )
+ || ( nSplitPos >= aPlaygroundSize.Height() )
+ )
+ {
+ // let the selection browse box determine an optimal size
+ Size aSelectionBoxSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
+ nSplitPos = aPlaygroundSize.Height() - aSelectionBoxSize.Height() - m_aSplitter.GetSizePixel().Height();
+ // still an invalid size?
+ if ( nSplitPos == -1 || nSplitPos >= aPlaygroundSize.Height() )
+ nSplitPos = sal_Int32(aPlaygroundSize.Height()*0.6);
+
+ static_cast<OQueryController&>(getController()).setSplitPos(nSplitPos);
+ }
+
+ if ( !m_bInSplitHandler )
+ { // the resize is triggered by something else than the split handler
+ // our main focus is to try to preserve the size of the selectionbrowse box
+ Size aSelBoxSize = m_pSelectionBox->GetSizePixel();
+ if ( aSelBoxSize.Height() )
+ {
+ // keep the size of the sel box constant
+ nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxSize.Height();
+
+ // and if the box is smaller than the optimal size, try to do something about it
+ Size aSelBoxOptSize = m_pSelectionBox->CalcOptimalSize( aPlaygroundSize );
+ if ( aSelBoxOptSize.Height() > aSelBoxSize.Height() )
+ {
+ nSplitPos = aPlaygroundSize.Height() - m_aSplitter.GetSizePixel().Height() - aSelBoxOptSize.Height();
+ }
+
+ static_cast< OQueryController& >(getController()).setSplitPos( nSplitPos );
+ }
+ }
+ }
+
+ // normalize the split pos
+ Point aSplitPos = Point( _rPlayground.Left(), nSplitPos );
+ Size aSplitSize = Size( _rPlayground.GetSize().Width(), m_aSplitter.GetSizePixel().Height() );
+
+ if( ( aSplitPos.Y() + aSplitSize.Height() ) > ( aPlaygroundSize.Height() ))
+ aSplitPos.Y() = aPlaygroundSize.Height() - aSplitSize.Height();
+
+ if( aSplitPos.Y() <= aPlaygroundPos.Y() )
+ aSplitPos.Y() = aPlaygroundPos.Y() + sal_Int32(aPlaygroundSize.Height() * 0.2);
+
+ // position the table
+ Size aTableViewSize(aPlaygroundSize.Width(), aSplitPos.Y() - aPlaygroundPos.Y());
+ m_pScrollWindow->SetPosSizePixel(aPlaygroundPos, aTableViewSize);
+
+ // position the selection browse box
+ Point aPos( aPlaygroundPos.X(), aSplitPos.Y() + aSplitSize.Height() );
+ m_pSelectionBox->SetPosSizePixel( aPos, Size( aPlaygroundSize.Width(), aPlaygroundSize.Height() - aSplitSize.Height() - aTableViewSize.Height() ));
+
+ // set the size of the splitter
+ m_aSplitter.SetPosSizePixel( aSplitPos, aSplitSize );
+ m_aSplitter.SetDragRectPixel( _rPlayground );
+
+ // just for completeness: there is no space left, we occupied it all ...
+ _rPlayground.SetPos( _rPlayground.BottomRight() );
+ _rPlayground.SetSize( Size( 0, 0 ) );
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::setReadOnly(sal_Bool _bReadOnly)
+{
+ m_pSelectionBox->SetReadOnly(_bReadOnly);
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::clear()
+{
+ m_pSelectionBox->ClearAll(); // clear the whole selection
+ m_pTableView->ClearAll();
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::setStatement(const ::rtl::OUString& /*_rsStatement*/)
+{
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::copy()
+{
+ if( m_eChildFocus == SELECTION)
+ m_pSelectionBox->copy();
+}
+// -----------------------------------------------------------------------------
+sal_Bool OQueryDesignView::isCutAllowed()
+{
+ sal_Bool bAllowed = sal_False;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isCutAllowed();
+ return bAllowed;
+}
+// -----------------------------------------------------------------------------
+sal_Bool OQueryDesignView::isPasteAllowed()
+{
+ sal_Bool bAllowed = sal_False;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isPasteAllowed();
+ return bAllowed;
+}
+// -----------------------------------------------------------------------------
+sal_Bool OQueryDesignView::isCopyAllowed()
+{
+ sal_Bool bAllowed = sal_False;
+ if ( SELECTION == m_eChildFocus )
+ bAllowed = m_pSelectionBox->isCopyAllowed();
+ return bAllowed;
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::stopTimer()
+{
+ m_pSelectionBox->stopTimer();
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::startTimer()
+{
+ m_pSelectionBox->startTimer();
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::cut()
+{
+ if( m_eChildFocus == SELECTION)
+ {
+ m_pSelectionBox->cut();
+ static_cast<OQueryController&>(getController()).setModified(sal_True);
+ }
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::paste()
+{
+ if( m_eChildFocus == SELECTION)
+ {
+ m_pSelectionBox->paste();
+ static_cast<OQueryController&>(getController()).setModified(sal_True);
+ }
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::TableDeleted(const ::rtl::OUString& rAliasName)
+{
+ // Nachricht, dass Tabelle aus dem Fenster gel"oscht wurde
+ DeleteFields(rAliasName);
+ static_cast<OQueryController&>(getController()).InvalidateFeature(ID_BROWSER_ADDTABLE); // view nochmal bescheid sagen
+}
+//------------------------------------------------------------------------------
+void OQueryDesignView::DeleteFields( const ::rtl::OUString& rAliasName )
+{
+ m_pSelectionBox->DeleteFields( rAliasName );
+}
+// -----------------------------------------------------------------------------
+bool OQueryDesignView::HasFieldByAliasName(const ::rtl::OUString& rFieldName, OTableFieldDescRef& rInfo) const
+{
+ return m_pSelectionBox->HasFieldByAliasName( rFieldName, rInfo);
+}
+// -----------------------------------------------------------------------------
+SqlParseError OQueryDesignView::InsertField( const OTableFieldDescRef& rInfo, sal_Bool bVis, sal_Bool bActivate)
+{
+ return m_pSelectionBox->InsertField( rInfo, BROWSER_INVALIDID,bVis, bActivate ).isValid() ? eOk : eTooManyColumns;
+}
+// -----------------------------------------------------------------------------
+sal_Int32 OQueryDesignView::getColWidth(sal_uInt16 _nColPos) const
+{
+ static sal_Int32 s_nDefaultWidth = GetTextWidth(String(RTL_CONSTASCII_USTRINGPARAM("0"))) * 15;
+ sal_Int32 nWidth = static_cast<OQueryController&>(getController()).getColWidth(_nColPos);
+ if ( !nWidth )
+ nWidth = s_nDefaultWidth;
+ return nWidth;
+}
+//------------------------------------------------------------------------------
+void OQueryDesignView::fillValidFields(const ::rtl::OUString& sAliasName, ComboBox* pFieldList)
+{
+ DBG_ASSERT(pFieldList != NULL, "OQueryDesignView::FillValidFields : What the hell do you think I can do with a NULL-ptr ? This will crash !");
+ pFieldList->Clear();
+
+ sal_Bool bAllTables = sAliasName.getLength() == 0;
+
+ OJoinTableView::OTableWindowMap* pTabWins = m_pTableView->GetTabWinMap();
+ ::rtl::OUString strCurrentPrefix;
+ ::std::vector< ::rtl::OUString> aFields;
+ OJoinTableView::OTableWindowMap::iterator aIter = pTabWins->begin();
+ OJoinTableView::OTableWindowMap::iterator aEnd = pTabWins->end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OQueryTableWindow* pCurrentWin = static_cast<OQueryTableWindow*>(aIter->second);
+ if (bAllTables || (pCurrentWin->GetAliasName() == sAliasName))
+ {
+ strCurrentPrefix = pCurrentWin->GetAliasName();
+ strCurrentPrefix += ::rtl::OUString('.');
+
+ pCurrentWin->EnumValidFields(aFields);
+
+ ::std::vector< ::rtl::OUString>::iterator aStrIter = aFields.begin();
+ ::std::vector< ::rtl::OUString>::iterator aStrEnd = aFields.end();
+ for(;aStrIter != aStrEnd;++aStrIter)
+ {
+ if (bAllTables || aStrIter->toChar() == '*')
+ pFieldList->InsertEntry(::rtl::OUString(strCurrentPrefix) += *aStrIter);
+ else
+ pFieldList->InsertEntry(*aStrIter);
+ }
+
+ if (!bAllTables)
+ // das heisst, dass ich in diesen Block kam, weil der Tabellenname genau der gesuchte war, also bin ich fertig
+ // (dadurch verhindere ich auch das doppelte Einfuegen von Feldern, wenn eine Tabelle mehrmals als TabWin vorkommt)
+ break;
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+long OQueryDesignView::PreNotify(NotifyEvent& rNEvt)
+{
+ switch (rNEvt.GetType())
+ {
+ case EVENT_GETFOCUS:
+#if OSL_DEBUG_LEVEL > 0
+ {
+ Window* pFocus = Application::GetFocusWindow();
+ (void)pFocus;
+ }
+#endif
+
+ if ( m_pSelectionBox && m_pSelectionBox->HasChildPathFocus() )
+ m_eChildFocus = SELECTION;
+ else
+ m_eChildFocus = TABLEVIEW;
+ break;
+ }
+
+ return OQueryView::PreNotify(rNEvt);
+}
+//------------------------------------------------------------------------------
+
+
+// -----------------------------------------------------------------------------
+// check if the statement is correct when not returning false
+sal_Bool OQueryDesignView::checkStatement()
+{
+ sal_Bool bRet = sal_True;
+ if ( m_pSelectionBox )
+ bRet = m_pSelectionBox->Save(); // a error occured so we return no
+ return bRet;
+}
+//-------------------------------------------------------------------------------
+::rtl::OUString OQueryDesignView::getStatement()
+{
+ OQueryController& rController = static_cast<OQueryController&>(getController());
+ m_rController.clearError();
+ // used for fields which aren't any longer in the statement
+ OTableFields& rUnUsedFields = rController.getUnUsedFields();
+ OTableFields().swap( rUnUsedFields );
+
+ // create the select columns
+ sal_uInt32 nFieldcount = 0;
+ OTableFields& rFieldList = rController.getTableFieldDesc();
+ OTableFields::iterator aIter = rFieldList.begin();
+ OTableFields::iterator aEnd = rFieldList.end();
+ for(;aIter != aEnd;++aIter)
+ {
+ OTableFieldDescRef pEntryField = *aIter;
+ if ( pEntryField->GetField().getLength() && pEntryField->IsVisible() )
+ ++nFieldcount;
+ else if (pEntryField->GetField().getLength() &&
+ !pEntryField->HasCriteria() &&
+ pEntryField->isNoneFunction() &&
+ pEntryField->GetOrderDir() == ORDER_NONE &&
+ !pEntryField->IsGroupBy() &&
+ !pEntryField->GetFunction().getLength() )
+ rUnUsedFields.push_back(pEntryField);
+ }
+ if ( !nFieldcount ) // keine Felder sichtbar also zur"uck
+ {
+ rUnUsedFields = rFieldList;
+ return ::rtl::OUString();
+ }
+
+ OQueryTableView::OTableWindowMap* pTabList = m_pTableView->GetTabWinMap();
+ sal_uInt32 nTabcount = pTabList->size();
+
+ ::rtl::OUString aFieldListStr(GenerateSelectList(this,rFieldList,nTabcount>1));
+ if( !aFieldListStr.getLength() )
+ return ::rtl::OUString();
+ // Ausnahmebehandlung, wenn keine Felder angegeben worden sind
+ // Dann darf die Tabpage nicht gewechselt werden
+ // Im TabBarSelectHdl wird der SQL-::rtl::OUString auf STATEMENT_NOFIELDS abgefragt
+ // und eine Errormeldung erzeugt
+ // ----------------- Tabellenliste aufbauen ----------------------
+
+ const ::std::vector<OTableConnection*>* pConnList = m_pTableView->getTableConnections();
+ Reference< XConnection> xConnection = rController.getConnection();
+ ::rtl::OUString aTableListStr(GenerateFromClause(xConnection,pTabList,pConnList));
+ DBG_ASSERT(aTableListStr.getLength(), "OQueryDesignView::getStatement() : unerwartet : habe Felder, aber keine Tabellen !");
+ // wenn es Felder gibt, koennen die nur durch Einfuegen aus einer schon existenten Tabelle entstanden sein; wenn andererseits
+ // eine Tabelle geloescht wird, verschwinden auch die zugehoerigen Felder -> ergo KANN es das nicht geben, dass Felder
+ // existieren, aber keine Tabellen (und aFieldListStr hat schon eine Laenge, das stelle ich oben sicher)
+ ::rtl::OUStringBuffer aHavingStr,aCriteriaListStr;
+ // ----------------- Kriterien aufbauen ----------------------
+ if (!GenerateCriterias(this,aCriteriaListStr,aHavingStr,rFieldList, nTabcount > 1))
+ return ::rtl::OUString();
+
+ ::rtl::OUString aJoinCrit;
+ GenerateInnerJoinCriterias(xConnection,aJoinCrit,pConnList);
+ if(aJoinCrit.getLength())
+ {
+ ::rtl::OUString aTmp = ::rtl::OUString::createFromAscii("( ");
+ aTmp += aJoinCrit;
+ aTmp += ::rtl::OUString::createFromAscii(" )");
+ if(aCriteriaListStr.getLength())
+ {
+ aTmp += C_AND;
+ aTmp += aCriteriaListStr.makeStringAndClear();
+ }
+ aCriteriaListStr = aTmp;
+ }
+ // ----------------- Statement aufbauen ----------------------
+ ::rtl::OUStringBuffer aSqlCmd(::rtl::OUString::createFromAscii("SELECT "));
+ if(static_cast<OQueryController&>(getController()).isDistinct())
+ aSqlCmd.append(::rtl::OUString::createFromAscii(" DISTINCT "));
+ aSqlCmd.append(aFieldListStr);
+ aSqlCmd.append(::rtl::OUString::createFromAscii(" FROM "));
+ aSqlCmd.append(aTableListStr);
+
+ if (aCriteriaListStr.getLength())
+ {
+ aSqlCmd.append(::rtl::OUString::createFromAscii(" WHERE "));
+ aSqlCmd.append(aCriteriaListStr.makeStringAndClear());
+ }
+ // ----------------- GroupBy aufbauen und Anh"angen ------------
+ Reference<XDatabaseMetaData> xMeta;
+ if ( xConnection.is() )
+ xMeta = xConnection->getMetaData();
+ sal_Bool bUseAlias = nTabcount > 1;
+ if ( xMeta.is() )
+ bUseAlias = bUseAlias || !xMeta->supportsGroupByUnrelated();
+
+ aSqlCmd.append(GenerateGroupBy(this,rFieldList,bUseAlias));
+ // ----------------- having Anh"angen ------------
+ if(aHavingStr.getLength())
+ {
+ aSqlCmd.append(::rtl::OUString::createFromAscii(" HAVING "));
+ aSqlCmd.append(aHavingStr.makeStringAndClear());
+ }
+ // ----------------- Sortierung aufbauen und Anh"angen ------------
+ ::rtl::OUString sOrder;
+ SqlParseError eErrorCode = eOk;
+ if ( (eErrorCode = GenerateOrder(this,rFieldList,nTabcount > 1,sOrder)) == eOk)
+ aSqlCmd.append(sOrder);
+ else
+ {
+ if ( !m_rController.hasError() )
+ m_rController.appendError( getParseErrorMessage( eErrorCode ) );
+
+ m_rController.displayError();
+ }
+
+ ::rtl::OUString sSQL = aSqlCmd.makeStringAndClear();
+ if ( xConnection.is() )
+ {
+ ::connectivity::OSQLParser& rParser( rController.getParser() );
+ ::rtl::OUString sErrorMessage;
+ ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( sErrorMessage, sSQL, sal_True ) );
+ if ( pParseNode.get() )
+ {
+ OSQLParseNode* pNode = pParseNode->getChild(3)->getChild(1);
+ if ( pNode->count() > 1 )
+ {
+ ::connectivity::OSQLParseNode * pCondition = pNode->getChild(1);
+ if ( pCondition ) // no where clause
+ {
+ OSQLParseNode::compress(pCondition);
+ ::rtl::OUString sTemp;
+ pParseNode->parseNodeToStr(sTemp,xConnection);
+ sSQL = sTemp;
+ }
+ }
+ }
+ }
+ return sSQL;
+}
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+void OQueryDesignView::setSlotEnabled(sal_Int32 _nSlotId,sal_Bool _bEnable)
+{
+ sal_uInt16 nRow;
+ switch (_nSlotId)
+ {
+ case SID_QUERY_VIEW_FUNCTIONS:
+ nRow = BROW_FUNCTION_ROW;
+ break;
+ case SID_QUERY_VIEW_TABLES:
+ nRow = BROW_TABLE_ROW;
+ break;
+ case SID_QUERY_VIEW_ALIASES:
+ nRow = BROW_COLUMNALIAS_ROW;
+ break;
+ default:
+ // ????????????
+ nRow = 0;
+ break;
+ }
+ m_pSelectionBox->SetRowVisible(nRow,_bEnable);
+ m_pSelectionBox->Invalidate();
+}
+// -----------------------------------------------------------------------------
+sal_Bool OQueryDesignView::isSlotEnabled(sal_Int32 _nSlotId)
+{
+ sal_uInt16 nRow;
+ switch (_nSlotId)
+ {
+ case SID_QUERY_VIEW_FUNCTIONS:
+ nRow = BROW_FUNCTION_ROW;
+ break;
+ case SID_QUERY_VIEW_TABLES:
+ nRow = BROW_TABLE_ROW;
+ break;
+ case SID_QUERY_VIEW_ALIASES:
+ nRow = BROW_COLUMNALIAS_ROW;
+ break;
+ default:
+ // ?????????
+ nRow = 0;
+ break;
+ }
+ return m_pSelectionBox->IsRowVisible(nRow);
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::SaveUIConfig()
+{
+ OQueryController& rCtrl = static_cast<OQueryController&>(getController());
+ rCtrl.SaveTabWinsPosSize( m_pTableView->GetTabWinMap(), m_pScrollWindow->GetHScrollBar()->GetThumbPos(), m_pScrollWindow->GetVScrollBar()->GetThumbPos() );
+ // rCtrl.SaveTabFieldsWidth( m_pSelectionBox );
+ rCtrl.setVisibleRows( m_pSelectionBox->GetNoneVisibleRows() );
+ if ( m_aSplitter.GetSplitPosPixel() != 0 )
+ rCtrl.setSplitPos( m_aSplitter.GetSplitPosPixel() );
+}
+// -----------------------------------------------------------------------------
+OSQLParseNode* OQueryDesignView::getPredicateTreeFromEntry(OTableFieldDescRef pEntry,
+ const String& _sCriteria,
+ ::rtl::OUString& _rsErrorMessage,
+ Reference<XPropertySet>& _rxColumn) const
+{
+ OSL_ENSURE(pEntry.isValid(),"Entry is null!");
+ if(!pEntry.isValid())
+ return NULL;
+ Reference< XConnection> xConnection = static_cast<OQueryController&>(getController()).getConnection();
+ if(!xConnection.is())
+ return NULL;
+
+ ::connectivity::OSQLParser& rParser( static_cast<OQueryController&>(getController()).getParser() );
+ OQueryTableWindow* pWin = static_cast<OQueryTableWindow*>(pEntry->GetTabWindow());
+
+ String sTest(_sCriteria);
+ // special handling for functions
+ if ( pEntry->GetFunctionType() & (FKT_OTHER | FKT_AGGREGATE | FKT_NUMERIC) )
+ {
+ // we have a function here so we have to distinguish the type of return value
+ String sFunction;
+ if ( pEntry->isNumericOrAggreateFunction() )
+ sFunction = pEntry->GetFunction();
+
+ if ( !sFunction.Len() )
+ sFunction = pEntry->GetField();
+
+ if(sFunction.GetTokenCount('(') > 1)
+ sFunction = sFunction.GetToken(0,'('); // this should be the name of the function
+
+ sal_Int32 nType = ::connectivity::OSQLParser::getFunctionReturnType(sFunction,&rParser.getContext());
+ if ( nType == DataType::OTHER || (!sFunction.Len() && pEntry->isNumericOrAggreateFunction()) )
+ {
+ // first try the international version
+ ::rtl::OUString sSql;
+ sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * "));
+ sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FROM x WHERE "));
+ sSql += pEntry->GetField();
+ sSql += _sCriteria;
+ ::std::auto_ptr<OSQLParseNode> pParseNode( rParser.parseTree( _rsErrorMessage, sSql, sal_True ) );
+ nType = DataType::DOUBLE;
+ if ( pParseNode.get() )
+ {
+ OSQLParseNode* pColumnRef = pParseNode->getByRule(OSQLParseNode::column_ref);
+ if ( pColumnRef )
+ {
+ OTableFieldDescRef aField = new OTableFieldDesc();
+ if ( eOk == FillDragInfo(this,pColumnRef,aField) )
+ {
+ nType = aField->GetDataType();
+ }
+ }
+ }
+ }
+
+ Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
+ parse::OParseColumn* pColumn = new parse::OParseColumn( pEntry->GetField(),
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ::rtl::OUString(),
+ ColumnValue::NULLABLE_UNKNOWN,
+ 0,
+ 0,
+ nType,
+ sal_False,
+ sal_False,
+ xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers());
+ _rxColumn = pColumn;
+ pColumn->setFunction(sal_True);
+ pColumn->setRealName(pEntry->GetField());
+ }
+ else
+ {
+ if (pWin)
+ {
+ Reference<XNameAccess> xColumns = pWin->GetOriginalColumns();
+ if (xColumns.is() && xColumns->hasByName(pEntry->GetField()))
+ xColumns->getByName(pEntry->GetField()) >>= _rxColumn;
+ }
+ }
+
+ OSQLParseNode* pParseNode = rParser.predicateTree( _rsErrorMessage,
+ sTest,
+ static_cast<OQueryController&>(getController()).getNumberFormatter(),
+ _rxColumn);
+ return pParseNode;
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::GetFocus()
+{
+ OQueryView::GetFocus();
+ if ( m_pSelectionBox && !m_pSelectionBox->HasChildPathFocus() )
+ {
+ // first we have to deactivate the current cell to refill when nescessary
+ m_pSelectionBox->DeactivateCell();
+ m_pSelectionBox->ActivateCell(m_pSelectionBox->GetCurRow(), m_pSelectionBox->GetCurColumnId());
+ m_pSelectionBox->GrabFocus();
+ }
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::reset()
+{
+ m_pTableView->ClearAll();
+ m_pTableView->ReSync();
+}
+// -----------------------------------------------------------------------------
+void OQueryDesignView::setNoneVisbleRow(sal_Int32 _nRows)
+{
+ m_pSelectionBox->SetNoneVisbleRow(_nRows);
+}
+
+// -----------------------------------------------------------------------------
+void OQueryDesignView::initByFieldDescriptions( const Sequence< PropertyValue >& i_rFieldDescriptions )
+{
+ OQueryController& rController = static_cast< OQueryController& >( getController() );
+
+ m_pSelectionBox->PreFill();
+ m_pSelectionBox->SetReadOnly( rController.isReadOnly() );
+ m_pSelectionBox->Fill();
+
+ for ( const PropertyValue* field = i_rFieldDescriptions.getConstArray();
+ field != i_rFieldDescriptions.getConstArray() + i_rFieldDescriptions.getLength();
+ ++field
+ )
+ {
+ ::vos::ORef< OTableFieldDesc > pField( new OTableFieldDesc() );
+ pField->Load( *field, true );
+ InsertField( pField, sal_True, sal_False );
+ }
+
+ rController.getUndoMgr()->Clear();
+ m_pSelectionBox->Invalidate();
+}
+
+// -----------------------------------------------------------------------------
+bool OQueryDesignView::initByParseIterator( ::dbtools::SQLExceptionInfo* _pErrorInfo )
+{
+ SqlParseError eErrorCode = eNativeMode;
+ m_rController.clearError();
+
+ try
+ {
+ eErrorCode = InitFromParseNodeImpl( this, m_pSelectionBox );
+
+ if ( eErrorCode != eOk )
+ {
+ if ( !m_rController.hasError() )
+ m_rController.appendError( getParseErrorMessage( eErrorCode ) );
+
+ if ( _pErrorInfo )
+ {
+ *_pErrorInfo = m_rController.getError();
+ }
+ else
+ {
+ m_rController.displayError();
+ }
+ }
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+ return eErrorCode == eOk;
+}
+//------------------------------------------------------------------------------
+void OQueryDesignView::fillFunctionInfo( const ::connectivity::OSQLParseNode* pNode
+ ,const ::rtl::OUString& sFunctionTerm
+ ,OTableFieldDescRef& aInfo)
+{
+ // get the type out of the funtion name
+ OQueryController& rController = static_cast<OQueryController&>(getController());
+ sal_Int32 nDataType = DataType::DOUBLE;
+ ::rtl::OUString sFieldName = sFunctionTerm;
+ OSQLParseNode* pFunctionName = pNode->getChild(0);
+ if ( !SQL_ISPUNCTUATION(pFunctionName,"{") )
+ {
+ if ( SQL_ISRULEOR2(pNode,length_exp,char_value_fct) )
+ pFunctionName = pFunctionName->getChild(0);
+
+ ::rtl::OUString sFunctionName = pFunctionName->getTokenValue();
+ if ( !sFunctionName.getLength() )
+ sFunctionName = ::rtl::OStringToOUString(OSQLParser::TokenIDToStr(pFunctionName->getTokenID()),RTL_TEXTENCODING_UTF8);
+
+ nDataType = OSQLParser::getFunctionReturnType(
+ sFunctionName
+ ,&rController.getParser().getContext());
+ }
+ aInfo->SetDataType(nDataType);
+ aInfo->SetFieldType(TAB_NORMAL_FIELD);
+ aInfo->SetField(sFieldName);
+ aInfo->SetTabWindow(NULL);
+}
+// -----------------------------------------------------------------------------