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/propertysequence.hxx>
70 #include <comphelper/processfactory.hxx>
71 #include <comphelper/property.hxx>
72 #include <comphelper/seqstream.hxx>
73 #include <comphelper/streamsection.hxx>
74 #include <comphelper/types.hxx>
75 #include <connectivity/dbexception.hxx>
76 #include <connectivity/dbtools.hxx>
77 #include <cppuhelper/exc_hlp.hxx>
78 #include <sfx2/sfxsids.hrc>
79 #include <svtools/localresaccess.hxx>
80 #include <toolkit/helper/vclunohelper.hxx>
81 #include <tools/diagnose_ex.h>
82 #include <osl/diagnose.h>
83 #include <vcl/msgbox.hxx>
84 #include <vcl/svapp.hxx>
85 #include <osl/mutex.hxx>
86 #include <rtl/strbuf.hxx>
89 extern "C" void SAL_CALL
createRegistryInfo_OQueryControl()
91 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::OQueryController
> aAutoRegistration
;
96 using namespace ::com::sun::star::uno
;
97 using namespace ::com::sun::star::beans
;
98 using namespace ::com::sun::star::frame
;
99 using namespace ::com::sun::star::util
;
100 using namespace ::com::sun::star::lang
;
102 class OViewController
: public OQueryController
104 virtual OUString SAL_CALL
getImplementationName() throw( RuntimeException
, std::exception
) override
106 return getImplementationName_Static();
108 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() throw(RuntimeException
, std::exception
) override
110 return getSupportedServiceNames_Static();
114 explicit OViewController(const Reference
< XComponentContext
>& _rM
) : OQueryController(_rM
){}
116 // need by registration
117 static OUString
getImplementationName_Static() throw( RuntimeException
)
119 return OUString("org.openoffice.comp.dbu.OViewDesign");
121 static Sequence
< OUString
> getSupportedServiceNames_Static() throw( RuntimeException
)
123 Sequence
<OUString
> aSupported
{ "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 > 0
144 void insertParseTree(SvTreeListBox
* _pBox
,::connectivity::OSQLParseNode
* _pNode
,SvTreeListEntry
* _pParent
= nullptr)
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 SQLNodeType::Keyword
:
171 rString
+= "SQL_KEYWORD:";
172 OString sT
= OSQLParser::TokenIDToStr(_pNode
->getTokenID());
173 rString
+= OStringToOUString(sT
, RTL_TEXTENCODING_UTF8
);
176 case SQLNodeType::Comparison
:
178 rString
+= "SQL_COMPARISON:" + _pNode
->getTokenValue(); // append Nodevalue
179 // and start new line
182 case SQLNodeType::Name
:
184 rString
+= "SQL_NAME:\"" + _pNode
->getTokenValue() + "\"";
187 case SQLNodeType::String
:
189 rString
+= "SQL_STRING:'" + _pNode
->getTokenValue();
192 case SQLNodeType::IntNum
:
194 rString
+= "SQL_INTNUM:" + _pNode
->getTokenValue();
197 case SQLNodeType::ApproxNum
:
199 rString
+= "SQL_APPROXNUM:" + _pNode
->getTokenValue();
202 case SQLNodeType::Punctuation
:
204 rString
+= "SQL_PUNCTUATION:" + _pNode
->getTokenValue(); // append Nodevalue
207 case SQLNodeType::AMMSC
:
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
< css::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
{ "com.sun.star.sdb.QueryDesign" };
317 Sequence
< OUString
> SAL_CALL
OQueryController::getSupportedServiceNames() throw(RuntimeException
, std::exception
)
319 return getSupportedServiceNames_Static();
322 Reference
< XInterface
> SAL_CALL
OQueryController::Create(const Reference
<XMultiServiceFactory
>& _rxFactory
)
324 return *(new OQueryController(comphelper::getComponentContext(_rxFactory
)));
327 OQueryController::OQueryController(const Reference
< XComponentContext
>& _rM
)
328 :OJoinController(_rM
)
329 ,OQueryController_PBase( getBroadcastHelper() )
330 ,m_pParseContext( new svxform::OSystemParseContext
)
331 ,m_aSqlParser( _rM
, m_pParseContext
)
332 ,m_pSqlIterator(nullptr)
334 ,m_nVisibleRows(0x400)
336 ,m_nCommandType( CommandType::QUERY
)
337 ,m_bGraphicalDesign(false)
339 ,m_bEscapeProcessing(true)
343 registerProperty( PROPERTY_ACTIVECOMMAND
, PROPERTY_ID_ACTIVECOMMAND
, PropertyAttribute::READONLY
| PropertyAttribute::BOUND
,
344 &m_sStatement
, cppu::UnoType
<decltype(m_sStatement
)>::get() );
345 registerProperty( PROPERTY_ESCAPE_PROCESSING
, PROPERTY_ID_ESCAPE_PROCESSING
, PropertyAttribute::READONLY
| PropertyAttribute::BOUND
,
346 &m_bEscapeProcessing
, cppu::UnoType
<decltype(m_bEscapeProcessing
)>::get() );
349 OQueryController::~OQueryController()
351 if ( !getBroadcastHelper().bDisposed
&& !getBroadcastHelper().bInDispose
)
353 OSL_FAIL("Please check who doesn't dispose this component!");
354 // increment ref count to prevent double call of Dtor
355 osl_atomic_increment( &m_refCount
);
360 IMPLEMENT_FORWARD_XINTERFACE2( OQueryController
, OJoinController
, OQueryController_PBase
)
361 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController
, OJoinController
, OQueryController_PBase
)
363 Reference
< XPropertySetInfo
> SAL_CALL
OQueryController::getPropertySetInfo() throw(RuntimeException
, std::exception
)
365 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
369 sal_Bool SAL_CALL
OQueryController::convertFastPropertyValue( Any
& o_rConvertedValue
, Any
& o_rOldValue
, sal_Int32 i_nHandle
, const Any
& i_rValue
) throw (IllegalArgumentException
)
371 return OPropertyContainer::convertFastPropertyValue( o_rConvertedValue
, o_rOldValue
, i_nHandle
, i_rValue
);
374 void SAL_CALL
OQueryController::setFastPropertyValue_NoBroadcast( sal_Int32 i_nHandle
, const Any
& i_rValue
) throw ( Exception
, std::exception
)
376 OPropertyContainer::setFastPropertyValue_NoBroadcast( i_nHandle
, i_rValue
);
379 void SAL_CALL
OQueryController::getFastPropertyValue( Any
& o_rValue
, sal_Int32 i_nHandle
) const
383 case PROPERTY_ID_CURRENT_QUERY_DESIGN
:
385 ::comphelper::NamedValueCollection aCurrentDesign
;
386 aCurrentDesign
.put( "GraphicalDesign", isGraphicalDesign() );
387 aCurrentDesign
.put( OUString(PROPERTY_ESCAPE_PROCESSING
), m_bEscapeProcessing
);
389 if ( isGraphicalDesign() )
391 getContainer()->SaveUIConfig();
392 saveViewSettings( aCurrentDesign
, true );
393 aCurrentDesign
.put( "Statement", m_sStatement
);
397 aCurrentDesign
.put( "Statement", getContainer()->getStatement() );
400 o_rValue
<<= aCurrentDesign
.getPropertyValues();
405 OPropertyContainer::getFastPropertyValue( o_rValue
, i_nHandle
);
410 ::cppu::IPropertyArrayHelper
& OQueryController::getInfoHelper()
412 return *getArrayHelper();
415 ::cppu::IPropertyArrayHelper
* OQueryController::createArrayHelper( ) const
417 Sequence
< Property
> aProps
;
418 describeProperties( aProps
);
420 // one additional property:
421 const sal_Int32 nLength
= aProps
.getLength();
422 aProps
.realloc( nLength
+ 1 );
423 aProps
[ nLength
] = Property(
424 "CurrentQueryDesign",
425 PROPERTY_ID_CURRENT_QUERY_DESIGN
,
426 ::cppu::UnoType
< Sequence
< PropertyValue
> >::get(),
427 PropertyAttribute::READONLY
432 aProps
.getArray() + aProps
.getLength(),
433 ::comphelper::PropertyCompareByName()
436 return new ::cppu::OPropertyArrayHelper(aProps
);
439 void OQueryController::deleteIterator()
443 delete m_pSqlIterator
->getParseTree();
444 m_pSqlIterator
->dispose();
445 delete m_pSqlIterator
;
446 m_pSqlIterator
= nullptr;
450 void OQueryController::disposing()
452 OQueryController_PBase::disposing();
456 delete m_pParseContext
;
459 OTableFields().swap(m_vUnUsedFieldsDesc
);
461 ::comphelper::disposeComponent(m_xComposer
);
462 OJoinController::disposing();
463 OQueryController_PBase::disposing();
466 void OQueryController::clearFields()
468 OTableFields().swap(m_vTableFieldDesc
);
471 FeatureState
OQueryController::GetState(sal_uInt16 _nId
) const
473 FeatureState aReturn
;
474 aReturn
.bEnabled
= true;
475 // (disabled automatically)
479 case ID_BROWSER_EDITDOC
:
480 if ( editingCommand() )
481 aReturn
.bEnabled
= false;
482 else if ( editingView() && !m_xAlterView
.is() )
483 aReturn
.bEnabled
= false;
485 aReturn
= OJoinController::GetState( _nId
);
488 case ID_BROWSER_ESCAPEPROCESSING
:
489 aReturn
.bChecked
= !m_bEscapeProcessing
;
490 aReturn
.bEnabled
= ( m_pSqlIterator
!= nullptr ) && !m_bGraphicalDesign
;
492 case SID_RELATION_ADD_RELATION
:
493 aReturn
.bEnabled
= isEditable() && m_bGraphicalDesign
&& m_vTableData
.size() > 1;
495 case ID_BROWSER_SAVEASDOC
:
496 aReturn
.bEnabled
= !editingCommand() && !editingView() && (!m_bGraphicalDesign
|| !(m_vTableFieldDesc
.empty() || m_vTableData
.empty()));
498 case ID_BROWSER_SAVEDOC
:
499 aReturn
.bEnabled
= isEditable() && (!m_bGraphicalDesign
|| !(m_vTableFieldDesc
.empty() || m_vTableData
.empty()));
501 case SID_PRINTDOCDIRECT
:
504 aReturn
.bEnabled
= isEditable() && getContainer() && getContainer()->isCutAllowed();
506 case ID_BROWSER_COPY
:
507 aReturn
.bEnabled
= getContainer() && getContainer()->isCopyAllowed();
509 case ID_BROWSER_PASTE
:
510 aReturn
.bEnabled
= isEditable() && getContainer() && getContainer()->isPasteAllowed();
513 aReturn
.bEnabled
= m_bEscapeProcessing
&& m_pSqlIterator
;
514 aReturn
.bChecked
= m_bGraphicalDesign
;
516 case SID_BROWSER_CLEAR_QUERY
:
517 aReturn
.bEnabled
= isEditable() && (!m_sStatement
.isEmpty() || !m_vTableData
.empty());
519 case SID_QUERY_VIEW_FUNCTIONS
:
520 case SID_QUERY_VIEW_TABLES
:
521 case SID_QUERY_VIEW_ALIASES
:
522 aReturn
.bChecked
= getContainer() && getContainer()->isSlotEnabled(_nId
);
523 aReturn
.bEnabled
= m_bGraphicalDesign
;
525 case SID_QUERY_DISTINCT_VALUES
:
526 aReturn
.bEnabled
= m_bGraphicalDesign
&& isEditable();
527 aReturn
.bChecked
= m_bDistinct
;
529 case SID_QUERY_LIMIT
:
530 aReturn
.bEnabled
= m_bGraphicalDesign
;
531 if( aReturn
.bEnabled
)
532 aReturn
.aValue
= makeAny( m_nLimit
);
534 case SID_QUERY_PROP_DLG
:
535 aReturn
.bEnabled
= m_bGraphicalDesign
;
537 case ID_BROWSER_QUERY_EXECUTE
:
538 aReturn
.bEnabled
= true;
540 case SID_DB_QUERY_PREVIEW
:
541 aReturn
.bEnabled
= true;
542 aReturn
.bChecked
= getContainer() && getContainer()->getPreviewFrame().is();
544 #if OSL_DEBUG_LEVEL > 0
545 case ID_EDIT_QUERY_SQL
:
547 case ID_EDIT_QUERY_DESIGN
:
550 case ID_BROWSER_ADDTABLE
:
551 if ( !m_bGraphicalDesign
)
553 aReturn
.bEnabled
= false;
558 aReturn
= OJoinController::GetState(_nId
);
564 void OQueryController::Execute(sal_uInt16 _nId
, const Sequence
< PropertyValue
>& aArgs
)
568 case ID_BROWSER_ESCAPEPROCESSING
:
569 setEscapeProcessing_fireEvent( !m_bEscapeProcessing
);
570 if ( !editingView() )
572 InvalidateFeature(ID_BROWSER_SQL
);
574 case ID_BROWSER_SAVEASDOC
:
575 case ID_BROWSER_SAVEDOC
:
576 grabFocusFromLimitBox(*this);
577 doSaveAsDoc(ID_BROWSER_SAVEASDOC
== _nId
);
579 case SID_RELATION_ADD_RELATION
:
581 OJoinDesignView
* pView
= getJoinView();
583 static_cast<OQueryTableView
*>(pView
->getTableView())->createNewConnection();
586 case SID_PRINTDOCDIRECT
:
589 getContainer()->cut();
591 case ID_BROWSER_COPY
:
592 getContainer()->copy();
594 case ID_BROWSER_PASTE
:
595 getContainer()->paste();
599 grabFocusFromLimitBox(*this);
600 if ( !getContainer()->checkStatement() )
602 SQLExceptionInfo aError
;
606 setStatement_fireEvent( getContainer()->getStatement() );
607 if(m_sStatement
.isEmpty() && m_pSqlIterator
)
609 // change the view of the data
610 delete m_pSqlIterator
->getParseTree();
611 m_pSqlIterator
->setParseTree(nullptr);
612 m_bGraphicalDesign
= !m_bGraphicalDesign
;
613 impl_setViewMode( &aError
);
617 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree(aErrorMsg
,m_sStatement
,m_bGraphicalDesign
);
620 delete m_pSqlIterator
->getParseTree();
621 m_pSqlIterator
->setParseTree(pNode
);
622 m_pSqlIterator
->traverseAll();
624 if ( m_pSqlIterator
->hasErrors() )
626 aError
= m_pSqlIterator
->getErrors();
630 const OSQLTables
& rTabs
= m_pSqlIterator
->getTables();
631 if ( m_pSqlIterator
->getStatementType() != OSQLStatementType::Select
|| rTabs
.begin() == rTabs
.end() )
633 aError
= SQLException(
634 OUString( ModuleRes( STR_QRY_NOSELECT
) ),
643 // change the view of the data
644 m_bGraphicalDesign
= !m_bGraphicalDesign
;
645 OUString sNewStatement
;
646 pNode
->parseNodeToStr( sNewStatement
, getConnection() );
647 setStatement_fireEvent( sNewStatement
);
648 getContainer()->SaveUIConfig();
649 m_vTableConnectionData
.clear();
650 impl_setViewMode( &aError
);
656 aError
= SQLException(
657 OUString( ModuleRes( STR_QRY_SYNTAX
) ),
666 catch(const SQLException
&)
668 aError
= ::cppu::getCaughtException();
670 catch(const Exception
&)
672 DBG_UNHANDLED_EXCEPTION();
675 if ( aError
.isValid() )
678 if(m_bGraphicalDesign
)
680 InvalidateFeature(ID_BROWSER_ADDTABLE
);
681 InvalidateFeature(SID_RELATION_ADD_RELATION
);
685 case SID_BROWSER_CLEAR_QUERY
:
687 GetUndoManager().EnterListAction( OUString( ModuleRes(STR_QUERY_UNDO_TABWINDELETE
) ), OUString() );
688 getContainer()->clear();
689 GetUndoManager().LeaveListAction();
691 setStatement_fireEvent( OUString() );
692 if(m_bGraphicalDesign
)
693 InvalidateFeature(ID_BROWSER_ADDTABLE
);
696 case SID_QUERY_VIEW_FUNCTIONS
:
697 case SID_QUERY_VIEW_TABLES
:
698 case SID_QUERY_VIEW_ALIASES
:
699 getContainer()->setSlotEnabled(_nId
,!getContainer()->isSlotEnabled(_nId
));
702 case SID_QUERY_DISTINCT_VALUES
:
703 m_bDistinct
= !m_bDistinct
;
706 case SID_QUERY_LIMIT
:
707 if ( aArgs
.getLength() >= 1 && aArgs
[0].Name
== "DBLimit.Value" )
709 aArgs
[0].Value
>>= m_nLimit
;
713 case SID_QUERY_PROP_DLG
:
714 grabFocusFromLimitBox(*this);
715 execute_QueryPropDlg();
717 case ID_BROWSER_QUERY_EXECUTE
:
718 grabFocusFromLimitBox(*this);
719 if ( getContainer()->checkStatement() )
722 case SID_DB_QUERY_PREVIEW
:
725 Reference
< css::util::XCloseable
> xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY
);
726 if ( xCloseFrame
.is() )
730 xCloseFrame
->close( true );
732 catch(const Exception
&)
734 OSL_FAIL( "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" );
738 Execute(ID_BROWSER_QUERY_EXECUTE
,Sequence
< PropertyValue
>());
740 catch(const Exception
&)
744 case ID_QUERY_ZOOM_IN
:
748 case ID_QUERY_ZOOM_OUT
:
752 #if OSL_DEBUG_LEVEL > 0
753 case ID_EDIT_QUERY_DESIGN
:
754 case ID_EDIT_QUERY_SQL
:
757 setStatement_fireEvent( getContainer()->getStatement() );
758 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
);
761 vcl::Window
* pView
= getView();
762 ScopedVclPtrInstance
<ModalDialog
> pWindow( pView
, WB_STDMODAL
| WB_SIZEMOVE
| WB_CENTER
);
763 pWindow
->SetSizePixel( ::Size( pView
->GetSizePixel().Width() / 2, pView
->GetSizePixel().Height() / 2 ) );
764 ScopedVclPtrInstance
<SvTreeListBox
> pTreeBox( pWindow
, WB_BORDER
| WB_HASLINES
| WB_HASBUTTONS
| WB_HASBUTTONSATROOT
| WB_HASLINESATROOT
| WB_VSCROLL
);
765 pTreeBox
->SetPosSizePixel( ::Point( 6, 6 ), ::Size( pWindow
->GetSizePixel().Width() - 12, pWindow
->GetSizePixel().Height() - 12 ));
766 pTreeBox
->SetNodeDefaultImages();
768 if ( _nId
== ID_EDIT_QUERY_DESIGN
)
770 ::connectivity::OSQLParseNode
* pTemp
= pNode
? pNode
->getChild(3)->getChild(1) : nullptr;
771 // no where clause found
772 if ( pTemp
&& !pTemp
->isLeaf() )
774 ::connectivity::OSQLParseNode
* pCondition
= pTemp
->getChild(1);
775 if ( pCondition
) // no where clause
777 ::connectivity::OSQLParseNode::negateSearchCondition(pCondition
);
778 ::connectivity::OSQLParseNode
*pNodeTmp
= pTemp
->getChild(1);
780 ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp
);
781 pNodeTmp
= pTemp
->getChild(1);
782 ::connectivity::OSQLParseNode::absorptions(pNodeTmp
);
783 pNodeTmp
= pTemp
->getChild(1);
784 OSQLParseNode::compress(pNodeTmp
);
787 pNode
->parseNodeToStr(sTemp
,getConnection());
788 getContainer()->setStatement(sTemp
);
792 insertParseTree(pTreeBox
,pNode
);
803 OJoinController::Execute(_nId
,aArgs
);
804 return; // else we would invalidate twice
806 InvalidateFeature(_nId
);
809 void OQueryController::impl_showAutoSQLViewError( const css::uno::Any
& _rErrorDetails
)
811 SQLContext aErrorContext
;
812 aErrorContext
.Message
= lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT
, m_nCommandType
);
813 aErrorContext
.Context
= *this;
814 aErrorContext
.Details
= lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW
, m_nCommandType
);
815 aErrorContext
.NextException
= _rErrorDetails
;
816 showError( aErrorContext
);
819 void OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo
* _pErrorInfo
)
821 OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" );
823 bool wasModified
= isModified();
825 SQLExceptionInfo aError
;
826 bool bSuccess
= getContainer()->switchView( &aError
);
829 m_bGraphicalDesign
= !m_bGraphicalDesign
;
831 getContainer()->switchView( nullptr );
832 // don't pass &aError here, this would overwrite the error which the first switchView call
833 // returned in this location.
835 *_pErrorInfo
= aError
;
841 ensureToolbars( *this, m_bGraphicalDesign
);
844 setModified( wasModified
);
847 void OQueryController::impl_initialize()
849 OJoinController::impl_initialize();
851 const NamedValueCollection
& rArguments( getInitParams() );
854 m_nCommandType
= CommandType::QUERY
;
856 // reading parameters:
858 // legacy parameters first (later overwritten by regular parameters)
859 OUString sIndependentSQLCommand
;
860 if ( rArguments
.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand
) )
862 OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" );
863 sCommand
= sIndependentSQLCommand
;
864 m_nCommandType
= CommandType::COMMAND
;
867 OUString sCurrentQuery
;
868 if ( rArguments
.get_ensureType( "CurrentQuery", sCurrentQuery
) )
870 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
871 sCommand
= sCurrentQuery
;
872 m_nCommandType
= CommandType::QUERY
;
875 bool bCreateView( false );
876 if ( rArguments
.get_ensureType( "CreateView", bCreateView
) && bCreateView
)
878 OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
879 m_nCommandType
= CommandType::TABLE
;
882 // non-legacy parameters which overwrite the legacy parameters
883 rArguments
.get_ensureType( PROPERTY_COMMAND
, sCommand
);
884 rArguments
.get_ensureType( PROPERTY_COMMAND_TYPE
, m_nCommandType
);
886 // translate Command/Type into proper members
887 // TODO/Later: all this (including those members) should be hidden behind some abstract interface,
888 // which is implemented for all the three commands
889 switch ( m_nCommandType
)
891 case CommandType::QUERY
:
894 case CommandType::TABLE
:
897 case CommandType::COMMAND
:
898 setStatement_fireEvent( sCommand
);
902 OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" );
903 throw RuntimeException();
906 // more legacy parameters
907 bool bGraphicalDesign( true );
908 if ( rArguments
.get_ensureType( PROPERTY_QUERYDESIGNVIEW
, bGraphicalDesign
) )
910 OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" );
911 m_bGraphicalDesign
= bGraphicalDesign
;
915 rArguments
.get_ensureType( PROPERTY_GRAPHICAL_DESIGN
, m_bGraphicalDesign
);
917 bool bEscapeProcessing( true );
918 if ( rArguments
.get_ensureType( PROPERTY_ESCAPE_PROCESSING
, bEscapeProcessing
) )
920 setEscapeProcessing_fireEvent( bEscapeProcessing
);
922 OSL_ENSURE( m_bEscapeProcessing
|| !m_bGraphicalDesign
, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" );
923 if ( !m_bEscapeProcessing
)
924 m_bGraphicalDesign
= false;
928 bool bForceInitialDesign
= false;
929 Sequence
< PropertyValue
> aCurrentQueryDesignProps
;
930 aCurrentQueryDesignProps
= rArguments
.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps
);
932 if ( aCurrentQueryDesignProps
.getLength() )
934 ::comphelper::NamedValueCollection
aCurrentQueryDesign( aCurrentQueryDesignProps
);
935 if ( aCurrentQueryDesign
.has( OUString(PROPERTY_GRAPHICAL_DESIGN
) ) )
937 aCurrentQueryDesign
.get_ensureType( PROPERTY_GRAPHICAL_DESIGN
, m_bGraphicalDesign
);
939 if ( aCurrentQueryDesign
.has( OUString(PROPERTY_ESCAPE_PROCESSING
) ) )
941 aCurrentQueryDesign
.get_ensureType( PROPERTY_ESCAPE_PROCESSING
, m_bEscapeProcessing
);
943 if ( aCurrentQueryDesign
.has( "Statement" ) )
946 aCurrentQueryDesign
.get_ensureType( "Statement", sStatement
);
947 aCurrentQueryDesign
.remove( "Statement" );
948 setStatement_fireEvent( sStatement
);
951 loadViewSettings( aCurrentQueryDesign
);
953 bForceInitialDesign
= true;
956 if ( !ensureConnected() )
957 { // we have no connection so what else should we do
958 m_bGraphicalDesign
= false;
961 connectionLostMessage();
962 throw SQLException();
966 // check the view capabilities
967 if ( isConnected() && editingView() )
969 Reference
< XViewsSupplier
> xViewsSup( getConnection(), UNO_QUERY
);
970 Reference
< XNameAccess
> xViews
;
971 if ( xViewsSup
.is() )
972 xViews
= xViewsSup
->getViews();
975 { // we can't create views so we ask if the user wants to create a query instead
976 m_nCommandType
= CommandType::QUERY
;
979 OUString
aTitle( ModuleRes( STR_QUERYDESIGN_NO_VIEW_SUPPORT
) );
980 OUString
aMessage( ModuleRes( STR_QUERYDESIGN_NO_VIEW_ASK
) );
981 ODataView
* pWindow
= getView();
982 ScopedVclPtrInstance
< OSQLMessageBox
> aDlg( pWindow
, aTitle
, aMessage
, WB_YES_NO
| WB_DEF_YES
, OSQLMessageBox::Query
);
983 bClose
= aDlg
->Execute() == RET_NO
;
986 throw VetoException();
989 // now if we are to edit an existing view, check whether this is possible
990 if ( !m_sName
.isEmpty() )
992 Any
aView( xViews
->getByName( m_sName
) );
993 // will throw if there is no such view
994 if ( !( aView
>>= m_xAlterView
) )
996 throw IllegalArgumentException(
997 OUString( ModuleRes( STR_NO_ALTER_VIEW_SUPPORT
) ),
1005 OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!");
1009 getContainer()->initialize();
1010 impl_reset( bForceInitialDesign
);
1012 SQLExceptionInfo aError
;
1013 const bool bAttemptedGraphicalDesign
= m_bGraphicalDesign
;
1015 if ( bForceInitialDesign
)
1017 getContainer()->forceInitialView();
1021 impl_setViewMode( &aError
);
1024 if ( aError
.isValid() && bAttemptedGraphicalDesign
&& !m_bGraphicalDesign
)
1026 // we tried initializing the graphical view, this failed, and we were automatically switched to SQL
1027 // view => tell this to the user
1028 if ( !editingView() )
1030 impl_showAutoSQLViewError( aError
.get() );
1036 if ( ( m_bGraphicalDesign
)
1037 && ( ( m_sName
.isEmpty() && !editingCommand() )
1038 || ( m_sStatement
.isEmpty() && editingCommand() )
1042 Application::PostUserEvent( LINK( this, OQueryController
, OnExecuteAddTable
) );
1047 catch(const SQLException
& e
)
1049 DBG_UNHANDLED_EXCEPTION();
1050 // we caught an exception so we switch to text only mode
1052 m_bGraphicalDesign
= false;
1053 getContainer()->initialize();
1054 ODataView
* pWindow
= getView();
1055 ScopedVclPtrInstance
<OSQLMessageBox
>(pWindow
,e
)->Execute();
1061 void OQueryController::onLoadedMenu(const Reference
< css::frame::XLayoutManager
>& /*_xLayoutManager*/)
1063 ensureToolbars( *this, m_bGraphicalDesign
);
1066 OUString
OQueryController::getPrivateTitle( ) const
1068 OUString sName
= m_sName
;
1069 if ( sName
.isEmpty() )
1071 if ( !editingCommand() )
1073 SolarMutexGuard aSolarGuard
;
1074 ::osl::MutexGuard
aGuard( getMutex() );
1075 OUString aDefaultName
= ModuleRes( editingView() ? STR_VIEW_TITLE
: STR_QRY_TITLE
);
1076 sName
= aDefaultName
.getToken(0,' ');
1077 sName
+= OUString::number(getCurrentStartNumber());
1083 void OQueryController::setQueryComposer()
1087 Reference
< XSQLQueryComposerFactory
> xFactory(getConnection(), UNO_QUERY
);
1088 OSL_ENSURE(xFactory
.is(),"Connection doesn't support a querycomposer");
1089 if ( xFactory
.is() && getContainer() )
1093 m_xComposer
= xFactory
->createQueryComposer();
1094 getContainer()->setStatement(m_sStatement
);
1096 catch(const Exception
&)
1098 m_xComposer
= nullptr;
1100 OSL_ENSURE(m_xComposer
.is(),"No querycomposer available!");
1101 Reference
<XTablesSupplier
> xTablesSup(getConnection(), UNO_QUERY
);
1103 m_pSqlIterator
= new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup
->getTables(), m_aSqlParser
, nullptr );
1108 bool OQueryController::Construct(vcl::Window
* pParent
)
1110 // TODO: we have to check if we should create the text view or the design view
1112 setView( VclPtr
<OQueryContainerWindow
>::Create( pParent
, *this, getORB() ) );
1114 return OJoinController::Construct(pParent
);
1117 OJoinDesignView
* OQueryController::getJoinView()
1119 return getContainer()->getDesignView();
1122 void OQueryController::describeSupportedFeatures()
1124 OJoinController::describeSupportedFeatures();
1125 implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC
, CommandGroup::DOCUMENT
);
1126 implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESCAPEPROCESSING
,CommandGroup::FORMAT
);
1127 implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS
, CommandGroup::VIEW
);
1128 implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES
, CommandGroup::VIEW
);
1129 implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES
, CommandGroup::VIEW
);
1130 implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES
, CommandGroup::FORMAT
);
1131 implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL
, CommandGroup::VIEW
);
1132 implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY
, CommandGroup::EDIT
);
1133 implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE
, CommandGroup::VIEW
);
1134 implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION
, CommandGroup::EDIT
);
1135 implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW
, CommandGroup::VIEW
);
1136 implDescribeSupportedFeature( ".uno:DBLimit", SID_QUERY_LIMIT
, CommandGroup::FORMAT
);
1137 implDescribeSupportedFeature( ".uno:DBQueryPropertiesDialog", SID_QUERY_PROP_DLG
, CommandGroup::FORMAT
);
1139 #if OSL_DEBUG_LEVEL > 0
1140 implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL
);
1141 implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN
);
1145 void OQueryController::impl_onModifyChanged()
1147 OJoinController::impl_onModifyChanged();
1148 InvalidateFeature(SID_BROWSER_CLEAR_QUERY
);
1149 InvalidateFeature(ID_BROWSER_SAVEASDOC
);
1150 InvalidateFeature(ID_BROWSER_QUERY_EXECUTE
);
1153 void SAL_CALL
OQueryController::disposing( const EventObject
& Source
) throw(RuntimeException
, std::exception
)
1155 SolarMutexGuard aGuard
;
1157 if ( getContainer() && Source
.Source
.is() )
1159 if ( Source
.Source
== m_aCurrentFrame
.getFrame() )
1160 { // our frame is being disposed -> close the preview window (if we have one)
1161 Reference
< XFrame2
> xPreviewFrame( getContainer()->getPreviewFrame() );
1162 ::comphelper::disposeComponent( xPreviewFrame
);
1164 else if ( Source
.Source
== getContainer()->getPreviewFrame() )
1166 getContainer()->disposingPreview();
1170 OJoinController::disposing(Source
);
1173 void OQueryController::reconnect(bool _bUI
)
1176 ::comphelper::disposeComponent(m_xComposer
);
1178 OJoinController::reconnect( _bUI
);
1186 if(m_bGraphicalDesign
)
1188 m_bGraphicalDesign
= false;
1189 // don't call Execute(SQL) because this changes the sql statement
1190 impl_setViewMode( nullptr );
1196 void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection
& o_rViewSettings
, const bool i_includingCriteria
) const
1198 saveTableWindows( o_rViewSettings
);
1200 OTableFields::const_iterator field
= m_vTableFieldDesc
.begin();
1201 OTableFields::const_iterator fieldEnd
= m_vTableFieldDesc
.end();
1203 ::comphelper::NamedValueCollection aAllFieldsData
;
1204 ::comphelper::NamedValueCollection aFieldData
;
1205 for ( sal_Int32 i
= 1; field
!= fieldEnd
; ++field
, ++i
)
1207 if ( !(*field
)->IsEmpty() )
1210 (*field
)->Save( aFieldData
, i_includingCriteria
);
1212 const OUString sFieldSettingName
= "Field" + OUString::number( i
);
1213 aAllFieldsData
.put( sFieldSettingName
, aFieldData
.getPropertyValues() );
1217 o_rViewSettings
.put( "Fields", aAllFieldsData
.getPropertyValues() );
1218 o_rViewSettings
.put( "SplitterPosition", m_nSplitPos
);
1219 o_rViewSettings
.put( "VisibleRows", m_nVisibleRows
);
1222 void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection
& o_rViewSettings
)
1224 loadTableWindows( o_rViewSettings
);
1226 m_nSplitPos
= o_rViewSettings
.getOrDefault( "SplitterPosition", m_nSplitPos
);
1227 m_nVisibleRows
= o_rViewSettings
.getOrDefault( "VisibleRows", m_nVisibleRows
);
1228 m_aFieldInformation
= o_rViewSettings
.getOrDefault( "Fields", m_aFieldInformation
);
1231 void OQueryController::execute_QueryPropDlg()
1233 ScopedVclPtrInstance
<QueryPropertiesDialog
> aQueryPropDlg(
1234 getContainer(), m_bDistinct
, m_nLimit
);
1236 if( aQueryPropDlg
->Execute() == RET_OK
)
1238 m_bDistinct
= aQueryPropDlg
->getDistinct();
1239 m_nLimit
= aQueryPropDlg
->getLimit();
1240 InvalidateFeature( SID_QUERY_DISTINCT_VALUES
);
1241 InvalidateFeature( SID_QUERY_LIMIT
, nullptr, true );
1245 sal_Int32
OQueryController::getColWidth(sal_uInt16 _nColPos
) const
1247 if ( _nColPos
< m_aFieldInformation
.getLength() )
1249 rtl::Reference
<OTableFieldDesc
> pField( new OTableFieldDesc());
1250 pField
->Load( m_aFieldInformation
[ _nColPos
], false );
1251 return pField
->GetColWidth();
1256 Reference
<XNameAccess
> OQueryController::getObjectContainer() const
1258 Reference
< XNameAccess
> xElements
;
1259 if ( editingView() )
1261 Reference
< XViewsSupplier
> xViewsSupp( getConnection(), UNO_QUERY
);
1262 if ( xViewsSupp
.is() )
1263 xElements
= xViewsSupp
->getViews();
1267 Reference
< XQueriesSupplier
> xQueriesSupp( getConnection(), UNO_QUERY
);
1268 if ( xQueriesSupp
.is() )
1269 xElements
= xQueriesSupp
->getQueries();
1272 Reference
< XQueryDefinitionsSupplier
> xQueryDefsSupp( getDataSource(), UNO_QUERY
);
1273 if ( xQueryDefsSupp
.is() )
1274 xElements
= xQueryDefsSupp
->getQueryDefinitions();
1278 OSL_ENSURE( xElements
.is(), "OQueryController::getObjectContainer: unable to obtain the container!" );
1282 void OQueryController::executeQuery()
1284 // we don't need to check the connection here because we already check the composer
1285 // which can't live without his connection
1286 OUString sTranslatedStmt
= translateStatement( false );
1288 OUString sDataSourceName
= getDataSourceName();
1289 if ( !(sDataSourceName
.isEmpty() || sTranslatedStmt
.isEmpty()) )
1293 getContainer()->showPreview( getFrame() );
1294 InvalidateFeature(SID_DB_QUERY_PREVIEW
);
1296 URL aWantToDispatch
;
1297 aWantToDispatch
.Complete
= ".component:DB/DataSourceBrowser";
1299 OUString
sFrameName( FRAME_NAME_QUERY_PREVIEW
);
1300 sal_Int32 nSearchFlags
= FrameSearchFlag::CHILDREN
;
1302 Reference
< XDispatch
> xDisp
;
1303 Reference
< XDispatchProvider
> xProv( getFrame()->findFrame( sFrameName
, nSearchFlags
), UNO_QUERY
);
1306 xProv
.set( getFrame(), UNO_QUERY
);
1308 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, nSearchFlags
);
1312 xDisp
= xProv
->queryDispatch(aWantToDispatch
, sFrameName
, FrameSearchFlag::SELF
);
1316 auto aProps(::comphelper::InitPropertySequence(
1318 { PROPERTY_DATASOURCENAME
, makeAny(sDataSourceName
) },
1319 { PROPERTY_COMMAND_TYPE
, makeAny(CommandType::COMMAND
) },
1320 { PROPERTY_COMMAND
, makeAny(sTranslatedStmt
) },
1321 { PROPERTY_ENABLE_BROWSER
, makeAny(false) },
1322 { PROPERTY_ACTIVE_CONNECTION
, makeAny(getConnection()) },
1323 { PROPERTY_UPDATE_CATALOGNAME
, makeAny(m_sUpdateCatalogName
) },
1324 { PROPERTY_UPDATE_SCHEMANAME
, makeAny(m_sUpdateSchemaName
) },
1325 { PROPERTY_UPDATE_TABLENAME
, makeAny(m_sUpdateTableName
) },
1326 { PROPERTY_ESCAPE_PROCESSING
, makeAny(m_bEscapeProcessing
) }
1329 xDisp
->dispatch(aWantToDispatch
, aProps
);
1330 // check the state of the beamer
1331 // be notified when the beamer frame is closed
1332 Reference
< XComponent
> xComponent( getFrame()->findFrame( sFrameName
, nSearchFlags
), UNO_QUERY
);
1333 if (xComponent
.is())
1335 OSL_ENSURE(Reference
< XFrame
>(xComponent
, UNO_QUERY
).get() == getContainer()->getPreviewFrame().get(),
1336 "OQueryController::executeQuery: oops ... which window do I have here?");
1337 Reference
< XEventListener
> xEvtL(static_cast<cppu::OWeakObject
*>(this),UNO_QUERY
);
1338 xComponent
->addEventListener(xEvtL
);
1343 OSL_FAIL("Couldn't create a beamer window!");
1346 catch(const Exception
&)
1348 OSL_FAIL("Couldn't create a beamer window!");
1353 bool OQueryController::askForNewName(const Reference
<XNameAccess
>& _xElements
, bool _bSaveAs
)
1355 OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" );
1356 if ( editingCommand() )
1359 OSL_PRECOND( _xElements
.is(), "OQueryController::askForNewName: invalid container!" );
1360 if ( !_xElements
.is() )
1364 bool bNew
= _bSaveAs
|| !_xElements
->hasByName( m_sName
);
1367 OUString aDefaultName
;
1368 if ( ( _bSaveAs
&& !bNew
) || ( bNew
&& !m_sName
.isEmpty() ) )
1369 aDefaultName
= m_sName
;
1372 OUString sName
= ModuleRes( editingView() ? STR_VIEW_TITLE
: STR_QRY_TITLE
);
1373 aDefaultName
= sName
.getToken(0,' ');
1374 aDefaultName
= ::dbtools::createUniqueName(_xElements
,aDefaultName
);
1377 DynamicTableOrQueryNameCheck
aNameChecker( getConnection(), CommandType::QUERY
);
1378 ScopedVclPtrInstance
<OSaveAsDlg
> aDlg(
1387 bRet
= ( aDlg
->Execute() == RET_OK
);
1390 m_sName
= aDlg
->getName();
1391 if ( editingView() )
1393 m_sUpdateCatalogName
= aDlg
->getCatalog();
1394 m_sUpdateSchemaName
= aDlg
->getSchema();
1401 bool OQueryController::doSaveAsDoc(bool _bSaveAs
)
1403 OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
1404 if ( !editingCommand() && !haveDataSource() )
1406 OUString
aMessage(ModuleRes(STR_DATASOURCE_DELETED
));
1407 ScopedVclPtrInstance
<OSQLWarningBox
>(getView(), aMessage
)->Execute();
1411 Reference
< XNameAccess
> xElements
= getObjectContainer();
1412 if ( !xElements
.is() )
1415 if ( !getContainer()->checkStatement() )
1418 OUString sTranslatedStmt
= translateStatement();
1419 if ( editingCommand() )
1421 setModified( false );
1422 // this is all we need to do here. translateStatement implicitly set our m_sStatement, and
1423 // notified it, and that's all
1427 if ( sTranslatedStmt
.isEmpty() )
1430 // first we need a name for our query so ask the user
1431 // did we get a name
1432 OUString
sOriginalName( m_sName
);
1433 if ( !askForNewName( xElements
, _bSaveAs
) || m_sName
.isEmpty() )
1436 SQLExceptionInfo aInfo
;
1437 bool bSuccess
= false;
1442 || ( !xElements
->hasByName( m_sName
) );
1444 Reference
<XPropertySet
> xQuery
;
1445 if ( bNew
) // just to make sure the query already exists
1447 // drop the query, in case it already exists
1448 if ( xElements
->hasByName( m_sName
) )
1450 Reference
< XDrop
> xNameCont( xElements
, UNO_QUERY
);
1451 if ( xNameCont
.is() )
1452 xNameCont
->dropByName( m_sName
);
1455 Reference
< XNameContainer
> xCont( xElements
, UNO_QUERY
);
1457 xCont
->removeByName( m_sName
);
1461 // create a new (empty, uninitialized) query resp. view
1462 Reference
< XDataDescriptorFactory
> xFact( xElements
, UNO_QUERY
);
1465 xQuery
= xFact
->createDataDescriptor();
1466 // to set the name is only allowed when the query is new
1467 xQuery
->setPropertyValue( PROPERTY_NAME
, makeAny( m_sName
) );
1471 Reference
< XSingleServiceFactory
> xSingleFac( xElements
, UNO_QUERY
);
1472 if ( xSingleFac
.is() )
1473 xQuery
.set(xSingleFac
->createInstance(), css::uno::UNO_QUERY
);
1478 xElements
->getByName( m_sName
) >>= xQuery
;
1481 throw RuntimeException();
1484 if ( editingView() && !bNew
)
1486 OSL_ENSURE( xQuery
== m_xAlterView
, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" );
1487 m_xAlterView
.set( xQuery
, UNO_QUERY_THROW
);
1488 m_xAlterView
->alterCommand( sTranslatedStmt
);
1491 { // we're creating a query, or a *new* view
1492 xQuery
->setPropertyValue( PROPERTY_COMMAND
, makeAny( sTranslatedStmt
) );
1494 if ( editingView() )
1496 xQuery
->setPropertyValue( PROPERTY_CATALOGNAME
, makeAny( m_sUpdateCatalogName
) );
1497 xQuery
->setPropertyValue( PROPERTY_SCHEMANAME
, makeAny( m_sUpdateSchemaName
) );
1500 if ( editingQuery() )
1502 xQuery
->setPropertyValue( PROPERTY_UPDATE_TABLENAME
, makeAny( m_sUpdateTableName
) );
1503 xQuery
->setPropertyValue( PROPERTY_ESCAPE_PROCESSING
, css::uno::makeAny( m_bEscapeProcessing
) );
1505 xQuery
->setPropertyValue( PROPERTY_LAYOUTINFORMATION
, getViewData() );
1511 Reference
< XAppend
> xAppend( xElements
, UNO_QUERY
);
1514 xAppend
->appendByDescriptor( xQuery
);
1518 Reference
< XNameContainer
> xCont( xElements
, UNO_QUERY
);
1520 xCont
->insertByName( m_sName
, makeAny( xQuery
) );
1523 if ( editingView() )
1525 Reference
< XPropertySet
> xViewProps
;
1526 if ( xElements
->hasByName( m_sName
) )
1527 xViewProps
.set( xElements
->getByName( m_sName
), UNO_QUERY
);
1529 if ( !xViewProps
.is() ) // correct name and try again
1530 m_sName
= ::dbtools::composeTableName( getMetaData(), xQuery
, ::dbtools::EComposeRule::InDataManipulation
, false, false, false );
1532 OSL_ENSURE( xElements
->hasByName( m_sName
), "OQueryController::doSaveAsDoc: newly created view does not exist!" );
1534 if ( xElements
->hasByName( m_sName
) )
1535 m_xAlterView
.set( xElements
->getByName( m_sName
), UNO_QUERY
);
1537 // now check if our datasource has set a tablefilter and if so, append the new table name to it
1538 ::dbaui::appendToFilter( getConnection(), m_sName
, getORB(), getView() );
1540 Reference
< XTitleChangeListener
> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY
);
1541 if ( xEventListener
.is() )
1543 TitleChangedEvent aEvent
;
1544 xEventListener
->titleChanged(aEvent
);
1546 releaseNumberForComponent();
1549 setModified( false );
1553 catch(const SQLException
&)
1556 m_sName
= sOriginalName
;
1557 aInfo
= SQLExceptionInfo( ::cppu::getCaughtException() );
1559 catch(const Exception
&)
1562 m_sName
= sOriginalName
;
1563 DBG_UNHANDLED_EXCEPTION();
1568 // if we successfully saved a view we were creating, then close the designer
1569 if ( bSuccess
&& editingView() && !m_xAlterView
.is() )
1574 if ( bSuccess
&& editingView() )
1575 InvalidateFeature( ID_BROWSER_EDITDOC
);
1585 CommentStrip( const OUString
& rComment
, bool bLastOnLine
)
1586 : maComment( rComment
), mbLastOnLine( bLastOnLine
) {}
1591 /** Obtain all comments in a query.
1593 See also delComment() implementation for OSQLParser::parseTree().
1595 static ::std::vector
< CommentStrip
> getComment( const OUString
& rQuery
)
1597 ::std::vector
< CommentStrip
> aRet
;
1598 // First a quick search if there is any "--" or "//" or "/*", if not then
1599 // the whole copying loop is pointless.
1600 if (rQuery
.indexOf( "--" ) < 0 && rQuery
.indexOf( "//" ) < 0 &&
1601 rQuery
.indexOf( "/*" ) < 0)
1604 const sal_Unicode
* pCopy
= rQuery
.getStr();
1605 const sal_Int32 nQueryLen
= rQuery
.getLength();
1606 bool bIsText1
= false; // "text"
1607 bool bIsText2
= false; // 'text'
1608 bool bComment2
= false; // /* comment */
1609 bool bComment
= false; // -- or // comment
1610 OUStringBuffer aBuf
;
1611 for (sal_Int32 i
=0; i
< nQueryLen
; ++i
)
1615 aBuf
.append( &pCopy
[i
], 1);
1616 if ((i
+1) < nQueryLen
)
1618 if (pCopy
[i
]=='*' && pCopy
[i
+1]=='/')
1621 aBuf
.append( &pCopy
[++i
], 1);
1622 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), false));
1627 // comment can't close anymore, actually an error, but..
1628 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), false));
1632 if (pCopy
[i
] == '\n' || i
== nQueryLen
-1)
1636 if (i
== nQueryLen
-1 && pCopy
[i
] != '\n')
1637 aBuf
.append( &pCopy
[i
], 1);
1638 aRet
.push_back( CommentStrip( aBuf
.makeStringAndClear(), true));
1641 else if (!aRet
.empty())
1642 aRet
.back().mbLastOnLine
= true;
1646 if (pCopy
[i
] == '\"' && !bIsText2
)
1647 bIsText1
= !bIsText1
;
1648 else if (pCopy
[i
] == '\'' && !bIsText1
)
1649 bIsText2
= !bIsText2
;
1650 if (!bIsText1
&& !bIsText2
&& (i
+1) < nQueryLen
)
1652 if ((pCopy
[i
]=='-' && pCopy
[i
+1]=='-') || (pCopy
[i
]=='/' && pCopy
[i
+1]=='/'))
1654 else if ((pCopy
[i
]=='/' && pCopy
[i
+1]=='*'))
1658 if (bComment
|| bComment2
)
1659 aBuf
.append( &pCopy
[i
], 1);
1664 /** Concat/insert comments that were previously obtained with getComment().
1666 NOTE: The current parser implementation does not preserve newlines, so all
1667 comments are always appended to the entire query, also inline comments
1668 that would need positioning anyway that can't be obtained after
1669 recomposition. This is ugly but at least allows commented queries while
1670 preserving the comments _somehow_.
1672 static OUString
concatComment( const OUString
& rQuery
, const ::std::vector
< CommentStrip
>& rComments
)
1674 // No comments => return query.
1675 if (rComments
.empty())
1678 const sal_Unicode
* pBeg
= rQuery
.getStr();
1679 const sal_Int32 nLen
= rQuery
.getLength();
1680 const size_t nComments
= rComments
.size();
1681 // Obtaining the needed size once should be faster than reallocating.
1682 // Also add a blank or linefeed for each comment.
1683 sal_Int32 nBufSize
= nLen
+ nComments
;
1684 for (::std::vector
< CommentStrip
>::const_iterator
it( rComments
.begin()); it
!= rComments
.end(); ++it
)
1685 nBufSize
+= (*it
).maComment
.getLength();
1686 OUStringBuffer
aBuf( nBufSize
);
1687 sal_Int32 nIndBeg
= 0;
1688 sal_Int32 nIndLF
= rQuery
.indexOf('\n');
1690 while (nIndLF
>= 0 && i
< nComments
)
1692 aBuf
.append( pBeg
+ nIndBeg
, nIndLF
- nIndBeg
);
1695 aBuf
.append( rComments
[i
].maComment
);
1696 } while (!rComments
[i
++].mbLastOnLine
&& i
< nComments
);
1697 aBuf
.append( pBeg
+ nIndLF
, 1); // the LF
1698 nIndBeg
= nIndLF
+ 1;
1699 nIndLF
= (nIndBeg
< nLen
? rQuery
.indexOf( '\n', nIndBeg
) : -1);
1701 // Append remainder of query.
1703 aBuf
.append( pBeg
+ nIndBeg
, nLen
- nIndBeg
);
1704 // Append all remaining comments, preserve lines.
1705 bool bNewLine
= false;
1706 for ( ; i
< nComments
; ++i
)
1710 aBuf
.append( rComments
[i
].maComment
);
1711 if (rComments
[i
].mbLastOnLine
)
1719 return aBuf
.makeStringAndClear();
1722 OUString
OQueryController::translateStatement( bool _bFireStatementChange
)
1724 // now set the properties
1725 setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange
);
1726 OUString sTranslatedStmt
;
1727 if(!m_sStatement
.isEmpty() && m_xComposer
.is() && m_bEscapeProcessing
)
1733 ::std::vector
< CommentStrip
> aComments
= getComment( m_sStatement
);
1735 ::connectivity::OSQLParseNode
* pNode
= m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
);
1738 pNode
->parseNodeToStr( sTranslatedStmt
, getConnection() );
1742 m_xComposer
->setQuery(sTranslatedStmt
);
1743 sTranslatedStmt
= m_xComposer
->getComposedQuery();
1744 sTranslatedStmt
= concatComment( sTranslatedStmt
, aComments
);
1746 catch(const SQLException
& e
)
1748 ::dbtools::SQLExceptionInfo
aInfo(e
);
1750 // an error occurred so we clear the statement
1751 sTranslatedStmt
.clear();
1754 else if(m_sStatement
.isEmpty())
1756 ModuleRes
aModuleRes(STR_QRY_NOSELECT
);
1757 OUString
sTmpStr(aModuleRes
);
1758 showError(SQLException(sTmpStr
,nullptr,"S1000",1000,Any()));
1761 sTranslatedStmt
= m_sStatement
;
1763 return sTranslatedStmt
;
1766 short OQueryController::saveModified()
1768 SolarMutexGuard aSolarGuard
;
1769 ::osl::MutexGuard
aGuard( getMutex() );
1770 short nRet
= RET_YES
;
1771 if ( !isConnected() || !isModified() )
1774 if ( !m_bGraphicalDesign
1775 || ( !m_vTableFieldDesc
.empty()
1776 && !m_vTableData
.empty()
1780 OUString
sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED
, m_nCommandType
) );
1781 ScopedVclPtrInstance
< QueryBox
> aQry( getView(), WB_YES_NO_CANCEL
| WB_DEF_YES
, sMessageText
);
1783 nRet
= aQry
->Execute();
1784 if ( ( nRet
== RET_YES
)
1785 && !doSaveAsDoc( false )
1794 void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings
)
1796 bool bValid
= false;
1798 Sequence
< PropertyValue
> aLayoutInformation
;
1799 // get command from the query if a query name was supplied
1800 if ( !i_bForceCurrentControllerSettings
&& !editingCommand() )
1802 if ( !m_sName
.isEmpty() )
1804 Reference
< XNameAccess
> xQueries
= getObjectContainer();
1805 if ( xQueries
.is() )
1807 Reference
< XPropertySet
> xProp
;
1808 if( xQueries
->hasByName( m_sName
) && ( xQueries
->getByName( m_sName
) >>= xProp
) && xProp
.is() )
1810 OUString sNewStatement
;
1811 xProp
->getPropertyValue( PROPERTY_COMMAND
) >>= sNewStatement
;
1812 setStatement_fireEvent( sNewStatement
);
1814 if ( editingQuery() )
1816 bool bNewEscapeProcessing( true );
1817 xProp
->getPropertyValue( PROPERTY_ESCAPE_PROCESSING
) >>= bNewEscapeProcessing
;
1818 setEscapeProcessing_fireEvent( bNewEscapeProcessing
);
1821 m_bGraphicalDesign
= m_bGraphicalDesign
&& m_bEscapeProcessing
;
1826 if ( editingQuery() )
1827 xProp
->getPropertyValue( PROPERTY_LAYOUTINFORMATION
) >>= aLayoutInformation
;
1829 catch( const Exception
& )
1831 OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" );
1840 // assume that we got all necessary information during initialization
1845 // load the layoutInformation
1846 if ( aLayoutInformation
.getLength() )
1850 loadViewSettings( aLayoutInformation
);
1852 catch( const Exception
& )
1854 DBG_UNHANDLED_EXCEPTION();
1858 if ( !m_sStatement
.isEmpty() )
1862 bool bError( false );
1864 if ( !m_pSqlIterator
)
1868 else if ( m_bEscapeProcessing
)
1871 ::std::unique_ptr
< ::connectivity::OSQLParseNode
> pNode(
1872 m_aSqlParser
.parseTree( aErrorMsg
, m_sStatement
, m_bGraphicalDesign
) );
1876 delete m_pSqlIterator
->getParseTree();
1877 m_pSqlIterator
->setParseTree( pNode
.release() );
1878 m_pSqlIterator
->traverseAll();
1879 if ( m_pSqlIterator
->hasErrors() )
1881 if ( !i_bForceCurrentControllerSettings
&& m_bGraphicalDesign
&& !editingView() )
1883 impl_showAutoSQLViewError( makeAny( m_pSqlIterator
->getErrors() ) );
1890 if ( !i_bForceCurrentControllerSettings
&& !editingView() )
1892 OUString
aTitle(ModuleRes(STR_SVT_SQL_SYNTAX_ERROR
));
1893 ScopedVclPtrInstance
< OSQLMessageBox
> aDlg(getView(),aTitle
,aErrorMsg
);
1902 m_bGraphicalDesign
= false;
1903 if ( editingView() )
1904 // if we're editing a view whose statement could not be parsed, default to "no escape processing"
1905 setEscapeProcessing_fireEvent( false );
1912 OSL_ENSURE(m_pSqlIterator
,"No SQLIterator set!");
1914 getContainer()->setNoneVisbleRow(m_nVisibleRows
);
1917 void OQueryController::reset()
1920 getContainer()->reset( nullptr );
1924 void OQueryController::setStatement_fireEvent( const OUString
& _rNewStatement
, bool _bFireStatementChange
)
1926 Any aOldValue
= makeAny( m_sStatement
);
1927 m_sStatement
= _rNewStatement
;
1928 Any aNewValue
= makeAny( m_sStatement
);
1930 sal_Int32 nHandle
= PROPERTY_ID_ACTIVECOMMAND
;
1931 if ( _bFireStatementChange
)
1932 fire( &nHandle
, &aNewValue
, &aOldValue
, 1, false );
1935 void OQueryController::setEscapeProcessing_fireEvent( const bool _bEscapeProcessing
)
1937 if ( _bEscapeProcessing
== m_bEscapeProcessing
)
1940 Any aOldValue
= makeAny( m_bEscapeProcessing
);
1941 m_bEscapeProcessing
= _bEscapeProcessing
;
1942 Any aNewValue
= makeAny( m_bEscapeProcessing
);
1944 sal_Int32 nHandle
= PROPERTY_ID_ESCAPE_PROCESSING
;
1945 fire( &nHandle
, &aNewValue
, &aOldValue
, 1, false );
1948 IMPL_LINK_NOARG_TYPED( OQueryController
, OnExecuteAddTable
, void*, void )
1950 Execute( ID_BROWSER_ADDTABLE
,Sequence
<PropertyValue
>() );
1953 bool OQueryController::allowViews() const
1958 bool OQueryController::allowQueries() const
1960 OSL_ENSURE( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" );
1961 if ( !getSdbMetaData().supportsSubqueriesInFrom() )
1964 const NamedValueCollection
& rArguments( getInitParams() );
1965 sal_Int32 nCommandType
= rArguments
.getOrDefault( PROPERTY_COMMAND_TYPE
, (sal_Int32
)CommandType::QUERY
);
1966 bool bCreatingView
= ( nCommandType
== CommandType::TABLE
);
1967 return !bCreatingView
;
1970 Any SAL_CALL
OQueryController::getViewData() throw( RuntimeException
, std::exception
)
1972 ::osl::MutexGuard
aGuard( getMutex() );
1974 getContainer()->SaveUIConfig();
1976 ::comphelper::NamedValueCollection aViewSettings
;
1977 saveViewSettings( aViewSettings
, false );
1979 return makeAny( aViewSettings
.getPropertyValues() );
1982 void SAL_CALL
OQueryController::restoreViewData(const Any
& /*Data*/) throw( RuntimeException
, std::exception
)
1987 } // namespace dbaui
1989 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */