Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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 "QTableWindow.hxx"
29 : #include "QTableWindowData.hxx"
30 : #include "querycontainerwindow.hxx"
31 : #include "querycontroller.hxx"
32 : #include "QueryDesignView.hxx"
33 : #include "QueryTableView.hxx"
34 : #include "QueryTextView.hxx"
35 : #include "queryview.hxx"
36 : #include "QueryViewSwitch.hxx"
37 : #include "sqlmessage.hxx"
38 : #include "TableConnectionData.hxx"
39 : #include "TableFieldDescription.hxx"
40 : #include "UITools.hxx"
41 : #include "QueryPropertiesDialog.hxx"
42 :
43 : #include <com/sun/star/beans/PropertyAttribute.hpp>
44 : #include <com/sun/star/container/XChild.hpp>
45 : #include <com/sun/star/container/XNameContainer.hpp>
46 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
47 : #include <com/sun/star/frame/XLoadEventListener.hpp>
48 : #include <com/sun/star/io/XActiveDataSink.hpp>
49 : #include <com/sun/star/io/XActiveDataSource.hpp>
50 : #include <com/sun/star/sdb/CommandType.hpp>
51 : #include <com/sun/star/sdb/SQLContext.hpp>
52 : #include <com/sun/star/sdb/XQueriesSupplier.hpp>
53 : #include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
54 : #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
55 : #include <com/sun/star/sdbc/SQLWarning.hpp>
56 : #include <com/sun/star/sdbc/XRow.hpp>
57 : #include <com/sun/star/sdbcx/XAppend.hpp>
58 : #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp>
59 : #include <com/sun/star/sdbcx/XDrop.hpp>
60 : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
61 : #include <com/sun/star/sdbcx/XViewsSupplier.hpp>
62 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
63 : #include <com/sun/star/util/XCloseable.hpp>
64 : #include <com/sun/star/util/VetoException.hpp>
65 : #include <com/sun/star/frame/XUntitledNumbers.hpp>
66 : #include <com/sun/star/ui/XUIElement.hpp>
67 :
68 : #include <comphelper/processfactory.hxx>
69 : #include <comphelper/property.hxx>
70 : #include <comphelper/seqstream.hxx>
71 : #include <comphelper/streamsection.hxx>
72 : #include <comphelper/types.hxx>
73 : #include <connectivity/dbexception.hxx>
74 : #include <connectivity/dbtools.hxx>
75 : #include <cppuhelper/exc_hlp.hxx>
76 : #include <sfx2/sfxsids.hrc>
77 : #include <svtools/localresaccess.hxx>
78 : #include <toolkit/helper/vclunohelper.hxx>
79 : #include <tools/diagnose_ex.h>
80 : #include <osl/diagnose.h>
81 : #include <vcl/msgbox.hxx>
82 : #include <vcl/svapp.hxx>
83 : #include <osl/mutex.hxx>
84 : #include <rtl/strbuf.hxx>
85 : #include <vector>
86 :
87 0 : extern "C" void SAL_CALL createRegistryInfo_OQueryControl()
88 : {
89 0 : static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OQueryController > aAutoRegistration;
90 0 : }
91 :
92 : namespace dbaui
93 : {
94 : using namespace ::com::sun::star::uno;
95 : using namespace ::com::sun::star::beans;
96 : using namespace ::com::sun::star::frame;
97 : using namespace ::com::sun::star::util;
98 : using namespace ::com::sun::star::lang;
99 :
100 0 : class OViewController : public OQueryController
101 : {
102 0 : virtual OUString SAL_CALL getImplementationName() throw( RuntimeException, std::exception ) SAL_OVERRIDE
103 : {
104 0 : return getImplementationName_Static();
105 : }
106 0 : virtual Sequence< OUString> SAL_CALL getSupportedServiceNames() throw(RuntimeException, std::exception) SAL_OVERRIDE
107 : {
108 0 : return getSupportedServiceNames_Static();
109 : }
110 :
111 : public:
112 0 : OViewController(const Reference< XComponentContext >& _rM) : OQueryController(_rM){}
113 :
114 : // need by registration
115 0 : static OUString getImplementationName_Static() throw( RuntimeException )
116 : {
117 0 : return OUString("org.openoffice.comp.dbu.OViewDesign");
118 : }
119 0 : static Sequence< OUString > getSupportedServiceNames_Static(void) throw( RuntimeException )
120 : {
121 0 : Sequence< OUString> aSupported(1);
122 0 : aSupported.getArray()[0] = "com.sun.star.sdb.ViewDesign";
123 0 : return aSupported;
124 : }
125 0 : static Reference< XInterface > SAL_CALL Create(const Reference< XMultiServiceFactory >& _rM)
126 : {
127 0 : return *(new OViewController(comphelper::getComponentContext(_rM)));
128 : }
129 : };
130 : }
131 :
132 0 : extern "C" void SAL_CALL createRegistryInfo_OViewControl()
133 : {
134 0 : static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::OViewController > aAutoRegistration;
135 0 : }
136 :
137 : namespace dbaui
138 : {
139 : using namespace ::connectivity;
140 : #if OSL_DEBUG_LEVEL > 1
141 : namespace
142 : {
143 : void insertParseTree(SvTreeListBox* _pBox,::connectivity::OSQLParseNode* _pNode,SvTreeListEntry* _pParent = NULL)
144 : {
145 : OUString rString;
146 : if (!_pNode->isToken())
147 : {
148 : // rule name as rule: ...
149 : rString = "RULE_ID: " + OUString::number( (sal_Int32)_pNode->getRuleID() ) +
150 : "(" + OSQLParser::RuleIDToStr(_pNode->getRuleID()) + ")";
151 :
152 : _pParent = _pBox->InsertEntry(rString,_pParent);
153 :
154 : // determine how much subtrees this node has
155 : sal_uInt32 nStop = _pNode->count();
156 : // fetch first subtree
157 : for(sal_uInt32 i=0;i<nStop;++i)
158 : insertParseTree(_pBox,_pNode->getChild(i),_pParent);
159 : }
160 : else
161 : {
162 : // token found
163 : // tabs to insert according to nLevel
164 :
165 : switch (_pNode->getNodeType())
166 : {
167 :
168 : case SQL_NODE_KEYWORD:
169 : {
170 : rString += "SQL_KEYWORD:";
171 : OString sT = OSQLParser::TokenIDToStr(_pNode->getTokenID());
172 : rString += OStringToOUString(sT, RTL_TEXTENCODING_UTF8);
173 : break;}
174 :
175 : case SQL_NODE_COMPARISON:
176 : {
177 : rString += "SQL_COMPARISON:" + _pNode->getTokenValue(); // append Nodevalue
178 : // and start new line
179 : break;}
180 :
181 : case SQL_NODE_NAME:
182 : {
183 : rString += "SQL_NAME:\"" + _pNode->getTokenValue() + "\"";
184 : break;}
185 :
186 : case SQL_NODE_STRING:
187 : {
188 : rString += "SQL_STRING:'" + _pNode->getTokenValue();
189 : break;}
190 :
191 : case SQL_NODE_INTNUM:
192 : {
193 : rString += "SQL_INTNUM:" + _pNode->getTokenValue();
194 : break;}
195 :
196 : case SQL_NODE_APPROXNUM:
197 : {
198 : rString += "SQL_APPROXNUM:" + _pNode->getTokenValue();
199 : break;}
200 :
201 : case SQL_NODE_PUNCTUATION:
202 : {
203 : rString += "SQL_PUNCTUATION:" + _pNode->getTokenValue(); // append Nodevalue
204 : break;}
205 :
206 : case SQL_NODE_AMMSC:
207 : {
208 : rString += "SQL_AMMSC:" + _pNode->getTokenValue(); // append Nodevalue
209 : break;}
210 :
211 : default:
212 : OSL_FAIL("OSQLParser::ShowParseTree: unzulaessiger NodeType");
213 : rString += _pNode->getTokenValue();
214 : }
215 : _pBox->InsertEntry(rString,_pParent);
216 : }
217 : }
218 : }
219 : #endif // OSL_DEBUG_LEVEL
220 :
221 : namespace
222 : {
223 0 : OUString lcl_getObjectResourceString( sal_uInt16 _nResId, sal_Int32 _nCommandType )
224 : {
225 0 : OUString sMessageText = ModuleRes( _nResId );
226 0 : OUString sObjectType;
227 : {
228 0 : LocalResourceAccess aLocalRes( RSC_QUERY_OBJECT_TYPE, RSC_RESOURCE );
229 0 : sObjectType = ModuleRes( (sal_uInt16)( _nCommandType + 1 ) );
230 : }
231 0 : sMessageText = sMessageText.replaceFirst( "$object$", sObjectType );
232 0 : return sMessageText;
233 : }
234 : }
235 :
236 : using namespace ::com::sun::star::uno;
237 : using namespace ::com::sun::star::io;
238 : using namespace ::com::sun::star::beans;
239 : using namespace ::com::sun::star::frame;
240 : using namespace ::com::sun::star::util;
241 : using namespace ::com::sun::star::lang;
242 : using namespace ::com::sun::star::container;
243 : using namespace ::com::sun::star::sdbcx;
244 : using namespace ::com::sun::star::sdbc;
245 : using namespace ::com::sun::star::sdb;
246 : using namespace ::com::sun::star::ui;
247 : using namespace ::com::sun::star::ui::dialogs;
248 : using namespace ::com::sun::star::awt;
249 : using namespace ::dbtools;
250 :
251 : using namespace ::comphelper;
252 :
253 : namespace
254 : {
255 0 : void ensureToolbars( OQueryController& _rController, sal_Bool _bDesign )
256 : {
257 0 : Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager = _rController.getLayoutManager( _rController.getFrame() );
258 0 : if ( xLayoutManager.is() )
259 : {
260 0 : xLayoutManager->lock();
261 0 : static OUString s_sDesignToolbar("private:resource/toolbar/designobjectbar");
262 0 : static OUString s_sSqlToolbar("private:resource/toolbar/sqlobjectbar");
263 0 : if ( _bDesign )
264 : {
265 0 : xLayoutManager->destroyElement( s_sSqlToolbar );
266 0 : xLayoutManager->createElement( s_sDesignToolbar );
267 : }
268 : else
269 : {
270 0 : xLayoutManager->destroyElement( s_sDesignToolbar );
271 0 : xLayoutManager->createElement( s_sSqlToolbar );
272 : }
273 0 : xLayoutManager->unlock();
274 0 : xLayoutManager->doLayout();
275 0 : }
276 0 : }
277 :
278 : /**
279 : * The value of m_nLimit is updated when LimitBox loose its focus
280 : * So in those case when execution needs recent data, grab the focus
281 : * (e.g. execute SQL statement, change views)
282 : */
283 0 : void grabFocusFromLimitBox( OQueryController& _rController )
284 : {
285 0 : static const OUString sResourceURL( "private:resource/toolbar/designobjectbar" );
286 0 : Reference< XLayoutManager > xLayoutManager = _rController.getLayoutManager( _rController.getFrame() );
287 0 : Reference< XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL);
288 0 : if (xUIElement.is())
289 : {
290 0 : Reference< XWindow > xWindow(xUIElement->getRealInterface(), css::uno::UNO_QUERY);
291 0 : Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
292 0 : if( pWindow || pWindow->HasChildPathFocus() )
293 : {
294 0 : pWindow->GrabFocusToDocument();
295 0 : }
296 0 : }
297 0 : }
298 : }
299 :
300 0 : OUString SAL_CALL OQueryController::getImplementationName() throw( RuntimeException, std::exception )
301 : {
302 0 : return getImplementationName_Static();
303 : }
304 :
305 0 : OUString OQueryController::getImplementationName_Static() throw( RuntimeException )
306 : {
307 0 : return OUString("org.openoffice.comp.dbu.OQueryDesign");
308 : }
309 :
310 0 : Sequence< OUString> OQueryController::getSupportedServiceNames_Static(void) throw( RuntimeException )
311 : {
312 0 : Sequence< OUString> aSupported(1);
313 0 : aSupported.getArray()[0] = "com.sun.star.sdb.QueryDesign";
314 0 : return aSupported;
315 : }
316 :
317 0 : Sequence< OUString> SAL_CALL OQueryController::getSupportedServiceNames() throw(RuntimeException, std::exception)
318 : {
319 0 : return getSupportedServiceNames_Static();
320 : }
321 :
322 0 : Reference< XInterface > SAL_CALL OQueryController::Create(const Reference<XMultiServiceFactory >& _rxFactory)
323 : {
324 0 : return *(new OQueryController(comphelper::getComponentContext(_rxFactory)));
325 : }
326 :
327 0 : OQueryController::OQueryController(const Reference< XComponentContext >& _rM)
328 : :OJoinController(_rM)
329 0 : ,OQueryController_PBase( getBroadcastHelper() )
330 0 : ,m_pParseContext( new svxform::OSystemParseContext )
331 : ,m_aSqlParser( _rM, m_pParseContext )
332 : ,m_pSqlIterator(NULL)
333 : ,m_nLimit(-1)
334 : ,m_nVisibleRows(0x400)
335 : ,m_nSplitPos(-1)
336 : ,m_nCommandType( CommandType::QUERY )
337 : ,m_bGraphicalDesign(sal_False)
338 : ,m_bDistinct(sal_False)
339 : ,m_bViewAlias(sal_False)
340 : ,m_bViewTable(sal_False)
341 : ,m_bViewFunction(sal_False)
342 0 : ,m_bEscapeProcessing(sal_True)
343 : {
344 0 : InvalidateAll();
345 :
346 : registerProperty( PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
347 0 : &m_sStatement, ::getCppuType( &m_sStatement ) );
348 : registerProperty( PROPERTY_ESCAPE_PROCESSING, PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::READONLY | PropertyAttribute::BOUND,
349 0 : &m_bEscapeProcessing, ::getCppuType( &m_bEscapeProcessing ) );
350 0 : }
351 :
352 0 : OQueryController::~OQueryController()
353 : {
354 0 : if ( !getBroadcastHelper().bDisposed && !getBroadcastHelper().bInDispose )
355 : {
356 : OSL_FAIL("Please check who doesn't dispose this component!");
357 : // increment ref count to prevent double call of Dtor
358 0 : osl_atomic_increment( &m_refCount );
359 0 : dispose();
360 : }
361 0 : }
362 :
363 0 : IMPLEMENT_FORWARD_XINTERFACE2( OQueryController, OJoinController, OQueryController_PBase )
364 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( OQueryController, OJoinController, OQueryController_PBase )
365 :
366 0 : Reference< XPropertySetInfo > SAL_CALL OQueryController::getPropertySetInfo() throw(RuntimeException, std::exception)
367 : {
368 0 : Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
369 0 : return xInfo;
370 : }
371 :
372 0 : sal_Bool SAL_CALL OQueryController::convertFastPropertyValue( Any& o_rConvertedValue, Any& o_rOldValue, sal_Int32 i_nHandle, const Any& i_rValue ) throw (IllegalArgumentException)
373 : {
374 0 : return OPropertyContainer::convertFastPropertyValue( o_rConvertedValue, o_rOldValue, i_nHandle, i_rValue );
375 : }
376 :
377 0 : void SAL_CALL OQueryController::setFastPropertyValue_NoBroadcast( sal_Int32 i_nHandle, const Any& i_rValue ) throw ( Exception, std::exception )
378 : {
379 0 : OPropertyContainer::setFastPropertyValue_NoBroadcast( i_nHandle, i_rValue );
380 0 : }
381 :
382 0 : void SAL_CALL OQueryController::getFastPropertyValue( Any& o_rValue, sal_Int32 i_nHandle ) const
383 : {
384 0 : switch ( i_nHandle )
385 : {
386 : case PROPERTY_ID_CURRENT_QUERY_DESIGN:
387 : {
388 0 : ::comphelper::NamedValueCollection aCurrentDesign;
389 0 : aCurrentDesign.put( "GraphicalDesign", isGraphicalDesign() );
390 0 : aCurrentDesign.put( (OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing );
391 :
392 0 : if ( isGraphicalDesign() )
393 : {
394 0 : getContainer()->SaveUIConfig();
395 0 : saveViewSettings( aCurrentDesign, true );
396 0 : aCurrentDesign.put( "Statement", m_sStatement );
397 : }
398 : else
399 : {
400 0 : aCurrentDesign.put( "Statement", getContainer()->getStatement() );
401 : }
402 :
403 0 : o_rValue <<= aCurrentDesign.getPropertyValues();
404 : }
405 0 : break;
406 :
407 : default:
408 0 : OPropertyContainer::getFastPropertyValue( o_rValue, i_nHandle );
409 0 : break;
410 : }
411 0 : }
412 :
413 0 : ::cppu::IPropertyArrayHelper& OQueryController::getInfoHelper()
414 : {
415 0 : return *const_cast< OQueryController* >( this )->getArrayHelper();
416 : }
417 :
418 0 : ::cppu::IPropertyArrayHelper* OQueryController::createArrayHelper( ) const
419 : {
420 0 : Sequence< Property > aProps;
421 0 : describeProperties( aProps );
422 :
423 : // one additional property:
424 0 : const sal_Int32 nLength = aProps.getLength();
425 0 : aProps.realloc( nLength + 1 );
426 0 : aProps[ nLength ] = Property(
427 : "CurrentQueryDesign",
428 : PROPERTY_ID_CURRENT_QUERY_DESIGN,
429 0 : ::cppu::UnoType< Sequence< PropertyValue > >::get(),
430 : PropertyAttribute::READONLY
431 0 : );
432 :
433 : ::std::sort(
434 : aProps.getArray(),
435 0 : aProps.getArray() + aProps.getLength(),
436 : ::comphelper::PropertyCompareByName()
437 0 : );
438 :
439 0 : return new ::cppu::OPropertyArrayHelper(aProps);
440 : }
441 :
442 0 : void OQueryController::deleteIterator()
443 : {
444 0 : if(m_pSqlIterator)
445 : {
446 0 : delete m_pSqlIterator->getParseTree();
447 0 : m_pSqlIterator->dispose();
448 0 : delete m_pSqlIterator;
449 0 : m_pSqlIterator = NULL;
450 : }
451 0 : }
452 :
453 0 : void OQueryController::disposing()
454 : {
455 0 : OQueryController_PBase::disposing();
456 :
457 0 : deleteIterator();
458 :
459 0 : delete m_pParseContext;
460 :
461 0 : clearFields();
462 0 : OTableFields().swap(m_vUnUsedFieldsDesc);
463 :
464 0 : ::comphelper::disposeComponent(m_xComposer);
465 0 : OJoinController::disposing();
466 0 : OQueryController_PBase::disposing();
467 0 : }
468 :
469 0 : void OQueryController::clearFields()
470 : {
471 0 : OTableFields().swap(m_vTableFieldDesc);
472 0 : }
473 :
474 0 : FeatureState OQueryController::GetState(sal_uInt16 _nId) const
475 : {
476 0 : FeatureState aReturn;
477 0 : aReturn.bEnabled = true;
478 : // (disabled automatically)
479 :
480 0 : switch (_nId)
481 : {
482 : case ID_BROWSER_EDITDOC:
483 0 : if ( editingCommand() )
484 0 : aReturn.bEnabled = false;
485 0 : else if ( editingView() && !m_xAlterView.is() )
486 0 : aReturn.bEnabled = false;
487 : else
488 0 : aReturn = OJoinController::GetState( _nId );
489 0 : break;
490 :
491 : case ID_BROWSER_ESACPEPROCESSING:
492 0 : aReturn.bChecked = !m_bEscapeProcessing;
493 0 : aReturn.bEnabled = ( m_pSqlIterator != NULL ) && !m_bGraphicalDesign;
494 0 : break;
495 : case SID_RELATION_ADD_RELATION:
496 0 : aReturn.bEnabled = isEditable() && m_bGraphicalDesign && m_vTableData.size() > 1;
497 0 : break;
498 : case ID_BROWSER_SAVEASDOC:
499 0 : aReturn.bEnabled = !editingCommand() && !editingView() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
500 0 : break;
501 : case ID_BROWSER_SAVEDOC:
502 0 : aReturn.bEnabled = impl_isModified() && (!m_bGraphicalDesign || !(m_vTableFieldDesc.empty() || m_vTableData.empty()));
503 0 : break;
504 : case SID_PRINTDOCDIRECT:
505 0 : break;
506 : case ID_BROWSER_CUT:
507 0 : aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isCutAllowed();
508 0 : break;
509 : case ID_BROWSER_COPY:
510 0 : aReturn.bEnabled = getContainer() && getContainer()->isCopyAllowed();
511 0 : break;
512 : case ID_BROWSER_PASTE:
513 0 : aReturn.bEnabled = isEditable() && getContainer() && getContainer()->isPasteAllowed();
514 0 : break;
515 : case ID_BROWSER_SQL:
516 0 : aReturn.bEnabled = m_bEscapeProcessing && m_pSqlIterator;
517 0 : aReturn.bChecked = m_bGraphicalDesign;
518 0 : break;
519 : case SID_BROWSER_CLEAR_QUERY:
520 0 : aReturn.bEnabled = isEditable() && (!m_sStatement.isEmpty() || !m_vTableData.empty());
521 0 : break;
522 : case SID_QUERY_VIEW_FUNCTIONS:
523 : case SID_QUERY_VIEW_TABLES:
524 : case SID_QUERY_VIEW_ALIASES:
525 0 : aReturn.bChecked = getContainer() && getContainer()->isSlotEnabled(_nId);
526 0 : aReturn.bEnabled = m_bGraphicalDesign;
527 0 : break;
528 : case SID_QUERY_DISTINCT_VALUES:
529 0 : aReturn.bEnabled = m_bGraphicalDesign && isEditable();
530 0 : aReturn.bChecked = m_bDistinct;
531 0 : break;
532 : case SID_QUERY_LIMIT:
533 0 : aReturn.bEnabled = m_bGraphicalDesign;
534 0 : if( aReturn.bEnabled )
535 0 : aReturn.aValue = makeAny( m_nLimit );
536 0 : break;
537 : case SID_QUERY_PROP_DLG:
538 0 : aReturn.bEnabled = m_bGraphicalDesign;
539 0 : break;
540 : case ID_BROWSER_QUERY_EXECUTE:
541 0 : aReturn.bEnabled = true;
542 0 : break;
543 : case SID_DB_QUERY_PREVIEW:
544 0 : aReturn.bEnabled = true;
545 0 : aReturn.bChecked = getContainer() && getContainer()->getPreviewFrame().is();
546 0 : break;
547 : #if OSL_DEBUG_LEVEL > 1
548 : case ID_EDIT_QUERY_SQL:
549 : break;
550 : case ID_EDIT_QUERY_DESIGN:
551 : break;
552 : #endif
553 : case ID_BROWSER_ADDTABLE:
554 0 : if ( !m_bGraphicalDesign )
555 : {
556 0 : aReturn.bEnabled = false;
557 0 : break;
558 : }
559 : // run through
560 : default:
561 0 : aReturn = OJoinController::GetState(_nId);
562 0 : break;
563 : }
564 0 : return aReturn;
565 : }
566 :
567 0 : void OQueryController::Execute(sal_uInt16 _nId, const Sequence< PropertyValue >& aArgs)
568 : {
569 0 : switch(_nId)
570 : {
571 : case ID_BROWSER_ESACPEPROCESSING:
572 0 : setEscapeProcessing_fireEvent( !m_bEscapeProcessing );
573 0 : if ( !editingView() )
574 0 : setModified(sal_True);
575 0 : InvalidateFeature(ID_BROWSER_SQL);
576 0 : break;
577 : case ID_BROWSER_SAVEASDOC:
578 : case ID_BROWSER_SAVEDOC:
579 0 : grabFocusFromLimitBox(*this);
580 0 : doSaveAsDoc(ID_BROWSER_SAVEASDOC == _nId);
581 0 : break;
582 : case SID_RELATION_ADD_RELATION:
583 : {
584 0 : OJoinDesignView* pView = getJoinView();
585 0 : if( pView )
586 0 : static_cast<OQueryTableView*>(pView->getTableView())->createNewConnection();
587 : }
588 0 : break;
589 : case SID_PRINTDOCDIRECT:
590 0 : break;
591 : case ID_BROWSER_CUT:
592 0 : getContainer()->cut();
593 0 : break;
594 : case ID_BROWSER_COPY:
595 0 : getContainer()->copy();
596 0 : break;
597 : case ID_BROWSER_PASTE:
598 0 : getContainer()->paste();
599 0 : break;
600 : case ID_BROWSER_SQL:
601 : {
602 0 : grabFocusFromLimitBox(*this);
603 0 : if ( !getContainer()->checkStatement() )
604 0 : break;
605 0 : SQLExceptionInfo aError;
606 : try
607 : {
608 0 : OUString aErrorMsg;
609 0 : setStatement_fireEvent( getContainer()->getStatement() );
610 0 : if(m_sStatement.isEmpty() && m_pSqlIterator)
611 : {
612 : // change the view of the data
613 0 : delete m_pSqlIterator->getParseTree();
614 0 : m_pSqlIterator->setParseTree(NULL);
615 0 : m_bGraphicalDesign = !m_bGraphicalDesign;
616 0 : impl_setViewMode( &aError );
617 : }
618 : else
619 : {
620 0 : ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree(aErrorMsg,m_sStatement,m_bGraphicalDesign);
621 0 : if ( pNode )
622 : {
623 0 : delete m_pSqlIterator->getParseTree();
624 0 : m_pSqlIterator->setParseTree(pNode);
625 0 : m_pSqlIterator->traverseAll();
626 :
627 0 : if ( m_pSqlIterator->hasErrors() )
628 : {
629 0 : aError = m_pSqlIterator->getErrors();
630 : }
631 : else
632 : {
633 0 : const OSQLTables& xTabs = m_pSqlIterator->getTables();
634 0 : if ( m_pSqlIterator->getStatementType() != SQL_STATEMENT_SELECT || xTabs.begin() == xTabs.end() )
635 : {
636 0 : aError = SQLException(
637 : OUString( ModuleRes( STR_QRY_NOSELECT ) ),
638 : NULL,
639 : "S1000",
640 : 1000,
641 : Any()
642 0 : );
643 : }
644 : else
645 : {
646 : // change the view of the data
647 0 : m_bGraphicalDesign = !m_bGraphicalDesign;
648 0 : OUString sNewStatement;
649 0 : pNode->parseNodeToStr( sNewStatement, getConnection() );
650 0 : setStatement_fireEvent( sNewStatement );
651 0 : getContainer()->SaveUIConfig();
652 0 : m_vTableConnectionData.clear();
653 0 : impl_setViewMode( &aError );
654 : }
655 : }
656 : }
657 : else
658 : {
659 0 : aError = SQLException(
660 : OUString( ModuleRes( STR_QRY_SYNTAX ) ),
661 : NULL,
662 : "S1000",
663 : 1000,
664 : Any()
665 0 : );
666 : }
667 0 : }
668 : }
669 0 : catch(const SQLException&)
670 : {
671 0 : aError = ::cppu::getCaughtException();
672 : }
673 0 : catch(const Exception&)
674 : {
675 : DBG_UNHANDLED_EXCEPTION();
676 : }
677 :
678 0 : if ( aError.isValid() )
679 0 : showError( aError );
680 :
681 0 : if(m_bGraphicalDesign)
682 : {
683 0 : InvalidateFeature(ID_BROWSER_ADDTABLE);
684 0 : InvalidateFeature(SID_RELATION_ADD_RELATION);
685 0 : }
686 : }
687 0 : break;
688 : case SID_BROWSER_CLEAR_QUERY:
689 : {
690 0 : GetUndoManager().EnterListAction( OUString( ModuleRes(STR_QUERY_UNDO_TABWINDELETE) ), OUString() );
691 0 : getContainer()->clear();
692 0 : GetUndoManager().LeaveListAction();
693 :
694 0 : setStatement_fireEvent( OUString() );
695 0 : if(m_bGraphicalDesign)
696 0 : InvalidateFeature(ID_BROWSER_ADDTABLE);
697 : }
698 0 : break;
699 : case SID_QUERY_VIEW_FUNCTIONS:
700 : case SID_QUERY_VIEW_TABLES:
701 : case SID_QUERY_VIEW_ALIASES:
702 0 : getContainer()->setSlotEnabled(_nId,!getContainer()->isSlotEnabled(_nId));
703 0 : setModified(sal_True);
704 0 : break;
705 : case SID_QUERY_DISTINCT_VALUES:
706 0 : m_bDistinct = !m_bDistinct;
707 0 : setModified(sal_True);
708 0 : break;
709 : case SID_QUERY_LIMIT:
710 0 : if ( aArgs.getLength() >= 1 && aArgs[0].Name == "DBLimit.Value" )
711 : {
712 0 : aArgs[0].Value >>= m_nLimit;
713 0 : setModified(sal_True);
714 : }
715 0 : break;
716 : case SID_QUERY_PROP_DLG:
717 0 : grabFocusFromLimitBox(*this);
718 0 : execute_QueryPropDlg();
719 0 : break;
720 : case ID_BROWSER_QUERY_EXECUTE:
721 0 : grabFocusFromLimitBox(*this);
722 0 : if ( getContainer()->checkStatement() )
723 0 : executeQuery();
724 0 : break;
725 : case SID_DB_QUERY_PREVIEW:
726 : try
727 : {
728 0 : Reference< ::com::sun::star::util::XCloseable > xCloseFrame( getContainer()->getPreviewFrame(), UNO_QUERY );
729 0 : if ( xCloseFrame.is() )
730 : {
731 : try
732 : {
733 0 : xCloseFrame->close( sal_True );
734 : }
735 0 : catch(const Exception&)
736 : {
737 : OSL_FAIL( "OQueryController::Execute(SID_DB_QUERY_PREVIEW): *nobody* is expected to veto closing the preview frame!" );
738 : }
739 : }
740 : else
741 0 : Execute(ID_BROWSER_QUERY_EXECUTE,Sequence< PropertyValue >());
742 : }
743 0 : catch(const Exception&)
744 : {
745 : }
746 0 : break;
747 : case ID_QUERY_ZOOM_IN:
748 : {
749 : }
750 0 : break;
751 : case ID_QUERY_ZOOM_OUT:
752 : {
753 : }
754 0 : break;
755 : #if OSL_DEBUG_LEVEL > 1
756 : case ID_EDIT_QUERY_DESIGN:
757 : case ID_EDIT_QUERY_SQL:
758 : {
759 : OUString aErrorMsg;
760 : setStatement_fireEvent( getContainer()->getStatement() );
761 : ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign );
762 : if ( pNode )
763 : {
764 : Window* pView = getView();
765 : ModalDialog* pWindow = new ModalDialog( pView, WB_STDMODAL | WB_SIZEMOVE | WB_CENTER );
766 : pWindow->SetSizePixel( ::Size( pView->GetSizePixel().Width() / 2, pView->GetSizePixel().Height() / 2 ) );
767 : SvTreeListBox* pTreeBox = new SvTreeListBox( pWindow, WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT | WB_HASLINESATROOT | WB_VSCROLL );
768 : pTreeBox->SetPosSizePixel( ::Point( 6, 6 ), ::Size( pWindow->GetSizePixel().Width() - 12, pWindow->GetSizePixel().Height() - 12 ));
769 : pTreeBox->SetNodeDefaultImages();
770 :
771 : if ( _nId == ID_EDIT_QUERY_DESIGN )
772 : {
773 : ::connectivity::OSQLParseNode* pTemp = pNode ? pNode->getChild(3)->getChild(1) : NULL;
774 : // no where clause found
775 : if ( pTemp && !pTemp->isLeaf() )
776 : {
777 : ::connectivity::OSQLParseNode * pCondition = pTemp->getChild(1);
778 : if ( pCondition ) // no where clause
779 : {
780 : ::connectivity::OSQLParseNode::negateSearchCondition(pCondition);
781 : ::connectivity::OSQLParseNode *pNodeTmp = pTemp->getChild(1);
782 :
783 : ::connectivity::OSQLParseNode::disjunctiveNormalForm(pNodeTmp);
784 : pNodeTmp = pTemp->getChild(1);
785 : ::connectivity::OSQLParseNode::absorptions(pNodeTmp);
786 : pNodeTmp = pTemp->getChild(1);
787 : OSQLParseNode::compress(pNodeTmp);
788 : pNodeTmp = pTemp->getChild(1);
789 : }
790 : OUString sTemp;
791 : pNode->parseNodeToStr(sTemp,getConnection());
792 : getContainer()->setStatement(sTemp);
793 : }
794 : }
795 :
796 : insertParseTree(pTreeBox,pNode);
797 :
798 : pTreeBox->Show();
799 : pWindow->Execute();
800 :
801 : delete pTreeBox;
802 : delete pWindow;
803 : delete pNode;
804 : }
805 : break;
806 : }
807 : #endif
808 : default:
809 0 : OJoinController::Execute(_nId,aArgs);
810 0 : return; // else we would invalidate twice
811 : }
812 0 : InvalidateFeature(_nId);
813 : }
814 :
815 0 : void OQueryController::impl_showAutoSQLViewError( const ::com::sun::star::uno::Any& _rErrorDetails )
816 : {
817 0 : SQLContext aErrorContext;
818 0 : aErrorContext.Message = lcl_getObjectResourceString( STR_ERROR_PARSING_STATEMENT, m_nCommandType );
819 0 : aErrorContext.Context = *this;
820 0 : aErrorContext.Details = lcl_getObjectResourceString( STR_INFO_OPENING_IN_SQL_VIEW, m_nCommandType );
821 0 : aErrorContext.NextException = _rErrorDetails;
822 0 : showError( aErrorContext );
823 0 : }
824 :
825 0 : bool OQueryController::impl_setViewMode( ::dbtools::SQLExceptionInfo* _pErrorInfo )
826 : {
827 : OSL_PRECOND( getContainer(), "OQueryController::impl_setViewMode: illegal call!" );
828 :
829 0 : bool wasModified = isModified();
830 :
831 0 : SQLExceptionInfo aError;
832 0 : bool bSuccess = getContainer()->switchView( &aError );
833 0 : if ( !bSuccess )
834 : {
835 0 : m_bGraphicalDesign = !m_bGraphicalDesign;
836 : // restore old state
837 0 : getContainer()->switchView( NULL );
838 : // don't pass &aError here, this would overwrite the error which the first switchView call
839 : // returned in this location.
840 0 : if ( _pErrorInfo )
841 0 : *_pErrorInfo = aError;
842 : else
843 0 : showError( aError );
844 : }
845 : else
846 : {
847 0 : ensureToolbars( *this, m_bGraphicalDesign );
848 : }
849 :
850 0 : setModified( wasModified );
851 0 : return bSuccess;
852 : }
853 :
854 0 : void OQueryController::impl_initialize()
855 : {
856 0 : OJoinController::impl_initialize();
857 :
858 0 : const NamedValueCollection& rArguments( getInitParams() );
859 :
860 0 : OUString sCommand;
861 0 : m_nCommandType = CommandType::QUERY;
862 :
863 : // reading parameters:
864 :
865 : // legacy parameters first (later overwritten by regular parameters)
866 0 : OUString sIndependentSQLCommand;
867 0 : if ( rArguments.get_ensureType( "IndependentSQLCommand", sIndependentSQLCommand ) )
868 : {
869 : OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" );
870 0 : sCommand = sIndependentSQLCommand;
871 0 : m_nCommandType = CommandType::COMMAND;
872 : }
873 :
874 0 : OUString sCurrentQuery;
875 0 : if ( rArguments.get_ensureType( "CurrentQuery", sCurrentQuery ) )
876 : {
877 : OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
878 0 : sCommand = sCurrentQuery;
879 0 : m_nCommandType = CommandType::QUERY;
880 : }
881 :
882 0 : sal_Bool bCreateView( sal_False );
883 0 : if ( rArguments.get_ensureType( "CreateView", bCreateView ) && bCreateView )
884 : {
885 : OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
886 0 : m_nCommandType = CommandType::TABLE;
887 : }
888 :
889 : // non-legacy parameters which overwrite the legacy parameters
890 0 : rArguments.get_ensureType( (OUString)PROPERTY_COMMAND, sCommand );
891 0 : rArguments.get_ensureType( (OUString)PROPERTY_COMMAND_TYPE, m_nCommandType );
892 :
893 : // translate Command/Type into proper members
894 : // TODO/Later: all this (including those members) should be hidden behind some abstact interface,
895 : // which is implemented for all the three commands
896 0 : switch ( m_nCommandType )
897 : {
898 : case CommandType::QUERY:
899 0 : m_sName = sCommand;
900 0 : break;
901 : case CommandType::TABLE:
902 0 : m_sName = sCommand;
903 0 : break;
904 : case CommandType::COMMAND:
905 0 : setStatement_fireEvent( sCommand );
906 0 : m_sName = OUString();
907 0 : break;
908 : default:
909 : OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" );
910 0 : throw RuntimeException();
911 : }
912 :
913 : // more legacy parameters
914 0 : sal_Bool bGraphicalDesign( sal_True );
915 0 : if ( rArguments.get_ensureType( (OUString)PROPERTY_QUERYDESIGNVIEW, bGraphicalDesign ) )
916 : {
917 : OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" );
918 0 : m_bGraphicalDesign = bGraphicalDesign;
919 : }
920 :
921 : // more non-legacy
922 0 : rArguments.get_ensureType( (OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign );
923 :
924 0 : bool bEscapeProcessing( true );
925 0 : if ( rArguments.get_ensureType( (OUString)PROPERTY_ESCAPE_PROCESSING, bEscapeProcessing ) )
926 : {
927 0 : setEscapeProcessing_fireEvent( bEscapeProcessing );
928 :
929 : OSL_ENSURE( m_bEscapeProcessing || !m_bGraphicalDesign, "OQueryController::impl_initialize: can't do the graphical design without escape processing!" );
930 0 : if ( !m_bEscapeProcessing )
931 0 : m_bGraphicalDesign = false;
932 : }
933 :
934 : // initial design
935 0 : bool bForceInitialDesign = false;
936 0 : Sequence< PropertyValue > aCurrentQueryDesignProps;
937 0 : aCurrentQueryDesignProps = rArguments.getOrDefault( "CurrentQueryDesign", aCurrentQueryDesignProps );
938 :
939 0 : if ( aCurrentQueryDesignProps.getLength() )
940 : {
941 0 : ::comphelper::NamedValueCollection aCurrentQueryDesign( aCurrentQueryDesignProps );
942 0 : if ( aCurrentQueryDesign.has( (OUString)PROPERTY_GRAPHICAL_DESIGN ) )
943 : {
944 0 : aCurrentQueryDesign.get_ensureType( (OUString)PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign );
945 : }
946 0 : if ( aCurrentQueryDesign.has( (OUString)PROPERTY_ESCAPE_PROCESSING ) )
947 : {
948 0 : aCurrentQueryDesign.get_ensureType( (OUString)PROPERTY_ESCAPE_PROCESSING, m_bEscapeProcessing );
949 : }
950 0 : if ( aCurrentQueryDesign.has( "Statement" ) )
951 : {
952 0 : OUString sStatement;
953 0 : aCurrentQueryDesign.get_ensureType( "Statement", sStatement );
954 0 : aCurrentQueryDesign.remove( "Statement" );
955 0 : setStatement_fireEvent( sStatement );
956 : }
957 :
958 0 : loadViewSettings( aCurrentQueryDesign );
959 :
960 0 : bForceInitialDesign = true;
961 : }
962 :
963 0 : if ( !ensureConnected( false ) )
964 : { // we have no connection so what else should we do
965 0 : m_bGraphicalDesign = sal_False;
966 0 : if ( editingView() )
967 : {
968 0 : connectionLostMessage();
969 0 : throw SQLException();
970 : }
971 : }
972 :
973 : // check the view capabilities
974 0 : if ( isConnected() && editingView() )
975 : {
976 0 : Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY );
977 0 : Reference< XNameAccess > xViews;
978 0 : if ( xViewsSup.is() )
979 0 : xViews = xViewsSup->getViews();
980 :
981 0 : if ( !xViews.is() )
982 : { // we can't create views so we ask if the user wants to create a query instead
983 0 : m_nCommandType = CommandType::QUERY;
984 0 : sal_Bool bClose = sal_False;
985 : {
986 0 : OUString aTitle( ModuleRes( STR_QUERYDESIGN_NO_VIEW_SUPPORT ) );
987 0 : OUString aMessage( ModuleRes( STR_QUERYDESIGN_NO_VIEW_ASK ) );
988 0 : ODataView* pWindow = getView();
989 0 : OSQLMessageBox aDlg( pWindow, aTitle, aMessage, WB_YES_NO | WB_DEF_YES, OSQLMessageBox::Query );
990 0 : bClose = aDlg.Execute() == RET_NO;
991 : }
992 0 : if ( bClose )
993 0 : throw VetoException();
994 : }
995 :
996 : // now if we are to edit an existing view, check whether this is possible
997 0 : if ( !m_sName.isEmpty() )
998 : {
999 0 : Any aView( xViews->getByName( m_sName ) );
1000 : // will throw if there is no such view
1001 0 : if ( !( aView >>= m_xAlterView ) )
1002 : {
1003 : throw IllegalArgumentException(
1004 : OUString( ModuleRes( STR_NO_ALTER_VIEW_SUPPORT ) ),
1005 : *this,
1006 : 1
1007 0 : );
1008 0 : }
1009 0 : }
1010 : }
1011 :
1012 : OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!");
1013 :
1014 : try
1015 : {
1016 0 : getContainer()->initialize();
1017 0 : impl_reset( bForceInitialDesign );
1018 :
1019 0 : SQLExceptionInfo aError;
1020 0 : const bool bAttemptedGraphicalDesign = m_bGraphicalDesign;
1021 :
1022 0 : if ( bForceInitialDesign )
1023 : {
1024 0 : getContainer()->forceInitialView();
1025 : }
1026 : else
1027 : {
1028 0 : impl_setViewMode( &aError );
1029 : }
1030 :
1031 0 : if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign )
1032 : {
1033 : // we tried initializing the graphical view, this failed, and we were automatically switched to SQL
1034 : // view => tell this to the user
1035 0 : if ( !editingView() )
1036 : {
1037 0 : impl_showAutoSQLViewError( aError.get() );
1038 : }
1039 : }
1040 :
1041 0 : ClearUndoManager();
1042 :
1043 0 : if ( ( m_bGraphicalDesign )
1044 0 : && ( ( m_sName.isEmpty() && !editingCommand() )
1045 0 : || ( m_sStatement.isEmpty() && editingCommand() )
1046 : )
1047 : )
1048 : {
1049 0 : Application::PostUserEvent( LINK( this, OQueryController, OnExecuteAddTable ) );
1050 : }
1051 :
1052 0 : setModified(sal_False);
1053 : }
1054 0 : catch(const SQLException& e)
1055 : {
1056 : DBG_UNHANDLED_EXCEPTION();
1057 : // we caught an exception so we switch to text only mode
1058 : {
1059 0 : m_bGraphicalDesign = sal_False;
1060 0 : getContainer()->initialize();
1061 0 : ODataView* pWindow = getView();
1062 0 : OSQLMessageBox(pWindow,e).Execute();
1063 : }
1064 0 : throw;
1065 0 : }
1066 0 : }
1067 :
1068 0 : void OQueryController::onLoadedMenu(const Reference< ::com::sun::star::frame::XLayoutManager >& /*_xLayoutManager*/)
1069 : {
1070 0 : ensureToolbars( *this, m_bGraphicalDesign );
1071 0 : }
1072 :
1073 0 : OUString OQueryController::getPrivateTitle( ) const
1074 : {
1075 0 : OUString sName = m_sName;
1076 0 : if ( sName.isEmpty() )
1077 : {
1078 0 : if ( !editingCommand() )
1079 : {
1080 0 : SolarMutexGuard aSolarGuard;
1081 0 : ::osl::MutexGuard aGuard( getMutex() );
1082 0 : OUString aDefaultName = ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE );
1083 0 : sName = aDefaultName.getToken(0,' ');
1084 0 : sName += OUString::number(getCurrentStartNumber());
1085 : }
1086 : }
1087 0 : return sName;
1088 : }
1089 :
1090 0 : void OQueryController::setQueryComposer()
1091 : {
1092 0 : if(isConnected())
1093 : {
1094 0 : Reference< XSQLQueryComposerFactory > xFactory(getConnection(), UNO_QUERY);
1095 : OSL_ENSURE(xFactory.is(),"Connection doesn't support a querycomposer");
1096 0 : if ( xFactory.is() && getContainer() )
1097 : {
1098 : try
1099 : {
1100 0 : m_xComposer = xFactory->createQueryComposer();
1101 0 : getContainer()->setStatement(m_sStatement);
1102 : }
1103 0 : catch(const Exception&)
1104 : {
1105 0 : m_xComposer = NULL;
1106 : }
1107 : OSL_ENSURE(m_xComposer.is(),"No querycomposer available!");
1108 0 : Reference<XTablesSupplier> xTablesSup(getConnection(), UNO_QUERY);
1109 0 : deleteIterator();
1110 0 : m_pSqlIterator = new ::connectivity::OSQLParseTreeIterator( getConnection(), xTablesSup->getTables(), m_aSqlParser, NULL );
1111 0 : }
1112 : }
1113 0 : }
1114 :
1115 0 : bool OQueryController::Construct(Window* pParent)
1116 : {
1117 : // TODO: we have to check if we should create the text view or the design view
1118 :
1119 0 : setView( * new OQueryContainerWindow( pParent, *this, getORB() ) );
1120 :
1121 0 : return OJoinController::Construct(pParent);
1122 : }
1123 :
1124 0 : OJoinDesignView* OQueryController::getJoinView()
1125 : {
1126 0 : return getContainer()->getDesignView();
1127 : }
1128 :
1129 0 : void OQueryController::describeSupportedFeatures()
1130 : {
1131 0 : OJoinController::describeSupportedFeatures();
1132 0 : implDescribeSupportedFeature( ".uno:SaveAs", ID_BROWSER_SAVEASDOC, CommandGroup::DOCUMENT );
1133 0 : implDescribeSupportedFeature( ".uno:SbaNativeSql", ID_BROWSER_ESACPEPROCESSING,CommandGroup::FORMAT );
1134 0 : implDescribeSupportedFeature( ".uno:DBViewFunctions", SID_QUERY_VIEW_FUNCTIONS, CommandGroup::VIEW );
1135 0 : implDescribeSupportedFeature( ".uno:DBViewTableNames", SID_QUERY_VIEW_TABLES, CommandGroup::VIEW );
1136 0 : implDescribeSupportedFeature( ".uno:DBViewAliases", SID_QUERY_VIEW_ALIASES, CommandGroup::VIEW );
1137 0 : implDescribeSupportedFeature( ".uno:DBDistinctValues", SID_QUERY_DISTINCT_VALUES, CommandGroup::FORMAT );
1138 0 : implDescribeSupportedFeature( ".uno:DBChangeDesignMode",ID_BROWSER_SQL, CommandGroup::VIEW );
1139 0 : implDescribeSupportedFeature( ".uno:DBClearQuery", SID_BROWSER_CLEAR_QUERY, CommandGroup::EDIT );
1140 0 : implDescribeSupportedFeature( ".uno:SbaExecuteSql", ID_BROWSER_QUERY_EXECUTE, CommandGroup::VIEW );
1141 0 : implDescribeSupportedFeature( ".uno:DBAddRelation", SID_RELATION_ADD_RELATION, CommandGroup::EDIT );
1142 0 : implDescribeSupportedFeature( ".uno:DBQueryPreview", SID_DB_QUERY_PREVIEW, CommandGroup::VIEW );
1143 0 : implDescribeSupportedFeature( ".uno:DBLimit", SID_QUERY_LIMIT, CommandGroup::FORMAT );
1144 0 : implDescribeSupportedFeature( ".uno:DBQueryPropertiesDialog", SID_QUERY_PROP_DLG, CommandGroup::FORMAT );
1145 :
1146 : #if OSL_DEBUG_LEVEL > 1
1147 : implDescribeSupportedFeature( ".uno:DBShowParseTree", ID_EDIT_QUERY_SQL );
1148 : implDescribeSupportedFeature( ".uno:DBMakeDisjunct", ID_EDIT_QUERY_DESIGN );
1149 : #endif
1150 0 : }
1151 :
1152 0 : void OQueryController::impl_onModifyChanged()
1153 : {
1154 0 : OJoinController::impl_onModifyChanged();
1155 0 : InvalidateFeature(SID_BROWSER_CLEAR_QUERY);
1156 0 : InvalidateFeature(ID_BROWSER_SAVEASDOC);
1157 0 : InvalidateFeature(ID_BROWSER_QUERY_EXECUTE);
1158 0 : }
1159 :
1160 0 : void SAL_CALL OQueryController::disposing( const EventObject& Source ) throw(RuntimeException, std::exception)
1161 : {
1162 0 : SolarMutexGuard aGuard;
1163 :
1164 0 : if ( getContainer() && Source.Source.is() )
1165 : {
1166 0 : if ( Source.Source == m_aCurrentFrame.getFrame() )
1167 : { // our frame is being disposed -> close the preview window (if we have one)
1168 0 : Reference< XFrame2 > xPreviewFrame( getContainer()->getPreviewFrame() );
1169 0 : ::comphelper::disposeComponent( xPreviewFrame );
1170 : }
1171 0 : else if ( Source.Source == getContainer()->getPreviewFrame() )
1172 : {
1173 0 : getContainer()->disposingPreview();
1174 : }
1175 : }
1176 :
1177 0 : OJoinController::disposing(Source);
1178 0 : }
1179 :
1180 0 : void OQueryController::reconnect(bool _bUI)
1181 : {
1182 0 : deleteIterator();
1183 0 : ::comphelper::disposeComponent(m_xComposer);
1184 :
1185 0 : OJoinController::reconnect( _bUI );
1186 :
1187 0 : if (isConnected())
1188 : {
1189 0 : setQueryComposer();
1190 : }
1191 : else
1192 : {
1193 0 : if(m_bGraphicalDesign)
1194 : {
1195 0 : m_bGraphicalDesign = sal_False;
1196 : // don't call Execute(SQL) because this changes the sql statement
1197 0 : impl_setViewMode( NULL );
1198 : }
1199 0 : InvalidateAll();
1200 : }
1201 0 : }
1202 :
1203 0 : void OQueryController::saveViewSettings( ::comphelper::NamedValueCollection& o_rViewSettings, const bool i_includingCriteria ) const
1204 : {
1205 0 : saveTableWindows( o_rViewSettings );
1206 :
1207 0 : OTableFields::const_iterator field = m_vTableFieldDesc.begin();
1208 0 : OTableFields::const_iterator fieldEnd = m_vTableFieldDesc.end();
1209 :
1210 0 : ::comphelper::NamedValueCollection aAllFieldsData;
1211 0 : ::comphelper::NamedValueCollection aFieldData;
1212 0 : for ( sal_Int32 i = 1; field != fieldEnd; ++field, ++i )
1213 : {
1214 0 : if ( !(*field)->IsEmpty() )
1215 : {
1216 0 : aFieldData.clear();
1217 0 : (*field)->Save( aFieldData, i_includingCriteria );
1218 :
1219 0 : const OUString sFieldSettingName = "Field" + OUString::number( i );
1220 0 : aAllFieldsData.put( sFieldSettingName, aFieldData.getPropertyValues() );
1221 : }
1222 : }
1223 :
1224 0 : o_rViewSettings.put( "Fields", aAllFieldsData.getPropertyValues() );
1225 0 : o_rViewSettings.put( "SplitterPosition", m_nSplitPos );
1226 0 : o_rViewSettings.put( "VisibleRows", m_nVisibleRows );
1227 0 : }
1228 :
1229 0 : void OQueryController::loadViewSettings( const ::comphelper::NamedValueCollection& o_rViewSettings )
1230 : {
1231 0 : loadTableWindows( o_rViewSettings );
1232 :
1233 0 : m_nSplitPos = o_rViewSettings.getOrDefault( "SplitterPosition", m_nSplitPos );
1234 0 : m_nVisibleRows = o_rViewSettings.getOrDefault( "VisibleRows", m_nVisibleRows );
1235 0 : m_aFieldInformation = o_rViewSettings.getOrDefault( "Fields", m_aFieldInformation );
1236 0 : }
1237 :
1238 0 : void OQueryController::execute_QueryPropDlg()
1239 : {
1240 : QueryPropertiesDialog aQueryPropDlg(
1241 0 : getContainer(), m_bDistinct, m_nLimit );
1242 :
1243 0 : if( aQueryPropDlg.Execute() == RET_OK )
1244 : {
1245 0 : m_bDistinct = aQueryPropDlg.getDistinct();
1246 0 : m_nLimit = aQueryPropDlg.getLimit();
1247 0 : InvalidateFeature( SID_QUERY_DISTINCT_VALUES );
1248 0 : InvalidateFeature( SID_QUERY_LIMIT, 0, true );
1249 0 : }
1250 0 : }
1251 :
1252 0 : sal_Int32 OQueryController::getColWidth(sal_uInt16 _nColPos) const
1253 : {
1254 0 : if ( _nColPos < m_aFieldInformation.getLength() )
1255 : {
1256 0 : ::std::auto_ptr<OTableFieldDesc> pField( new OTableFieldDesc());
1257 0 : pField->Load( m_aFieldInformation[ _nColPos ], false );
1258 0 : return pField->GetColWidth();
1259 : }
1260 0 : return 0;
1261 : }
1262 :
1263 0 : Reference<XNameAccess> OQueryController::getObjectContainer() const
1264 : {
1265 0 : Reference< XNameAccess > xElements;
1266 0 : if ( editingView() )
1267 : {
1268 0 : Reference< XViewsSupplier > xViewsSupp( getConnection(), UNO_QUERY );
1269 0 : if ( xViewsSupp.is() )
1270 0 : xElements = xViewsSupp->getViews();
1271 : }
1272 : else
1273 : {
1274 0 : Reference< XQueriesSupplier > xQueriesSupp( getConnection(), UNO_QUERY );
1275 0 : if ( xQueriesSupp.is() )
1276 0 : xElements = xQueriesSupp->getQueries();
1277 : else
1278 : {
1279 0 : Reference< XQueryDefinitionsSupplier > xQueryDefsSupp( getDataSource(), UNO_QUERY );
1280 0 : if ( xQueryDefsSupp.is() )
1281 0 : xElements = xQueryDefsSupp->getQueryDefinitions();
1282 0 : }
1283 : }
1284 :
1285 : OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" );
1286 0 : return xElements;
1287 : }
1288 :
1289 0 : void OQueryController::executeQuery()
1290 : {
1291 : // we don't need to check the connection here because we already check the composer
1292 : // which can't live without his connection
1293 0 : OUString sTranslatedStmt = translateStatement( false );
1294 :
1295 0 : OUString sDataSourceName = getDataSourceName();
1296 0 : if ( !(sDataSourceName.isEmpty() || sTranslatedStmt.isEmpty()) )
1297 : {
1298 : try
1299 : {
1300 0 : getContainer()->showPreview( getFrame() );
1301 0 : InvalidateFeature(SID_DB_QUERY_PREVIEW);
1302 :
1303 0 : URL aWantToDispatch;
1304 0 : aWantToDispatch.Complete = ".component:DB/DataSourceBrowser";
1305 :
1306 0 : OUString sFrameName( FRAME_NAME_QUERY_PREVIEW );
1307 0 : sal_Int32 nSearchFlags = FrameSearchFlag::CHILDREN;
1308 :
1309 0 : Reference< XDispatch> xDisp;
1310 0 : Reference< XDispatchProvider> xProv( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY );
1311 0 : if(!xProv.is())
1312 : {
1313 0 : xProv.set( getFrame(), UNO_QUERY );
1314 0 : if (xProv.is())
1315 0 : xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, nSearchFlags);
1316 : }
1317 : else
1318 : {
1319 0 : xDisp = xProv->queryDispatch(aWantToDispatch, sFrameName, FrameSearchFlag::SELF);
1320 : }
1321 0 : if (xDisp.is())
1322 : {
1323 0 : Sequence< PropertyValue> aProps(9);
1324 0 : aProps[0].Name = PROPERTY_DATASOURCENAME;
1325 0 : aProps[0].Value <<= sDataSourceName;
1326 :
1327 0 : aProps[1].Name = PROPERTY_COMMAND_TYPE;
1328 0 : aProps[1].Value <<= CommandType::COMMAND;
1329 :
1330 0 : aProps[2].Name = PROPERTY_COMMAND;
1331 0 : aProps[2].Value <<= sTranslatedStmt;
1332 :
1333 0 : aProps[3].Name = PROPERTY_ENABLE_BROWSER;
1334 0 : aProps[3].Value <<= false;
1335 :
1336 0 : aProps[4].Name = PROPERTY_ACTIVE_CONNECTION;
1337 0 : aProps[4].Value <<= getConnection();
1338 :
1339 0 : aProps[5].Name = PROPERTY_UPDATE_CATALOGNAME;
1340 0 : aProps[5].Value <<= m_sUpdateCatalogName;
1341 :
1342 0 : aProps[6].Name = PROPERTY_UPDATE_SCHEMANAME;
1343 0 : aProps[6].Value <<= m_sUpdateSchemaName;
1344 :
1345 0 : aProps[7].Name = PROPERTY_UPDATE_TABLENAME;
1346 0 : aProps[7].Value <<= m_sUpdateTableName;
1347 :
1348 0 : aProps[8].Name = PROPERTY_ESCAPE_PROCESSING;
1349 0 : aProps[8].Value <<= m_bEscapeProcessing;
1350 :
1351 0 : xDisp->dispatch(aWantToDispatch, aProps);
1352 : // check the state of the beamer
1353 : // be notified when the beamer frame is closed
1354 0 : Reference< XComponent > xComponent( getFrame()->findFrame( sFrameName, nSearchFlags ), UNO_QUERY );
1355 0 : if (xComponent.is())
1356 : {
1357 : OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(),
1358 : "OQueryController::executeQuery: oops ... which window do I have here?");
1359 0 : Reference< XEventListener> xEvtL((::cppu::OWeakObject*)this,UNO_QUERY);
1360 0 : xComponent->addEventListener(xEvtL);
1361 0 : }
1362 : }
1363 : else
1364 : {
1365 : OSL_FAIL("Couldn't create a beamer window!");
1366 0 : }
1367 : }
1368 0 : catch(const Exception&)
1369 : {
1370 : OSL_FAIL("Couldn't create a beamer window!");
1371 : }
1372 0 : }
1373 0 : }
1374 :
1375 0 : sal_Bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements,sal_Bool _bSaveAs)
1376 : {
1377 : OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" );
1378 0 : if ( editingCommand() )
1379 0 : return sal_False;
1380 :
1381 : OSL_PRECOND( _xElements.is(), "OQueryController::askForNewName: invalid container!" );
1382 0 : if ( !_xElements.is() )
1383 0 : return sal_False;
1384 :
1385 0 : sal_Bool bRet = sal_True;
1386 0 : sal_Bool bNew = _bSaveAs || !_xElements->hasByName( m_sName );
1387 0 : if(bNew)
1388 : {
1389 0 : OUString aDefaultName;
1390 0 : if ( ( _bSaveAs && !bNew ) || ( bNew && !m_sName.isEmpty() ) )
1391 0 : aDefaultName = m_sName;
1392 : else
1393 : {
1394 0 : OUString sName = ModuleRes( editingView() ? STR_VIEW_TITLE : STR_QRY_TITLE );
1395 0 : aDefaultName = sName.getToken(0,' ');
1396 0 : aDefaultName = ::dbtools::createUniqueName(_xElements,aDefaultName);
1397 : }
1398 :
1399 0 : DynamicTableOrQueryNameCheck aNameChecker( getConnection(), CommandType::QUERY );
1400 : OSaveAsDlg aDlg(
1401 0 : getView(),
1402 : m_nCommandType,
1403 : getORB(),
1404 0 : getConnection(),
1405 : aDefaultName,
1406 : aNameChecker,
1407 0 : SAD_DEFAULT );
1408 :
1409 0 : bRet = ( aDlg.Execute() == RET_OK );
1410 0 : if ( bRet )
1411 : {
1412 0 : m_sName = aDlg.getName();
1413 0 : if ( editingView() )
1414 : {
1415 0 : m_sUpdateCatalogName = aDlg.getCatalog();
1416 0 : m_sUpdateSchemaName = aDlg.getSchema();
1417 : }
1418 0 : }
1419 : }
1420 0 : return bRet;
1421 : }
1422 :
1423 0 : bool OQueryController::doSaveAsDoc(sal_Bool _bSaveAs)
1424 : {
1425 : OSL_ENSURE(isEditable(),"Slot ID_BROWSER_SAVEDOC should not be enabled!");
1426 0 : if ( !editingCommand() && !haveDataSource() )
1427 : {
1428 0 : OUString aMessage(ModuleRes(STR_DATASOURCE_DELETED));
1429 0 : OSQLWarningBox( getView(), aMessage ).Execute();
1430 0 : return false;
1431 : }
1432 :
1433 0 : Reference< XNameAccess > xElements = getObjectContainer();
1434 0 : if ( !xElements.is() )
1435 0 : return false;
1436 :
1437 0 : if ( !getContainer()->checkStatement() )
1438 0 : return false;
1439 :
1440 0 : OUString sTranslatedStmt = translateStatement();
1441 0 : if ( editingCommand() )
1442 : {
1443 0 : setModified( sal_False );
1444 : // this is all we need to do here. translateStatement implicitly set our m_sStatement, and
1445 : // notified it, and that's all
1446 0 : return true;
1447 : }
1448 :
1449 0 : if ( sTranslatedStmt.isEmpty() )
1450 0 : return false;
1451 :
1452 : // first we need a name for our query so ask the user
1453 : // did we get a name
1454 0 : OUString sOriginalName( m_sName );
1455 0 : if ( !askForNewName( xElements, _bSaveAs ) || m_sName.isEmpty() )
1456 0 : return false;
1457 :
1458 0 : SQLExceptionInfo aInfo;
1459 0 : bool bSuccess = false;
1460 0 : bool bNew = false;
1461 : try
1462 : {
1463 : bNew = ( _bSaveAs )
1464 0 : || ( !xElements->hasByName( m_sName ) );
1465 :
1466 0 : Reference<XPropertySet> xQuery;
1467 0 : if ( bNew ) // just to make sure the query already exists
1468 : {
1469 : // drop the query, in case it already exists
1470 0 : if ( xElements->hasByName( m_sName ) )
1471 : {
1472 0 : Reference< XDrop > xNameCont( xElements, UNO_QUERY );
1473 0 : if ( xNameCont.is() )
1474 0 : xNameCont->dropByName( m_sName );
1475 : else
1476 : {
1477 0 : Reference< XNameContainer > xCont( xElements, UNO_QUERY );
1478 0 : if ( xCont.is() )
1479 0 : xCont->removeByName( m_sName );
1480 0 : }
1481 : }
1482 :
1483 : // create a new (empty, uninitialized) query resp. view
1484 0 : Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY );
1485 0 : if ( xFact.is() )
1486 : {
1487 0 : xQuery = xFact->createDataDescriptor();
1488 : // to set the name is only allowed when the query is new
1489 0 : xQuery->setPropertyValue( PROPERTY_NAME, makeAny( m_sName ) );
1490 : }
1491 : else
1492 : {
1493 0 : Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY );
1494 0 : if ( xSingleFac.is() )
1495 0 : xQuery = xQuery.query( xSingleFac->createInstance() );
1496 0 : }
1497 : }
1498 : else
1499 : {
1500 0 : xElements->getByName( m_sName ) >>= xQuery;
1501 : }
1502 0 : if ( !xQuery.is() )
1503 0 : throw RuntimeException();
1504 :
1505 : // the new commands
1506 0 : if ( editingView() && !bNew )
1507 : {
1508 : OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" );
1509 0 : m_xAlterView.set( xQuery, UNO_QUERY_THROW );
1510 0 : m_xAlterView->alterCommand( sTranslatedStmt );
1511 : }
1512 : else
1513 : { // we're creating a query, or a *new* view
1514 0 : xQuery->setPropertyValue( PROPERTY_COMMAND, makeAny( sTranslatedStmt ) );
1515 :
1516 0 : if ( editingView() )
1517 : {
1518 0 : xQuery->setPropertyValue( PROPERTY_CATALOGNAME, makeAny( m_sUpdateCatalogName ) );
1519 0 : xQuery->setPropertyValue( PROPERTY_SCHEMANAME, makeAny( m_sUpdateSchemaName ) );
1520 : }
1521 :
1522 0 : if ( editingQuery() )
1523 : {
1524 0 : xQuery->setPropertyValue( PROPERTY_UPDATE_TABLENAME, makeAny( m_sUpdateTableName ) );
1525 0 : xQuery->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, css::uno::makeAny( m_bEscapeProcessing ) );
1526 :
1527 0 : xQuery->setPropertyValue( PROPERTY_LAYOUTINFORMATION, getViewData() );
1528 : }
1529 : }
1530 :
1531 0 : if ( bNew )
1532 : {
1533 0 : Reference< XAppend > xAppend( xElements, UNO_QUERY );
1534 0 : if ( xAppend.is() )
1535 : {
1536 0 : xAppend->appendByDescriptor( xQuery );
1537 : }
1538 : else
1539 : {
1540 0 : Reference< XNameContainer > xCont( xElements, UNO_QUERY );
1541 0 : if ( xCont.is() )
1542 0 : xCont->insertByName( m_sName, makeAny( xQuery ) );
1543 : }
1544 :
1545 0 : if ( editingView() )
1546 : {
1547 0 : Reference< XPropertySet > xViewProps;
1548 0 : if ( xElements->hasByName( m_sName ) )
1549 0 : xViewProps.set( xElements->getByName( m_sName ), UNO_QUERY );
1550 :
1551 0 : if ( !xViewProps.is() ) // correct name and try again
1552 0 : m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::eInDataManipulation, false, false, false );
1553 :
1554 : OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly creaed view does not exist!" );
1555 :
1556 0 : if ( xElements->hasByName( m_sName ) )
1557 0 : m_xAlterView.set( xElements->getByName( m_sName ), UNO_QUERY );
1558 :
1559 : // now check if our datasource has set a tablefilter and if so, append the new table name to it
1560 0 : ::dbaui::appendToFilter( getConnection(), m_sName, getORB(), getView() );
1561 : }
1562 0 : Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY);
1563 0 : if ( xEventListener.is() )
1564 : {
1565 0 : TitleChangedEvent aEvent;
1566 0 : xEventListener->titleChanged(aEvent);
1567 : }
1568 0 : releaseNumberForComponent();
1569 : }
1570 :
1571 0 : setModified( sal_False );
1572 0 : bSuccess = true;
1573 :
1574 : }
1575 0 : catch(const SQLException&)
1576 : {
1577 0 : if ( !bNew )
1578 0 : m_sName = sOriginalName;
1579 0 : aInfo = SQLExceptionInfo( ::cppu::getCaughtException() );
1580 : }
1581 0 : catch(const Exception&)
1582 : {
1583 0 : if ( !bNew )
1584 0 : m_sName = sOriginalName;
1585 : DBG_UNHANDLED_EXCEPTION();
1586 : }
1587 :
1588 0 : showError( aInfo );
1589 :
1590 : // if we successfully saved a view we were creating, then close the designer
1591 0 : if ( bSuccess && editingView() && !m_xAlterView.is() )
1592 : {
1593 0 : closeTask();
1594 : }
1595 :
1596 0 : if ( bSuccess && editingView() )
1597 0 : InvalidateFeature( ID_BROWSER_EDITDOC );
1598 :
1599 0 : return bSuccess;
1600 : }
1601 :
1602 : namespace {
1603 0 : struct CommentStrip
1604 : {
1605 : OUString maComment;
1606 : bool mbLastOnLine;
1607 0 : CommentStrip( const OUString& rComment, bool bLastOnLine )
1608 0 : : maComment( rComment), mbLastOnLine( bLastOnLine) {}
1609 : };
1610 :
1611 : }
1612 :
1613 : /** Obtain all comments in a query.
1614 :
1615 : See also delComment() implementation for OSQLParser::parseTree().
1616 : */
1617 0 : static ::std::vector< CommentStrip > getComment( const OUString& rQuery )
1618 : {
1619 0 : ::std::vector< CommentStrip > aRet;
1620 : // First a quick search if there is any "--" or "//" or "/*", if not then
1621 : // the whole copying loop is pointless.
1622 0 : if (rQuery.indexOfAsciiL( "--", 2, 0) < 0 && rQuery.indexOfAsciiL( "//", 2, 0) < 0 &&
1623 0 : rQuery.indexOfAsciiL( "/*", 2, 0) < 0)
1624 0 : return aRet;
1625 :
1626 0 : const sal_Unicode* pCopy = rQuery.getStr();
1627 0 : const sal_Int32 nQueryLen = rQuery.getLength();
1628 0 : bool bIsText1 = false; // "text"
1629 0 : bool bIsText2 = false; // 'text'
1630 0 : bool bComment2 = false; // /* comment */
1631 0 : bool bComment = false; // -- or // comment
1632 0 : OUStringBuffer aBuf;
1633 0 : for (sal_Int32 i=0; i < nQueryLen; ++i)
1634 : {
1635 0 : if (bComment2)
1636 : {
1637 0 : aBuf.append( &pCopy[i], 1);
1638 0 : if ((i+1) < nQueryLen)
1639 : {
1640 0 : if (pCopy[i]=='*' && pCopy[i+1]=='/')
1641 : {
1642 0 : bComment2 = false;
1643 0 : aBuf.append( &pCopy[++i], 1);
1644 0 : aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), false));
1645 : }
1646 : }
1647 : else
1648 : {
1649 : // comment can't close anymore, actually an error, but..
1650 0 : aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), false));
1651 : }
1652 0 : continue;
1653 : }
1654 0 : if (pCopy[i] == '\n' || i == nQueryLen-1)
1655 : {
1656 0 : if (bComment)
1657 : {
1658 0 : if (i == nQueryLen-1 && pCopy[i] != '\n')
1659 0 : aBuf.append( &pCopy[i], 1);
1660 0 : aRet.push_back( CommentStrip( aBuf.makeStringAndClear(), true));
1661 0 : bComment = false;
1662 : }
1663 0 : else if (!aRet.empty())
1664 0 : aRet.back().mbLastOnLine = true;
1665 : }
1666 0 : else if (!bComment)
1667 : {
1668 0 : if (pCopy[i] == '\"' && !bIsText2)
1669 0 : bIsText1 = !bIsText1;
1670 0 : else if (pCopy[i] == '\'' && !bIsText1)
1671 0 : bIsText2 = !bIsText2;
1672 0 : if (!bIsText1 && !bIsText2 && (i+1) < nQueryLen)
1673 : {
1674 0 : if ((pCopy[i]=='-' && pCopy[i+1]=='-') || (pCopy[i]=='/' && pCopy[i+1]=='/'))
1675 0 : bComment = true;
1676 0 : else if ((pCopy[i]=='/' && pCopy[i+1]=='*'))
1677 0 : bComment2 = true;
1678 : }
1679 : }
1680 0 : if (bComment || bComment2)
1681 0 : aBuf.append( &pCopy[i], 1);
1682 : }
1683 0 : return aRet;
1684 : }
1685 :
1686 : /** Concat/insert comments that were previously obtained with getComment().
1687 :
1688 : NOTE: The current parser implementation does not preserve newlines, so all
1689 : comments are always appended to the entire query, also inline comments
1690 : that would need positioning anyway that can't be obtained after
1691 : recomposition. This is ugly but at least allows commented queries while
1692 : preserving the comments _somehow_.
1693 : */
1694 0 : static OUString concatComment( const OUString& rQuery, const ::std::vector< CommentStrip >& rComments )
1695 : {
1696 : // No comments => return query.
1697 0 : if (rComments.empty())
1698 0 : return rQuery;
1699 :
1700 0 : const sal_Unicode* pBeg = rQuery.getStr();
1701 0 : const sal_Int32 nLen = rQuery.getLength();
1702 0 : const size_t nComments = rComments.size();
1703 : // Obtaining the needed size once should be faster than reallocating.
1704 : // Also add a blank or linefeed for each comment.
1705 0 : sal_Int32 nBufSize = nLen + nComments;
1706 0 : for (::std::vector< CommentStrip >::const_iterator it( rComments.begin()); it != rComments.end(); ++it)
1707 0 : nBufSize += (*it).maComment.getLength();
1708 0 : OUStringBuffer aBuf( nBufSize );
1709 0 : sal_Int32 nIndBeg = 0;
1710 0 : sal_Int32 nIndLF = rQuery.indexOf('\n');
1711 0 : size_t i = 0;
1712 0 : while (nIndLF >= 0 && i < nComments)
1713 : {
1714 0 : aBuf.append( pBeg + nIndBeg, nIndLF - nIndBeg);
1715 0 : do
1716 : {
1717 0 : aBuf.append( rComments[i].maComment);
1718 0 : } while (!rComments[i++].mbLastOnLine && i < nComments);
1719 0 : aBuf.append( pBeg + nIndLF, 1); // the LF
1720 0 : nIndBeg = nIndLF + 1;
1721 0 : nIndLF = (nIndBeg < nLen ? rQuery.indexOf( '\n', nIndBeg) : -1);
1722 : }
1723 : // Append remainder of query.
1724 0 : if (nIndBeg < nLen)
1725 0 : aBuf.append( pBeg + nIndBeg, nLen - nIndBeg);
1726 : // Append all remaining comments, preserve lines.
1727 0 : bool bNewLine = false;
1728 0 : for ( ; i < nComments; ++i)
1729 : {
1730 0 : if (!bNewLine)
1731 0 : aBuf.append( ' ');
1732 0 : aBuf.append( rComments[i].maComment);
1733 0 : if (rComments[i].mbLastOnLine)
1734 : {
1735 0 : aBuf.append( '\n');
1736 0 : bNewLine = true;
1737 : }
1738 : else
1739 0 : bNewLine = false;
1740 : }
1741 0 : return aBuf.makeStringAndClear();
1742 : }
1743 :
1744 0 : OUString OQueryController::translateStatement( bool _bFireStatementChange )
1745 : {
1746 : // now set the properties
1747 0 : setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange );
1748 0 : OUString sTranslatedStmt;
1749 0 : if(!m_sStatement.isEmpty() && m_xComposer.is() && m_bEscapeProcessing)
1750 : {
1751 : try
1752 : {
1753 0 : OUString aErrorMsg;
1754 :
1755 0 : ::std::vector< CommentStrip > aComments = getComment( m_sStatement);
1756 :
1757 0 : ::connectivity::OSQLParseNode* pNode = m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign );
1758 0 : if(pNode)
1759 : {
1760 0 : pNode->parseNodeToStr( sTranslatedStmt, getConnection() );
1761 0 : delete pNode;
1762 : }
1763 :
1764 0 : m_xComposer->setQuery(sTranslatedStmt);
1765 0 : sTranslatedStmt = m_xComposer->getComposedQuery();
1766 0 : sTranslatedStmt = concatComment( sTranslatedStmt, aComments);
1767 : }
1768 0 : catch(const SQLException& e)
1769 : {
1770 0 : ::dbtools::SQLExceptionInfo aInfo(e);
1771 0 : showError(aInfo);
1772 : // an error occurred so we clear the statement
1773 0 : sTranslatedStmt = OUString();
1774 : }
1775 : }
1776 0 : else if(m_sStatement.isEmpty())
1777 : {
1778 0 : ModuleRes aModuleRes(STR_QRY_NOSELECT);
1779 0 : OUString sTmpStr(aModuleRes);
1780 0 : OUString sError(sTmpStr);
1781 0 : showError(SQLException(sError,NULL,"S1000",1000,Any()));
1782 : }
1783 : else
1784 0 : sTranslatedStmt = m_sStatement;
1785 :
1786 0 : return sTranslatedStmt;
1787 : }
1788 :
1789 0 : short OQueryController::saveModified()
1790 : {
1791 0 : SolarMutexGuard aSolarGuard;
1792 0 : ::osl::MutexGuard aGuard( getMutex() );
1793 0 : short nRet = RET_YES;
1794 0 : if ( !isConnected() || !isModified() )
1795 0 : return nRet;
1796 :
1797 0 : if ( !m_bGraphicalDesign
1798 0 : || ( !m_vTableFieldDesc.empty()
1799 0 : && !m_vTableData.empty()
1800 : )
1801 : )
1802 : {
1803 0 : OUString sMessageText( lcl_getObjectResourceString( STR_QUERY_SAVEMODIFIED, m_nCommandType ) );
1804 0 : QueryBox aQry( getView(), WB_YES_NO_CANCEL | WB_DEF_YES, sMessageText );
1805 :
1806 0 : nRet = aQry.Execute();
1807 0 : if ( ( nRet == RET_YES )
1808 0 : && !doSaveAsDoc( sal_False )
1809 : )
1810 : {
1811 0 : nRet = RET_CANCEL;
1812 0 : }
1813 : }
1814 0 : return nRet;
1815 : }
1816 :
1817 0 : void OQueryController::impl_reset( const bool i_bForceCurrentControllerSettings )
1818 : {
1819 0 : bool bValid = false;
1820 :
1821 0 : Sequence< PropertyValue > aLayoutInformation;
1822 : // get command from the query if a query name was supplied
1823 0 : if ( !i_bForceCurrentControllerSettings && !editingCommand() )
1824 : {
1825 0 : if ( !m_sName.isEmpty() )
1826 : {
1827 0 : Reference< XNameAccess > xQueries = getObjectContainer();
1828 0 : if ( xQueries.is() )
1829 : {
1830 0 : Reference< XPropertySet > xProp;
1831 0 : if( xQueries->hasByName( m_sName ) && ( xQueries->getByName( m_sName ) >>= xProp ) && xProp.is() )
1832 : {
1833 0 : OUString sNewStatement;
1834 0 : xProp->getPropertyValue( PROPERTY_COMMAND ) >>= sNewStatement;
1835 0 : setStatement_fireEvent( sNewStatement );
1836 :
1837 0 : sal_Bool bNewEscapeProcessing( sal_True );
1838 0 : if ( editingQuery() )
1839 : {
1840 0 : xProp->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bNewEscapeProcessing;
1841 0 : setEscapeProcessing_fireEvent( bNewEscapeProcessing );
1842 : }
1843 :
1844 0 : m_bGraphicalDesign = m_bGraphicalDesign && m_bEscapeProcessing;
1845 0 : bValid = true;
1846 :
1847 : try
1848 : {
1849 0 : if ( editingQuery() )
1850 0 : xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation;
1851 : }
1852 0 : catch( const Exception& )
1853 : {
1854 : OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" );
1855 0 : }
1856 0 : }
1857 0 : }
1858 : }
1859 : }
1860 : else
1861 : {
1862 0 : bValid = true;
1863 : // assume that we got all necessary information during initialization
1864 : }
1865 :
1866 0 : if ( bValid )
1867 : {
1868 : // load the layoutInformation
1869 0 : if ( aLayoutInformation.getLength() )
1870 : {
1871 : try
1872 : {
1873 0 : loadViewSettings( aLayoutInformation );
1874 : }
1875 0 : catch( const Exception& )
1876 : {
1877 : DBG_UNHANDLED_EXCEPTION();
1878 : }
1879 : }
1880 :
1881 0 : if ( !m_sStatement.isEmpty() )
1882 : {
1883 0 : setQueryComposer();
1884 :
1885 0 : bool bError( false );
1886 :
1887 0 : if ( !m_pSqlIterator )
1888 : {
1889 0 : bError = true;
1890 : }
1891 0 : else if ( m_bEscapeProcessing )
1892 : {
1893 0 : OUString aErrorMsg;
1894 : ::std::auto_ptr< ::connectivity::OSQLParseNode > pNode(
1895 0 : m_aSqlParser.parseTree( aErrorMsg, m_sStatement, m_bGraphicalDesign ) );
1896 :
1897 0 : if ( pNode.get() )
1898 : {
1899 0 : delete m_pSqlIterator->getParseTree();
1900 0 : m_pSqlIterator->setParseTree( pNode.release() );
1901 0 : m_pSqlIterator->traverseAll();
1902 0 : if ( m_pSqlIterator->hasErrors() )
1903 : {
1904 0 : if ( !i_bForceCurrentControllerSettings && m_bGraphicalDesign && !editingView() )
1905 : {
1906 0 : impl_showAutoSQLViewError( makeAny( m_pSqlIterator->getErrors() ) );
1907 : }
1908 0 : bError = true;
1909 : }
1910 : }
1911 : else
1912 : {
1913 0 : if ( !i_bForceCurrentControllerSettings && !editingView() )
1914 : {
1915 0 : OUString aTitle(ModuleRes(STR_SVT_SQL_SYNTAX_ERROR));
1916 0 : OSQLMessageBox aDlg(getView(),aTitle,aErrorMsg);
1917 0 : aDlg.Execute();
1918 : }
1919 0 : bError = true;
1920 0 : }
1921 : }
1922 :
1923 0 : if ( bError )
1924 : {
1925 0 : m_bGraphicalDesign = sal_False;
1926 0 : if ( editingView() )
1927 : // if we're editing a view whose statement could not be parsed, default to "no escape processing"
1928 0 : setEscapeProcessing_fireEvent( sal_False );
1929 : }
1930 : }
1931 : }
1932 :
1933 0 : if(!m_pSqlIterator)
1934 0 : setQueryComposer();
1935 : OSL_ENSURE(m_pSqlIterator,"No SQLIterator set!");
1936 :
1937 0 : getContainer()->setNoneVisbleRow(m_nVisibleRows);
1938 0 : }
1939 :
1940 0 : void OQueryController::reset()
1941 : {
1942 0 : impl_reset();
1943 0 : getContainer()->reset( NULL );
1944 0 : ClearUndoManager();
1945 0 : }
1946 :
1947 0 : void OQueryController::setStatement_fireEvent( const OUString& _rNewStatement, bool _bFireStatementChange )
1948 : {
1949 0 : Any aOldValue = makeAny( m_sStatement );
1950 0 : m_sStatement = _rNewStatement;
1951 0 : Any aNewValue = makeAny( m_sStatement );
1952 :
1953 0 : sal_Int32 nHandle = PROPERTY_ID_ACTIVECOMMAND;
1954 0 : if ( _bFireStatementChange )
1955 0 : fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False );
1956 0 : }
1957 :
1958 0 : void OQueryController::setEscapeProcessing_fireEvent( const sal_Bool _bEscapeProcessing )
1959 : {
1960 0 : if ( _bEscapeProcessing == m_bEscapeProcessing )
1961 0 : return;
1962 :
1963 0 : Any aOldValue = makeAny( m_bEscapeProcessing );
1964 0 : m_bEscapeProcessing = _bEscapeProcessing;
1965 0 : Any aNewValue = makeAny( m_bEscapeProcessing );
1966 :
1967 0 : sal_Int32 nHandle = PROPERTY_ID_ESCAPE_PROCESSING;
1968 0 : fire( &nHandle, &aNewValue, &aOldValue, 1, sal_False );
1969 : }
1970 :
1971 0 : IMPL_LINK( OQueryController, OnExecuteAddTable, void*, /*pNotInterestedIn*/ )
1972 : {
1973 0 : Execute( ID_BROWSER_ADDTABLE,Sequence<PropertyValue>() );
1974 0 : return 0L;
1975 : }
1976 :
1977 0 : bool OQueryController::allowViews() const
1978 : {
1979 0 : return true;
1980 : }
1981 :
1982 0 : bool OQueryController::allowQueries() const
1983 : {
1984 : OSL_ENSURE( getSdbMetaData().isConnected(), "OQueryController::allowQueries: illegal call!" );
1985 0 : if ( !getSdbMetaData().supportsSubqueriesInFrom() )
1986 0 : return false;
1987 :
1988 0 : const NamedValueCollection& rArguments( getInitParams() );
1989 0 : sal_Int32 nCommandType = rArguments.getOrDefault( (OUString)PROPERTY_COMMAND_TYPE, (sal_Int32)CommandType::QUERY );
1990 0 : sal_Bool bCreatingView = ( nCommandType == CommandType::TABLE );
1991 0 : return !bCreatingView;
1992 : }
1993 :
1994 0 : Any SAL_CALL OQueryController::getViewData() throw( RuntimeException, std::exception )
1995 : {
1996 0 : ::osl::MutexGuard aGuard( getMutex() );
1997 :
1998 0 : getContainer()->SaveUIConfig();
1999 :
2000 0 : ::comphelper::NamedValueCollection aViewSettings;
2001 0 : saveViewSettings( aViewSettings, false );
2002 :
2003 0 : return makeAny( aViewSettings.getPropertyValues() );
2004 : }
2005 :
2006 0 : void SAL_CALL OQueryController::restoreViewData(const Any& /*Data*/) throw( RuntimeException, std::exception )
2007 : {
2008 : // TODO
2009 0 : }
2010 :
2011 : } // namespace dbaui
2012 :
2013 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|