1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "adtabdlg.hxx"
21 #include "browserids.hxx"
22 #include "dbu_qry.hrc"
23 #include "dbu_reghelper.hxx"
24 #include "dbustrings.hrc"
25 #include "defaultobjectnamecheck.hxx"
26 #include "dlgsave.hxx"
27 #include "localresaccess.hxx"
28 #include "uiservices.hxx"
29 #include "QTableWindow.hxx"
30 #include "QTableWindowData.hxx"
31 #include "querycontainerwindow.hxx"
32 #include "querycontroller.hxx"
33 #include "QueryDesignView.hxx"
34 #include "QueryTableView.hxx"
35 #include "QueryTextView.hxx"
36 #include "queryview.hxx"
37 #include "QueryViewSwitch.hxx"
38 #include "sqlmessage.hxx"
39 #include "TableConnectionData.hxx"
40 #include "TableFieldDescription.hxx"
41 #include "UITools.hxx"
42 #include "QueryPropertiesDialog.hxx"
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/container/XChild.hpp>
46 #include <com/sun/star/container/XNameContainer.hpp>
47 #include <com/sun/star/frame/FrameSearchFlag.hpp>
48 #include <com/sun/star/frame/XLoadEventListener.hpp>
49 #include <com/sun/star/io/XActiveDataSink.hpp>
50 #include <com/sun/star/io/XActiveDataSource.hpp>
51 #include <com/sun/star/sdb/CommandType.hpp>
52 #include <com/sun/star/sdb/SQLContext.hpp>
53 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
54 #include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
55 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
56 #include <com/sun/star/sdbc/SQLWarning.hpp>
57 #include <com/sun/star/sdbc/XRow.hpp>
58 #include <com/sun/star/sdbcx/XAppend.hpp>
59 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
60 #include <com/sun/star/sdbcx/XDrop.hpp>
61 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
62 #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
63 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
64 #include <com/sun/star/util/XCloseable.hpp>
65 #include <com/sun/star/util/VetoException.hpp>
66 #include <com/sun/star/frame/XUntitledNumbers.hpp>
67 #include <com/sun/star/ui/XUIElement.hpp>
69 #include <comphelper/processfactory.hxx>
70 #include <comphelper/property.hxx>
71 #include <comphelper/seqstream.hxx>
72 #include <comphelper/streamsection.hxx>
73 #include <comphelper/types.hxx>
74 #include <connectivity/dbexception.hxx>
75 #include <connectivity/dbtools.hxx>
76 #include <cppuhelper/exc_hlp.hxx>
77 #include <sfx2/sfxsids.hrc>
78 #include <svtools/localresaccess.hxx>
79 #include <toolkit/helper/vclunohelper.hxx>
80 #include <tools/diagnose_ex.h>
81 #include <osl/diagnose.h>
82 #include <vcl/msgbox.hxx>
83 #include <vcl/svapp.hxx>
84 #include <osl/mutex.hxx>
85 #include <rtl/strbuf.hxx>
88 extern "C" void SAL_CALL
createRegistryInfo_OQueryControl()
90 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OQueryController
> aAutoRegistration
;
95 using namespace ::com::sun::star::uno
;
96 using namespace ::com::sun::star::beans
;
97 using namespace ::com::sun::star::frame
;
98 using namespace ::com::sun::star::util
;
99 using namespace ::com::sun::star::lang
;
101 class OViewController
: public OQueryController
103 virtual OUString SAL_CALL
getImplementationName() throw( RuntimeException
, std::exception
) SAL_OVERRIDE
105 return getImplementationName_Static();
107 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() throw(RuntimeException
, std::exception
) SAL_OVERRIDE
109 return getSupportedServiceNames_Static();
113 OViewController(const Reference
< XComponentContext
>& _rM
) : OQueryController(_rM
){}
115 // need by registration
116 static OUString
getImplementationName_Static() throw( RuntimeException
)
118 return OUString("org.openoffice.comp.dbu.OViewDesign");
120 static Sequence
< OUString
> getSupportedServiceNames_Static() throw( RuntimeException
)
122 Sequence
< OUString
> aSupported(1);
123 aSupported
.getArray()[0] = "com.sun.star.sdb.ViewDesign";
126 static Reference
< XInterface
> SAL_CALL
Create(const Reference
< XMultiServiceFactory
>& _rM
)
128 return *(new OViewController(comphelper::getComponentContext(_rM
)));
133 extern "C" void SAL_CALL
createRegistryInfo_OViewControl()
135 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OViewController
> aAutoRegistration
;
140 using namespace ::connectivity
;
141 #if OSL_DEBUG_LEVEL > 1
144 void insertParseTree(SvTreeListBox
* _pBox
,::connectivity::OSQLParseNode
* _pNode
,SvTreeListEntry
* _pParent
= NULL
)
147 if (!_pNode
->isToken())
149 // rule name as rule: ...
150 rString
= "RULE_ID: " + OUString::number( (sal_Int32
)_pNode
->getRuleID() ) +
151 "(" + OSQLParser::RuleIDToStr(_pNode
->getRuleID()) + ")";
153 _pParent
= _pBox
->InsertEntry(rString
,_pParent
);
155 // determine how much subtrees this node has
156 sal_uInt32 nStop
= _pNode
->count();
157 // fetch first subtree
158 for(sal_uInt32 i
=0;i
<nStop
;++i
)
159 insertParseTree(_pBox
,_pNode
->getChild(i
),_pParent
);
164 // tabs to insert according to nLevel
166 switch (_pNode
->getNodeType())
169 case SQL_NODE_KEYWORD
:
171 rString
+= "SQL_KEYWORD:";
172 OString sT
= OSQLParser::TokenIDToStr(_pNode
->getTokenID());
173 rString
+= OStringToOUString(sT
, RTL_TEXTENCODING_UTF8
);
176 case SQL_NODE_COMPARISON
:
178 rString
+= "SQL_COMPARISON:" + _pNode
->getTokenValue(); // append Nodevalue
179 // and start new line
184 rString
+= "SQL_NAME:\"" + _pNode
->getTokenValue() + "\"";
187 case SQL_NODE_STRING
:
189 rString
+= "SQL_STRING:'" + _pNode
->getTokenValue();
192 case SQL_NODE_INTNUM
:
194 rString
+= "SQL_INTNUM:" + _pNode
->getTokenValue();
197 case SQL_NODE_APPROXNUM
:
199 rString
+= "SQL_APPROXNUM:" + _pNode
->getTokenValue();
202 case SQL_NODE_PUNCTUATION
:
204 rString
+= "SQL_PUNCTUATION:" + _pNode
->getTokenValue(); // append Nodevalue
209 rString
+= "SQL_AMMSC:" + _pNode
->getTokenValue(); // append Nodevalue
213 OSL_FAIL("OSQLParser::ShowParseTree: unzulaessiger NodeType");
214 rString
+= _pNode
->getTokenValue();
216 _pBox
->InsertEntry(rString
,_pParent
);
220 #endif // OSL_DEBUG_LEVEL
224 OUString
lcl_getObjectResourceString( sal_uInt16 _nResId
, sal_Int32 _nCommandType
)
226 OUString sMessageText
= ModuleRes( _nResId
);
227 OUString sObjectType
;
229 LocalResourceAccess
aLocalRes( RSC_QUERY_OBJECT_TYPE
, RSC_RESOURCE
);
230 sObjectType
= ModuleRes( (sal_uInt16
)( _nCommandType
+ 1 ) );
232 sMessageText
= sMessageText
.replaceFirst( "$object$", sObjectType
);
237 using namespace ::com::sun::star::uno
;
238 using namespace ::com::sun::star::io
;
239 using namespace ::com::sun::star::beans
;
240 using namespace ::com::sun::star::frame
;
241 using namespace ::com::sun::star::util
;
242 using namespace ::com::sun::star::lang
;
243 using namespace ::com::sun::star::container
;
244 using namespace ::com::sun::star::sdbcx
;
245 using namespace ::com::sun::star::sdbc
;
246 using namespace ::com::sun::star::sdb
;
247 using namespace ::com::sun::star::ui
;
248 using namespace ::com::sun::star::ui::dialogs
;
249 using namespace ::com::sun::star::awt
;
250 using namespace ::dbtools
;
252 using namespace ::comphelper
;
256 void ensureToolbars( OQueryController
& _rController
, bool _bDesign
)
258 Reference
< ::com::sun::star::frame::XLayoutManager
> xLayoutManager
= OGenericUnoController::getLayoutManager( _rController
.getFrame() );
259 if ( xLayoutManager
.is() )
261 xLayoutManager
->lock();
262 static const char s_sDesignToolbar
[] = "private:resource/toolbar/designobjectbar";
263 static const char s_sSqlToolbar
[] = "private:resource/toolbar/sqlobjectbar";
266 xLayoutManager
->destroyElement( s_sSqlToolbar
);
267 xLayoutManager
->createElement( s_sDesignToolbar
);
271 xLayoutManager
->destroyElement( s_sDesignToolbar
);
272 xLayoutManager
->createElement( s_sSqlToolbar
);
274 xLayoutManager
->unlock();
275 xLayoutManager
->doLayout();
280 * The value of m_nLimit is updated when LimitBox loses its focus
281 * So in those case when execution needs recent data, grab the focus
282 * (e.g. execute SQL statement, change views)
284 void grabFocusFromLimitBox( OQueryController
& _rController
)
286 static const char sResourceURL
[] = "private:resource/toolbar/designobjectbar";
287 Reference
< XLayoutManager
> xLayoutManager
= OGenericUnoController::getLayoutManager( _rController
.getFrame() );
288 Reference
< XUIElement
> xUIElement
= xLayoutManager
->getElement(sResourceURL
);
291 Reference
< XWindow
> xWindow(xUIElement
->getRealInterface(), css::uno::UNO_QUERY
);
292 vcl::Window
* pWindow
= VCLUnoHelper::GetWindow( xWindow
);
293 if( pWindow
&& pWindow
->HasChildPathFocus() )
295 pWindow
->GrabFocusToDocument();
301 OUString SAL_CALL
OQueryController::getImplementationName() throw( RuntimeException
, std::exception
)
303 return getImplementationName_Static();
306 OUString
OQueryController::getImplementationName_Static() throw( RuntimeException
)
308 return OUString("org.openoffice.comp.dbu.OQueryDesign");
311 Sequence
< OUString
> OQueryController::getSupportedServiceNames_Static() throw( RuntimeException
)
313 Sequence
< OUString
> aSupported(1);
314 aSupported
.getArray()[0] = "com.sun.star.sdb.QueryDesign";
318 Sequence
< OUString
> SAL_CALL
OQueryController::getSupportedServiceNames() throw(RuntimeException
, std::exception
)
320 return getSupportedServiceNames_Static();
323 Reference
< XInterface
> SAL_CALL
OQueryController::Create(const Reference
<XMultiServiceFactory
>& _rxFactory
)
325 return *(new OQueryController(comphelper::getComponentContext(_rxFactory
)));
328 OQueryController::OQueryController(const Reference
< XComponentContext
>& _rM
)
329 :OJoinController(_rM
)
330 ,OQueryController_PBase( getBroadcastHelper() )
331 ,m_pParseContext( new svxform::OSystemParseContext
)
332 ,m_aSqlParser( _rM
, m_pParseContext
)
333 ,m_pSqlIterator(NULL
)
335 ,m_nVisibleRows(0x400)
337 ,m_nCommandType( CommandType::QUERY
)
338 ,m_bGraphicalDesign(false)
342 ,m_bViewFunction(false)
343 ,m_bEscapeProcessing(true)
347 registerProperty( PROPERTY_ACTIVECOMMAND
, PROPERTY_ID_ACTIVECOMMAND
, PropertyAttribute::READONLY
| PropertyAttribute::BOUND
,
348 &m_sStatement
, cppu::UnoType
<decltype(m_sStatement
)>::get() );
349 registerProperty( PROPERTY_ESCAPE_PROCESSING
, PROPERTY_ID_ESCAPE_PROCESSING
, PropertyAttribute::READONLY
| PropertyAttribute::BOUND
,
350 &m_bEscapeProcessing
, cppu::UnoType
<decltype(m_bEscapeProcessing
)>::get() );
353 OQueryController::~OQueryController()
355 if ( !getBroadcastHelper().bDisposed
&& !getBroadcastHelper().bInDispose
)
357 OSL_FAIL("Please check who doesn't dispose this component!");
358 // increment ref count to prevent double call of Dtor
359 osl_atomic_increment( &m_refCount
);
364 IMPLEMENT_FORWARD_XINTERFACE2( OQueryController
, OJoinController
, OQueryController_PBase
)
365 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController
, OJoinController
, OQueryController_PBase
)
367 Reference
< XPropertySetInfo
> SAL_CALL
OQueryController::getPropertySetInfo() throw(RuntimeException
, std::exception
)
369 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
373 sal_Bool SAL_CALL
OQueryController::convertFastPropertyValue( Any
& o_rConvertedValue
, Any
& o_rOldValue
, sal_Int32 i_nHandle
, const Any
& i_rValue
) throw (IllegalArgumentException
)
375 return OPropertyContainer::convertFastPropertyValue( o_rConvertedValue
, o_rOldValue
, i_nHandle
, i_rValue
);
378 void SAL_CALL
OQueryController::setFastPropertyValue_NoBroadcast( sal_Int32 i_nHandle
, const Any
& i_rValue
) throw ( Exception
, std::exception
)
380 OPropertyContainer::setFastPropertyValue_NoBroadcast( i_nHandle
, i_rValue
);
383 void SAL_CALL
OQueryController::getFastPropertyValue( Any
& o_rValue
, sal_Int32 i_nHandle
) const
387 case PROPERTY_ID_CURRENT_QUERY_DESIGN
:
389 ::comphelper::NamedValueCollection aCurrentDesign
;
390 aCurrentDesign
.put( "GraphicalDesign", isGraphicalDesign() );
391 aCurrentDesign
.put( OUString(PROPERTY_ESCAPE_PROCESSING
), m_bEscapeProcessing
);
393 if ( isGraphicalDesign() )
395 getContainer()->SaveUIConfig();
396 saveViewSettings( aCurrentDesign
, true );
397 aCurrentDesign
.put( "Statement", m_sStatement
);
401 aCurrentDesign
.put( "Statement", getContainer()->getStatement() );
404 o_rValue
<<= aCurrentDesign
.getPropertyValues();
409 OPropertyContainer::getFastPropertyValue( o_rValue
, i_nHandle
);
414 ::cppu::IPropertyArrayHelper
& OQueryController::getInfoHelper()
416 return *getArrayHelper();
419 ::cppu::IPropertyArrayHelper
* OQueryController::createArrayHelper( ) const
421 Sequence
< Property
> aProps
;
422 describeProperties( aProps
);
424 // one additional property:
425 const sal_Int32 nLength
= aProps
.getLength();
426 aProps
.realloc( nLength
+ 1 );
427 aProps
[ nLength
] = Property(
428 "CurrentQueryDesign",
429 PROPERTY_ID_CURRENT_QUERY_DESIGN
,
430 ::cppu::UnoType
< Sequence
< PropertyValue
> >::get(),
431 PropertyAttribute::READONLY
436 aProps
.getArray() + aProps
.getLength(),
437 ::comphelper::PropertyCompareByName()
440 return new ::cppu::OPropertyArrayHelper(aProps
);
443 void OQueryController::deleteIterator()
447 delete m_pSqlIterator
->getParseTree();
448 m_pSqlIterator
->dispose();
449 delete m_pSqlIterator
;
450 m_pSqlIterator
= NULL
;
454 void OQueryController::disposing()
456 OQueryController_PBase::disposing();
460 delete m_pParseContext
;
463 OTableFields().swap(m_vUnUsedFieldsDesc
);
465 ::comphelper::disposeComponent(m_xComposer
);
466 OJoinController::disposing();
467 OQueryController_PBase::disposing();
470 void OQueryController::clearFields()
472 OTableFields().swap(m_vTableFieldDesc
);
475 FeatureState
OQueryController::GetState(sal_uInt16 _nId
) const
477 FeatureState aReturn
;
478 aReturn
.bEnabled
= true;
479 // (disabled automatically)
483 case ID_BROWSER_EDITDOC
:
484 if ( editingCommand() )
485 aReturn
.bEnabled
= false;
486 else if ( editingView() && !m_xAlterView
.is() )
487 aReturn
.bEnabled
= false;
489 aReturn
= OJoinController::GetState( _nId
);
492 case ID_BROWSER_ESCAPEPROCESSING
:
493 aReturn
.bChecked
= !m_bEscapeProcessing
;
494 aReturn
.bEnabled
= ( m_pSqlIterator
!= NULL
) && !m_bGraphicalDesign
;
496 case SID_RELATION_ADD_RELATION
:
497 aReturn
.bEnabled
= isEditable() && m_bGraphicalDesign
&& m_vTableData
.size() > 1;
499 case ID_BROWSER_SAVEASDOC
:
500 aReturn
.bEnabled
= !editingCommand() && !editingView() && (!m_bGraphicalDesign
|| !(m_vTableFieldDesc
.empty() || m_vTableData
.empty()));
502 case ID_BROWSER_SAVEDOC
:
503 aReturn
.bEnabled
= impl_isModified() && (!m_bGraphicalDesign
|| !(m_vTableFieldDesc
.empty() || m_vTableData
.empty()));
505 case SID_PRINTDOCDIRECT
:
508 aReturn
.bEnabled
= isEditable() && getContainer() && getContainer()->isCutAllowed();
510 case ID_BROWSER_COPY
:
511 aReturn
.bEnabled
= getContainer() && getContainer()->isCopyAllowed();
513 case ID_BROWSER_PASTE
:
514 aReturn
.bEnabled
= isEditable() && getContainer() && getContainer()->isPasteAllowed();
517 aReturn
.bEnabled
= m_bEscapeProcessing
&& m_pSqlIterator
;
518 aReturn
.bChecked
= m_bGraphicalDesign
;
520 case SID_BROWSER_CLEAR_QUERY
:
521 aReturn
.bEnabled
= isEditable() && (!m_sStatement
.isEmpty() || !m_vTableData
.empty());
523 case SID_QUERY_VIEW_FUNCTIONS
:
524 case SID_QUERY_VIEW_TABLES
:
525 case SID_QUERY_VIEW_ALIASES
:
526 aReturn
.bChecked
= getContainer() && getContainer()->isSlotEnabled(_nId
);
527 aReturn
.bEnabled
= m_bGraphicalDesign
;
529 case SID_QUERY_DISTINCT_VALUES
:
530 aReturn
.bEnabled
= m_bGraphicalDesign
&& isEditable();
531 aReturn
.bChecked
= m_bDistinct
;
533 case SID_QUERY_LIMIT
:
534 aReturn
.bEnabled
= m_bGraphicalDesign
;
535 if( aReturn
.bEnabled
)
536 aReturn
.aValue
= makeAny( m_nLimit
);
538 case SID_QUERY_PROP_DLG
:
539 aReturn
.bEnabled
= m_bGraphicalDesign
;
541 case ID_BROWSER_QUERY_EXECUTE
:
542 aReturn
.bEnabled
= true;
544 case SID_DB_QUERY_PREVIEW
:
545 aReturn
.bEnabled
= true;
546 aReturn
.bChecked
= getContainer() && getContainer()->getPreviewFrame().is();
548 #if OSL_DEBUG_LEVEL > 1
549 case ID_EDIT_QUERY_SQL
:
551 case ID_EDIT_QUERY_DESIGN
:
554 case ID_BROWSER_ADDTABLE
:
555 if ( !m_bGraphicalDesign
)
557 aReturn
.bEnabled
= false;
562 aReturn
= OJoinController::GetState(_nId
);
568 void OQueryController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
572 case ID_BROWSER_ESCAPEPROCESSING
:
573 setEscapeProcessing_fireEvent( !m_bEscapeProcessing
);
574 if ( !editingView() )
575 setModified(sal_True
);
576 InvalidateFeature(ID_BROWSER_SQL
);
578 case ID_BROWSER_SAVEASDOC
:
579 case ID_BROWSER_SAVEDOC
:
580 grabFocusFromLimitBox(*this);
581 doSaveAsDoc(ID_BROWSER_SAVEASDOC
== _nId
);
583 case SID_RELATION_ADD_RELATION
:
585 OJoinDesignView
* pView
= getJoinView();
587 static_cast<OQueryTableView
*>(pView
->getTableView())->createNewConnection();
590 case SID_PRINTDOCDIRECT
:
593 getContainer()->cut();
595 case ID_BROWSER_COPY
:
596 getContainer()->copy();
598 case ID_BROWSER_PASTE
:
599 getContainer()->paste();
603 grabFocusFromLimitBox(*this);
604 if ( !getContainer()->checkStatement() )
606 SQLExceptionInfo aError
;
610 setStatement_fireEvent( getContainer()->getStatement() );
611 if(m_sStatement
.isEmpty() && m_pSqlIterator
)
613 // change the view of the data
614 delete m_pSqlIterator
->getParseTree();
615 m_pSqlIterator
->setParseTree(NULL
);
616 m_bGraphicalDesign
= !m_bGraphicalDesign
;
617 impl_setViewMode( &aError
);
621 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree(aErrorMsg
,m_sStatement
,m_bGraphicalDesign
);
624 delete m_pSqlIterator
->getParseTree();
625 m_pSqlIterator
->setParseTree(pNode
);
626 m_pSqlIterator
->traverseAll();
628 if ( m_pSqlIterator
->hasErrors() )
630 aError
= m_pSqlIterator
->getErrors();
634 const OSQLTables
& xTabs
= m_pSqlIterator
->getTables();
635 if ( m_pSqlIterator
->getStatementType() != SQL_STATEMENT_SELECT
|| xTabs
.begin() == xTabs
.end() )
637 aError
= SQLException(
638 OUString( ModuleRes( STR_QRY_NOSELECT
) ),
647 // change the view of the data
648 m_bGraphicalDesign
= !m_bGraphicalDesign
;
649 OUString sNewStatement
;
650 pNode
->parseNodeToStr( sNewStatement
, getConnection() );
651 setStatement_fireEvent( sNewStatement
);
652 getContainer()->SaveUIConfig();
653 m_vTableConnectionData
.clear();
654 impl_setViewMode( &aError
);
660 aError
= SQLException(
661 OUString( ModuleRes( STR_QRY_SYNTAX
) ),
670 catch(const SQLException
&)
672 aError
= ::cppu::getCaughtException();
674 catch(const Exception
&)
676 DBG_UNHANDLED_EXCEPTION();
679 if ( aError
.isValid() )
682 if(m_bGraphicalDesign
)
684 InvalidateFeature(ID_BROWSER_ADDTABLE
);
685 InvalidateFeature(SID_RELATION_ADD_RELATION
);
689 case SID_BROWSER_CLEAR_QUERY
:
691 GetUndoManager().EnterListAction( OUString( ModuleRes(STR_QUERY_UNDO_TABWINDELETE
) ), OUString() );
692 getContainer()->clear();
693 GetUndoManager().LeaveListAction();
695 setStatement_fireEvent( OUString() );
696 if(m_bGraphicalDesign
)
697 InvalidateFeature(ID_BROWSER_ADDTABLE
);
700 case SID_QUERY_VIEW_FUNCTIONS
:
701 case SID_QUERY_VIEW_TABLES
:
702 case SID_QUERY_VIEW_ALIASES
:
703 getContainer()->setSlotEnabled(_nId
,!getContainer()->isSlotEnabled(_nId
));
704 setModified(sal_True
);
706 case SID_QUERY_DISTINCT_VALUES
:
707 m_bDistinct
= !m_bDistinct
;
708 setModified(sal_True
);
710 case SID_QUERY_LIMIT
:
711 if ( aArgs
.getLength() >= 1 && aArgs
[0].Name
== "DBLimit.Value" )
713 aArgs
[0].Value
>>= m_nLimit
;
714 setModified(sal_True
);
717 case SID_QUERY_PROP_DLG
:
718 grabFocusFromLimitBox(*this);
719 execute_QueryPropDlg();
721 case ID_BROWSER_QUERY_EXECUTE
:
722 grabFocusFromLimitBox(*this);
723 if ( getContainer()->checkStatement() )
726 case SID_DB_QUERY_PREVIEW
:
729 Reference
< ::com::sun::star::util::XCloseable
> xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY
);
730 if ( xCloseFrame
.is() )
734 xCloseFrame
->close( sal_True
);
736 catch(const Exception
&)
738 OSL_FAIL( "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" );
742 Execute(ID_BROWSER_QUERY_EXECUTE
,Sequence
< PropertyValue
>());
744 catch(const Exception
&)
748 case ID_QUERY_ZOOM_IN
:
752 case ID_QUERY_ZOOM_OUT
:
756 #if OSL_DEBUG_LEVEL > 1
757 case ID_EDIT_QUERY_DESIGN
:
758 case ID_EDIT_QUERY_SQL
:
761 setStatement_fireEvent( getContainer()->getStatement() );
762 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
);
765 vcl::Window
* pView
= getView();
766 ScopedVclPtrInstance
<ModalDialog
> pWindow( pView
, WB_STDMODAL
| WB_SIZEMOVE
| WB_CENTER
);
767 pWindow
->SetSizePixel( ::Size( pView
->GetSizePixel().Width() / 2, pView
->GetSizePixel().Height() / 2 ) );
768 ScopedVclPtrInstance
<SvTreeListBox
> pTreeBox( pWindow
, WB_BORDER
| WB_HASLINES
| WB_HASBUTTONS
| WB_HASBUTTONSATROOT
| WB_HASLINESATROOT
| WB_VSCROLL
);
769 pTreeBox
->SetPosSizePixel( ::Point( 6, 6 ), ::Size( pWindow
->GetSizePixel().Width() - 12, pWindow
->GetSizePixel().Height() - 12 ));
770 pTreeBox
->SetNodeDefaultImages();
772 if ( _nId
== ID_EDIT_QUERY_DESIGN
)
774 ::connectivity::OSQLParseNode
* pTemp
= pNode
? pNode
->getChild(3)->getChild(1) : NULL
;
775 // no where clause found
776 if ( pTemp
&& !pTemp
->isLeaf() )
778 ::connectivity::OSQLParseNode
* pCondition
= pTemp
->getChild(1);
779 if ( pCondition
) // no where clause
781 ::connectivity::OSQLParseNode::negateSearchCondition(pCondition
);
782 ::connectivity::OSQLParseNode
*pNodeTmp
= pTemp
->getChild(1);
784 ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp
);
785 pNodeTmp
= pTemp
->getChild(1);
786 ::connectivity::OSQLParseNode::absorptions(pNodeTmp
);
787 pNodeTmp
= pTemp
->getChild(1);
788 OSQLParseNode::compress(pNodeTmp
);
789 pNodeTmp
= pTemp
->getChild(1);
792 pNode
->parseNodeToStr(sTemp
,getConnection());
793 getContainer()->setStatement(sTemp
);
797 insertParseTree(pTreeBox
,pNode
);
808 OJoinController::Execute(_nId
,aArgs
);
809 return; // else we would invalidate twice
811 InvalidateFeature(_nId
);
814 void OQueryController::impl_showAutoSQLViewError( const ::com::sun::star::uno::Any
& _rErrorDetails
)
816 SQLContext aErrorContext
;
817 aErrorContext
.Message
= lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT
, m_nCommandType
);
818 aErrorContext
.Context
= *this;
819 aErrorContext
.Details
= lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW
, m_nCommandType
);
820 aErrorContext
.NextException
= _rErrorDetails
;
821 showError( aErrorContext
);
824 bool OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo
* _pErrorInfo
)
826 OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" );
828 bool wasModified
= isModified();
830 SQLExceptionInfo aError
;
831 bool bSuccess
= getContainer()->switchView( &aError
);
834 m_bGraphicalDesign
= !m_bGraphicalDesign
;
836 getContainer()->switchView( NULL
);
837 // don't pass &aError here, this would overwrite the error which the first switchView call
838 // returned in this location.
840 *_pErrorInfo
= aError
;
846 ensureToolbars( *this, m_bGraphicalDesign
);
849 setModified( wasModified
);
853 void OQueryController::impl_initialize()
855 OJoinController::impl_initialize();
857 const NamedValueCollection
& rArguments( getInitParams() );
860 m_nCommandType
= CommandType::QUERY
;
862 // reading parameters:
864 // legacy parameters first (later overwritten by regular parameters)
865 OUString sIndependentSQLCommand
;
866 if ( rArguments
.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand
) )
868 OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" );
869 sCommand
= sIndependentSQLCommand
;
870 m_nCommandType
= CommandType::COMMAND
;
873 OUString sCurrentQuery
;
874 if ( rArguments
.get_ensureType( "CurrentQuery", sCurrentQuery
) )
876 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
877 sCommand
= sCurrentQuery
;
878 m_nCommandType
= CommandType::QUERY
;
881 bool bCreateView( false );
882 if ( rArguments
.get_ensureType( "CreateView", bCreateView
) && bCreateView
)
884 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
885 m_nCommandType
= CommandType::TABLE
;
888 // non-legacy parameters which overwrite the legacy parameters
889 rArguments
.get_ensureType( OUString(PROPERTY_COMMAND
), sCommand
);
890 rArguments
.get_ensureType( OUString(PROPERTY_COMMAND_TYPE
), m_nCommandType
);
892 // translate Command/Type into proper members
893 // TODO/Later: all this (including those members) should be hidden behind some abstact interface,
894 // which is implemented for all the three commands
895 switch ( m_nCommandType
)
897 case CommandType::QUERY
:
900 case CommandType::TABLE
:
903 case CommandType::COMMAND
:
904 setStatement_fireEvent( sCommand
);
908 OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" );
909 throw RuntimeException();
912 // more legacy parameters
913 bool bGraphicalDesign( true );
914 if ( rArguments
.get_ensureType( OUString(PROPERTY_QUERYDESIGNVIEW
), bGraphicalDesign
) )
916 OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" );
917 m_bGraphicalDesign
= bGraphicalDesign
;
921 rArguments
.get_ensureType( OUString(PROPERTY_GRAPHICAL_DESIGN
), m_bGraphicalDesign
);
923 bool bEscapeProcessing( true );
924 if ( rArguments
.get_ensureType( OUString(PROPERTY_ESCAPE_PROCESSING
), bEscapeProcessing
) )
926 setEscapeProcessing_fireEvent( bEscapeProcessing
);
928 OSL_ENSURE( m_bEscapeProcessing
|| !m_bGraphicalDesign
, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" );
929 if ( !m_bEscapeProcessing
)
930 m_bGraphicalDesign
= false;
934 bool bForceInitialDesign
= false;
935 Sequence
< PropertyValue
> aCurrentQueryDesignProps
;
936 aCurrentQueryDesignProps
= rArguments
.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps
);
938 if ( aCurrentQueryDesignProps
.getLength() )
940 ::comphelper::NamedValueCollection
aCurrentQueryDesign( aCurrentQueryDesignProps
);
941 if ( aCurrentQueryDesign
.has( OUString(PROPERTY_GRAPHICAL_DESIGN
) ) )
943 aCurrentQueryDesign
.get_ensureType( OUString(PROPERTY_GRAPHICAL_DESIGN
), m_bGraphicalDesign
);
945 if ( aCurrentQueryDesign
.has( OUString(PROPERTY_ESCAPE_PROCESSING
) ) )
947 aCurrentQueryDesign
.get_ensureType( OUString(PROPERTY_ESCAPE_PROCESSING
), m_bEscapeProcessing
);
949 if ( aCurrentQueryDesign
.has( "Statement" ) )
952 aCurrentQueryDesign
.get_ensureType( "Statement", sStatement
);
953 aCurrentQueryDesign
.remove( "Statement" );
954 setStatement_fireEvent( sStatement
);
957 loadViewSettings( aCurrentQueryDesign
);
959 bForceInitialDesign
= true;
962 if ( !ensureConnected( false ) )
963 { // we have no connection so what else should we do
964 m_bGraphicalDesign
= false;
967 connectionLostMessage();
968 throw SQLException();
972 // check the view capabilities
973 if ( isConnected() && editingView() )
975 Reference
< XViewsSupplier
> xViewsSup( getConnection(), UNO_QUERY
);
976 Reference
< XNameAccess
> xViews
;
977 if ( xViewsSup
.is() )
978 xViews
= xViewsSup
->getViews();
981 { // we can't create views so we ask if the user wants to create a query instead
982 m_nCommandType
= CommandType::QUERY
;
985 OUString
aTitle( ModuleRes( STR_QUERYDESIGN_NO_VIEW_SUPPORT
) );
986 OUString
aMessage( ModuleRes( STR_QUERYDESIGN_NO_VIEW_ASK
) );
987 ODataView
* pWindow
= getView();
988 ScopedVclPtrInstance
< OSQLMessageBox
> aDlg( pWindow
, aTitle
, aMessage
, WB_YES_NO
| WB_DEF_YES
, OSQLMessageBox::Query
);
989 bClose
= aDlg
->Execute() == RET_NO
;
992 throw VetoException();
995 // now if we are to edit an existing view, check whether this is possible
996 if ( !m_sName
.isEmpty() )
998 Any
aView( xViews
->getByName( m_sName
) );
999 // will throw if there is no such view
1000 if ( !( aView
>>= m_xAlterView
) )
1002 throw IllegalArgumentException(
1003 OUString( ModuleRes( STR_NO_ALTER_VIEW_SUPPORT
) ),
1011 OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!");
1015 getContainer()->initialize();
1016 impl_reset( bForceInitialDesign
);
1018 SQLExceptionInfo aError
;
1019 const bool bAttemptedGraphicalDesign
= m_bGraphicalDesign
;
1021 if ( bForceInitialDesign
)
1023 getContainer()->forceInitialView();
1027 impl_setViewMode( &aError
);
1030 if ( aError
.isValid() && bAttemptedGraphicalDesign
&& !m_bGraphicalDesign
)
1032 // we tried initializing the graphical view, this failed, and we were automatically switched to SQL
1033 // view => tell this to the user
1034 if ( !editingView() )
1036 impl_showAutoSQLViewError( aError
.get() );
1042 if ( ( m_bGraphicalDesign
)
1043 && ( ( m_sName
.isEmpty() && !editingCommand() )
1044 || ( m_sStatement
.isEmpty() && editingCommand() )
1048 Application::PostUserEvent( LINK( this, OQueryController
, OnExecuteAddTable
) );
1051 setModified(sal_False
);
1053 catch(const SQLException
& e
)
1055 DBG_UNHANDLED_EXCEPTION();
1056 // we caught an exception so we switch to text only mode
1058 m_bGraphicalDesign
= false;
1059 getContainer()->initialize();
1060 ODataView
* pWindow
= getView();
1061 ScopedVclPtr
<OSQLMessageBox
>::Create(pWindow
,e
)->Execute();
1067 void OQueryController::onLoadedMenu(const Reference
< ::com::sun::star::frame::XLayoutManager
>& /*_xLayoutManager*/)
1069 ensureToolbars( *this, m_bGraphicalDesign
);
1072 OUString
OQueryController::getPrivateTitle( ) const
1074 OUString sName
= m_sName
;
1075 if ( sName
.isEmpty() )
1077 if ( !editingCommand() )
1079 SolarMutexGuard aSolarGuard
;
1080 ::osl::MutexGuard
aGuard( getMutex() );
1081 OUString aDefaultName
= ModuleRes( editingView() ? STR_VIEW_TITLE
: STR_QRY_TITLE
);
1082 sName
= aDefaultName
.getToken(0,' ');
1083 sName
+= OUString::number(getCurrentStartNumber());
1089 void OQueryController::setQueryComposer()
1093 Reference
< XSQLQueryComposerFactory
> xFactory(getConnection(), UNO_QUERY
);
1094 OSL_ENSURE(xFactory
.is(),"Connection doesn't support a querycomposer");
1095 if ( xFactory
.is() && getContainer() )
1099 m_xComposer
= xFactory
->createQueryComposer();
1100 getContainer()->setStatement(m_sStatement
);
1102 catch(const Exception
&)
1106 OSL_ENSURE(m_xComposer
.is(),"No querycomposer available!");
1107 Reference
<XTablesSupplier
> xTablesSup(getConnection(), UNO_QUERY
);
1109 m_pSqlIterator
= new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup
->getTables(), m_aSqlParser
, NULL
);
1114 bool OQueryController::Construct(vcl::Window
* pParent
)
1116 // TODO: we have to check if we should create the text view or the design view
1118 setView( VclPtr
<OQueryContainerWindow
>::Create( pParent
, *this, getORB() ) );
1120 return OJoinController::Construct(pParent
);
1123 OJoinDesignView
* OQueryController::getJoinView()
1125 return getContainer()->getDesignView();
1128 void OQueryController::describeSupportedFeatures()
1130 OJoinController::describeSupportedFeatures();
1131 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
1132 implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESCAPEPROCESSING
,CommandGroup::FORMAT
);
1133 implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS
, CommandGroup::VIEW
);
1134 implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES
, CommandGroup::VIEW
);
1135 implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES
, CommandGroup::VIEW
);
1136 implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES
, CommandGroup::FORMAT
);
1137 implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL
, CommandGroup::VIEW
);
1138 implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY
, CommandGroup::EDIT
);
1139 implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE
, CommandGroup::VIEW
);
1140 implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION
, CommandGroup::EDIT
);
1141 implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW
, CommandGroup::VIEW
);
1142 implDescribeSupportedFeature( ".uno:DBLimit", SID_QUERY_LIMIT
, CommandGroup::FORMAT
);
1143 implDescribeSupportedFeature( ".uno:DBQueryPropertiesDialog", SID_QUERY_PROP_DLG
, CommandGroup::FORMAT
);
1145 #if OSL_DEBUG_LEVEL > 1
1146 implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL
);
1147 implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN
);
1151 void OQueryController::impl_onModifyChanged()
1153 OJoinController::impl_onModifyChanged();
1154 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
1155 InvalidateFeature(ID_BROWSER_SAVEASDOC
);
1156 InvalidateFeature(ID_BROWSER_QUERY_EXECUTE
);
1159 void SAL_CALL
OQueryController::disposing( const EventObject
& Source
) throw(RuntimeException
, std::exception
)
1161 SolarMutexGuard aGuard
;
1163 if ( getContainer() && Source
.Source
.is() )
1165 if ( Source
.Source
== m_aCurrentFrame
.getFrame() )
1166 { // our frame is being disposed -> close the preview window (if we have one)
1167 Reference
< XFrame2
> xPreviewFrame( getContainer()->getPreviewFrame() );
1168 ::comphelper::disposeComponent( xPreviewFrame
);
1170 else if ( Source
.Source
== getContainer()->getPreviewFrame() )
1172 getContainer()->disposingPreview();
1176 OJoinController::disposing(Source
);
1179 void OQueryController::reconnect(bool _bUI
)
1182 ::comphelper::disposeComponent(m_xComposer
);
1184 OJoinController::reconnect( _bUI
);
1192 if(m_bGraphicalDesign
)
1194 m_bGraphicalDesign
= false;
1195 // don't call Execute(SQL) because this changes the sql statement
1196 impl_setViewMode( NULL
);
1202 void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection
& o_rViewSettings
, const bool i_includingCriteria
) const
1204 saveTableWindows( o_rViewSettings
);
1206 OTableFields::const_iterator field
= m_vTableFieldDesc
.begin();
1207 OTableFields::const_iterator fieldEnd
= m_vTableFieldDesc
.end();
1209 ::comphelper::NamedValueCollection aAllFieldsData
;
1210 ::comphelper::NamedValueCollection aFieldData
;
1211 for ( sal_Int32 i
= 1; field
!= fieldEnd
; ++field
, ++i
)
1213 if ( !(*field
)->IsEmpty() )
1216 (*field
)->Save( aFieldData
, i_includingCriteria
);
1218 const OUString sFieldSettingName
= "Field" + OUString::number( i
);
1219 aAllFieldsData
.put( sFieldSettingName
, aFieldData
.getPropertyValues() );
1223 o_rViewSettings
.put( "Fields", aAllFieldsData
.getPropertyValues() );
1224 o_rViewSettings
.put( "SplitterPosition", m_nSplitPos
);
1225 o_rViewSettings
.put( "VisibleRows", m_nVisibleRows
);
1228 void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection
& o_rViewSettings
)
1230 loadTableWindows( o_rViewSettings
);
1232 m_nSplitPos
= o_rViewSettings
.getOrDefault( "SplitterPosition", m_nSplitPos
);
1233 m_nVisibleRows
= o_rViewSettings
.getOrDefault( "VisibleRows", m_nVisibleRows
);
1234 m_aFieldInformation
= o_rViewSettings
.getOrDefault( "Fields", m_aFieldInformation
);
1237 void OQueryController::execute_QueryPropDlg()
1239 ScopedVclPtrInstance
<QueryPropertiesDialog
> aQueryPropDlg(
1240 getContainer(), m_bDistinct
, m_nLimit
);
1242 if( aQueryPropDlg
->Execute() == RET_OK
)
1244 m_bDistinct
= aQueryPropDlg
->getDistinct();
1245 m_nLimit
= aQueryPropDlg
->getLimit();
1246 InvalidateFeature( SID_QUERY_DISTINCT_VALUES
);
1247 InvalidateFeature( SID_QUERY_LIMIT
, 0, true );
1251 sal_Int32
OQueryController::getColWidth(sal_uInt16 _nColPos
) const
1253 if ( _nColPos
< m_aFieldInformation
.getLength() )
1255 ::std::unique_ptr
<OTableFieldDesc
> pField( new OTableFieldDesc());
1256 pField
->Load( m_aFieldInformation
[ _nColPos
], false );
1257 return pField
->GetColWidth();
1262 Reference
<XNameAccess
> OQueryController::getObjectContainer() const
1264 Reference
< XNameAccess
> xElements
;
1265 if ( editingView() )
1267 Reference
< XViewsSupplier
> xViewsSupp( getConnection(), UNO_QUERY
);
1268 if ( xViewsSupp
.is() )
1269 xElements
= xViewsSupp
->getViews();
1273 Reference
< XQueriesSupplier
> xQueriesSupp( getConnection(), UNO_QUERY
);
1274 if ( xQueriesSupp
.is() )
1275 xElements
= xQueriesSupp
->getQueries();
1278 Reference
< XQueryDefinitionsSupplier
> xQueryDefsSupp( getDataSource(), UNO_QUERY
);
1279 if ( xQueryDefsSupp
.is() )
1280 xElements
= xQueryDefsSupp
->getQueryDefinitions();
1284 OSL_ENSURE( xElements
.is(), "OQueryController::getObjectContainer: unable to obtain the container!" );
1288 void OQueryController::executeQuery()
1290 // we don't need to check the connection here because we already check the composer
1291 // which can't live without his connection
1292 OUString sTranslatedStmt
= translateStatement( false );
1294 OUString sDataSourceName
= getDataSourceName();
1295 if ( !(sDataSourceName
.isEmpty() || sTranslatedStmt
.isEmpty()) )
1299 getContainer()->showPreview( getFrame() );
1300 InvalidateFeature(SID_DB_QUERY_PREVIEW
);
1302 URL aWantToDispatch
;
1303 aWantToDispatch
.Complete
= ".component:DB/DataSourceBrowser";
1305 OUString
sFrameName( FRAME_NAME_QUERY_PREVIEW
);
1306 sal_Int32 nSearchFlags
= FrameSearchFlag::CHILDREN
;
1308 Reference
< XDispatch
> xDisp
;
1309 Reference
< XDispatchProvider
> xProv( getFrame()->findFrame( sFrameName
, nSearchFlags
), UNO_QUERY
);
1312 xProv
.set( getFrame(), UNO_QUERY
);
1314 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, nSearchFlags
);
1318 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, FrameSearchFlag::SELF
);
1322 Sequence
< PropertyValue
> aProps(9);
1323 aProps
[0].Name
= PROPERTY_DATASOURCENAME
;
1324 aProps
[0].Value
<<= sDataSourceName
;
1326 aProps
[1].Name
= PROPERTY_COMMAND_TYPE
;
1327 aProps
[1].Value
<<= CommandType::COMMAND
;
1329 aProps
[2].Name
= PROPERTY_COMMAND
;
1330 aProps
[2].Value
<<= sTranslatedStmt
;
1332 aProps
[3].Name
= PROPERTY_ENABLE_BROWSER
;
1333 aProps
[3].Value
<<= false;
1335 aProps
[4].Name
= PROPERTY_ACTIVE_CONNECTION
;
1336 aProps
[4].Value
<<= getConnection();
1338 aProps
[5].Name
= PROPERTY_UPDATE_CATALOGNAME
;
1339 aProps
[5].Value
<<= m_sUpdateCatalogName
;
1341 aProps
[6].Name
= PROPERTY_UPDATE_SCHEMANAME
;
1342 aProps
[6].Value
<<= m_sUpdateSchemaName
;
1344 aProps
[7].Name
= PROPERTY_UPDATE_TABLENAME
;
1345 aProps
[7].Value
<<= m_sUpdateTableName
;
1347 aProps
[8].Name
= PROPERTY_ESCAPE_PROCESSING
;
1348 aProps
[8].Value
<<= m_bEscapeProcessing
;
1350 xDisp
->dispatch(aWantToDispatch
, aProps
);
1351 // check the state of the beamer
1352 // be notified when the beamer frame is closed
1353 Reference
< XComponent
> xComponent( getFrame()->findFrame( sFrameName
, nSearchFlags
), UNO_QUERY
);
1354 if (xComponent
.is())
1356 OSL_ENSURE(Reference
< XFrame
>(xComponent
, UNO_QUERY
).get() == getContainer()->getPreviewFrame().get(),
1357 "OQueryController::executeQuery: oops ... which window do I have here?");
1358 Reference
< XEventListener
> xEvtL((::cppu::OWeakObject
*)this,UNO_QUERY
);
1359 xComponent
->addEventListener(xEvtL
);
1364 OSL_FAIL("Couldn't create a beamer window!");
1367 catch(const Exception
&)
1369 OSL_FAIL("Couldn't create a beamer window!");
1374 bool OQueryController::askForNewName(const Reference
<XNameAccess
>& _xElements
, bool _bSaveAs
)
1376 OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" );
1377 if ( editingCommand() )
1380 OSL_PRECOND( _xElements
.is(), "OQueryController::askForNewName: invalid container!" );
1381 if ( !_xElements
.is() )
1385 bool bNew
= _bSaveAs
|| !_xElements
->hasByName( m_sName
);
1388 OUString aDefaultName
;
1389 if ( ( _bSaveAs
&& !bNew
) || ( bNew
&& !m_sName
.isEmpty() ) )
1390 aDefaultName
= m_sName
;
1393 OUString sName
= ModuleRes( editingView() ? STR_VIEW_TITLE
: STR_QRY_TITLE
);
1394 aDefaultName
= sName
.getToken(0,' ');
1395 aDefaultName
= ::dbtools::createUniqueName(_xElements
,aDefaultName
);
1398 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::QUERY
);
1399 ScopedVclPtrInstance
<OSaveAsDlg
> aDlg(
1408 bRet
= ( aDlg
->Execute() == RET_OK
);
1411 m_sName
= aDlg
->getName();
1412 if ( editingView() )
1414 m_sUpdateCatalogName
= aDlg
->getCatalog();
1415 m_sUpdateSchemaName
= aDlg
->getSchema();
1422 bool OQueryController::doSaveAsDoc(bool _bSaveAs
)
1424 OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
1425 if ( !editingCommand() && !haveDataSource() )
1427 OUString
aMessage(ModuleRes(STR_DATASOURCE_DELETED
));
1428 ScopedVclPtr
<OSQLWarningBox
>::Create( getView(), aMessage
)->Execute();
1432 Reference
< XNameAccess
> xElements
= getObjectContainer();
1433 if ( !xElements
.is() )
1436 if ( !getContainer()->checkStatement() )
1439 OUString sTranslatedStmt
= translateStatement();
1440 if ( editingCommand() )
1442 setModified( sal_False
);
1443 // this is all we need to do here. translateStatement implicitly set our m_sStatement, and
1444 // notified it, and that's all
1448 if ( sTranslatedStmt
.isEmpty() )
1451 // first we need a name for our query so ask the user
1452 // did we get a name
1453 OUString
sOriginalName( m_sName
);
1454 if ( !askForNewName( xElements
, _bSaveAs
) || m_sName
.isEmpty() )
1457 SQLExceptionInfo aInfo
;
1458 bool bSuccess
= false;
1463 || ( !xElements
->hasByName( m_sName
) );
1465 Reference
<XPropertySet
> xQuery
;
1466 if ( bNew
) // just to make sure the query already exists
1468 // drop the query, in case it already exists
1469 if ( xElements
->hasByName( m_sName
) )
1471 Reference
< XDrop
> xNameCont( xElements
, UNO_QUERY
);
1472 if ( xNameCont
.is() )
1473 xNameCont
->dropByName( m_sName
);
1476 Reference
< XNameContainer
> xCont( xElements
, UNO_QUERY
);
1478 xCont
->removeByName( m_sName
);
1482 // create a new (empty, uninitialized) query resp. view
1483 Reference
< XDataDescriptorFactory
> xFact( xElements
, UNO_QUERY
);
1486 xQuery
= xFact
->createDataDescriptor();
1487 // to set the name is only allowed when the query is new
1488 xQuery
->setPropertyValue( PROPERTY_NAME
, makeAny( m_sName
) );
1492 Reference
< XSingleServiceFactory
> xSingleFac( xElements
, UNO_QUERY
);
1493 if ( xSingleFac
.is() )
1494 xQuery
.set(xSingleFac
->createInstance(), css::uno::UNO_QUERY
);
1499 xElements
->getByName( m_sName
) >>= xQuery
;
1502 throw RuntimeException();
1505 if ( editingView() && !bNew
)
1507 OSL_ENSURE( xQuery
== m_xAlterView
, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" );
1508 m_xAlterView
.set( xQuery
, UNO_QUERY_THROW
);
1509 m_xAlterView
->alterCommand( sTranslatedStmt
);
1512 { // we're creating a query, or a *new* view
1513 xQuery
->setPropertyValue( PROPERTY_COMMAND
, makeAny( sTranslatedStmt
) );
1515 if ( editingView() )
1517 xQuery
->setPropertyValue( PROPERTY_CATALOGNAME
, makeAny( m_sUpdateCatalogName
) );
1518 xQuery
->setPropertyValue( PROPERTY_SCHEMANAME
, makeAny( m_sUpdateSchemaName
) );
1521 if ( editingQuery() )
1523 xQuery
->setPropertyValue( PROPERTY_UPDATE_TABLENAME
, makeAny( m_sUpdateTableName
) );
1524 xQuery
->setPropertyValue( PROPERTY_ESCAPE_PROCESSING
, css::uno::makeAny( m_bEscapeProcessing
) );
1526 xQuery
->setPropertyValue( PROPERTY_LAYOUTINFORMATION
, getViewData() );
1532 Reference
< XAppend
> xAppend( xElements
, UNO_QUERY
);
1535 xAppend
->appendByDescriptor( xQuery
);
1539 Reference
< XNameContainer
> xCont( xElements
, UNO_QUERY
);
1541 xCont
->insertByName( m_sName
, makeAny( xQuery
) );
1544 if ( editingView() )
1546 Reference
< XPropertySet
> xViewProps
;
1547 if ( xElements
->hasByName( m_sName
) )
1548 xViewProps
.set( xElements
->getByName( m_sName
), UNO_QUERY
);
1550 if ( !xViewProps
.is() ) // correct name and try again
1551 m_sName
= ::dbtools::composeTableName( getMetaData(), xQuery
, ::dbtools::eInDataManipulation
, false, false, false );
1553 OSL_ENSURE( xElements
->hasByName( m_sName
), "OQueryController::doSaveAsDoc: newly creaed view does not exist!" );
1555 if ( xElements
->hasByName( m_sName
) )
1556 m_xAlterView
.set( xElements
->getByName( m_sName
), UNO_QUERY
);
1558 // now check if our datasource has set a tablefilter and if so, append the new table name to it
1559 ::dbaui::appendToFilter( getConnection(), m_sName
, getORB(), getView() );
1561 Reference
< XTitleChangeListener
> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY
);
1562 if ( xEventListener
.is() )
1564 TitleChangedEvent aEvent
;
1565 xEventListener
->titleChanged(aEvent
);
1567 releaseNumberForComponent();
1570 setModified( sal_False
);
1574 catch(const SQLException
&)
1577 m_sName
= sOriginalName
;
1578 aInfo
= SQLExceptionInfo( ::cppu::getCaughtException() );
1580 catch(const Exception
&)
1583 m_sName
= sOriginalName
;
1584 DBG_UNHANDLED_EXCEPTION();
1589 // if we successfully saved a view we were creating, then close the designer
1590 if ( bSuccess
&& editingView() && !m_xAlterView
.is() )
1595 if ( bSuccess
&& editingView() )
1596 InvalidateFeature( ID_BROWSER_EDITDOC
);
1606 CommentStrip( const OUString
& rComment
, bool bLastOnLine
)
1607 : maComment( rComment
), mbLastOnLine( bLastOnLine
) {}
1612 /** Obtain all comments in a query.
1614 See also delComment() implementation for OSQLParser::parseTree().
1616 static ::std::vector
< CommentStrip
> getComment( const OUString
& rQuery
)
1618 ::std::vector
< CommentStrip
> aRet
;
1619 // First a quick search if there is any "--" or "//" or "/*", if not then
1620 // the whole copying loop is pointless.
1621 if (rQuery
.indexOf( "--" ) < 0 && rQuery
.indexOf( "//" ) < 0 &&
1622 rQuery
.indexOf( "/*" ) < 0)
1625 const sal_Unicode
* pCopy
= rQuery
.getStr();
1626 const sal_Int32 nQueryLen
= rQuery
.getLength();
1627 bool bIsText1
= false; // "text"
1628 bool bIsText2
= false; // 'text'
1629 bool bComment2
= false; // /* comment */
1630 bool bComment
= false; // -- or // comment
1631 OUStringBuffer aBuf
;
1632 for (sal_Int32 i
=0; i
< nQueryLen
; ++i
)
1636 aBuf
.append( &pCopy
[i
], 1);
1637 if ((i
+1) < nQueryLen
)
1639 if (pCopy
[i
]=='*' && pCopy
[i
+1]=='/')
1642 aBuf
.append( &pCopy
[++i
], 1);
1643 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), false));
1648 // comment can't close anymore, actually an error, but..
1649 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), false));
1653 if (pCopy
[i
] == '\n' || i
== nQueryLen
-1)
1657 if (i
== nQueryLen
-1 && pCopy
[i
] != '\n')
1658 aBuf
.append( &pCopy
[i
], 1);
1659 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), true));
1662 else if (!aRet
.empty())
1663 aRet
.back().mbLastOnLine
= true;
1667 if (pCopy
[i
] == '\"' && !bIsText2
)
1668 bIsText1
= !bIsText1
;
1669 else if (pCopy
[i
] == '\'' && !bIsText1
)
1670 bIsText2
= !bIsText2
;
1671 if (!bIsText1
&& !bIsText2
&& (i
+1) < nQueryLen
)
1673 if ((pCopy
[i
]=='-' && pCopy
[i
+1]=='-') || (pCopy
[i
]=='/' && pCopy
[i
+1]=='/'))
1675 else if ((pCopy
[i
]=='/' && pCopy
[i
+1]=='*'))
1679 if (bComment
|| bComment2
)
1680 aBuf
.append( &pCopy
[i
], 1);
1685 /** Concat/insert comments that were previously obtained with getComment().
1687 NOTE: The current parser implementation does not preserve newlines, so all
1688 comments are always appended to the entire query, also inline comments
1689 that would need positioning anyway that can't be obtained after
1690 recomposition. This is ugly but at least allows commented queries while
1691 preserving the comments _somehow_.
1693 static OUString
concatComment( const OUString
& rQuery
, const ::std::vector
< CommentStrip
>& rComments
)
1695 // No comments => return query.
1696 if (rComments
.empty())
1699 const sal_Unicode
* pBeg
= rQuery
.getStr();
1700 const sal_Int32 nLen
= rQuery
.getLength();
1701 const size_t nComments
= rComments
.size();
1702 // Obtaining the needed size once should be faster than reallocating.
1703 // Also add a blank or linefeed for each comment.
1704 sal_Int32 nBufSize
= nLen
+ nComments
;
1705 for (::std::vector
< CommentStrip
>::const_iterator
it( rComments
.begin()); it
!= rComments
.end(); ++it
)
1706 nBufSize
+= (*it
).maComment
.getLength();
1707 OUStringBuffer
aBuf( nBufSize
);
1708 sal_Int32 nIndBeg
= 0;
1709 sal_Int32 nIndLF
= rQuery
.indexOf('\n');
1711 while (nIndLF
>= 0 && i
< nComments
)
1713 aBuf
.append( pBeg
+ nIndBeg
, nIndLF
- nIndBeg
);
1716 aBuf
.append( rComments
[i
].maComment
);
1717 } while (!rComments
[i
++].mbLastOnLine
&& i
< nComments
);
1718 aBuf
.append( pBeg
+ nIndLF
, 1); // the LF
1719 nIndBeg
= nIndLF
+ 1;
1720 nIndLF
= (nIndBeg
< nLen
? rQuery
.indexOf( '\n', nIndBeg
) : -1);
1722 // Append remainder of query.
1724 aBuf
.append( pBeg
+ nIndBeg
, nLen
- nIndBeg
);
1725 // Append all remaining comments, preserve lines.
1726 bool bNewLine
= false;
1727 for ( ; i
< nComments
; ++i
)
1731 aBuf
.append( rComments
[i
].maComment
);
1732 if (rComments
[i
].mbLastOnLine
)
1740 return aBuf
.makeStringAndClear();
1743 OUString
OQueryController::translateStatement( bool _bFireStatementChange
)
1745 // now set the properties
1746 setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange
);
1747 OUString sTranslatedStmt
;
1748 if(!m_sStatement
.isEmpty() && m_xComposer
.is() && m_bEscapeProcessing
)
1754 ::std::vector
< CommentStrip
> aComments
= getComment( m_sStatement
);
1756 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
);
1759 pNode
->parseNodeToStr( sTranslatedStmt
, getConnection() );
1763 m_xComposer
->setQuery(sTranslatedStmt
);
1764 sTranslatedStmt
= m_xComposer
->getComposedQuery();
1765 sTranslatedStmt
= concatComment( sTranslatedStmt
, aComments
);
1767 catch(const SQLException
& e
)
1769 ::dbtools::SQLExceptionInfo
aInfo(e
);
1771 // an error occurred so we clear the statement
1772 sTranslatedStmt
.clear();
1775 else if(m_sStatement
.isEmpty())
1777 ModuleRes
aModuleRes(STR_QRY_NOSELECT
);
1778 OUString
sTmpStr(aModuleRes
);
1779 OUString
sError(sTmpStr
);
1780 showError(SQLException(sError
,NULL
,"S1000",1000,Any()));
1783 sTranslatedStmt
= m_sStatement
;
1785 return sTranslatedStmt
;
1788 short OQueryController::saveModified()
1790 SolarMutexGuard aSolarGuard
;
1791 ::osl::MutexGuard
aGuard( getMutex() );
1792 short nRet
= RET_YES
;
1793 if ( !isConnected() || !isModified() )
1796 if ( !m_bGraphicalDesign
1797 || ( !m_vTableFieldDesc
.empty()
1798 && !m_vTableData
.empty()
1802 OUString
sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED
, m_nCommandType
) );
1803 ScopedVclPtrInstance
< QueryBox
> aQry( getView(), WB_YES_NO_CANCEL
| WB_DEF_YES
, sMessageText
);
1805 nRet
= aQry
->Execute();
1806 if ( ( nRet
== RET_YES
)
1807 && !doSaveAsDoc( false )
1816 void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings
)
1818 bool bValid
= false;
1820 Sequence
< PropertyValue
> aLayoutInformation
;
1821 // get command from the query if a query name was supplied
1822 if ( !i_bForceCurrentControllerSettings
&& !editingCommand() )
1824 if ( !m_sName
.isEmpty() )
1826 Reference
< XNameAccess
> xQueries
= getObjectContainer();
1827 if ( xQueries
.is() )
1829 Reference
< XPropertySet
> xProp
;
1830 if( xQueries
->hasByName( m_sName
) && ( xQueries
->getByName( m_sName
) >>= xProp
) && xProp
.is() )
1832 OUString sNewStatement
;
1833 xProp
->getPropertyValue( PROPERTY_COMMAND
) >>= sNewStatement
;
1834 setStatement_fireEvent( sNewStatement
);
1836 if ( editingQuery() )
1838 bool bNewEscapeProcessing( true );
1839 xProp
->getPropertyValue( PROPERTY_ESCAPE_PROCESSING
) >>= bNewEscapeProcessing
;
1840 setEscapeProcessing_fireEvent( bNewEscapeProcessing
);
1843 m_bGraphicalDesign
= m_bGraphicalDesign
&& m_bEscapeProcessing
;
1848 if ( editingQuery() )
1849 xProp
->getPropertyValue( PROPERTY_LAYOUTINFORMATION
) >>= aLayoutInformation
;
1851 catch( const Exception
& )
1853 OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" );
1862 // assume that we got all necessary information during initialization
1867 // load the layoutInformation
1868 if ( aLayoutInformation
.getLength() )
1872 loadViewSettings( aLayoutInformation
);
1874 catch( const Exception
& )
1876 DBG_UNHANDLED_EXCEPTION();
1880 if ( !m_sStatement
.isEmpty() )
1884 bool bError( false );
1886 if ( !m_pSqlIterator
)
1890 else if ( m_bEscapeProcessing
)
1893 ::std::unique_ptr
< ::connectivity::OSQLParseNode
> pNode(
1894 m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
) );
1898 delete m_pSqlIterator
->getParseTree();
1899 m_pSqlIterator
->setParseTree( pNode
.release() );
1900 m_pSqlIterator
->traverseAll();
1901 if ( m_pSqlIterator
->hasErrors() )
1903 if ( !i_bForceCurrentControllerSettings
&& m_bGraphicalDesign
&& !editingView() )
1905 impl_showAutoSQLViewError( makeAny( m_pSqlIterator
->getErrors() ) );
1912 if ( !i_bForceCurrentControllerSettings
&& !editingView() )
1914 OUString
aTitle(ModuleRes(STR_SVT_SQL_SYNTAX_ERROR
));
1915 ScopedVclPtrInstance
< OSQLMessageBox
> aDlg(getView(),aTitle
,aErrorMsg
);
1924 m_bGraphicalDesign
= false;
1925 if ( editingView() )
1926 // if we're editing a view whose statement could not be parsed, default to "no escape processing"
1927 setEscapeProcessing_fireEvent( false );
1934 OSL_ENSURE(m_pSqlIterator
,"No SQLIterator set!");
1936 getContainer()->setNoneVisbleRow(m_nVisibleRows
);
1939 void OQueryController::reset()
1942 getContainer()->reset( NULL
);
1946 void OQueryController::setStatement_fireEvent( const OUString
& _rNewStatement
, bool _bFireStatementChange
)
1948 Any aOldValue
= makeAny( m_sStatement
);
1949 m_sStatement
= _rNewStatement
;
1950 Any aNewValue
= makeAny( m_sStatement
);
1952 sal_Int32 nHandle
= PROPERTY_ID_ACTIVECOMMAND
;
1953 if ( _bFireStatementChange
)
1954 fire( &nHandle
, &aNewValue
, &aOldValue
, 1, sal_False
);
1957 void OQueryController::setEscapeProcessing_fireEvent( const bool _bEscapeProcessing
)
1959 if ( _bEscapeProcessing
== m_bEscapeProcessing
)
1962 Any aOldValue
= makeAny( m_bEscapeProcessing
);
1963 m_bEscapeProcessing
= _bEscapeProcessing
;
1964 Any aNewValue
= makeAny( m_bEscapeProcessing
);
1966 sal_Int32 nHandle
= PROPERTY_ID_ESCAPE_PROCESSING
;
1967 fire( &nHandle
, &aNewValue
, &aOldValue
, 1, sal_False
);
1970 IMPL_LINK_NOARG( OQueryController
, OnExecuteAddTable
)
1972 Execute( ID_BROWSER_ADDTABLE
,Sequence
<PropertyValue
>() );
1976 bool OQueryController::allowViews() const
1981 bool OQueryController::allowQueries() const
1983 OSL_ENSURE( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" );
1984 if ( !getSdbMetaData().supportsSubqueriesInFrom() )
1987 const NamedValueCollection
& rArguments( getInitParams() );
1988 sal_Int32 nCommandType
= rArguments
.getOrDefault( OUString(PROPERTY_COMMAND_TYPE
), (sal_Int32
)CommandType::QUERY
);
1989 bool bCreatingView
= ( nCommandType
== CommandType::TABLE
);
1990 return !bCreatingView
;
1993 Any SAL_CALL
OQueryController::getViewData() throw( RuntimeException
, std::exception
)
1995 ::osl::MutexGuard
aGuard( getMutex() );
1997 getContainer()->SaveUIConfig();
1999 ::comphelper::NamedValueCollection aViewSettings
;
2000 saveViewSettings( aViewSettings
, false );
2002 return makeAny( aViewSettings
.getPropertyValues() );
2005 void SAL_CALL
OQueryController::restoreViewData(const Any
& /*Data*/) throw( RuntimeException
, std::exception
)
2010 } // namespace dbaui
2012 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */