/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
SQLExceptionInfo aError; bool bSuccess = getContainer()->switchView( &aError ); if ( !bSuccess )
{
m_bGraphicalDesign = !m_bGraphicalDesign; // restore old state
getContainer()->switchView( nullptr ); // don't pass &aError here, this would overwrite the error which the first switchView call // returned in this location. if ( _pErrorInfo )
*_pErrorInfo = std::move(aError); else
showError( aError );
} else
{
ensureToolbars( *this, m_bGraphicalDesign );
}
// legacy parameters first (later overwritten by regular parameters)
OUString sIndependentSQLCommand; if ( rArguments.get_ensureType( u"IndependentSQLCommand"_ustr, sIndependentSQLCommand ) )
{
OSL_FAIL( "OQueryController::impl_initialize: IndependentSQLCommand is regognized for compatibility only!" );
sCommand = sIndependentSQLCommand;
m_nCommandType = CommandType::COMMAND;
}
OUString sCurrentQuery; if ( rArguments.get_ensureType( u"CurrentQuery"_ustr, sCurrentQuery ) )
{
OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
sCommand = sCurrentQuery;
m_nCommandType = CommandType::QUERY;
}
bool bCreateView( false ); if ( rArguments.get_ensureType( u"CreateView"_ustr, bCreateView ) && bCreateView )
{
OSL_FAIL( "OQueryController::impl_initialize: CurrentQuery is regognized for compatibility only!" );
m_nCommandType = CommandType::TABLE;
}
// non-legacy parameters which overwrite the legacy parameters
rArguments.get_ensureType( PROPERTY_COMMAND, sCommand );
rArguments.get_ensureType( PROPERTY_COMMAND_TYPE, m_nCommandType );
// translate Command/Type into proper members // TODO/Later: all this (including those members) should be hidden behind some abstract interface, // which is implemented for all the three commands switch ( m_nCommandType )
{ case CommandType::QUERY: case CommandType::TABLE:
m_sName = sCommand; break; case CommandType::COMMAND:
setStatement_fireEvent( sCommand );
m_sName.clear(); break; default:
OSL_FAIL( "OQueryController::impl_initialize: logic error in code!" ); throw RuntimeException();
}
// more legacy parameters bool bGraphicalDesign( true ); if ( rArguments.get_ensureType( PROPERTY_QUERYDESIGNVIEW, bGraphicalDesign ) )
{
OSL_FAIL( "OQueryController::impl_initialize: QueryDesignView is regognized for compatibility only!" );
m_bGraphicalDesign = bGraphicalDesign;
}
// more non-legacy
rArguments.get_ensureType( PROPERTY_GRAPHICAL_DESIGN, m_bGraphicalDesign );
if ( !ensureConnected() )
{ // we have no connection so what else should we do
m_bGraphicalDesign = false; if ( editingView() )
{
connectionLostMessage(); throw SQLException();
}
}
// check the view capabilities if ( isConnected() && editingView() )
{
Reference< XViewsSupplier > xViewsSup( getConnection(), UNO_QUERY );
Reference< XNameAccess > xViews; if ( xViewsSup.is() )
xViews = xViewsSup->getViews();
if ( !xViews.is() )
{ // we can't create views so we ask if the user wants to create a query instead
m_nCommandType = CommandType::QUERY; bool bClose = false;
{
OUString aTitle(DBA_RES(STR_QUERYDESIGN_NO_VIEW_SUPPORT));
OUString aMessage(DBA_RES(STR_QUERYDESIGN_NO_VIEW_ASK));
OSQLMessageBox aDlg(getFrameWeld(), aTitle, aMessage, MessBoxStyle::YesNo | MessBoxStyle::DefaultYes, MessageType::Query);
bClose = aDlg.run() == RET_NO;
} if ( bClose ) throw VetoException();
}
// now if we are to edit an existing view, check whether this is possible if ( !m_sName.isEmpty() )
{
Any aView( xViews->getByName( m_sName ) ); // will throw if there is no such view if ( !( aView >>= m_xAlterView ) )
{ throw IllegalArgumentException(
DBA_RES(STR_NO_ALTER_VIEW_SUPPORT),
*this,
1
);
}
}
}
OSL_ENSURE(getDataSource().is(),"OQueryController::impl_initialize: need a datasource!");
if ( aError.isValid() && bAttemptedGraphicalDesign && !m_bGraphicalDesign )
{ // we tried initializing the graphical view, this failed, and we were automatically switched to SQL // view => tell this to the user if ( !editingView() )
{
impl_showAutoSQLViewError( aError.get() );
}
}
setModified(false);
} catch(const SQLException& e)
{
DBG_UNHANDLED_EXCEPTION("dbaccess"); // we caught an exception so we switch to text only mode
{
m_bGraphicalDesign = false;
getContainer()->initialize();
OSQLMessageBox aBox(getFrameWeld(), e);
aBox.run();
} throw;
}
}
OSL_ENSURE( xElements.is(), "OQueryController::getObjectContainer: unable to obtain the container!" ); return xElements;
}
void OQueryController::executeQuery()
{ // we don't need to check the connection here because we already check the composer // which can't live without his connection
OUString sTranslatedStmt = translateStatement( false );
xDisp->dispatch(aWantToDispatch, aProps); // check the state of the beamer // be notified when the beamer frame is closed
Reference< XComponent > xComponent = getFrame()->findFrame( sFrameName, nSearchFlags ); if (xComponent.is())
{
OSL_ENSURE(Reference< XFrame >(xComponent, UNO_QUERY).get() == getContainer()->getPreviewFrame().get(), "OQueryController::executeQuery: oops ... which window do I have here?");
Reference< XEventListener> xEvtL(static_cast<cppu::OWeakObject*>(this),UNO_QUERY);
xComponent->addEventListener(xEvtL);
}
} else
{
OSL_FAIL("Couldn't create a beamer window!");
}
} catch(const Exception&)
{
OSL_FAIL("Couldn't create a beamer window!");
}
}
bool OQueryController::askForNewName(const Reference<XNameAccess>& _xElements, bool _bSaveAs)
{
OSL_ENSURE( !editingCommand(), "OQueryController::askForNewName: not to be called when designing an independent statement!" ); if ( editingCommand() ) returnfalse;
if ( !getContainer()->checkStatement() ) returnfalse;
OUString sTranslatedStmt = translateStatement(); if ( editingCommand() )
{
setModified( false ); // this is all we need to do here. translateStatement implicitly set our m_sStatement, and // notified it, and that's all returntrue;
}
if ( sTranslatedStmt.isEmpty() ) returnfalse;
// first we need a name for our query so ask the user // did we get a name
OUString sOriginalName( m_sName ); if ( !askForNewName( xElements, _bSaveAs ) || m_sName.isEmpty() ) returnfalse;
Reference<XPropertySet> xQuery; if ( bNew ) // just to make sure the query already exists
{ // drop the query, in case it already exists if ( xElements->hasByName( m_sName ) )
{
Reference< XDrop > xNameCont( xElements, UNO_QUERY ); if ( xNameCont.is() )
xNameCont->dropByName( m_sName ); else
{
Reference< XNameContainer > xCont( xElements, UNO_QUERY ); if ( xCont.is() )
xCont->removeByName( m_sName );
}
}
// create a new (empty, uninitialized) query resp. view
Reference< XDataDescriptorFactory > xFact( xElements, UNO_QUERY ); if ( xFact.is() )
{
xQuery = xFact->createDataDescriptor(); // to set the name is only allowed when the query is new
xQuery->setPropertyValue( PROPERTY_NAME, Any( m_sName ) );
} else
{
Reference< XSingleServiceFactory > xSingleFac( xElements, UNO_QUERY ); if ( xSingleFac.is() )
xQuery.set(xSingleFac->createInstance(), css::uno::UNO_QUERY);
}
} else
{
xElements->getByName( m_sName ) >>= xQuery;
} if ( !xQuery.is() ) throw RuntimeException();
// the new commands if ( editingView() && !bNew )
{
OSL_ENSURE( xQuery == m_xAlterView, "OQueryController::doSaveAsDoc: already have another alterable view ...!?" );
m_xAlterView.set( xQuery, UNO_QUERY_THROW );
m_xAlterView->alterCommand( sTranslatedStmt );
} else
{ // we're creating a query, or a *new* view
xQuery->setPropertyValue( PROPERTY_COMMAND, Any( sTranslatedStmt ) );
if ( !xViewProps.is() ) // correct name and try again
m_sName = ::dbtools::composeTableName( getMetaData(), xQuery, ::dbtools::EComposeRule::InDataManipulation, false );
OSL_ENSURE( xElements->hasByName( m_sName ), "OQueryController::doSaveAsDoc: newly created view does not exist!" );
// now check if our datasource has set a tablefilter and if so, append the new table name to it
::dbaui::appendToFilter(getConnection(), m_sName, getORB(), getFrameWeld());
}
Reference< XTitleChangeListener> xEventListener(impl_getTitleHelper_throw(),UNO_QUERY); if ( xEventListener.is() )
{
TitleChangedEvent aEvent;
xEventListener->titleChanged(aEvent);
}
releaseNumberForComponent();
}
See also delComment() implementation for OSQLParser::parseTree().
*/ static std::vector< CommentStrip > getComment( const OUString& rQuery )
{
std::vector< CommentStrip > aRet; // First a quick search if there is any "--" or "//" or "/*", if not then // the whole copying loop is pointless. if (rQuery.indexOf( "--" ) < 0 && rQuery.indexOf( "//" ) < 0 &&
rQuery.indexOf( "/*" ) < 0) return aRet;
/** Concat/insert comments that were previously obtained with getComment().
NOTE: The current parser implementation does not preserve newlines, so all comments are always appended to the entire query, also inline comments that would need positioning anyway that can't be obtained after recomposition. This is ugly but at least allows commented queries while preserving the comments _somehow_.
*/ static OUString concatComment( const OUString& rQuery, const std::vector< CommentStrip >& rComments )
{ // No comments => return query. if (rComments.empty()) return rQuery;
const sal_Unicode* pBeg = rQuery.getStr(); const sal_Int32 nLen = rQuery.getLength(); const size_t nComments = rComments.size(); // Obtaining the needed size once should be faster than reallocating. // Also add a blank or linefeed for each comment.
sal_Int32 nBufSize = nLen + nComments; for (autoconst& comment : rComments)
nBufSize += comment.maComment.getLength();
OUStringBuffer aBuf( nBufSize );
sal_Int32 nIndBeg = 0;
sal_Int32 nIndLF = rQuery.indexOf('\n');
size_t i = 0; while (nIndLF >= 0 && i < nComments)
{
aBuf.append( pBeg + nIndBeg, nIndLF - nIndBeg); do
{
aBuf.append( rComments[i].maComment);
} while (!rComments[i++].mbLastOnLine && i < nComments);
aBuf.append( pBeg + nIndLF, 1); // the LF
nIndBeg = nIndLF + 1;
nIndLF = (nIndBeg < nLen ? rQuery.indexOf( '\n', nIndBeg) : -1);
} // Append remainder of query. if (nIndBeg < nLen)
aBuf.append( pBeg + nIndBeg, nLen - nIndBeg); // Append all remaining comments, preserve lines. bool bNewLine = false; for ( ; i < nComments; ++i)
{ if (!bNewLine)
aBuf.append( ' ');
aBuf.append( rComments[i].maComment); if (rComments[i].mbLastOnLine)
{
aBuf.append( '\n');
bNewLine = true;
} else
bNewLine = false;
} return aBuf.makeStringAndClear();
}
OUString OQueryController::translateStatement( bool _bFireStatementChange )
{ // now set the properties
setStatement_fireEvent( getContainer()->getStatement(), _bFireStatementChange );
OUString sTranslatedStmt; if(!m_sStatement.isEmpty() && m_xComposer.is() && m_bEscapeProcessing)
{ try
{
OUString aErrorMsg;
try
{ if ( editingQuery() )
xProp->getPropertyValue( PROPERTY_LAYOUTINFORMATION ) >>= aLayoutInformation;
} catch( const Exception& )
{
OSL_FAIL( "OQueryController::impl_reset: could not retrieve the layout information from the query!" );
}
}
}
}
} else
{
bValid = true; // assume that we got all necessary information during initialization
}
if ( bValid )
{ // load the layoutInformation if ( aLayoutInformation.hasElements() )
{ try
{
loadViewSettings( aLayoutInformation );
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("dbaccess");
}
}
if ( !m_sStatement.isEmpty() )
{
setQueryComposer();
if ( bError )
{
m_bGraphicalDesign = false; if ( editingView() ) // if we're editing a view whose statement could not be parsed, default to "no escape processing"
setEscapeProcessing_fireEvent( false );
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.