In the evolution address book where we have real column names of e.g. first_name, second_name and city. On parsing via OSQLParseTreeIterator::appendColumns that creates some labels using those real names but the evo XResultSet gives them proper labels of First Name, Second Name and City the munge means that here we have e.g. just "City" as a label because it matches, while the others don't The symptoms are to load the evolocal.odb and of the 128 columns column 5 is repeated until 128 This is all a horrible confusing mess. It seems safest to catch the mismatch of column counts and throw away the partial list and force a generate of a full list. Change-Id: I1d6e2a282bdd43acac63c366eb2a9d029aa17878
1829 lines
78 KiB
C++
1829 lines
78 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "composertools.hxx"
|
|
#include "core_resource.hrc"
|
|
#include "core_resource.hxx"
|
|
#include "dbastrings.hrc"
|
|
#include "HelperCollections.hxx"
|
|
#include "SingleSelectQueryComposer.hxx"
|
|
#include "sdbcoretools.hxx"
|
|
|
|
#include <com/sun/star/beans/PropertyAttribute.hpp>
|
|
#include <com/sun/star/container/XChild.hpp>
|
|
#include <com/sun/star/i18n/LocaleData.hpp>
|
|
#include <com/sun/star/lang/DisposedException.hpp>
|
|
#include <com/sun/star/script/Converter.hpp>
|
|
#include <com/sun/star/sdb/BooleanComparisonMode.hpp>
|
|
#include <com/sun/star/sdb/SQLFilterOperator.hpp>
|
|
#include <com/sun/star/sdb/XQueriesSupplier.hpp>
|
|
#include <com/sun/star/sdb/CommandType.hpp>
|
|
#include <com/sun/star/sdbc/ColumnSearch.hpp>
|
|
#include <com/sun/star/sdbc/DataType.hpp>
|
|
#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
|
|
#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
|
|
#include <com/sun/star/sdbc/XParameters.hpp>
|
|
#include <com/sun/star/uno/XAggregation.hpp>
|
|
#include <com/sun/star/util/NumberFormatter.hpp>
|
|
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/sequence.hxx>
|
|
#include <comphelper/types.hxx>
|
|
#include <cppuhelper/typeprovider.hxx>
|
|
#include <connectivity/predicateinput.hxx>
|
|
#include <rtl/logfile.hxx>
|
|
#include <unotools/syslocale.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <tools/diagnose_ex.h>
|
|
#include <osl/diagnose.h>
|
|
#include <unotools/configmgr.hxx>
|
|
#include <unotools/sharedunocomponent.hxx>
|
|
|
|
#include <memory>
|
|
|
|
using namespace ::dbaccess;
|
|
using namespace ::dbtools;
|
|
using namespace ::comphelper;
|
|
using namespace ::connectivity;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::sdbc;
|
|
using namespace ::com::sun::star::sdb;
|
|
using namespace ::com::sun::star::sdbcx;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::i18n;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::script;
|
|
using namespace ::com::sun::star::util;
|
|
using namespace ::cppu;
|
|
using namespace ::osl;
|
|
using namespace ::utl;
|
|
|
|
namespace dbaccess {
|
|
namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
|
|
}
|
|
|
|
#define STR_SELECT "SELECT "
|
|
#define STR_FROM " FROM "
|
|
#define STR_WHERE " WHERE "
|
|
#define STR_GROUP_BY " GROUP BY "
|
|
#define STR_HAVING " HAVING "
|
|
#define STR_ORDER_BY " ORDER BY "
|
|
#define STR_AND " AND "
|
|
#define STR_OR " OR "
|
|
#define STR_LIKE OUString(" LIKE ")
|
|
#define L_BRACKET "("
|
|
#define R_BRACKET ")"
|
|
#define COMMA ","
|
|
|
|
namespace
|
|
{
|
|
/** parses the given statement, using the given parser, returns a parse node representing
|
|
the statement
|
|
|
|
If the statement cannot be parsed, an error is thrown.
|
|
*/
|
|
const OSQLParseNode* parseStatement_throwError( OSQLParser& _rParser, const OUString& _rStatement, const Reference< XInterface >& _rxContext )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseStatement_throwError" );
|
|
OUString aErrorMsg;
|
|
const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement );
|
|
if ( !pNewSqlParseNode )
|
|
{
|
|
OUString sSQLStateGeneralError( getStandardSQLState( SQL_GENERAL_ERROR ) );
|
|
SQLException aError2( aErrorMsg, _rxContext, sSQLStateGeneralError, 1000, Any() );
|
|
SQLException aError1( _rStatement, _rxContext, sSQLStateGeneralError, 1000, makeAny( aError2 ) );
|
|
throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,sSQLStateGeneralError,1000,makeAny(aError1));
|
|
}
|
|
return pNewSqlParseNode;
|
|
}
|
|
|
|
// .....................................................................
|
|
/** checks whether the given parse node describes a valid single select statement, throws
|
|
an error if not
|
|
*/
|
|
void checkForSingleSelect_throwError( const OSQLParseNode* pStatementNode, OSQLParseTreeIterator& _rIterator,
|
|
const Reference< XInterface >& _rxContext, const OUString& _rOriginatingCommand )
|
|
{
|
|
const OSQLParseNode* pOldNode = _rIterator.getParseTree();
|
|
|
|
// determine the statement type
|
|
_rIterator.setParseTree( pStatementNode );
|
|
_rIterator.traverseAll();
|
|
bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT );
|
|
|
|
// throw the error, if necessary
|
|
if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ
|
|
{
|
|
// restore the old node before throwing the exception
|
|
_rIterator.setParseTree( pOldNode );
|
|
// and now really ...
|
|
SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() );
|
|
throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext,
|
|
getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) );
|
|
}
|
|
|
|
delete pOldNode;
|
|
}
|
|
|
|
// .....................................................................
|
|
/** combines parseStatement_throwError and checkForSingleSelect_throwError
|
|
*/
|
|
void parseAndCheck_throwError( OSQLParser& _rParser, const OUString& _rStatement,
|
|
OSQLParseTreeIterator& _rIterator, const Reference< XInterface >& _rxContext )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "SingleSelectQueryComposer.cxx::parseAndCheck_throwError" );
|
|
const OSQLParseNode* pNode = parseStatement_throwError( _rParser, _rStatement, _rxContext );
|
|
checkForSingleSelect_throwError( pNode, _rIterator, _rxContext, _rStatement );
|
|
}
|
|
|
|
// .....................................................................
|
|
/** transforms a parse node describing a complete statement into a pure select
|
|
statement, without any filter/order/groupby/having clauses
|
|
*/
|
|
OUString getPureSelectStatement( const OSQLParseNode* _pRootNode, Reference< XConnection > _rxConnection )
|
|
{
|
|
OUString sSQL = STR_SELECT;
|
|
_pRootNode->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
|
|
_pRootNode->getChild(2)->parseNodeToStr( sSQL, _rxConnection );
|
|
sSQL += STR_FROM;
|
|
_pRootNode->getChild(3)->getChild(0)->getChild(1)->parseNodeToStr( sSQL, _rxConnection );
|
|
return sSQL;
|
|
}
|
|
|
|
/** resets an SQL iterator, including deletion of the parse tree, and disposal if desired
|
|
*/
|
|
void resetIterator( OSQLParseTreeIterator& _rIterator, bool _bDispose )
|
|
{
|
|
const OSQLParseNode* pSqlParseNode = _rIterator.getParseTree();
|
|
_rIterator.setParseTree(NULL);
|
|
delete pSqlParseNode;
|
|
if ( _bDispose )
|
|
_rIterator.dispose();
|
|
}
|
|
void lcl_addFilterCriteria_throw(sal_Int32 i_nFilterOperator,const OUString& i_sValue,OUStringBuffer& o_sRet)
|
|
{
|
|
switch( i_nFilterOperator )
|
|
{
|
|
case SQLFilterOperator::EQUAL:
|
|
o_sRet.append(" = " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::NOT_EQUAL:
|
|
o_sRet.append(" <> " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::LESS:
|
|
o_sRet.append(" < " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::GREATER:
|
|
o_sRet.append(" > " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::LESS_EQUAL:
|
|
o_sRet.append(" <= " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::GREATER_EQUAL:
|
|
o_sRet.append(" >= " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::LIKE:
|
|
o_sRet.append(" LIKE " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::NOT_LIKE:
|
|
o_sRet.append(" NOT LIKE " + i_sValue);
|
|
break;
|
|
case SQLFilterOperator::SQLNULL:
|
|
o_sRet.append(" IS NULL");
|
|
break;
|
|
case SQLFilterOperator::NOT_SQLNULL:
|
|
o_sRet.append(" IS NOT NULL");
|
|
break;
|
|
default:
|
|
throw SQLException();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
DBG_NAME(OSingleSelectQueryComposer)
|
|
|
|
OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables,
|
|
const Reference< XConnection>& _xConnection,
|
|
const ::comphelper::ComponentContext& _rContext )
|
|
:OSubComponent(m_aMutex,_xConnection)
|
|
,OPropertyContainer(m_aBHelper)
|
|
,m_aSqlParser( _rContext.getUNOContext() )
|
|
,m_aSqlIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
|
|
,m_aAdditiveIterator( _xConnection, _rxTables, m_aSqlParser, NULL )
|
|
,m_aElementaryParts( (size_t)SQLPartCount )
|
|
,m_xConnection(_xConnection)
|
|
,m_xMetaData(_xConnection->getMetaData())
|
|
,m_xConnectionTables( _rxTables )
|
|
,m_aContext( _rContext )
|
|
,m_pTables(NULL)
|
|
,m_nBoolCompareMode( BooleanComparisonMode::EQUAL_INTEGER )
|
|
,m_nCommandType(CommandType::COMMAND)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::OSingleSelectQueryComposer" );
|
|
DBG_CTOR(OSingleSelectQueryComposer,NULL);
|
|
|
|
if ( !m_aContext.is() || !m_xConnection.is() || !m_xConnectionTables.is() )
|
|
throw IllegalArgumentException();
|
|
|
|
registerProperty(PROPERTY_ORIGINAL,PROPERTY_ID_ORIGINAL,PropertyAttribute::BOUND|PropertyAttribute::READONLY,&m_sOrignal,::getCppuType(&m_sOrignal));
|
|
|
|
m_aCurrentColumns.resize(4);
|
|
|
|
m_aLocale = SvtSysLocale().GetLanguageTag().getLocale();
|
|
m_xNumberFormatsSupplier = dbtools::getNumberFormats( m_xConnection, sal_True, m_aContext.getUNOContext() );
|
|
Reference< XLocaleData4 > xLocaleData( LocaleData::create(m_aContext.getUNOContext()) );
|
|
LocaleDataItem aData = xLocaleData->getLocaleItem(m_aLocale);
|
|
m_sDecimalSep = aData.decimalSeparator;
|
|
OSL_ENSURE(m_sDecimalSep.getLength() == 1,"OSingleSelectQueryComposer::OSingleSelectQueryComposer decimal separator is not 1 length");
|
|
try
|
|
{
|
|
Any aValue;
|
|
Reference<XInterface> xDs = dbaccess::getDataSource(_xConnection);
|
|
if ( dbtools::getDataSourceSetting(xDs,static_cast <rtl::OUString> (PROPERTY_BOOLEANCOMPARISONMODE),aValue) )
|
|
{
|
|
OSL_VERIFY( aValue >>= m_nBoolCompareMode );
|
|
}
|
|
Reference< XQueriesSupplier > xQueriesAccess(m_xConnection, UNO_QUERY);
|
|
if (xQueriesAccess.is())
|
|
m_xConnectionQueries = xQueriesAccess->getQueries();
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
}
|
|
}
|
|
|
|
OSingleSelectQueryComposer::~OSingleSelectQueryComposer()
|
|
{
|
|
DBG_DTOR(OSingleSelectQueryComposer,NULL);
|
|
::std::vector<OPrivateColumns*>::iterator aColIter = m_aColumnsCollection.begin();
|
|
::std::vector<OPrivateColumns*>::iterator aEnd = m_aColumnsCollection.end();
|
|
for(;aColIter != aEnd;++aColIter)
|
|
delete *aColIter;
|
|
|
|
::std::vector<OPrivateTables*>::iterator aTabIter = m_aTablesCollection.begin();
|
|
::std::vector<OPrivateTables*>::iterator aTabEnd = m_aTablesCollection.end();
|
|
for(;aTabIter != aTabEnd;++aTabIter)
|
|
delete *aTabIter;
|
|
}
|
|
|
|
// OComponentHelper
|
|
void SAL_CALL OSingleSelectQueryComposer::disposing(void)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::disposing" );
|
|
OSubComponent::disposing();
|
|
|
|
MutexGuard aGuard(m_aMutex);
|
|
|
|
resetIterator( m_aSqlIterator, true );
|
|
resetIterator( m_aAdditiveIterator, true );
|
|
|
|
m_xConnectionTables = NULL;
|
|
m_xConnection = NULL;
|
|
|
|
clearCurrentCollections();
|
|
}
|
|
IMPLEMENT_FORWARD_XINTERFACE3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
|
|
IMPLEMENT_SERVICE_INFO1(OSingleSelectQueryComposer,"org.openoffice.comp.dba.OSingleSelectQueryComposer",SERVICE_NAME_SINGLESELECTQUERYCOMPOSER.ascii)
|
|
IMPLEMENT_TYPEPROVIDER3(OSingleSelectQueryComposer,OSubComponent,OSingleSelectQueryComposer_BASE,OPropertyContainer)
|
|
IMPLEMENT_PROPERTYCONTAINER_DEFAULTS(OSingleSelectQueryComposer)
|
|
|
|
// com::sun::star::lang::XUnoTunnel
|
|
sal_Int64 SAL_CALL OSingleSelectQueryComposer::getSomething( const Sequence< sal_Int8 >& rId ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSomething" );
|
|
if (rId.getLength() == 16 && 0 == memcmp(getImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
|
|
return reinterpret_cast<sal_Int64>(this);
|
|
|
|
return sal_Int64(0);
|
|
}
|
|
|
|
// XSingleSelectQueryAnalyzer
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getQuery( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQuery" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
|
|
TGetParseNode F_tmp(&OSQLParseTreeIterator::getParseTree);
|
|
return getStatementPart(F_tmp,m_aSqlIterator);
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setQuery( const OUString& command ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
m_nCommandType = CommandType::COMMAND;
|
|
// first clear the tables and columns
|
|
clearCurrentCollections();
|
|
// now set the new one
|
|
setQuery_Impl(command);
|
|
m_sOrignal = command;
|
|
|
|
// reset the additive iterator to the same statement
|
|
parseAndCheck_throwError( m_aSqlParser, m_sOrignal, m_aAdditiveIterator, *this );
|
|
|
|
// we have no "elementary" parts anymore (means filter/groupby/having/order clauses)
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
m_aElementaryParts[ eLoopParts ] = OUString();
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setCommand( const OUString& Command,sal_Int32 _nCommandType ) throw(SQLException, RuntimeException)
|
|
{
|
|
OUStringBuffer sSQL;
|
|
switch(_nCommandType)
|
|
{
|
|
case CommandType::COMMAND:
|
|
setElementaryQuery(Command);
|
|
return;
|
|
case CommandType::TABLE:
|
|
if ( m_xConnectionTables->hasByName(Command) )
|
|
{
|
|
sSQL.appendAscii("SELECT * FROM ");
|
|
Reference< XPropertySet > xTable;
|
|
try
|
|
{
|
|
m_xConnectionTables->getByName( Command ) >>= xTable;
|
|
}
|
|
catch(const WrappedTargetException& e)
|
|
{
|
|
SQLException e2;
|
|
if ( e.TargetException >>= e2 )
|
|
throw e2;
|
|
}
|
|
catch(Exception&)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
}
|
|
|
|
sSQL.append(dbtools::composeTableNameForSelect(m_xConnection,xTable));
|
|
}
|
|
else
|
|
{
|
|
String sMessage( DBACORE_RESSTRING( RID_STR_TABLE_DOES_NOT_EXIST ) );
|
|
sMessage.SearchAndReplaceAscii( "$table$", Command );
|
|
throwGenericSQLException(sMessage,*this);
|
|
}
|
|
break;
|
|
case CommandType::QUERY:
|
|
if ( m_xConnectionQueries->hasByName(Command) )
|
|
{
|
|
|
|
Reference<XPropertySet> xQuery(m_xConnectionQueries->getByName(Command),UNO_QUERY);
|
|
OUString sCommand;
|
|
xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand;
|
|
sSQL.append(sCommand);
|
|
}
|
|
else
|
|
{
|
|
String sMessage( DBACORE_RESSTRING( RID_STR_QUERY_DOES_NOT_EXIST ) );
|
|
sMessage.SearchAndReplaceAscii( "$table$", Command );
|
|
throwGenericSQLException(sMessage,*this);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
m_nCommandType = _nCommandType;
|
|
m_sCommand = Command;
|
|
// first clear the tables and columns
|
|
clearCurrentCollections();
|
|
// now set the new one
|
|
OUString sCommand = sSQL.makeStringAndClear();
|
|
setElementaryQuery(sCommand);
|
|
m_sOrignal = sCommand;
|
|
}
|
|
|
|
void OSingleSelectQueryComposer::setQuery_Impl( const OUString& command )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setQuery_Impl" );
|
|
// parse this
|
|
parseAndCheck_throwError( m_aSqlParser, command, m_aSqlIterator, *this );
|
|
|
|
// strip it from all clauses, to have the pure SELECT statement
|
|
m_aPureSelectSQL = getPureSelectStatement( m_aSqlIterator.getParseTree(), m_xConnection );
|
|
|
|
// update tables
|
|
getTables();
|
|
}
|
|
|
|
Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredHavingClause( ) throw (RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredHavingClause" );
|
|
TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleHavingTree);
|
|
return getStructuredCondition(F_tmp);
|
|
}
|
|
|
|
Sequence< Sequence< PropertyValue > > SAL_CALL OSingleSelectQueryComposer::getStructuredFilter( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredFilter" );
|
|
TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
|
|
return getStructuredCondition(F_tmp);
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::appendHavingClauseByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw (SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendHavingClauseByColumn" );
|
|
::std::mem_fun1_t<bool,OSingleSelectQueryComposer,OUString> F_tmp(&OSingleSelectQueryComposer::implSetHavingClause);
|
|
setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria,sal_Int32 filterOperator ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendFilterByColumn" );
|
|
::std::mem_fun1_t<bool,OSingleSelectQueryComposer,OUString> F_tmp(&OSingleSelectQueryComposer::implSetFilter);
|
|
setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column)
|
|
{
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
getColumns();
|
|
if ( !column.is()
|
|
|| !m_aCurrentColumns[SelectColumns]
|
|
|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
|
|
)
|
|
{
|
|
String sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP));
|
|
sError.SearchAndReplaceAscii("%value", OUString(PROPERTY_NAME));
|
|
SQLException aErr(sError,*this,SQLSTATE_GENERAL,1000,Any() );
|
|
throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
|
|
}
|
|
|
|
OUString aName,aNewName;
|
|
column->getPropertyValue(PROPERTY_NAME) >>= aName;
|
|
|
|
if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName))
|
|
{
|
|
String sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
|
|
sError.SearchAndReplaceAscii("%name", aName);
|
|
throw SQLException(sError,*this,SQLSTATE_GENERAL,1000,Any() );
|
|
}
|
|
|
|
// Attach filter
|
|
// Construct SELECT without WHERE and ORDER BY
|
|
OUString aQuote = m_xMetaData->getIdentifierQuoteString();
|
|
if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) )
|
|
{
|
|
Reference<XPropertySet> xColumn;
|
|
m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName("Function"),"Property FUNCTION not available!");
|
|
|
|
OUString sRealName,sTableName;
|
|
xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
|
|
xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
|
|
sal_Bool bFunction = sal_False;
|
|
xColumn->getPropertyValue("Function") >>= bFunction;
|
|
if ( sRealName == aName )
|
|
{
|
|
if ( bFunction )
|
|
aNewName = aName;
|
|
else
|
|
{
|
|
if(sTableName.indexOf('.',0) != -1)
|
|
{
|
|
OUString aCatlog,aSchema,aTable;
|
|
::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
|
|
sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
|
|
}
|
|
else
|
|
sTableName = ::dbtools::quoteName(aQuote,sTableName);
|
|
|
|
aNewName = sTableName + "." + ::dbtools::quoteName(aQuote,sRealName);
|
|
}
|
|
}
|
|
else
|
|
aNewName = ::dbtools::quoteName(aQuote,aName);
|
|
}
|
|
else
|
|
aNewName = getTableAlias(column) + ::dbtools::quoteName(aQuote,aName);
|
|
return aNewName;
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::appendOrderByColumn( const Reference< XPropertySet >& column, sal_Bool ascending ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendOrderByColumn" );
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
OUString sColumnName( impl_getColumnName_throw(column) );
|
|
OUString sOrder = getOrder();
|
|
if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) )
|
|
sOrder += COMMA;
|
|
sOrder += sColumnName;
|
|
if ( !(ascending || sColumnName.isEmpty()) )
|
|
sOrder += " DESC ";
|
|
|
|
setOrder(sOrder);
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< XPropertySet >& column) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::appendGroupByColumn" );
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
OUString sColumnName( impl_getColumnName_throw(column) );
|
|
OrderCreator aComposer;
|
|
aComposer.append( getGroup() );
|
|
aComposer.append( sColumnName );
|
|
setGroup( aComposer.getComposedAndClear() );
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::composeStatementFromParts( const ::std::vector< OUString >& _rParts )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::composeStatementFromParts" );
|
|
OSL_ENSURE( _rParts.size() == (size_t)SQLPartCount, "OSingleSelectQueryComposer::composeStatementFromParts: invalid parts array!" );
|
|
|
|
OUStringBuffer aSql( m_aPureSelectSQL );
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
if ( !_rParts[ eLoopParts ].isEmpty() )
|
|
{
|
|
aSql.append( getKeyword( eLoopParts ) );
|
|
aSql.append( _rParts[ eLoopParts ] );
|
|
}
|
|
|
|
return aSql.makeStringAndClear();
|
|
}
|
|
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getElementaryQuery() throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getElementaryQuery" );
|
|
return composeStatementFromParts( m_aElementaryParts );
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setElementaryQuery( const OUString& _rElementary ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "frank.schoenheit@sun.com", "OSingleSelectQueryComposer::setElementaryQuery" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
|
|
// remember the 4 current "additive" clauses
|
|
::std::vector< OUString > aAdditiveClauses( SQLPartCount );
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
aAdditiveClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_False );
|
|
|
|
// clear the tables and columns
|
|
clearCurrentCollections();
|
|
// set and parse the new query
|
|
setQuery_Impl( _rElementary );
|
|
|
|
// get the 4 elementary parts of the statement
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
m_aElementaryParts[ eLoopParts ] = getSQLPart( eLoopParts, m_aSqlIterator, sal_False );
|
|
|
|
// reset the the AdditiveIterator: m_aPureSelectSQL may have changed
|
|
try
|
|
{
|
|
parseAndCheck_throwError( m_aSqlParser, composeStatementFromParts( aAdditiveClauses ), m_aAdditiveIterator, *this );
|
|
}
|
|
catch( const Exception& e )
|
|
{
|
|
(void)e;
|
|
OSL_FAIL( "OSingleSelectQueryComposer::setElementaryQuery: there should be no error anymore for the additive statement!" );
|
|
DBG_UNHANDLED_EXCEPTION();
|
|
// every part of the additive statement should have passed other tests already, and should not
|
|
// be able to cause any errors ... me thinks
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
OUString getComposedClause( const OUString _rElementaryClause, const OUString _rAdditionalClause,
|
|
TokenComposer& _rComposer, const OUString _rKeyword )
|
|
{
|
|
_rComposer.clear();
|
|
_rComposer.append( _rElementaryClause );
|
|
_rComposer.append( _rAdditionalClause );
|
|
OUString sComposed = _rComposer.getComposedAndClear();
|
|
if ( !sComposed.isEmpty() )
|
|
sComposed = _rKeyword + sComposed;
|
|
return sComposed;
|
|
}
|
|
}
|
|
|
|
void OSingleSelectQueryComposer::setSingleAdditiveClause( SQLPart _ePart, const OUString& _rClause )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setSingleAdditiveClause" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
|
|
// if nothing is changed, do nothing
|
|
if ( getSQLPart( _ePart, m_aAdditiveIterator, sal_False ) == _rClause )
|
|
return;
|
|
|
|
// collect the 4 single parts as they're currently set
|
|
::std::vector< OUString > aClauses;
|
|
aClauses.reserve( (size_t)SQLPartCount );
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
aClauses.push_back( getSQLPart( eLoopParts, m_aSqlIterator, sal_True ) );
|
|
|
|
// overwrite the one part in question here
|
|
SAL_WNODEPRECATED_DECLARATIONS_PUSH
|
|
::std::auto_ptr< TokenComposer > pComposer;
|
|
SAL_WNODEPRECATED_DECLARATIONS_POP
|
|
if ( ( _ePart == Where ) || ( _ePart == Having ) )
|
|
pComposer.reset( new FilterCreator );
|
|
else
|
|
pComposer.reset( new OrderCreator );
|
|
aClauses[ _ePart ] = getComposedClause( m_aElementaryParts[ _ePart ], _rClause,
|
|
*pComposer, getKeyword( _ePart ) );
|
|
|
|
// construct the complete statement
|
|
OUStringBuffer aSql(m_aPureSelectSQL);
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
aSql.append(aClauses[ eLoopParts ]);
|
|
|
|
// set the query
|
|
setQuery_Impl(aSql.makeStringAndClear());
|
|
|
|
// clear column collections which (might) have changed
|
|
clearColumns( ParameterColumns );
|
|
if ( _ePart == Order )
|
|
clearColumns( OrderColumns );
|
|
if ( _ePart == Group )
|
|
clearColumns( GroupByColumns );
|
|
|
|
// also, since the "additive filter" change, we need to rebuild our "additive" statement
|
|
aSql = m_aPureSelectSQL;
|
|
// again, first get all the old additive parts
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
aClauses[ eLoopParts ] = getSQLPart( eLoopParts, m_aAdditiveIterator, sal_True );
|
|
// then overwrite the one in question
|
|
aClauses[ _ePart ] = getComposedClause( OUString(), _rClause, *pComposer, getKeyword( _ePart ) );
|
|
// and parse it, so that m_aAdditiveIterator is up to date
|
|
for ( SQLPart eLoopParts = Where; eLoopParts != SQLPartCount; incSQLPart( eLoopParts ) )
|
|
aSql.append(aClauses[ eLoopParts ]);
|
|
try
|
|
{
|
|
parseAndCheck_throwError( m_aSqlParser, aSql.makeStringAndClear(), m_aAdditiveIterator, *this );
|
|
}
|
|
catch( const Exception& e )
|
|
{
|
|
(void)e;
|
|
OSL_FAIL( "OSingleSelectQueryComposer::setSingleAdditiveClause: there should be no error anymore for the additive statement!" );
|
|
// every part of the additive statement should have passed other tests already, and should not
|
|
// be able to cause any errors ... me thinks
|
|
}
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setFilter( const OUString& filter ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setFilter" );
|
|
setSingleAdditiveClause( Where, filter );
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setOrder( const OUString& order ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setOrder" );
|
|
setSingleAdditiveClause( Order, order );
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setGroup( const OUString& group ) throw (SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setGroup" );
|
|
setSingleAdditiveClause( Group, group );
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setHavingClause( const OUString& filter ) throw(SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setHavingClause" );
|
|
setSingleAdditiveClause( Having, filter );
|
|
}
|
|
|
|
// XTablesSupplier
|
|
Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getTables( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTables" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
if ( !m_pTables )
|
|
{
|
|
const OSQLTables& aTables = m_aSqlIterator.getTables();
|
|
::std::vector< OUString> aNames;
|
|
OSQLTables::const_iterator aEnd = aTables.end();
|
|
for(OSQLTables::const_iterator aIter = aTables.begin(); aIter != aEnd;++aIter)
|
|
aNames.push_back(aIter->first);
|
|
|
|
m_pTables = new OPrivateTables(aTables,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames);
|
|
}
|
|
|
|
return m_pTables;
|
|
}
|
|
|
|
// XColumnsSupplier
|
|
Reference< XNameAccess > SAL_CALL OSingleSelectQueryComposer::getColumns( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumns" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
if ( !!m_aCurrentColumns[SelectColumns] )
|
|
return m_aCurrentColumns[SelectColumns];
|
|
|
|
::std::vector< OUString> aNames;
|
|
::rtl::Reference< OSQLColumns> aSelectColumns;
|
|
sal_Bool bCase = sal_True;
|
|
Reference< XNameAccess> xQueryColumns;
|
|
if ( m_nCommandType == CommandType::QUERY )
|
|
{
|
|
Reference<XColumnsSupplier> xSup(m_xConnectionQueries->getByName(m_sCommand),UNO_QUERY);
|
|
if(xSup.is())
|
|
xQueryColumns = xSup->getColumns();
|
|
}
|
|
|
|
do {
|
|
|
|
try
|
|
{
|
|
SharedUNOComponent< XStatement, DisposableComponent > xStatement;
|
|
SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement;
|
|
|
|
bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers();
|
|
aSelectColumns = m_aSqlIterator.getSelectColumns();
|
|
|
|
OUStringBuffer aSQL( m_aPureSelectSQL + STR_WHERE + " ( 0 = 1 )");
|
|
|
|
// preserve the original WHERE clause
|
|
// #i102234#
|
|
OUString sOriginalWhereClause = getSQLPart( Where, m_aSqlIterator, sal_False );
|
|
if ( !sOriginalWhereClause.isEmpty() )
|
|
{
|
|
aSQL.append( " AND ( " + sOriginalWhereClause + " ) " );
|
|
}
|
|
|
|
OUString sGroupBy = getSQLPart( Group, m_aSqlIterator, sal_True );
|
|
if ( !sGroupBy.isEmpty() )
|
|
aSQL.append( sGroupBy );
|
|
|
|
OUString sSQL( aSQL.makeStringAndClear() );
|
|
// normalize the statement so that it doesn't contain any application-level features anymore
|
|
OUString sError;
|
|
SAL_WNODEPRECATED_DECLARATIONS_PUSH
|
|
const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSQL, false ) );
|
|
SAL_WNODEPRECATED_DECLARATIONS_POP
|
|
OSL_ENSURE( pStatementTree.get(), "OSingleSelectQueryComposer::getColumns: could not parse the column retrieval statement!" );
|
|
if ( pStatementTree.get() )
|
|
if ( !pStatementTree->parseNodeToExecutableStatement( sSQL, m_xConnection, m_aSqlParser, NULL ) )
|
|
break;
|
|
|
|
Reference< XResultSetMetaData > xResultSetMeta;
|
|
Reference< XResultSetMetaDataSupplier > xResMetaDataSup;
|
|
try
|
|
{
|
|
xPreparedStatement.set( m_xConnection->prepareStatement( sSQL ), UNO_QUERY_THROW );
|
|
xResMetaDataSup.set( xPreparedStatement, UNO_QUERY_THROW );
|
|
xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
|
|
}
|
|
catch( const Exception& ) { }
|
|
|
|
try
|
|
{
|
|
if ( !xResultSetMeta.is() )
|
|
{
|
|
xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) );
|
|
Reference< XPropertySet > xStatementProps( xStatement, UNO_QUERY_THROW );
|
|
try { xStatementProps->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( sal_False ) ); }
|
|
catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
|
|
xResMetaDataSup.set( xStatement->executeQuery( sSQL ), UNO_QUERY_THROW );
|
|
xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
|
|
}
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
//@see issue http://qa.openoffice.org/issues/show_bug.cgi?id=110111
|
|
// access returns a different order of column names when executing select * from
|
|
// and asking the columns from the metadata.
|
|
Reference< XParameters > xParameters( xPreparedStatement, UNO_QUERY_THROW );
|
|
Reference< XIndexAccess > xPara = getParameters();
|
|
for(sal_Int32 i = 1;i <= xPara->getCount();++i)
|
|
xParameters->setNull(i,DataType::VARCHAR);
|
|
xResMetaDataSup.set(xPreparedStatement->executeQuery(), UNO_QUERY_THROW );
|
|
xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW );
|
|
}
|
|
|
|
if ( aSelectColumns->get().empty() )
|
|
{
|
|
// This is a valid case. If we can syntactically parse the query, but not semantically
|
|
// (e.g. because it is based on a table we do not know), then there will be no SelectColumns
|
|
aSelectColumns = ::connectivity::parse::OParseColumn::createColumnsForResultSet( xResultSetMeta, m_xMetaData ,xQueryColumns);
|
|
break;
|
|
}
|
|
|
|
const ::comphelper::UStringMixEqual aCaseCompare( bCase );
|
|
const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase );
|
|
typedef ::std::set< size_t > SizeTSet;
|
|
SizeTSet aUsedSelectColumns;
|
|
::connectivity::parse::OParseColumn::StringMap aColumnNames;
|
|
|
|
sal_Int32 nCount = xResultSetMeta->getColumnCount();
|
|
OSL_ENSURE( (size_t) nCount == aSelectColumns->get().size(), "OSingleSelectQueryComposer::getColumns: inconsistent column counts, this might result in wrong columns!" );
|
|
for(sal_Int32 i=1;i<=nCount;++i)
|
|
{
|
|
OUString sColumnName = xResultSetMeta->getColumnName(i);
|
|
OUString sColumnLabel;
|
|
if ( xQueryColumns.is() && xQueryColumns->hasByName(sColumnName) )
|
|
{
|
|
Reference<XPropertySet> xQueryColumn(xQueryColumns->getByName(sColumnName),UNO_QUERY_THROW);
|
|
xQueryColumn->getPropertyValue(PROPERTY_LABEL) >>= sColumnLabel;
|
|
}
|
|
else
|
|
sColumnLabel = xResultSetMeta->getColumnLabel(i);
|
|
sal_Bool bFound = sal_False;
|
|
OSQLColumns::Vector::const_iterator aFind = ::connectivity::find(aSelectColumns->get().begin(),aSelectColumns->get().end(),sColumnLabel,aCaseCompare);
|
|
size_t nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
|
|
if ( aFind != aSelectColumns->get().end() )
|
|
{
|
|
if ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
|
|
{ // we found a column name which exists twice
|
|
// so we start after the first found
|
|
do
|
|
{
|
|
aFind = ::connectivity::findRealName(++aFind,aSelectColumns->get().end(),sColumnName,aCaseCompare);
|
|
nFoundSelectColumnPos = aFind - aSelectColumns->get().begin();
|
|
}
|
|
while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() )
|
|
&& ( aFind != aSelectColumns->get().end() )
|
|
);
|
|
}
|
|
if ( aFind != aSelectColumns->get().end() )
|
|
{
|
|
(*aFind)->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
|
|
aUsedSelectColumns.insert( nFoundSelectColumnPos );
|
|
aNames.push_back(sColumnName);
|
|
bFound = sal_True;
|
|
}
|
|
}
|
|
|
|
if ( bFound )
|
|
continue;
|
|
|
|
OSQLColumns::Vector::const_iterator aRealFind = ::connectivity::findRealName(
|
|
aSelectColumns->get().begin(), aSelectColumns->get().end(), sColumnName, aCaseCompare );
|
|
|
|
if ( i > static_cast< sal_Int32>( aSelectColumns->get().size() ) )
|
|
{
|
|
aSelectColumns->get().push_back(
|
|
::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ,aColumnNames)
|
|
);
|
|
OSL_ENSURE( aSelectColumns->get().size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" );
|
|
}
|
|
else if ( aRealFind == aSelectColumns->get().end() )
|
|
{
|
|
// we can now only look if we found it under the realname propertery
|
|
// here we have to make the assumption that the position is correct
|
|
OSQLColumns::Vector::iterator aFind2 = aSelectColumns->get().begin() + i-1;
|
|
Reference<XPropertySet> xProp(*aFind2,UNO_QUERY);
|
|
if ( !xProp.is() || !xProp->getPropertySetInfo()->hasPropertyByName( PROPERTY_REALNAME ) )
|
|
continue;
|
|
|
|
::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,bCase);
|
|
pColumn->setFunction(::comphelper::getBOOL(xProp->getPropertyValue("Function")));
|
|
pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue("AggregateFunction")));
|
|
|
|
OUString sRealName;
|
|
xProp->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
|
|
::std::vector< OUString>::iterator aFindName;
|
|
if ( sColumnName.isEmpty() )
|
|
xProp->getPropertyValue(PROPERTY_NAME) >>= sColumnName;
|
|
|
|
aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
|
|
sal_Int32 j = 0;
|
|
while ( aFindName != aNames.end() )
|
|
{
|
|
sColumnName += OUString::valueOf(++j);
|
|
aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sColumnName));
|
|
}
|
|
|
|
pColumn->setName(sColumnName);
|
|
pColumn->setRealName(sRealName);
|
|
pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME)));
|
|
|
|
(aSelectColumns->get())[i-1] = pColumn;
|
|
}
|
|
else
|
|
continue;
|
|
|
|
aUsedSelectColumns.insert( (size_t)(i - 1) );
|
|
aNames.push_back( sColumnName );
|
|
}
|
|
}
|
|
catch(const Exception&)
|
|
{
|
|
}
|
|
|
|
} while ( false );
|
|
|
|
bool bMissingSomeColumnLabels = !aNames.empty() && aNames.size() != aSelectColumns->get().size();
|
|
SAL_WARN_IF(bMissingSomeColumnLabels, "dbaccess", "We have column labels for *some* columns but not all");
|
|
//^^this happens in the evolution address book where we have real column names of e.g.
|
|
//first_name, second_name and city. On parsing via
|
|
//OSQLParseTreeIterator::appendColumns it creates some labels using those real names
|
|
//but the evo address book gives them proper labels of First Name, Second Name and City
|
|
//the munge means that here we have e.g. just "City" as a label because it matches
|
|
//
|
|
//This is all a horrible mess
|
|
if (bMissingSomeColumnLabels)
|
|
aNames.clear();
|
|
|
|
if ( aNames.empty() )
|
|
m_aCurrentColumns[ SelectColumns ] = OPrivateColumns::createWithIntrinsicNames( aSelectColumns, bCase, *this, m_aMutex );
|
|
else
|
|
m_aCurrentColumns[ SelectColumns ] = new OPrivateColumns( aSelectColumns, bCase, *this, m_aMutex, aNames );
|
|
|
|
return m_aCurrentColumns[SelectColumns];
|
|
}
|
|
|
|
sal_Bool OSingleSelectQueryComposer::setORCriteria(OSQLParseNode* pCondition, OSQLParseTreeIterator& _rIterator,
|
|
::std::vector< ::std::vector < PropertyValue > >& rFilters, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setORCriteria" );
|
|
// Round brackets around the expression
|
|
if (pCondition->count() == 3 &&
|
|
SQL_ISPUNCTUATION(pCondition->getChild(0),"(") &&
|
|
SQL_ISPUNCTUATION(pCondition->getChild(2),")"))
|
|
{
|
|
return setORCriteria(pCondition->getChild(1), _rIterator, rFilters, xFormatter);
|
|
}
|
|
// OR logic expression
|
|
// a searchcondition can only look like this: search_condition SQL_TOKEN_OR boolean_term
|
|
else if (SQL_ISRULE(pCondition,search_condition))
|
|
{
|
|
sal_Bool bResult = sal_True;
|
|
for (int i = 0; bResult && i < 3; i+=2)
|
|
{
|
|
// Is the first element a OR logic expression again?
|
|
// Then descend recursively ...
|
|
if (SQL_ISRULE(pCondition->getChild(i),search_condition))
|
|
bResult = setORCriteria(pCondition->getChild(i), _rIterator, rFilters, xFormatter);
|
|
else
|
|
{
|
|
rFilters.push_back( ::std::vector < PropertyValue >());
|
|
bResult = setANDCriteria(pCondition->getChild(i), _rIterator, rFilters[rFilters.size() - 1], xFormatter);
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|
|
else
|
|
{
|
|
rFilters.push_back(::std::vector < PropertyValue >());
|
|
return setANDCriteria(pCondition, _rIterator, rFilters[rFilters.size() - 1], xFormatter);
|
|
}
|
|
}
|
|
|
|
sal_Bool OSingleSelectQueryComposer::setANDCriteria( OSQLParseNode * pCondition,
|
|
OSQLParseTreeIterator& _rIterator, ::std::vector < PropertyValue >& rFilter, const Reference< XNumberFormatter > & xFormatter) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setANDCriteria" );
|
|
// Round brackets
|
|
if (SQL_ISRULE(pCondition,boolean_primary))
|
|
{
|
|
// this should not occur
|
|
OSL_FAIL("boolean_primary in And-Criteria");
|
|
return sal_False;
|
|
}
|
|
// The first element is an AND logical expression again
|
|
else if ( SQL_ISRULE(pCondition,boolean_term) && pCondition->count() == 3 )
|
|
{
|
|
return setANDCriteria(pCondition->getChild(0), _rIterator, rFilter, xFormatter) &&
|
|
setANDCriteria(pCondition->getChild(2), _rIterator, rFilter, xFormatter);
|
|
}
|
|
else if (SQL_ISRULE(pCondition, comparison_predicate))
|
|
{
|
|
return setComparsionPredicate(pCondition,_rIterator,rFilter,xFormatter);
|
|
}
|
|
else if (SQL_ISRULE(pCondition,like_predicate) ||
|
|
SQL_ISRULE(pCondition,test_for_null) ||
|
|
SQL_ISRULE(pCondition,in_predicate) ||
|
|
SQL_ISRULE(pCondition,all_or_any_predicate) ||
|
|
SQL_ISRULE(pCondition,between_predicate))
|
|
{
|
|
if (SQL_ISRULE(pCondition->getChild(0), column_ref))
|
|
{
|
|
PropertyValue aItem;
|
|
OUString aValue;
|
|
OUString aColumnName;
|
|
|
|
|
|
pCondition->parseNodeToStr( aValue, m_xConnection, NULL );
|
|
pCondition->getChild(0)->parseNodeToStr( aColumnName, m_xConnection, NULL );
|
|
|
|
// don't display the column name
|
|
aValue = aValue.copy(aColumnName.getLength());
|
|
aValue = aValue.trim();
|
|
|
|
aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
|
|
aItem.Value <<= aValue;
|
|
aItem.Handle = 0; // just to know that this is not one the known ones
|
|
if ( SQL_ISRULE(pCondition,like_predicate) )
|
|
{
|
|
if ( SQL_ISTOKEN(pCondition->getChild(1)->getChild(0),NOT) )
|
|
aItem.Handle = SQLFilterOperator::NOT_LIKE;
|
|
else
|
|
aItem.Handle = SQLFilterOperator::LIKE;
|
|
}
|
|
else if (SQL_ISRULE(pCondition,test_for_null))
|
|
{
|
|
if (SQL_ISTOKEN(pCondition->getChild(1)->getChild(1),NOT) )
|
|
aItem.Handle = SQLFilterOperator::NOT_SQLNULL;
|
|
else
|
|
aItem.Handle = SQLFilterOperator::SQLNULL;
|
|
}
|
|
else if (SQL_ISRULE(pCondition,in_predicate))
|
|
{
|
|
OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: in_predicate not implemented!" );
|
|
}
|
|
else if (SQL_ISRULE(pCondition,all_or_any_predicate))
|
|
{
|
|
OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: all_or_any_predicate not implemented!" );
|
|
}
|
|
else if (SQL_ISRULE(pCondition,between_predicate))
|
|
{
|
|
OSL_FAIL( "OSingleSelectQueryComposer::setANDCriteria: between_predicate not implemented!" );
|
|
}
|
|
|
|
rFilter.push_back(aItem);
|
|
}
|
|
else
|
|
return sal_False;
|
|
}
|
|
else if (SQL_ISRULE(pCondition,existence_test) ||
|
|
SQL_ISRULE(pCondition,unique_test))
|
|
{
|
|
// this couldn't be handled here, too complex
|
|
// as we need a field name
|
|
return sal_False;
|
|
}
|
|
else
|
|
return sal_False;
|
|
|
|
return sal_True;
|
|
}
|
|
|
|
sal_Int32 OSingleSelectQueryComposer::getPredicateType(OSQLParseNode * _pPredicate) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getPredicateType" );
|
|
sal_Int32 nPredicate = SQLFilterOperator::EQUAL;
|
|
switch (_pPredicate->getNodeType())
|
|
{
|
|
case SQL_NODE_EQUAL:
|
|
nPredicate = SQLFilterOperator::EQUAL;
|
|
break;
|
|
case SQL_NODE_NOTEQUAL:
|
|
nPredicate = SQLFilterOperator::NOT_EQUAL;
|
|
break;
|
|
case SQL_NODE_LESS:
|
|
nPredicate = SQLFilterOperator::LESS;
|
|
break;
|
|
case SQL_NODE_LESSEQ:
|
|
nPredicate = SQLFilterOperator::LESS_EQUAL;
|
|
break;
|
|
case SQL_NODE_GREAT:
|
|
nPredicate = SQLFilterOperator::GREATER;
|
|
break;
|
|
case SQL_NODE_GREATEQ:
|
|
nPredicate = SQLFilterOperator::GREATER_EQUAL;
|
|
break;
|
|
default:
|
|
OSL_FAIL("Wrong NodeType!");
|
|
}
|
|
return nPredicate;
|
|
}
|
|
|
|
sal_Bool OSingleSelectQueryComposer::setComparsionPredicate(OSQLParseNode * pCondition, OSQLParseTreeIterator& _rIterator,
|
|
::std::vector < PropertyValue >& rFilter, const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setComparsionPredicate" );
|
|
OSL_ENSURE(SQL_ISRULE(pCondition, comparison_predicate),"setComparsionPredicate: pCondition ist kein ComparsionPredicate");
|
|
if (SQL_ISRULE(pCondition->getChild(0), column_ref) ||
|
|
SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
|
|
{
|
|
PropertyValue aItem;
|
|
OUString aValue;
|
|
sal_uInt32 nPos;
|
|
if (SQL_ISRULE(pCondition->getChild(0), column_ref))
|
|
{
|
|
nPos = 0;
|
|
sal_uInt32 i=1;
|
|
|
|
aItem.Handle = getPredicateType(pCondition->getChild(i));
|
|
// don't display the equal
|
|
if (pCondition->getChild(i)->getNodeType() == SQL_NODE_EQUAL)
|
|
i++;
|
|
|
|
// go forward
|
|
for (;i < pCondition->count();i++)
|
|
pCondition->getChild(i)->parseNodeToPredicateStr(
|
|
aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>(m_sDecimalSep.toChar() ) );
|
|
}
|
|
else if (SQL_ISRULE(pCondition->getChild(pCondition->count()-1), column_ref))
|
|
{
|
|
nPos = pCondition->count()-1;
|
|
|
|
sal_Int32 i = pCondition->count() - 2;
|
|
switch (pCondition->getChild(i)->getNodeType())
|
|
{
|
|
case SQL_NODE_EQUAL:
|
|
// don't display the equal
|
|
i--;
|
|
aItem.Handle = SQLFilterOperator::EQUAL;
|
|
break;
|
|
case SQL_NODE_NOTEQUAL:
|
|
i--;
|
|
aItem.Handle = SQLFilterOperator::NOT_EQUAL;
|
|
break;
|
|
case SQL_NODE_LESS:
|
|
// take the opposite as we change the order
|
|
i--;
|
|
aValue = ">=";
|
|
aItem.Handle = SQLFilterOperator::GREATER_EQUAL;
|
|
break;
|
|
case SQL_NODE_LESSEQ:
|
|
// take the opposite as we change the order
|
|
i--;
|
|
aValue = ">";
|
|
aItem.Handle = SQLFilterOperator::GREATER;
|
|
break;
|
|
case SQL_NODE_GREAT:
|
|
// take the opposite as we change the order
|
|
i--;
|
|
aValue = "<=";
|
|
aItem.Handle = SQLFilterOperator::LESS_EQUAL;
|
|
break;
|
|
case SQL_NODE_GREATEQ:
|
|
// take the opposite as we change the order
|
|
i--;
|
|
aValue = "<";
|
|
aItem.Handle = SQLFilterOperator::LESS;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// go backward
|
|
for (; i >= 0; i--)
|
|
pCondition->getChild(i)->parseNodeToPredicateStr(
|
|
aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
|
|
}
|
|
else
|
|
return sal_False;
|
|
|
|
aItem.Name = getColumnName(pCondition->getChild(nPos),_rIterator);
|
|
aItem.Value <<= aValue;
|
|
rFilter.push_back(aItem);
|
|
}
|
|
else if (SQL_ISRULE(pCondition->getChild(0), set_fct_spec ) ||
|
|
SQL_ISRULE(pCondition->getChild(0), general_set_fct))
|
|
{
|
|
PropertyValue aItem;
|
|
OUString aValue;
|
|
OUString aColumnName;
|
|
|
|
pCondition->getChild(2)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
|
|
pCondition->getChild(0)->parseNodeToPredicateStr( aColumnName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep .toChar() ) );
|
|
|
|
aItem.Name = getColumnName(pCondition->getChild(0),_rIterator);
|
|
aItem.Value <<= aValue;
|
|
aItem.Handle = getPredicateType(pCondition->getChild(1));
|
|
rFilter.push_back(aItem);
|
|
}
|
|
else // Can only be an expression
|
|
{
|
|
PropertyValue aItem;
|
|
OUString aName, aValue;
|
|
|
|
OSQLParseNode *pLhs = pCondition->getChild(0);
|
|
OSQLParseNode *pRhs = pCondition->getChild(2);
|
|
|
|
// Field names
|
|
sal_uInt16 i;
|
|
for (i=0;i< pLhs->count();i++)
|
|
pLhs->getChild(i)->parseNodeToPredicateStr( aName, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
|
|
|
|
// Criterion
|
|
aItem.Handle = getPredicateType(pCondition->getChild(1));
|
|
aValue = pCondition->getChild(1)->getTokenValue();
|
|
for(i=0;i< pRhs->count();i++)
|
|
pRhs->getChild(i)->parseNodeToPredicateStr(aValue, m_xConnection, xFormatter, m_aLocale, static_cast<sal_Char>( m_sDecimalSep.toChar() ) );
|
|
|
|
aItem.Name = aName;
|
|
aItem.Value <<= aValue;
|
|
rFilter.push_back(aItem);
|
|
}
|
|
return sal_True;
|
|
}
|
|
|
|
// Functions for analysing SQL
|
|
OUString OSingleSelectQueryComposer::getColumnName( ::connectivity::OSQLParseNode* pColumnRef, OSQLParseTreeIterator& _rIterator ) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getColumnName" );
|
|
OUString aTableRange, aColumnName;
|
|
_rIterator.getColumnRange(pColumnRef,aColumnName,aTableRange);
|
|
return aColumnName;
|
|
}
|
|
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getFilter( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getFilter" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
return getSQLPart(Where,m_aAdditiveIterator,sal_False);
|
|
}
|
|
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getOrder( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrder" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
return getSQLPart(Order,m_aAdditiveIterator,sal_False);
|
|
}
|
|
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getGroup( ) throw (RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroup" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
return getSQLPart(Group,m_aAdditiveIterator,sal_False);
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::getHavingClause() throw (RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getHavingClause" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
return getSQLPart(Having,m_aAdditiveIterator,sal_False);
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::getTableAlias(const Reference< XPropertySet >& column) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getTableAlias" );
|
|
OUString sReturn;
|
|
if(m_pTables && m_pTables->getCount() > 1)
|
|
{
|
|
OUString aCatalog,aSchema,aTable,aComposedName,aColumnName;
|
|
if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_CATALOGNAME))
|
|
column->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog;
|
|
if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_SCHEMANAME))
|
|
column->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema;
|
|
if(column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME))
|
|
column->getPropertyValue(PROPERTY_TABLENAME) >>= aTable;
|
|
column->getPropertyValue(PROPERTY_NAME) >>= aColumnName;
|
|
|
|
Sequence< OUString> aNames(m_pTables->getElementNames());
|
|
const OUString* pBegin = aNames.getConstArray();
|
|
const OUString* pEnd = pBegin + aNames.getLength();
|
|
|
|
if(aTable.isEmpty())
|
|
{ // we haven't found a table name, now we must search every table for this column
|
|
for(;pBegin != pEnd;++pBegin)
|
|
{
|
|
Reference<XColumnsSupplier> xColumnsSupp;
|
|
m_pTables->getByName(*pBegin) >>= xColumnsSupp;
|
|
|
|
if(xColumnsSupp.is() && xColumnsSupp->getColumns()->hasByName(aColumnName))
|
|
{
|
|
aTable = *pBegin;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aComposedName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_False, ::dbtools::eInDataManipulation );
|
|
|
|
// first check if this is the table we want to or has it a tablealias
|
|
|
|
if(!m_pTables->hasByName(aComposedName))
|
|
{
|
|
::comphelper::UStringMixLess aTmp(m_aAdditiveIterator.getTables().key_comp());
|
|
::comphelper::UStringMixEqual aComp(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
|
|
for(;pBegin != pEnd;++pBegin)
|
|
{
|
|
Reference<XPropertySet> xTableProp;
|
|
m_pTables->getByName(*pBegin) >>= xTableProp;
|
|
OSL_ENSURE(xTableProp.is(),"Table isn't a propertyset!");
|
|
if(xTableProp.is())
|
|
{
|
|
OUString aCatalog2,aSchema2,aTable2;
|
|
xTableProp->getPropertyValue(PROPERTY_CATALOGNAME) >>= aCatalog2;
|
|
xTableProp->getPropertyValue(PROPERTY_SCHEMANAME) >>= aSchema2;
|
|
xTableProp->getPropertyValue(PROPERTY_NAME) >>= aTable2;
|
|
if(aComp(aCatalog,aCatalog2) && aComp(aSchema,aSchema2) && aComp(aTable,aTable2))
|
|
{
|
|
aCatalog = aCatalog2;
|
|
aSchema = aSchema2;
|
|
aTable = aTable2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(pBegin != pEnd)
|
|
{
|
|
sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ) + ".";
|
|
}
|
|
}
|
|
return sReturn;
|
|
}
|
|
|
|
Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getParameters( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getParameters" );
|
|
// now set the Parameters
|
|
if ( !m_aCurrentColumns[ParameterColumns] )
|
|
{
|
|
::rtl::Reference< OSQLColumns> aCols = m_aSqlIterator.getParameters();
|
|
::std::vector< OUString> aNames;
|
|
OSQLColumns::Vector::const_iterator aEnd = aCols->get().end();
|
|
for(OSQLColumns::Vector::const_iterator aIter = aCols->get().begin(); aIter != aEnd;++aIter)
|
|
aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
|
|
m_aCurrentColumns[ParameterColumns] = new OPrivateColumns(aCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
|
|
}
|
|
|
|
return m_aCurrentColumns[ParameterColumns];
|
|
}
|
|
|
|
void OSingleSelectQueryComposer::clearColumns( const EColumnType _eType )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearColumns" );
|
|
OPrivateColumns* pColumns = m_aCurrentColumns[ _eType ];
|
|
if ( pColumns != NULL )
|
|
{
|
|
pColumns->disposing();
|
|
m_aColumnsCollection.push_back( pColumns );
|
|
m_aCurrentColumns[ _eType ] = NULL;
|
|
}
|
|
}
|
|
|
|
void OSingleSelectQueryComposer::clearCurrentCollections()
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::clearCurrentCollections" );
|
|
::std::vector<OPrivateColumns*>::iterator aIter = m_aCurrentColumns.begin();
|
|
::std::vector<OPrivateColumns*>::iterator aEnd = m_aCurrentColumns.end();
|
|
for (;aIter != aEnd;++aIter)
|
|
{
|
|
if ( *aIter )
|
|
{
|
|
(*aIter)->disposing();
|
|
m_aColumnsCollection.push_back(*aIter);
|
|
*aIter = NULL;
|
|
}
|
|
}
|
|
|
|
if(m_pTables)
|
|
{
|
|
m_pTables->disposing();
|
|
m_aTablesCollection.push_back(m_pTables);
|
|
m_pTables = NULL;
|
|
}
|
|
}
|
|
|
|
Reference< XIndexAccess > OSingleSelectQueryComposer::setCurrentColumns( EColumnType _eType,
|
|
const ::rtl::Reference< OSQLColumns >& _rCols )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setCurrentColumns" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
// now set the group columns
|
|
if ( !m_aCurrentColumns[_eType] )
|
|
{
|
|
::std::vector< OUString> aNames;
|
|
OSQLColumns::Vector::const_iterator aEnd = _rCols->get().end();
|
|
for(OSQLColumns::Vector::const_iterator aIter = _rCols->get().begin(); aIter != aEnd;++aIter)
|
|
aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME)));
|
|
m_aCurrentColumns[_eType] = new OPrivateColumns(_rCols,m_xMetaData->supportsMixedCaseQuotedIdentifiers(),*this,m_aMutex,aNames,sal_True);
|
|
}
|
|
|
|
return m_aCurrentColumns[_eType];
|
|
}
|
|
|
|
Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getGroupColumns( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getGroupColumns" );
|
|
return setCurrentColumns( GroupByColumns, m_aAdditiveIterator.getGroupColumns() );
|
|
}
|
|
|
|
Reference< XIndexAccess > SAL_CALL OSingleSelectQueryComposer::getOrderColumns( ) throw(RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getOrderColumns" );
|
|
return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() );
|
|
}
|
|
|
|
OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getQueryWithSubstitution" );
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
OUString sSqlStatement( getQuery() );
|
|
|
|
const OSQLParseNode* pStatementNode = m_aSqlIterator.getParseTree();
|
|
if ( pStatementNode )
|
|
{
|
|
SQLException aError;
|
|
if ( !pStatementNode->parseNodeToExecutableStatement( sSqlStatement, m_xConnection, m_aSqlParser, &aError ) )
|
|
throw SQLException( aError );
|
|
}
|
|
|
|
return sSqlStatement;
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStatementPart" );
|
|
OUString sResult;
|
|
|
|
const OSQLParseNode* pNode = _aGetFunctor( &_rIterator );
|
|
if ( pNode )
|
|
pNode->parseNodeToStr( sResult, m_xConnection );
|
|
|
|
return sResult;
|
|
}
|
|
|
|
namespace
|
|
{
|
|
OUString lcl_getCondition(const Sequence< Sequence< PropertyValue > >& filter,const OPredicateInputController& i_aPredicateInputController,const Reference< XNameAccess >& i_xSelectColumns)
|
|
{
|
|
OUStringBuffer sRet;
|
|
const Sequence< PropertyValue >* pOrIter = filter.getConstArray();
|
|
const Sequence< PropertyValue >* pOrEnd = pOrIter + filter.getLength();
|
|
while ( pOrIter != pOrEnd )
|
|
{
|
|
if ( pOrIter->getLength() )
|
|
{
|
|
sRet.append(L_BRACKET);
|
|
const PropertyValue* pAndIter = pOrIter->getConstArray();
|
|
const PropertyValue* pAndEnd = pAndIter + pOrIter->getLength();
|
|
while ( pAndIter != pAndEnd )
|
|
{
|
|
sRet.append(pAndIter->Name);
|
|
OUString sValue;
|
|
pAndIter->Value >>= sValue;
|
|
if ( i_xSelectColumns.is() && i_xSelectColumns->hasByName(pAndIter->Name) )
|
|
{
|
|
Reference<XPropertySet> xColumn(i_xSelectColumns->getByName(pAndIter->Name),UNO_QUERY);
|
|
sValue = i_aPredicateInputController.getPredicateValue(sValue,xColumn,sal_True);
|
|
}
|
|
else
|
|
{
|
|
sValue = i_aPredicateInputController.getPredicateValue(pAndIter->Name,sValue,sal_True);
|
|
}
|
|
lcl_addFilterCriteria_throw(pAndIter->Handle,sValue,sRet);
|
|
++pAndIter;
|
|
if ( pAndIter != pAndEnd )
|
|
sRet.append(STR_AND);
|
|
}
|
|
sRet.append(R_BRACKET);
|
|
}
|
|
++pOrIter;
|
|
if ( pOrIter != pOrEnd && sRet.getLength() )
|
|
sRet.append(STR_OR);
|
|
}
|
|
return sRet.makeStringAndClear();
|
|
}
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setStructuredFilter( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, ::com::sun::star::lang::IllegalArgumentException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredFilter" );
|
|
OPredicateInputController aPredicateInput(m_aContext.getUNOContext(),m_xConnection);
|
|
setFilter(lcl_getCondition(filter,aPredicateInput,getColumns()));
|
|
}
|
|
|
|
void SAL_CALL OSingleSelectQueryComposer::setStructuredHavingClause( const Sequence< Sequence< PropertyValue > >& filter ) throw (SQLException, RuntimeException)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setStructuredHavingClause" );
|
|
OPredicateInputController aPredicateInput(m_aContext.getUNOContext(),m_xConnection);
|
|
setHavingClause(lcl_getCondition(filter,aPredicateInput,getColumns()));
|
|
}
|
|
|
|
void OSingleSelectQueryComposer::setConditionByColumn( const Reference< XPropertySet >& column, sal_Bool andCriteria ,::std::mem_fun1_t<bool,OSingleSelectQueryComposer,OUString>& _aSetFunctor,sal_Int32 filterOperator)
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::setConditionByColumn" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
if ( !column.is()
|
|
|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_VALUE)
|
|
|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME)
|
|
|| !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE))
|
|
throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,Any() );
|
|
|
|
sal_Int32 nType = 0;
|
|
column->getPropertyValue(PROPERTY_TYPE) >>= nType;
|
|
sal_Int32 nSearchable = dbtools::getSearchColumnFlag(m_xConnection,nType);
|
|
if(nSearchable == ColumnSearch::NONE)
|
|
throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_SEARCHABLE),*this,SQLSTATE_GENERAL,1000,Any() );
|
|
|
|
::osl::MutexGuard aGuard( m_aMutex );
|
|
|
|
OUString aName;
|
|
column->getPropertyValue(PROPERTY_NAME) >>= aName;
|
|
|
|
Any aValue;
|
|
column->getPropertyValue(PROPERTY_VALUE) >>= aValue;
|
|
|
|
OUStringBuffer aSQL;
|
|
const OUString aQuote = m_xMetaData->getIdentifierQuoteString();
|
|
getColumns();
|
|
|
|
if ( m_aCurrentColumns[SelectColumns] && m_aCurrentColumns[SelectColumns]->hasByName(aName) )
|
|
{
|
|
Reference<XPropertySet> xColumn;
|
|
m_aCurrentColumns[SelectColumns]->getByName(aName) >>= xColumn;
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
|
|
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName("AggregateFunction"),"Property AggregateFunction not available!");
|
|
|
|
OUString sRealName,sTableName;
|
|
xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
|
|
xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
|
|
if(sTableName.indexOf('.',0) != -1)
|
|
{
|
|
OUString aCatlog,aSchema,aTable;
|
|
::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation);
|
|
sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation );
|
|
}
|
|
else
|
|
sTableName = ::dbtools::quoteName(aQuote,sTableName);
|
|
|
|
if ( !::comphelper::getBOOL(xColumn->getPropertyValue("Function")) )
|
|
{
|
|
aSQL = sTableName + "." + ::dbtools::quoteName( aQuote, sRealName );
|
|
}
|
|
else
|
|
aSQL = sRealName;
|
|
|
|
}
|
|
else
|
|
{
|
|
aSQL = getTableAlias( column ) + ::dbtools::quoteName( aQuote, aName );
|
|
}
|
|
|
|
if ( aValue.hasValue() )
|
|
{
|
|
if( !m_xTypeConverter.is() )
|
|
m_xTypeConverter.set( Converter::create(m_aContext.getUNOContext()) );
|
|
OSL_ENSURE(m_xTypeConverter.is(),"NO typeconverter!");
|
|
|
|
if ( nType != DataType::BOOLEAN && DataType::BIT != nType )
|
|
{
|
|
OUString sEmpty;
|
|
lcl_addFilterCriteria_throw(filterOperator,sEmpty,aSQL);
|
|
}
|
|
|
|
switch(nType)
|
|
{
|
|
case DataType::VARCHAR:
|
|
case DataType::CHAR:
|
|
case DataType::LONGVARCHAR:
|
|
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
|
|
break;
|
|
case DataType::CLOB:
|
|
{
|
|
Reference< XClob > xClob(aValue,UNO_QUERY);
|
|
if ( xClob.is() )
|
|
{
|
|
const ::sal_Int64 nLength = xClob->length();
|
|
if ( sal_Int64(nLength + aSQL.getLength() + STR_LIKE.getLength() ) < sal_Int64(SAL_MAX_INT32) )
|
|
{
|
|
aSQL.append("'" + xClob->getSubString(1,(sal_Int32)nLength) + "'");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
|
|
}
|
|
}
|
|
break;
|
|
case DataType::VARBINARY:
|
|
case DataType::BINARY:
|
|
case DataType::LONGVARBINARY:
|
|
{
|
|
Sequence<sal_Int8> aSeq;
|
|
if(aValue >>= aSeq)
|
|
{
|
|
if(nSearchable == ColumnSearch::CHAR)
|
|
{
|
|
aSQL.append( "\'" );
|
|
}
|
|
aSQL.appendAscii( "0x" );
|
|
const sal_Int8* pBegin = aSeq.getConstArray();
|
|
const sal_Int8* pEnd = pBegin + aSeq.getLength();
|
|
for(;pBegin != pEnd;++pBegin)
|
|
{
|
|
aSQL.append( (sal_Int32)*pBegin, 16 ).getStr();
|
|
}
|
|
if(nSearchable == ColumnSearch::CHAR)
|
|
aSQL.append( "\'" );
|
|
}
|
|
else
|
|
throw SQLException(DBACORE_RESSTRING(RID_STR_NOT_SEQUENCE_INT8),*this,SQLSTATE_GENERAL,1000,Any() );
|
|
}
|
|
break;
|
|
case DataType::BIT:
|
|
case DataType::BOOLEAN:
|
|
{
|
|
sal_Bool bValue = sal_False;
|
|
m_xTypeConverter->convertToSimpleType(aValue, TypeClass_BOOLEAN) >>= bValue;
|
|
|
|
OUString sColumnExp = aSQL.makeStringAndClear();
|
|
getBoleanComparisonPredicate( sColumnExp, bValue, m_nBoolCompareMode, aSQL );
|
|
}
|
|
break;
|
|
default:
|
|
aSQL.append( DBTypeConversion::toSQLString( nType, aValue, sal_True, m_xTypeConverter ) );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sal_Int32 nFilterOp = filterOperator;
|
|
if ( filterOperator != SQLFilterOperator::SQLNULL && filterOperator != SQLFilterOperator::NOT_SQLNULL )
|
|
nFilterOp = SQLFilterOperator::SQLNULL;
|
|
OUString sEmpty;
|
|
lcl_addFilterCriteria_throw(nFilterOp,sEmpty,aSQL);
|
|
}
|
|
|
|
// Attach filter
|
|
// Construct SELECT without WHERE and ORDER BY
|
|
OUString sFilter = getFilter();
|
|
|
|
if ( !sFilter.isEmpty() && aSQL.getLength() )
|
|
{
|
|
OUString sTemp(L_BRACKET + sFilter + R_BRACKET);
|
|
sTemp += andCriteria ? OUString(STR_AND) : OUString(STR_OR);
|
|
sFilter = sTemp;
|
|
}
|
|
sFilter += aSQL.makeStringAndClear();
|
|
|
|
// add the filter and the sort order
|
|
_aSetFunctor(this,sFilter);
|
|
}
|
|
|
|
Sequence< Sequence< PropertyValue > > OSingleSelectQueryComposer::getStructuredCondition( TGetParseNode& _aGetFunctor )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getStructuredCondition" );
|
|
::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed);
|
|
|
|
MutexGuard aGuard(m_aMutex);
|
|
|
|
Sequence< Sequence< PropertyValue > > aFilterSeq;
|
|
OUString sFilter = getStatementPart( _aGetFunctor, m_aAdditiveIterator );
|
|
|
|
if ( !sFilter.isEmpty() )
|
|
{
|
|
OUString aSql(m_aPureSelectSQL + STR_WHERE + sFilter);
|
|
// build a temporary parse node
|
|
const OSQLParseNode* pTempNode = m_aAdditiveIterator.getParseTree();
|
|
|
|
OUString aErrorMsg;
|
|
SAL_WNODEPRECATED_DECLARATIONS_PUSH
|
|
::std::auto_ptr<OSQLParseNode> pSqlParseNode( m_aSqlParser.parseTree(aErrorMsg,aSql));
|
|
SAL_WNODEPRECATED_DECLARATIONS_POP
|
|
if ( pSqlParseNode.get() )
|
|
{
|
|
m_aAdditiveIterator.setParseTree(pSqlParseNode.get());
|
|
// normalize the filter
|
|
OSQLParseNode* pWhereNode = const_cast<OSQLParseNode*>(m_aAdditiveIterator.getWhereTree());
|
|
|
|
OSQLParseNode* pCondition = pWhereNode->getChild(1);
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
OUString sCondition;
|
|
pCondition->parseNodeToStr( sCondition, m_xConnection );
|
|
#endif
|
|
OSQLParseNode::negateSearchCondition(pCondition);
|
|
|
|
pCondition = pWhereNode->getChild(1);
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
sCondition = OUString();
|
|
pCondition->parseNodeToStr( sCondition, m_xConnection );
|
|
#endif
|
|
OSQLParseNode::disjunctiveNormalForm(pCondition);
|
|
|
|
pCondition = pWhereNode->getChild(1);
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
sCondition = OUString();
|
|
pCondition->parseNodeToStr( sCondition, m_xConnection );
|
|
#endif
|
|
OSQLParseNode::absorptions(pCondition);
|
|
|
|
pCondition = pWhereNode->getChild(1);
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
sCondition = OUString();
|
|
pCondition->parseNodeToStr( sCondition, m_xConnection );
|
|
#endif
|
|
if ( pCondition )
|
|
{
|
|
::std::vector< ::std::vector < PropertyValue > > aFilters;
|
|
Reference< XNumberFormatter > xFormatter( NumberFormatter::create(m_aContext.getUNOContext()), UNO_QUERY_THROW );
|
|
xFormatter->attachNumberFormatsSupplier( m_xNumberFormatsSupplier );
|
|
|
|
if (setORCriteria(pCondition, m_aAdditiveIterator, aFilters, xFormatter))
|
|
{
|
|
aFilterSeq.realloc(aFilters.size());
|
|
Sequence<PropertyValue>* pFilters = aFilterSeq.getArray();
|
|
::std::vector< ::std::vector < PropertyValue > >::const_iterator aEnd = aFilters.end();
|
|
::std::vector< ::std::vector < PropertyValue > >::const_iterator i = aFilters.begin();
|
|
for ( ; i != aEnd ; ++i)
|
|
{
|
|
const ::std::vector < PropertyValue >& rProperties = *i;
|
|
pFilters->realloc(rProperties.size());
|
|
PropertyValue* pFilter = pFilters->getArray();
|
|
::std::vector < PropertyValue >::const_iterator j = rProperties.begin();
|
|
::std::vector < PropertyValue >::const_iterator aEnd2 = rProperties.end();
|
|
for ( ; j != aEnd2 ; ++j)
|
|
{
|
|
*pFilter = *j;
|
|
++pFilter;
|
|
}
|
|
++pFilters;
|
|
}
|
|
}
|
|
}
|
|
// restore
|
|
m_aAdditiveIterator.setParseTree(pTempNode);
|
|
}
|
|
}
|
|
return aFilterSeq;
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::getKeyword( SQLPart _ePart ) const
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getKeyword" );
|
|
OUString sKeyword;
|
|
switch(_ePart)
|
|
{
|
|
default:
|
|
OSL_FAIL( "OSingleSelectQueryComposer::getKeyWord: Invalid enum value!" );
|
|
// no break, fallback to WHERE
|
|
case Where:
|
|
sKeyword = STR_WHERE;
|
|
break;
|
|
case Group:
|
|
sKeyword = STR_GROUP_BY;
|
|
break;
|
|
case Having:
|
|
sKeyword = STR_HAVING;
|
|
break;
|
|
case Order:
|
|
sKeyword = STR_ORDER_BY;
|
|
break;
|
|
}
|
|
return sKeyword;
|
|
}
|
|
|
|
OUString OSingleSelectQueryComposer::getSQLPart( SQLPart _ePart, OSQLParseTreeIterator& _rIterator, sal_Bool _bWithKeyword )
|
|
{
|
|
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OSingleSelectQueryComposer::getSQLPart" );
|
|
TGetParseNode F_tmp(&OSQLParseTreeIterator::getSimpleWhereTree);
|
|
OUString sKeyword( getKeyword( _ePart ) );
|
|
switch(_ePart)
|
|
{
|
|
case Where:
|
|
F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleWhereTree);
|
|
break;
|
|
case Group:
|
|
F_tmp = TGetParseNode (&OSQLParseTreeIterator::getSimpleGroupByTree);
|
|
break;
|
|
case Having:
|
|
F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleHavingTree);
|
|
break;
|
|
case Order:
|
|
F_tmp = TGetParseNode(&OSQLParseTreeIterator::getSimpleOrderTree);
|
|
break;
|
|
default:
|
|
OSL_FAIL("Invalid enum value!");
|
|
}
|
|
|
|
OUString sRet = getStatementPart( F_tmp, _rIterator );
|
|
if ( _bWithKeyword && !sRet.isEmpty() )
|
|
sRet = sKeyword + sRet;
|
|
return sRet;
|
|
}
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|