diff options
Diffstat (limited to 'dbaccess/source/ui/querydesign/querycontroller.cxx')
-rw-r--r-- | dbaccess/source/ui/querydesign/querycontroller.cxx | 1868 |
1 files changed, 1868 insertions, 0 deletions
diff --git a/dbaccess/source/ui/querydesign/querycontroller.cxx b/dbaccess/source/ui/querydesign/querycontroller.cxx new file mode 100644 index 000000000000..06b6804fa9be --- /dev/null +++ b/dbaccess/source/ui/querydesign/querycontroller.cxx @@ -0,0 +1,1868 @@ +/************************************************************************* + * + * 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" + +#include "adtabdlg.hxx" +#include "browserids.hxx" +#include "dbu_qry.hrc" +#include "dbu_reghelper.hxx" +#include "dbustrings.hrc" +#include "defaultobjectnamecheck.hxx" +#include "dlgsave.hxx" +#include "localresaccess.hxx" +#include "QTableWindow.hxx" +#include "QTableWindowData.hxx" +#include "querycontainerwindow.hxx" +#include "querycontroller.hxx" +#include "QueryDesignView.hxx" +#include "QueryTableView.hxx" +#include "QueryTextView.hxx" +#include "queryview.hxx" +#include "QueryViewSwitch.hxx" +#include "sqlmessage.hxx" +#include "TableConnectionData.hxx" +#include "TableFieldDescription.hxx" +#include "UITools.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XLoadEventListener.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdb/XQueriesSupplier.hpp> +#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp> +#include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/sdbc/XRow.hpp> +#include <com/sun/star/sdbcx/XAppend.hpp> +#include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> +#include <com/sun/star/sdbcx/XDrop.hpp> +#include <com/sun/star/sdbcx/XTablesSupplier.hpp> +#include <com/sun/star/sdbcx/XViewsSupplier.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/VetoException.hpp> +#include <com/sun/star/frame/XUntitledNumbers.hpp> +/** === end UNO includes === **/ + +#include <comphelper/basicio.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/property.hxx> +#include <comphelper/seqstream.hxx> +#include <comphelper/streamsection.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <sfx2/sfxsids.hrc> +#include <svtools/localresaccess.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/msgbox.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> + +extern "C" void SAL_CALL createRegistryInfo_OQueryControl() +{ + static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OQueryController > aAutoRegistration; +} +namespace dbaui +{ + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::frame; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::lang; + + class OViewController : public OQueryController + { + //------------------------------------------------------------------------------ + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( RuntimeException ) + { + return getImplementationName_Static(); + } + //------------------------------------------------------------------------- + virtual Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_Static(); + } + public: + OViewController(const Reference< XMultiServiceFactory >& _rM) : OQueryController(_rM){} + + // need by registration + static ::rtl::OUString getImplementationName_Static() throw( RuntimeException ) + { + return ::rtl::OUString::createFromAscii("org.openoffice.comp.dbu.OViewDesign"); + } + static Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( RuntimeException ) + { + Sequence< ::rtl::OUString> aSupported(1); + aSupported.getArray()[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.ViewDesign"); + return aSupported; + } + static Reference< XInterface > SAL_CALL Create(const Reference< XMultiServiceFactory >& _rM) + { + return *(new OViewController(_rM)); + } + }; +} +extern "C" void SAL_CALL createRegistryInfo_OViewControl() +{ + static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OViewController > aAutoRegistration; +} + +namespace dbaui +{ + using namespace ::connectivity; +#if OSL_DEBUG_LEVEL > 1 + namespace + { + // ----------------------------------------------------------------------------- + void insertParseTree(SvTreeListBox* _pBox,::connectivity::OSQLParseNode* _pNode,SvLBoxEntry* _pParent = NULL) + { + ::rtl::OUString rString; + if (!_pNode->isToken()) + { + // Regelnamen als rule: ... + rString = ::rtl::OUString::createFromAscii("RULE_ID: "); + rString += ::rtl::OUString::valueOf( (sal_Int32)_pNode->getRuleID()); + rString+= ::rtl::OUString::createFromAscii("("); + rString += OSQLParser::RuleIDToStr(_pNode->getRuleID()); + rString+= ::rtl::OUString::createFromAscii(")"); + + + _pParent = _pBox->InsertEntry(rString,_pParent); + + // einmal auswerten wieviel Subtrees dieser Knoten besitzt + sal_uInt32 nStop = _pNode->count(); + // hol dir den ersten Subtree + for(sal_uInt32 i=0;i<nStop;++i) + insertParseTree(_pBox,_pNode->getChild(i),_pParent); + } + else + { + // ein Token gefunden + // tabs fuer das Einruecken entsprechend nLevel + + switch (_pNode->getNodeType()) + { + + case SQL_NODE_KEYWORD: + { + rString+= ::rtl::OUString::createFromAscii("SQL_KEYWORD:"); + ::rtl::OString sT = OSQLParser::TokenIDToStr(_pNode->getTokenID()); + rString += ::rtl::OUString(sT,sT.getLength(),RTL_TEXTENCODING_UTF8); + break;} + + case SQL_NODE_COMPARISON: + {rString+= ::rtl::OUString::createFromAscii("SQL_COMPARISON:"); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + // und beginne neu Zeile + break;} + + case SQL_NODE_NAME: + {rString+= ::rtl::OUString::createFromAscii("SQL_NAME:"); + rString+= ::rtl::OUString::createFromAscii("\""); + rString += _pNode->getTokenValue(); + rString+= ::rtl::OUString::createFromAscii("\""); + + break;} + + case SQL_NODE_STRING: + {rString += ::rtl::OUString::createFromAscii("SQL_STRING:'"); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_INTNUM: + {rString += ::rtl::OUString::createFromAscii("SQL_INTNUM:"); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_APPROXNUM: + {rString += ::rtl::OUString::createFromAscii("SQL_APPROXNUM:"); + rString += _pNode->getTokenValue(); + break;} + + case SQL_NODE_PUNCTUATION: + {rString += ::rtl::OUString::createFromAscii("SQL_PUNCTUATION:"); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + break;} + + case SQL_NODE_AMMSC: + {rString += ::rtl::OUString::createFromAscii("SQL_AMMSC:"); + rString += _pNode->getTokenValue(); // haenge Nodevalue an + + break;} + + default: + OSL_ASSERT("OSQLParser::ShowParseTree: unzulaessiger NodeType"); + rString += _pNode->getTokenValue(); + } + _pBox->InsertEntry(rString,_pParent); + } + } + } +#endif // OSL_DEBUG_LEVEL + + namespace + { + // ----------------------------------------------------------------------------- + String lcl_getObjectResourceString( USHORT _nResId, sal_Int32 _nCommandType ) + { + String sMessageText = String( ModuleRes( _nResId ) ); + String sObjectType; + { + LocalResourceAccess aLocalRes( RSC_QUERY_OBJECT_TYPE, RSC_RESOURCE ); + sObjectType = String( ModuleRes( (USHORT)( _nCommandType + 1 ) ) ); + } + sMessageText.SearchAndReplace( String::CreateFromAscii( "$object$" ), sObjectType ); + return sMessageText; + } + } + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::awt; +using namespace ::dbtools; + +using namespace ::comphelper; + +namespace +{ + void ensureToolbars( OQueryController& _rController, sal_Bool _bDesign ) + { + Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager = _rController.getLayoutManager( _rController.getFrame() ); + if ( xLayoutManager.is() ) + { + xLayoutManager->lock(); + static ::rtl::OUString s_sDesignToolbar(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/designobjectbar")); + static ::rtl::OUString s_sSqlToolbar(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/sqlobjectbar")); + if ( _bDesign ) + { + xLayoutManager->destroyElement( s_sSqlToolbar ); + xLayoutManager->createElement( s_sDesignToolbar ); + } + else + { + xLayoutManager->destroyElement( s_sDesignToolbar ); + xLayoutManager->createElement( s_sSqlToolbar ); + } + xLayoutManager->unlock(); + xLayoutManager->doLayout(); + } + } +} + +//------------------------------------------------------------------------------ +::rtl::OUString SAL_CALL OQueryController::getImplementationName() throw( RuntimeException ) +{ + return getImplementationName_Static(); +} + +//------------------------------------------------------------------------------ +::rtl::OUString OQueryController::getImplementationName_Static() throw( RuntimeException ) +{ + return ::rtl::OUString::createFromAscii("org.openoffice.comp.dbu.OQueryDesign"); +} +//------------------------------------------------------------------------------ +Sequence< ::rtl::OUString> OQueryController::getSupportedServiceNames_Static(void) throw( RuntimeException ) +{ + Sequence< ::rtl::OUString> aSupported(1); + aSupported.getArray()[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdb.QueryDesign"); + return aSupported; +} +//------------------------------------------------------------------------- +Sequence< ::rtl::OUString> SAL_CALL OQueryController::getSupportedServiceNames() throw(RuntimeException) +{ + return getSupportedServiceNames_Static(); +} +// ------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL OQueryController::Create(const Reference<XMultiServiceFactory >& _rxFactory) +{ + return *(new OQueryController(_rxFactory)); +} +DBG_NAME(OQueryController); +// ----------------------------------------------------------------------------- +OQueryController::OQueryController(const Reference< XMultiServiceFactory >& _rM) + :OJoinController(_rM) + ,OQueryController_PBase( getBroadcastHelper() ) + ,m_pParseContext( new svxform::OSystemParseContext ) + ,m_aSqlParser( _rM, m_pParseContext ) + ,m_pSqlIterator(NULL) + ,m_nVisibleRows(0x400) + ,m_nSplitPos(-1) + ,m_nCommandType( CommandType::QUERY ) + ,m_bGraphicalDesign(sal_False) + ,m_bDistinct(sal_False) + ,m_bViewAlias(sal_False) + ,m_bViewTable(sal_False) + ,m_bViewFunction(sal_False) + ,m_bEscapeProcessing(sal_True) +{ + DBG_CTOR(OQueryController,NULL); + InvalidateAll(); + + registerProperty( PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, PropertyAttribute::READONLY | PropertyAttribute::BOUND, + &m_sStatement, ::getCppuType( &m_sStatement ) ); + registerProperty( PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::READONLY | PropertyAttribute::BOUND, + &m_bEscapeProcessing, ::getCppuType( &m_bEscapeProcessing ) ); +} + +// ----------------------------------------------------------------------------- +OQueryController::~OQueryController() +{ + DBG_DTOR(OQueryController,NULL); + if ( !getBroadcastHelper().bDisposed && !getBroadcastHelper().bInDispose ) + { + OSL_ENSURE(0,"Please check who doesn't dispose this component!"); + // increment ref count to prevent double call of Dtor + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +IMPLEMENT_FORWARD_XINTERFACE2( OQueryController, OJoinController, OQueryController_PBase ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController, OJoinController, OQueryController_PBase ) + +//------------------------------------------------------------------------- +Reference< XPropertySetInfo > SAL_CALL OQueryController::getPropertySetInfo() throw(RuntimeException) +{ + Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; +} + +//------------------------------------------------------------------------- +sal_Bool SAL_CALL OQueryController::convertFastPropertyValue( Any& o_rConvertedValue, Any& o_rOldValue, sal_Int32 i_nHandle, const Any& i_rValue ) throw (IllegalArgumentException) +{ + return OPropertyContainer::convertFastPropertyValue( o_rConvertedValue, o_rOldValue, i_nHandle, i_rValue ); +} + +//------------------------------------------------------------------------- +void SAL_CALL OQueryController::setFastPropertyValue_NoBroadcast( sal_Int32 i_nHandle, const Any& i_rValue ) throw ( Exception ) +{ + OPropertyContainer::setFastPropertyValue_NoBroadcast( i_nHandle, i_rValue ); +} + +//------------------------------------------------------------------------- +void SAL_CALL OQueryController::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const +{ + switch ( i_nHandle ) + { + case PROPERTY_ID_CURRENT_QUERY_DESIGN: + { + ::comphelper::NamedValueCollection aCurrentDesign; + aCurrentDesign.put( "GraphicalDesign", isGraphicalDesign() ); + aCurrentDesign.put( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing ); + + if ( isGraphicalDesign() ) + { + getContainer()->SaveUIConfig(); + saveViewSettings( aCurrentDesign, true ); + aCurrentDesign.put( "Statement", m_sStatement ); + } + else + { + aCurrentDesign.put( "Statement", getContainer()->getStatement() ); + } + + o_rValue <<= aCurrentDesign.getPropertyValues(); + } + break; + + default: + OPropertyContainer::getFastPropertyValue( o_rValue, i_nHandle ); + break; + } +} + +//------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper& OQueryController::getInfoHelper() +{ + return *const_cast< OQueryController* >( this )->getArrayHelper(); +} + +//-------------------------------------------------------------------- +::cppu::IPropertyArrayHelper* OQueryController::createArrayHelper( ) const +{ + Sequence< Property > aProps; + describeProperties( aProps ); + + // one additional property: + const sal_Int32 nLength = aProps.getLength(); + aProps.realloc( nLength + 1 ); + aProps[ nLength ] = Property( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CurrentQueryDesign" ) ), + PROPERTY_ID_CURRENT_QUERY_DESIGN, + ::cppu::UnoType< Sequence< PropertyValue > >::get(), + PropertyAttribute::READONLY + ); + + ::std::sort( + aProps.getArray(), + aProps.getArray() + aProps.getLength(), + ::comphelper::PropertyCompareByName() + ); + + return new ::cppu::OPropertyArrayHelper(aProps); +} + +// ----------------------------------------------------------------------------- +void OQueryController::deleteIterator() +{ + if(m_pSqlIterator) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->dispose(); + delete m_pSqlIterator; + m_pSqlIterator = NULL; + } +} +// ----------------------------------------------------------------------------- +void OQueryController::disposing() +{ + OQueryController_PBase::disposing(); + + deleteIterator(); + + delete m_pParseContext; + + clearFields(); + OTableFields().swap(m_vUnUsedFieldsDesc); + + ::comphelper::disposeComponent(m_xComposer); + OJoinController::disposing(); + OQueryController_PBase::disposing(); +} +// ----------------------------------------------------------------------------- +void OQueryController::clearFields() +{ + OTableFields().swap(m_vTableFieldDesc); +} +// ----------------------------------------------------------------------------- +FeatureState OQueryController::GetState(sal_uInt16 _nId) const +{ + FeatureState aReturn; + aReturn.bEnabled = sal_True; + // (disabled automatically) + + switch (_nId) + { + case ID_BROWSER_EDITDOC: + if ( editingCommand() ) + aReturn.bEnabled = sal_False; + else if ( editingView() && !m_xAlterView.is() ) + aReturn.bEnabled = sal_False; + else + aReturn = OJoinController::GetState( _nId ); + break; + + case ID_BROWSER_ESACPEPROCESSING: + aReturn.bChecked = !m_bEscapeProcessing; + aReturn.bEnabled = ( m_pSqlIterator != NULL ) && !m_bGraphicalDesign; + break; + case SID_RELATION_ADD_RELATION: + aReturn.bEnabled = isEditable() && m_bGraphicalDesign && m_vTableData.size() > 1; + break; + case ID_BROWSER_SAVEASDOC: + aReturn.bEnabled = !editingCommand() && !editingView() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty())); + break; + case ID_BROWSER_SAVEDOC: + aReturn.bEnabled = impl_isModified() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty())); + break; + case SID_PRINTDOCDIRECT: + break; + case ID_BROWSER_CUT: + aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isCutAllowed(); + break; + case ID_BROWSER_COPY: + aReturn.bEnabled = getContainer() && getContainer()->isCopyAllowed(); + break; + case ID_BROWSER_PASTE: + aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isPasteAllowed(); + break; + case ID_BROWSER_SQL: + aReturn.bEnabled = m_bEscapeProcessing && m_pSqlIterator; + aReturn.bChecked = m_bGraphicalDesign; + break; + case SID_BROWSER_CLEAR_QUERY: + aReturn.bEnabled = isEditable() && (m_sStatement.getLength() || !m_vTableData.empty()); + break; + case SID_QUERY_VIEW_FUNCTIONS: + case SID_QUERY_VIEW_TABLES: + case SID_QUERY_VIEW_ALIASES: + aReturn.bChecked = getContainer() && getContainer()->isSlotEnabled(_nId); + aReturn.bEnabled = m_bGraphicalDesign; + break; + case SID_QUERY_DISTINCT_VALUES: + aReturn.bEnabled = m_bGraphicalDesign && isEditable(); + aReturn.bChecked = m_bDistinct; + break; + case ID_BROWSER_QUERY_EXECUTE: + aReturn.bEnabled = sal_True; + break; + case SID_DB_QUERY_PREVIEW: + aReturn.bEnabled = sal_True; + aReturn.bChecked = getContainer() && getContainer()->getPreviewFrame().is(); + break; +#if OSL_DEBUG_LEVEL > 1 + case ID_EDIT_QUERY_SQL: + break; + case ID_EDIT_QUERY_DESIGN: + break; +#endif + case ID_BROWSER_ADDTABLE: + if ( !m_bGraphicalDesign ) + { + aReturn.bEnabled = sal_False; + break; + } + // run through + default: + aReturn = OJoinController::GetState(_nId); + break; + } + return aReturn; +} +// ----------------------------------------------------------------------------- +void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs) +{ + switch(_nId) + { + case ID_BROWSER_ESACPEPROCESSING: + setEscapeProcessing_fireEvent( !m_bEscapeProcessing ); + if ( !editingView() ) + setModified(sal_True); + InvalidateFeature(ID_BROWSER_SQL); + break; + case ID_BROWSER_SAVEASDOC: + case ID_BROWSER_SAVEDOC: + doSaveAsDoc(ID_BROWSER_SAVEASDOC == _nId); + break; + case SID_RELATION_ADD_RELATION: + { + OJoinDesignView* pView = getJoinView(); + if( pView ) + static_cast<OQueryTableView*>(pView->getTableView())->createNewConnection(); + } + break; + case SID_PRINTDOCDIRECT: + break; + case ID_BROWSER_CUT: + getContainer()->cut(); + break; + case ID_BROWSER_COPY: + getContainer()->copy(); + break; + case ID_BROWSER_PASTE: + getContainer()->paste(); + break; + case ID_BROWSER_SQL: + { + if ( !getContainer()->checkStatement() ) + break; + SQLExceptionInfo aError; + try + { + ::rtl::OUString aErrorMsg; + setStatement_fireEvent( getContainer()->getStatement() ); + if(!m_sStatement.getLength() && m_pSqlIterator) + { + // change the view of the data + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree(NULL); + m_bGraphicalDesign = !m_bGraphicalDesign; + impl_setViewMode( &aError ); + } + else + { + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree(aErrorMsg,m_sStatement,m_bGraphicalDesign); + if ( pNode ) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree(pNode); + m_pSqlIterator->traverseAll(); + + if ( m_pSqlIterator->hasErrors() ) + { + aError = m_pSqlIterator->getErrors(); + } + else + { + const OSQLTables& xTabs = m_pSqlIterator->getTables(); + if ( m_pSqlIterator->getStatementType() != SQL_STATEMENT_SELECT || xTabs.begin() == xTabs.end() ) + { + aError = SQLException( + String( ModuleRes( STR_QRY_NOSELECT ) ), + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ), + 1000, + Any() + ); + } + else + { + // change the view of the data + m_bGraphicalDesign = !m_bGraphicalDesign; + ::rtl::OUString sNewStatement; + pNode->parseNodeToStr( sNewStatement, getConnection() ); + setStatement_fireEvent( sNewStatement ); + getContainer()->SaveUIConfig(); + m_vTableConnectionData.clear(); + impl_setViewMode( &aError ); + } + } + } + else + { + aError = SQLException( + String( ModuleRes( STR_QRY_SYNTAX ) ), + NULL, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "S1000" ) ), + 1000, + Any() + ); + } + } + } + catch(const SQLException& e) + { + aError = ::cppu::getCaughtException(); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( aError.isValid() ) + showError( aError ); + + if(m_bGraphicalDesign) + { + InvalidateFeature(ID_BROWSER_ADDTABLE); + InvalidateFeature(SID_RELATION_ADD_RELATION); + } + } + break; + case SID_BROWSER_CLEAR_QUERY: + { + getUndoMgr()->EnterListAction( String( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), String() ); + getContainer()->clear(); + getUndoMgr()->LeaveListAction(); + + setStatement_fireEvent( ::rtl::OUString() ); + if(m_bGraphicalDesign) + InvalidateFeature(ID_BROWSER_ADDTABLE); + } + // InvalidateFeature(ID_BROWSER_QUERY_EXECUTE); + break; + case SID_QUERY_VIEW_FUNCTIONS: + case SID_QUERY_VIEW_TABLES: + case SID_QUERY_VIEW_ALIASES: + getContainer()->setSlotEnabled(_nId,!getContainer()->isSlotEnabled(_nId)); + setModified(sal_True); + break; + case SID_QUERY_DISTINCT_VALUES: + m_bDistinct = !m_bDistinct; + setModified(sal_True); + break; + case ID_BROWSER_QUERY_EXECUTE: + if ( getContainer()->checkStatement() ) + executeQuery(); + break; + case SID_DB_QUERY_PREVIEW: + try + { + Reference< ::com::sun::star::util::XCloseable > xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY ); + if ( xCloseFrame.is() ) + { + try + { + xCloseFrame->close( sal_True ); + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" ); + } + } + else + Execute(ID_BROWSER_QUERY_EXECUTE,Sequence< PropertyValue >()); + } + catch(Exception&) + { + } + break; + case ID_QUERY_ZOOM_IN: + { +// m_aZoom *= Fraction(1,10); +// static_cast<OQueryViewSwitch*>(getView())->zoomTableView(m_aZoom); + } + break; + case ID_QUERY_ZOOM_OUT: + { +// if(m_aZoom != Fraction(1,1)) +// m_aZoom /= Fraction(1,10); +// static_cast<OQueryViewSwitch*>(getView())->zoomTableView(m_aZoom); + } + break; +#if OSL_DEBUG_LEVEL > 1 + case ID_EDIT_QUERY_DESIGN: + case ID_EDIT_QUERY_SQL: + { + ::rtl::OUString aErrorMsg; + setStatement_fireEvent( getContainer()->getStatement() ); + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); + if ( pNode ) + { + Window* pView = getView(); + ModalDialog* pWindow = new ModalDialog( pView, WB_STDMODAL | WB_SIZEMOVE | WB_CENTER ); + pWindow->SetSizePixel( ::Size( pView->GetSizePixel().Width() / 2, pView->GetSizePixel().Height() / 2 ) ); + SvTreeListBox* pTreeBox = new SvTreeListBox( pWindow, WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HASLINESATROOT | WB_VSCROLL ); + pTreeBox->SetPosSizePixel( ::Point( 6, 6 ), ::Size( pWindow->GetSizePixel().Width() - 12, pWindow->GetSizePixel().Height() - 12 )); + pTreeBox->SetNodeDefaultImages(); + + if ( _nId == ID_EDIT_QUERY_DESIGN ) + { + ::connectivity::OSQLParseNode* pTemp = pNode ? pNode->getChild(3)->getChild(1) : NULL; + // no where clause found + if ( pTemp && !pTemp->isLeaf() ) + { + ::connectivity::OSQLParseNode * pCondition = pTemp->getChild(1); + if ( pCondition ) // no where clause + { + ::connectivity::OSQLParseNode::negateSearchCondition(pCondition); + ::connectivity::OSQLParseNode *pNodeTmp = pTemp->getChild(1); + + ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + ::connectivity::OSQLParseNode::absorptions(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + OSQLParseNode::compress(pNodeTmp); + pNodeTmp = pTemp->getChild(1); + } // if ( pCondition ) // no where clause + ::rtl::OUString sTemp; + pNode->parseNodeToStr(sTemp,getConnection()); + getContainer()->setStatement(sTemp); + + } + } + + insertParseTree(pTreeBox,pNode); + + pTreeBox->Show(); + pWindow->Execute(); + + delete pTreeBox; + delete pWindow; + delete pNode; + } + break; + } +#endif + default: + OJoinController::Execute(_nId,aArgs); + return; // else we would invalidate twice + } + InvalidateFeature(_nId); +} + +// ----------------------------------------------------------------------------- +void OQueryController::impl_showAutoSQLViewError( const ::com::sun::star::uno::Any& _rErrorDetails ) +{ + SQLContext aErrorContext; + aErrorContext.Message = lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT, m_nCommandType ); + aErrorContext.Context = *this; + aErrorContext.Details = lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW, m_nCommandType ); + aErrorContext.NextException = _rErrorDetails; + showError( aErrorContext ); +} + +// ----------------------------------------------------------------------------- +bool OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo ) +{ + OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" ); + + bool wasModified = isModified(); + + SQLExceptionInfo aError; + bool bSuccess = getContainer()->switchView( &aError ); + if ( !bSuccess ) + { + m_bGraphicalDesign = !m_bGraphicalDesign; + // restore old state + getContainer()->switchView( NULL ); + // don't pass &aError here, this would overwrite the error which the first switchView call + // returned in this location. + if ( _pErrorInfo ) + *_pErrorInfo = aError; + else + showError( aError ); + } + else + { + ensureToolbars( *this, m_bGraphicalDesign ); + } + + setModified( wasModified ); + return bSuccess; +} + +// ----------------------------------------------------------------------------- +void OQueryController::impl_initialize() +{ + OJoinController::impl_initialize(); + + const NamedValueCollection& rArguments( getInitParams() ); + + ::rtl::OUString sCommand; + m_nCommandType = CommandType::QUERY; + + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // ° reading parameters + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + // legacy parameters first (later overwritten by regular parameters) + ::rtl::OUString sIndependentSQLCommand; + if ( rArguments.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" ); + sCommand = sIndependentSQLCommand; + m_nCommandType = CommandType::COMMAND; + } + + ::rtl::OUString sCurrentQuery; + if ( rArguments.get_ensureType( "CurrentQuery", sCurrentQuery ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" ); + sCommand = sCurrentQuery; + m_nCommandType = CommandType::QUERY; + } + + sal_Bool bCreateView( sal_False ); + if ( rArguments.get_ensureType( "CreateView", bCreateView ) && bCreateView ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" ); + m_nCommandType = CommandType::TABLE; + } + + // non-legacy parameters which overwrite the legacy parameters + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_COMMAND, sCommand ); + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_COMMAND_TYPE, m_nCommandType ); + + // translate Command/Type into proper members + // TODO/Later: all this (including those members) should be hidden behind some abstact interface, + // which is implemented for all the three commands + switch ( m_nCommandType ) + { + case CommandType::QUERY: + m_sName = sCommand; + break; + case CommandType::TABLE: + m_sName = sCommand; + break; + case CommandType::COMMAND: + setStatement_fireEvent( sCommand ); + m_sName = ::rtl::OUString(); + break; + default: + OSL_ENSURE( false, "OQueryController::impl_initialize: logic error in code!" ); + throw RuntimeException(); + } + + // more legacy parameters + sal_Bool bGraphicalDesign( sal_True ); + if ( rArguments.get_ensureType( (::rtl::OUString)PROPERTY_QUERYDESIGNVIEW, bGraphicalDesign ) ) + { + OSL_ENSURE( false, "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" ); + m_bGraphicalDesign = bGraphicalDesign; + } + + // more non-legacy + rArguments.get_ensureType( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign ); + + bool bEscapeProcessing( sal_True ); + if ( rArguments.get_ensureType( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing ) ) + { + setEscapeProcessing_fireEvent( bEscapeProcessing ); + + OSL_ENSURE( m_bEscapeProcessing || !m_bGraphicalDesign, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" ); + if ( !m_bEscapeProcessing ) + m_bGraphicalDesign = false; + } + + // ................................................................................................................. + // . initial design + bool bForceInitialDesign = false; + Sequence< PropertyValue > aCurrentQueryDesignProps; + aCurrentQueryDesignProps = rArguments.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps ); + + if ( aCurrentQueryDesignProps.getLength() ) + { + ::comphelper::NamedValueCollection aCurrentQueryDesign( aCurrentQueryDesignProps ); + if ( aCurrentQueryDesign.has( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN ) ) + { + aCurrentQueryDesign.get_ensureType( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign ); + } + if ( aCurrentQueryDesign.has( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING ) ) + { + aCurrentQueryDesign.get_ensureType( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing ); + } + if ( aCurrentQueryDesign.has( "Statement" ) ) + { + ::rtl::OUString sStatement; + aCurrentQueryDesign.get_ensureType( "Statement", sStatement ); + aCurrentQueryDesign.remove( "Statement" ); + setStatement_fireEvent( sStatement ); + } + + loadViewSettings( aCurrentQueryDesign ); + + bForceInitialDesign = true; + } + + // °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + if ( !ensureConnected( sal_False ) ) + { // we have no connection so what else should we do + m_bGraphicalDesign = sal_False; + if ( editingView() ) + { + connectionLostMessage(); + throw SQLException(); + } + } + + // check the view capabilities + if ( isConnected() && editingView() ) + { + Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY ); + Reference< XNameAccess > xViews; + if ( xViewsSup.is() ) + xViews = xViewsSup->getViews(); + + if ( !xViews.is() ) + { // we can't create views so we ask if the user wants to create a query instead + m_nCommandType = CommandType::QUERY; + sal_Bool bClose = sal_False; + { + String aTitle( ModuleRes( STR_QUERYDESIGN_NO_VIEW_SUPPORT ) ); + String aMessage( ModuleRes( STR_QUERYDESIGN_NO_VIEW_ASK ) ); + ODataView* pWindow = getView(); + OSQLMessageBox aDlg( pWindow, aTitle, aMessage, WB_YES_NO | WB_DEF_YES, OSQLMessageBox::Query ); + bClose = aDlg.Execute() == RET_NO; + } + if ( bClose ) + throw VetoException(); + } + + // now if we are to edit an existing view, check whether this is possible + if ( m_sName.getLength() ) + { + Any aView( xViews->getByName( m_sName ) ); + // will throw if there is no such view + if ( !( aView >>= m_xAlterView ) ) + { + throw IllegalArgumentException( + ::rtl::OUString( String( ModuleRes( STR_NO_ALTER_VIEW_SUPPORT ) ) ), + *this, + 1 + ); + } + } + } + + OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!"); + + try + { + getContainer()->initialize(); + impl_reset( bForceInitialDesign ); + + SQLExceptionInfo aError; + const bool bAttemptedGraphicalDesign = m_bGraphicalDesign; + + if ( bForceInitialDesign ) + { + getContainer()->forceInitialView(); + } + else + { + impl_setViewMode( &aError ); + } + + if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign ) + { + // we tried initializing the graphical view, this failed, and we were automatically switched to SQL + // view => tell this to the user + if ( !editingView() ) + { + impl_showAutoSQLViewError( aError.get() ); + } + } + + getUndoMgr()->Clear(); + + if ( ( m_bGraphicalDesign ) + && ( ( !m_sName.getLength() && !editingCommand() ) + || ( !m_sStatement.getLength() && editingCommand() ) + ) + ) + { + Application::PostUserEvent( LINK( this, OQueryController, OnExecuteAddTable ) ); + } + + setModified(sal_False); + } + catch(SQLException& e) + { + DBG_UNHANDLED_EXCEPTION(); + // we caught an exception so we switch to text only mode + { + m_bGraphicalDesign = sal_False; + getContainer()->initialize(); + ODataView* pWindow = getView(); + OSQLMessageBox(pWindow,e).Execute(); + } + throw; + } +} + +// ----------------------------------------------------------------------------- +void OQueryController::onLoadedMenu(const Reference< ::com::sun::star::frame::XLayoutManager >& /*_xLayoutManager*/) +{ + ensureToolbars( *this, m_bGraphicalDesign ); +} + +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryController::getPrivateTitle( ) const +{ + ::rtl::OUString sName = m_sName; + if ( !sName.getLength() ) + { + if ( !editingCommand() ) + { + ::vos::OGuard aSolarGuard(Application::GetSolarMutex()); + ::osl::MutexGuard aGuard( getMutex() ); + String aDefaultName = String( ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE ) ); + sName = aDefaultName.GetToken(0,' '); + sName += ::rtl::OUString::valueOf(getCurrentStartNumber()); + } + } + return sName; +} +// ----------------------------------------------------------------------------- +void OQueryController::setQueryComposer() +{ + if(isConnected()) + { + Reference< XSQLQueryComposerFactory > xFactory(getConnection(), UNO_QUERY); + OSL_ENSURE(xFactory.is(),"Connection doesn't support a querycomposer"); + if ( xFactory.is() && getContainer() ) + { + try + { + m_xComposer = xFactory->createQueryComposer(); + getContainer()->setStatement(m_sStatement); + } + catch (Exception&) + { + m_xComposer = NULL; + } + OSL_ENSURE(m_xComposer.is(),"No querycomposer available!"); + Reference<XTablesSupplier> xTablesSup(getConnection(), UNO_QUERY); + deleteIterator(); + m_pSqlIterator = new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup->getTables(), m_aSqlParser, NULL ); + } + } +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryController::Construct(Window* pParent) +{ + // TODO: we have to check if we should create the text- or the design- view + + setView( * new OQueryContainerWindow( pParent, *this, getORB() ) ); + + return OJoinController::Construct(pParent); +} + +// ----------------------------------------------------------------------------- +OJoinDesignView* OQueryController::getJoinView() +{ + return getContainer()->getDesignView(); +} +// ----------------------------------------------------------------------------- +void OQueryController::describeSupportedFeatures() +{ + OJoinController::describeSupportedFeatures(); + implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT ); + implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESACPEPROCESSING,CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES, CommandGroup::FORMAT ); + implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE, CommandGroup::VIEW ); + implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT ); + implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW, CommandGroup::VIEW ); + +#if OSL_DEBUG_LEVEL > 1 + implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL ); + implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN ); +#endif +} +// ----------------------------------------------------------------------------- +void OQueryController::impl_onModifyChanged() +{ + OJoinController::impl_onModifyChanged(); + InvalidateFeature(SID_BROWSER_CLEAR_QUERY); + InvalidateFeature(ID_BROWSER_SAVEASDOC); + InvalidateFeature(ID_BROWSER_QUERY_EXECUTE); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryController::disposing( const EventObject& Source ) throw(RuntimeException) +{ + ::vos::OGuard aGuard(Application::GetSolarMutex()); + + if ( getContainer() && Source.Source.is() ) + { + if ( Source.Source == m_aCurrentFrame.getFrame() ) + { // our frame is beeing disposed -> close the preview window (if we have one) + Reference< XFrame > xPreviewFrame( getContainer()->getPreviewFrame() ); + ::comphelper::disposeComponent( xPreviewFrame ); + } + else if ( Source.Source == getContainer()->getPreviewFrame() ) + { + getContainer()->disposingPreview(); + } + } + + OJoinController::disposing(Source); +} +// ----------------------------------------------------------------------------- +void OQueryController::reconnect(sal_Bool _bUI) +{ + deleteIterator(); + ::comphelper::disposeComponent(m_xComposer); + + OJoinController::reconnect( _bUI ); + + if (isConnected()) + { + setQueryComposer(); + } + else + { + if(m_bGraphicalDesign) + { + m_bGraphicalDesign = sal_False; + // don't call Execute(SQL) because this changes the sql statement + impl_setViewMode( NULL ); + } + InvalidateAll(); + } +} + +// ----------------------------------------------------------------------------- +void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const +{ + saveTableWindows( o_rViewSettings ); + + OTableFields::const_iterator field = m_vTableFieldDesc.begin(); + OTableFields::const_iterator fieldEnd = m_vTableFieldDesc.end(); + + ::comphelper::NamedValueCollection aAllFieldsData; + ::comphelper::NamedValueCollection aFieldData; + for ( sal_Int32 i = 1; field != fieldEnd; ++field, ++i ) + { + if ( !(*field)->IsEmpty() ) + { + aFieldData.clear(); + (*field)->Save( aFieldData, i_includingCriteria ); + + const ::rtl::OUString sFieldSettingName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Field" ) ) + ::rtl::OUString::valueOf( i ); + aAllFieldsData.put( sFieldSettingName, aFieldData.getPropertyValues() ); + } + } + + o_rViewSettings.put( "Fields", aAllFieldsData.getPropertyValues() ); + o_rViewSettings.put( "SplitterPosition", m_nSplitPos ); + o_rViewSettings.put( "VisibleRows", m_nVisibleRows ); +} +// ----------------------------------------------------------------------------- +void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings ) +{ + loadTableWindows( o_rViewSettings ); + + m_nSplitPos = o_rViewSettings.getOrDefault( "SplitterPosition", m_nSplitPos ); + m_nVisibleRows = o_rViewSettings.getOrDefault( "VisibleRows", m_nVisibleRows ); + m_aFieldInformation = o_rViewSettings.getOrDefault( "Fields", m_aFieldInformation ); +} +// ----------------------------------------------------------------------------- +sal_Int32 OQueryController::getColWidth(sal_uInt16 _nColPos) const +{ + if ( _nColPos < m_aFieldInformation.getLength() ) + { + ::std::auto_ptr<OTableFieldDesc> pField( new OTableFieldDesc()); + pField->Load( m_aFieldInformation[ _nColPos ], false ); + return pField->GetColWidth(); + } + return 0; +} +// ----------------------------------------------------------------------------- +Reference<XNameAccess> OQueryController::getObjectContainer() const +{ + Reference< XNameAccess > xElements; + if ( editingView() ) + { + Reference< XViewsSupplier > xViewsSupp( getConnection(), UNO_QUERY ); + if ( xViewsSupp.is() ) + xElements = xViewsSupp->getViews(); + } + else + { + Reference< XQueriesSupplier > xQueriesSupp( getConnection(), UNO_QUERY ); + if ( xQueriesSupp.is() ) + xElements = xQueriesSupp->getQueries(); + else + { + Reference< XQueryDefinitionsSupplier > xQueryDefsSupp( getDataSource(), UNO_QUERY ); + if ( xQueryDefsSupp.is() ) + xElements = xQueryDefsSupp->getQueryDefinitions(); + } + } + + OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" ); + return xElements; +} + +// ----------------------------------------------------------------------------- +void OQueryController::executeQuery() +{ + // we don't need to check the connection here because we already check the composer + // which can't live without his connection + ::rtl::OUString sTranslatedStmt = translateStatement( false ); + + ::rtl::OUString sDataSourceName = getDataSourceName(); + if ( sDataSourceName.getLength() && sTranslatedStmt.getLength() ) + { + try + { + getContainer()->showPreview( getFrame() ); + InvalidateFeature(SID_DB_QUERY_PREVIEW); + + URL aWantToDispatch; + aWantToDispatch.Complete = ::rtl::OUString::createFromAscii(".component:DB/DataSourceBrowser"); + + ::rtl::OUString sFrameName( FRAME_NAME_QUERY_PREVIEW ); + sal_Int32 nSearchFlags = FrameSearchFlag::CHILDREN; + + Reference< XDispatch> xDisp; + Reference< XDispatchProvider> xProv( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY ); + if(!xProv.is()) + { + xProv.set( getFrame(), UNO_QUERY ); + if (xProv.is()) + xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags); + } + else + { + xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, FrameSearchFlag::SELF); + } + if (xDisp.is()) + { + Sequence< PropertyValue> aProps(9); + aProps[0].Name = PROPERTY_DATASOURCENAME; + aProps[0].Value <<= sDataSourceName; + + aProps[1].Name = PROPERTY_COMMAND_TYPE; + aProps[1].Value <<= CommandType::COMMAND; + + aProps[2].Name = PROPERTY_COMMAND; + aProps[2].Value <<= sTranslatedStmt; + + aProps[3].Name = PROPERTY_ENABLE_BROWSER; + aProps[3].Value = ::cppu::bool2any(sal_False); + + aProps[4].Name = PROPERTY_ACTIVE_CONNECTION; + aProps[4].Value <<= getConnection(); + + aProps[5].Name = PROPERTY_UPDATE_CATALOGNAME; + aProps[5].Value <<= m_sUpdateCatalogName; + + aProps[6].Name = PROPERTY_UPDATE_SCHEMANAME; + aProps[6].Value <<= m_sUpdateSchemaName; + + aProps[7].Name = PROPERTY_UPDATE_TABLENAME; + aProps[7].Value <<= m_sUpdateTableName; + + aProps[8].Name = PROPERTY_ESCAPE_PROCESSING; + aProps[8].Value = ::cppu::bool2any(m_bEscapeProcessing); + + xDisp->dispatch(aWantToDispatch, aProps); + // check the state of the beamer + // be notified when the beamer frame is closed + Reference< XComponent > xComponent( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY ); + if (xComponent.is()) + { + OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(), + "OQueryController::executeQuery: oops ... which window do I have here?"); + Reference< XEventListener> xEvtL((::cppu::OWeakObject*)this,UNO_QUERY); + xComponent->addEventListener(xEvtL); + } + } + else + { + OSL_ENSURE(0,"Couldn't create a beamer window!"); + } + } + catch(const Exception&) + { + OSL_ENSURE(0,"Couldn't create a beamer window!"); + } + } +} +// ----------------------------------------------------------------------------- +sal_Bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements,sal_Bool _bSaveAs) +{ + OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" ); + if ( editingCommand() ) + return sal_False; + + OSL_PRECOND( _xElements.is(), "OQueryController::askForNewName: invalid container!" ); + if ( !_xElements.is() ) + return sal_False; + + sal_Bool bRet = sal_True; + sal_Bool bNew = _bSaveAs || !_xElements->hasByName( m_sName ); + if(bNew) + { + String aDefaultName; + if ( ( _bSaveAs && !bNew ) || ( bNew && m_sName.getLength() ) ) + aDefaultName = String( m_sName ); + else + { + String sName = String( ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE ) ); + aDefaultName = sName.GetToken(0,' '); + //aDefaultName = getPrivateTitle( ); + aDefaultName = ::dbtools::createUniqueName(_xElements,aDefaultName); + } + + DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY ); + OSaveAsDlg aDlg( + getView(), + m_nCommandType, + getORB(), + getConnection(), + aDefaultName, + aNameChecker, + SAD_DEFAULT ); + + bRet = ( aDlg.Execute() == RET_OK ); + if ( bRet ) + { + m_sName = aDlg.getName(); + if ( editingView() ) + { + m_sUpdateCatalogName = aDlg.getCatalog(); + m_sUpdateSchemaName = aDlg.getSchema(); + } + } + } + return bRet; +} +// ----------------------------------------------------------------------------- +bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs) +{ + OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!"); + if ( !editingCommand() && !haveDataSource() ) + { + String aMessage(ModuleRes(STR_DATASOURCE_DELETED)); + OSQLWarningBox( getView(), aMessage ).Execute(); + return false; + } + + Reference< XNameAccess > xElements = getObjectContainer(); + if ( !xElements.is() ) + return false; + + if ( !getContainer()->checkStatement() ) + return false; + + ::rtl::OUString sTranslatedStmt = translateStatement(); + if ( editingCommand() ) + { + setModified( sal_False ); + // this is all we need to do here. translateStatement implicitly set our m_sStatement, and + // notified it, and that's all + return true; + } + + if ( !sTranslatedStmt.getLength() ) + return false; + + // first we need a name for our query so ask the user + // did we get a name + ::rtl::OUString sOriginalName( m_sName ); + if ( !askForNewName( xElements, _bSaveAs ) || !m_sName.getLength() ) + return false; + + SQLExceptionInfo aInfo; + bool bSuccess = false; + bool bNew = false; + try + { + bNew = ( _bSaveAs ) + || ( !xElements->hasByName( m_sName ) ); + + Reference<XPropertySet> xQuery; + if ( bNew ) // just to make sure the query already exists + { + // drop the query, in case it already exists + if ( xElements->hasByName( m_sName ) ) + { + Reference< XDrop > xNameCont( xElements, UNO_QUERY ); + if ( xNameCont.is() ) + xNameCont->dropByName( m_sName ); + else + { + Reference< XNameContainer > xCont( xElements, UNO_QUERY ); + if ( xCont.is() ) + xCont->removeByName( m_sName ); + } + } + + // create a new (empty, uninitialized) query resp. view + Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY ); + if ( xFact.is() ) + { + xQuery = xFact->createDataDescriptor(); + // to set the name is only allowed when the query is new + xQuery->setPropertyValue( PROPERTY_NAME, makeAny( m_sName ) ); + } + else + { + Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY ); + if ( xSingleFac.is() ) + xQuery = xQuery.query( xSingleFac->createInstance() ); + } + } + else + { + xElements->getByName( m_sName ) >>= xQuery; + } + if ( !xQuery.is() ) + throw RuntimeException(); + + // the new commands + if ( editingView() && !bNew ) + { + OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" ); + m_xAlterView.set( xQuery, UNO_QUERY_THROW ); + m_xAlterView->alterCommand( sTranslatedStmt ); + } + else + { // we're creating a query, or a *new* view + xQuery->setPropertyValue( PROPERTY_COMMAND, makeAny( sTranslatedStmt ) ); + + if ( editingView() ) + { + xQuery->setPropertyValue( PROPERTY_CATALOGNAME, makeAny( m_sUpdateCatalogName ) ); + xQuery->setPropertyValue( PROPERTY_SCHEMANAME, makeAny( m_sUpdateSchemaName ) ); + } + + if ( editingQuery() ) + { + xQuery->setPropertyValue( PROPERTY_UPDATE_TABLENAME, makeAny( m_sUpdateTableName ) ); + xQuery->setPropertyValue( PROPERTY_ESCAPE_PROCESSING,::cppu::bool2any( m_bEscapeProcessing ) ); + + xQuery->setPropertyValue( PROPERTY_LAYOUTINFORMATION, getViewData() ); + } + } + + if ( bNew ) + { + Reference< XAppend > xAppend( xElements, UNO_QUERY ); + if ( xAppend.is() ) + { + xAppend->appendByDescriptor( xQuery ); + } + else + { + Reference< XNameContainer > xCont( xElements, UNO_QUERY ); + if ( xCont.is() ) + xCont->insertByName( m_sName, makeAny( xQuery ) ); + } + + if ( editingView() ) + { + Reference< XPropertySet > xViewProps; + if ( xElements->hasByName( m_sName ) ) + xViewProps.set( xElements->getByName( m_sName ), UNO_QUERY ); + + if ( !xViewProps.is() ) // correct name and try again + m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::eInDataManipulation, false, false, false ); + + OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly creaed view does not exist!" ); + + if ( xElements->hasByName( m_sName ) ) + m_xAlterView.set( xElements->getByName( m_sName ), UNO_QUERY ); + + // now check if our datasource has set a tablefilter and if so, append the new table name to it + ::dbaui::appendToFilter( getConnection(), m_sName, getORB(), getView() ); + } // if ( editingView() ) + Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY); + if ( xEventListener.is() ) + { + TitleChangedEvent aEvent; + xEventListener->titleChanged(aEvent); + } + releaseNumberForComponent(); + } + + setModified( sal_False ); + bSuccess = true; + + } + catch( const SQLException& ) + { + if ( !bNew ) + m_sName = sOriginalName; + aInfo = SQLExceptionInfo( ::cppu::getCaughtException() ); + } + catch(Exception&) + { + if ( !bNew ) + m_sName = sOriginalName; + DBG_UNHANDLED_EXCEPTION(); + } + + showError( aInfo ); + + // update the title of our window + //updateTitle(); + + // if we successfully saved a view we were creating, then close the designer + if ( bSuccess && editingView() && !m_xAlterView.is() ) + { + closeTask(); + } + + if ( bSuccess && editingView() ) + InvalidateFeature( ID_BROWSER_EDITDOC ); + + return bSuccess; +} +// ----------------------------------------------------------------------------- +::rtl::OUString OQueryController::translateStatement( bool _bFireStatementChange ) +{ + // now set the properties + setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange ); + ::rtl::OUString sTranslatedStmt; + if(m_sStatement.getLength() && m_xComposer.is() && m_bEscapeProcessing) + { + try + { + ::rtl::OUString aErrorMsg; + + ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ); + if(pNode) + { + pNode->parseNodeToStr( sTranslatedStmt, getConnection() ); + delete pNode; + } + + m_xComposer->setQuery(sTranslatedStmt); + sTranslatedStmt = m_xComposer->getComposedQuery(); + } + catch(SQLException& e) + { + ::dbtools::SQLExceptionInfo aInfo(e); + showError(aInfo); + // an error occured so we clear the statement + sTranslatedStmt = ::rtl::OUString(); + } + } + else if(!m_sStatement.getLength()) + { + ModuleRes aModuleRes(STR_QRY_NOSELECT); + String sTmpStr(aModuleRes); + ::rtl::OUString sError(sTmpStr); + showError(SQLException(sError,NULL,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000") ),1000,Any())); + } + else + sTranslatedStmt = m_sStatement; + + return sTranslatedStmt; +} +// ----------------------------------------------------------------------------- +short OQueryController::saveModified() +{ + vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( getMutex() ); + short nRet = RET_YES; + if ( !isConnected() || !isModified() ) + return nRet; + + if ( !m_bGraphicalDesign + || ( !m_vTableFieldDesc.empty() + && !m_vTableData.empty() + ) + ) + { + String sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED, m_nCommandType ) ); + QueryBox aQry( getView(), WB_YES_NO_CANCEL | WB_DEF_YES, sMessageText ); + + nRet = aQry.Execute(); + if ( ( nRet == RET_YES ) + && !doSaveAsDoc( sal_False ) + ) + { + nRet = RET_CANCEL; + } + } + return nRet; +} +// ----------------------------------------------------------------------------- +void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings ) +{ + bool bValid = false; + + Sequence< PropertyValue > aLayoutInformation; + // get command from the query if a query name was supplied + if ( !i_bForceCurrentControllerSettings && !editingCommand() ) + { + if ( m_sName.getLength() ) + { + Reference< XNameAccess > xQueries = getObjectContainer(); + if ( xQueries.is() ) + { + Reference< XPropertySet > xProp; + if( xQueries->hasByName( m_sName ) && ( xQueries->getByName( m_sName ) >>= xProp ) && xProp.is() ) + { + ::rtl::OUString sNewStatement; + xProp->getPropertyValue( PROPERTY_COMMAND ) >>= sNewStatement; + setStatement_fireEvent( sNewStatement ); + + sal_Bool bNewEscapeProcessing( sal_True ); + if ( editingQuery() ) + { + xProp->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bNewEscapeProcessing; + setEscapeProcessing_fireEvent( bNewEscapeProcessing ); + } + + m_bGraphicalDesign = m_bGraphicalDesign && m_bEscapeProcessing; + bValid = true; + + try + { + if ( editingQuery() ) + xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation; + } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "OQueryController::impl_reset: could not retrieve the layout information from the query!" ); + } + } + } + } + } + else + { + bValid = true; + // assume that we got all necessary information during initialization + } + + if ( bValid ) + { + // load the layoutInformation + if ( aLayoutInformation.getLength() ) + { + try + { + loadViewSettings( aLayoutInformation ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + if ( m_sStatement.getLength() ) + { + setQueryComposer(); + + bool bError( false ); + + if ( !m_pSqlIterator ) + { + bError = true; + } + else if ( m_bEscapeProcessing ) + { + ::rtl::OUString aErrorMsg; + ::std::auto_ptr< ::connectivity::OSQLParseNode > pNode( + m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ) ); + + if ( pNode.get() ) + { + delete m_pSqlIterator->getParseTree(); + m_pSqlIterator->setParseTree( pNode.release() ); + m_pSqlIterator->traverseAll(); + if ( m_pSqlIterator->hasErrors() ) + { + if ( !i_bForceCurrentControllerSettings && m_bGraphicalDesign && !editingView() ) + { + impl_showAutoSQLViewError( makeAny( m_pSqlIterator->getErrors() ) ); + } + bError = true; + } + } + else + { + if ( !i_bForceCurrentControllerSettings && !editingView() ) + { + String aTitle(ModuleRes(STR_SVT_SQL_SYNTAX_ERROR)); + OSQLMessageBox aDlg(getView(),aTitle,aErrorMsg); + aDlg.Execute(); + } + bError = true; + } + } + + if ( bError ) + { + m_bGraphicalDesign = sal_False; + if ( editingView() ) + // if we're editing a view whose statement could not be parsed, default to "no escape processing" + setEscapeProcessing_fireEvent( sal_False ); + } + } + } + + if(!m_pSqlIterator) + setQueryComposer(); + OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!"); + + getContainer()->setNoneVisbleRow(m_nVisibleRows); +} + +// ----------------------------------------------------------------------------- +void OQueryController::reset() +{ + impl_reset(); + getContainer()->reset( NULL ); + getUndoMgr()->Clear(); +} + +// ----------------------------------------------------------------------------- +void OQueryController::setStatement_fireEvent( const ::rtl::OUString& _rNewStatement, bool _bFireStatementChange ) +{ + Any aOldValue = makeAny( m_sStatement ); + m_sStatement = _rNewStatement; + Any aNewValue = makeAny( m_sStatement ); + + sal_Int32 nHandle = PROPERTY_ID_ACTIVECOMMAND; + if ( _bFireStatementChange ) + fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +void OQueryController::setEscapeProcessing_fireEvent( const sal_Bool _bEscapeProcessing ) +{ + if ( _bEscapeProcessing == m_bEscapeProcessing ) + return; + + Any aOldValue = makeAny( m_bEscapeProcessing ); + m_bEscapeProcessing = _bEscapeProcessing; + Any aNewValue = makeAny( m_bEscapeProcessing ); + + sal_Int32 nHandle = PROPERTY_ID_ESCAPE_PROCESSING; + fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False ); +} + +// ----------------------------------------------------------------------------- +IMPL_LINK( OQueryController, OnExecuteAddTable, void*, /*pNotInterestedIn*/ ) +{ + Execute( ID_BROWSER_ADDTABLE,Sequence<PropertyValue>() ); + return 0L; +} + +// ----------------------------------------------------------------------------- +bool OQueryController::allowViews() const +{ + return true; +} + +// ----------------------------------------------------------------------------- +bool OQueryController::allowQueries() const +{ + DBG_ASSERT( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" ); + if ( !getSdbMetaData().supportsSubqueriesInFrom() ) + return false; + + const NamedValueCollection& rArguments( getInitParams() ); + sal_Int32 nCommandType = rArguments.getOrDefault( (::rtl::OUString)PROPERTY_COMMAND_TYPE, (sal_Int32)CommandType::QUERY ); + sal_Bool bCreatingView = ( nCommandType == CommandType::TABLE ); + return !bCreatingView; +} + +// ----------------------------------------------------------------------------- +Any SAL_CALL OQueryController::getViewData() throw( RuntimeException ) +{ + ::osl::MutexGuard aGuard( getMutex() ); + + getContainer()->SaveUIConfig(); + + ::comphelper::NamedValueCollection aViewSettings; + saveViewSettings( aViewSettings, false ); + + return makeAny( aViewSettings.getPropertyValues() ); +} +// ----------------------------------------------------------------------------- +void SAL_CALL OQueryController::restoreViewData(const Any& /*Data*/) throw( RuntimeException ) +{ + // TODO +} + +// ----------------------------------------------------------------------------- +} // namespace dbaui +// ----------------------------------------------------------------------------- + |