Tag: cws_src680_dba30 User: fs Date: 2006/07/19 05:10:20 Modified: dba/dbaccess/source/core/api/SingleSelectQueryComposer.cxx
Log: RESYNC: (1.13-1.15); FILE MERGED File Changes: Directory: /dba/dbaccess/source/core/api/ ========================================= File [changed]: SingleSelectQueryComposer.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/core/api/SingleSelectQueryComposer.cxx?r1=1.10.2.6&r2=1.10.2.7 Delta lines: +208 -138 ----------------------- --- SingleSelectQueryComposer.cxx 20 Apr 2006 06:44:37 -0000 1.10.2.6 +++ SingleSelectQueryComposer.cxx 19 Jul 2006 12:10:18 -0000 1.10.2.7 @@ -83,12 +83,18 @@ #ifndef _UTL_CONFIGMGR_HXX_ #include <unotools/configmgr.hxx> #endif +#ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX +#include <unotools/sharedunocomponent.hxx> +#endif #ifndef _COMPHELPER_TYPES_HXX_ #include <comphelper/types.hxx> #endif #ifndef _TOOLS_DEBUG_HXX #include <tools/debug.hxx> #endif +#ifndef TOOLS_DIAGNOSE_EX_H +#include <tools/diagnose_ex.h> +#endif #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ #include <com/sun/star/beans/PropertyAttribute.hpp> #endif @@ -160,9 +166,10 @@ const OSQLParseNode* pNewSqlParseNode = _rParser.parseTree( aErrorMsg, _rStatement ); if ( !pNewSqlParseNode ) { - SQLException aError2(aErrorMsg,_rxContext,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HY000")),1000,Any()); - SQLException aError1(_rStatement,_rxContext,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HY000")),1000,makeAny(aError2)); - throw SQLException(_rParser.getContext().getErrorMessage(OParseContext::ERROR_GENERAL),_rxContext,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HY000")),1000,makeAny(aError1)); + ::rtl::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; } @@ -179,8 +186,7 @@ // determine the statement type _rIterator.setParseTree( pStatementNode ); _rIterator.traverseAll(); - bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT ) - || ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT_COUNT ); + bool bIsSingleSelect = ( _rIterator.getStatementType() == SQL_STATEMENT_SELECT ); // throw the error, if necessary if ( !bIsSingleSelect || SQL_ISRULE( pStatementNode, union_statement ) ) // #i4229# OJ @@ -188,9 +194,9 @@ // restore the old node before throwing the exception _rIterator.setParseTree( pOldNode ); // and now really ... - SQLException aError1( _rOriginatingCommand, _rxContext, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HY000" ) ), 1000, Any() ); + SQLException aError1( _rOriginatingCommand, _rxContext, getStandardSQLState( SQL_GENERAL_ERROR ), 1000, Any() ); throw SQLException( DBACORE_RESSTRING( RID_STR_ONLY_QUERY ), _rxContext, - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HY000" ) ), 1000, makeAny( aError1 ) ); + getStandardSQLState( SQL_GENERAL_ERROR ), 1000, makeAny( aError1 ) ); } delete pOldNode; @@ -235,32 +241,31 @@ DBG_NAME(OSingleSelectQueryComposer) // ------------------------------------------------------------------------- -OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _xTableSupplier, +OSingleSelectQueryComposer::OSingleSelectQueryComposer(const Reference< XNameAccess>& _rxTables, const Reference< XConnection>& _xConnection, const Reference< XMultiServiceFactory >& _xServiceFactory) - : OSubComponent(m_aMutex,_xConnection) + :OSubComponent(m_aMutex,_xConnection) ,OPropertyContainer(m_aBHelper) - , m_xConnection(_xConnection) - , m_xMetaData(_xConnection->getMetaData()) - , m_aSqlIterator(_xTableSupplier,_xConnection->getMetaData(),NULL) - , m_aAdditiveIterator(_xTableSupplier,_xConnection->getMetaData(),NULL) - , m_xTableSupplier(_xTableSupplier) - , m_aSqlParser(_xServiceFactory) + ,m_aSqlParser(_xServiceFactory) + ,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_xServiceFactory(_xServiceFactory) ,m_pTables(NULL) ,m_nBoolCompareMode(BOOL_COMPARISON_DEFAULT) - ,m_aElementaryParts( (size_t)SQLPartCount ) { DBG_CTOR(OSingleSelectQueryComposer,NULL); - OSL_ENSURE(_xServiceFactory.is()," ServiceFactory cant be null!"); - OSL_ENSURE(_xConnection.is()," Connection cant be null!"); - OSL_ENSURE(_xTableSupplier.is(),"TableSupplier cant be null!"); + + if ( !m_xServiceFactory.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().GetLocaleData().getLocale(); m_xNumberFormatsSupplier = dbtools::getNumberFormats(m_xConnection,sal_True,m_xServiceFactory); Reference< XLocaleData> xLocaleData = Reference<XLocaleData>(m_xServiceFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.LocaleData"))),UNO_QUERY); @@ -317,7 +322,7 @@ resetIterator( m_aSqlIterator, true ); resetIterator( m_aAdditiveIterator, true ); - m_xTableSupplier = NULL; + m_xConnectionTables = NULL; m_xConnection = NULL; m_xServiceFactory = NULL; @@ -462,7 +467,7 @@ { ::rtl::OUString aCatlog,aSchema,aTable; ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); - ::dbtools::composeTableName(m_xMetaData,aCatlog,aSchema,aTable,sTableName,sal_True,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); } else sTableName = ::dbtools::quoteName(aQuote,sTableName); @@ -534,7 +539,7 @@ { ::rtl::OUString aCatlog,aSchema,aTable; ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); - ::dbtools::composeTableName(m_xMetaData,aCatlog,aSchema,aTable,sTableName,sal_True,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); } else sTableName = ::dbtools::quoteName(aQuote,sTableName); @@ -601,7 +606,7 @@ } catch( const Exception& e ) { - e; + (void)e; DBG_ERROR( "OSingleSelectQueryComposer::setElementaryQuery: 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 @@ -671,7 +676,7 @@ } catch( const Exception& e ) { - e; + (void)e; DBG_ERROR( "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 @@ -725,19 +730,23 @@ { ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); ::osl::MutexGuard aGuard( m_aMutex ); - if ( !m_aCurrentColumns[SelectColumns] ) - { + if ( !!m_aCurrentColumns[SelectColumns] ) + return m_aCurrentColumns[SelectColumns]; + ::std::vector< ::rtl::OUString> aNames; - ::vos::ORef< OSQLColumns> aCols; + ::vos::ORef< OSQLColumns> aSelectColumns; sal_Bool bCase = sal_True; + + do { + try { - bCase = m_xMetaData->storesMixedCaseQuotedIdentifiers(); - aCols = m_aSqlIterator.getSelectColumns(); - // now set the columns we have to look if the order of the columns is correct - Reference<XStatement> xStmt = m_xConnection->createStatement(); - if ( xStmt.is() ) - { + SharedUNOComponent< XStatement, DisposableComponent > xStatement; + SharedUNOComponent< XPreparedStatement, DisposableComponent > xPreparedStatement; + + bCase = m_xMetaData->supportsMixedCaseQuotedIdentifiers(); + aSelectColumns = m_aSqlIterator.getSelectColumns(); + ::rtl::OUString sSql = m_aPureSelectSQL; sSql += STR_WHERE; sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" 0 = 1 ")); @@ -745,53 +754,96 @@ if ( sGroupBy.getLength() ) sSql += sGroupBy; - Reference<XResultSetMetaDataSupplier> xResMetaDataSup; - xResMetaDataSup = Reference<XResultSetMetaDataSupplier>(xStmt->executeQuery(sSql),UNO_QUERY); - Reference<XResultSetMetaData> xMeta = xResMetaDataSup->getMetaData(); - - sal_Int32 nCount = xMeta.is() ? xMeta->getColumnCount() : sal_Int32(0); - ::comphelper::UStringMixEqual bCase(m_xMetaData->supportsMixedCaseQuotedIdentifiers()); - ::comphelper::TStringMixEqualFunctor bCase2(m_xMetaData->supportsMixedCaseQuotedIdentifiers()); - ::std::map<OSQLColumns::const_iterator,int> aColumnMap; + // normalize the statement so that it doesn't contain any application-level features anymore + ::rtl::OUString sError; + const ::std::auto_ptr< OSQLParseNode > pStatementTree( m_aSqlParser.parseTree( sError, sSql, false ) ); + DBG_ASSERT( 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; + try + { + xStatement.reset( Reference< XStatement >( m_xConnection->createStatement(), UNO_QUERY_THROW ) ); + Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xStatement->executeQuery( sSql ), UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + catch( const Exception& ) { } + + if ( !xResultSetMeta.is() ) + { + xPreparedStatement.set( m_xConnection->prepareStatement( sSql ), UNO_QUERY_THROW ); + Reference< XResultSetMetaDataSupplier > xResMetaDataSup( xPreparedStatement, UNO_QUERY_THROW ); + xResultSetMeta.set( xResMetaDataSup->getMetaData(), UNO_QUERY_THROW ); + } + + if ( aSelectColumns->empty() ) + { + // This is a valid casse. 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 ); + break; + } + + const ::comphelper::UStringMixEqual aCaseCompare( bCase ); + const ::comphelper::TStringMixEqualFunctor aCaseCompareFunctor( bCase ); + typedef ::std::set< size_t > SizeTSet; + SizeTSet aUsedSelectColumns; + + sal_Int32 nCount = xResultSetMeta.is() ? xResultSetMeta->getColumnCount() : sal_Int32(0); for(sal_Int32 i=1;i<=nCount;++i) { - ::rtl::OUString sName = xMeta->getColumnName(i); + ::rtl::OUString sName = xResultSetMeta->getColumnName(i); sal_Bool bFound = sal_False; - OSQLColumns::const_iterator aFind = ::connectivity::find(aCols->begin(),aCols->end(),sName,bCase); - if(aFind != aCols->end()) - //aNames.end() == ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(bCase2,sName))) + OSQLColumns::const_iterator aFind = ::connectivity::find(aSelectColumns->begin(),aSelectColumns->end(),sName,aCaseCompare); + size_t nFoundSelectColumnPos = aFind - aSelectColumns->begin(); + if ( aFind != aSelectColumns->end() ) { - if(aColumnMap.find(aFind) != aColumnMap.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,aCols->end(),sName,bCase); + aFind = ::connectivity::findRealName(++aFind,aSelectColumns->end(),sName,aCaseCompare); + nFoundSelectColumnPos = aFind - aSelectColumns->begin(); } - while(aColumnMap.find(aFind) != aColumnMap.end() && aFind != aCols->end()); + while ( ( aUsedSelectColumns.find( nFoundSelectColumnPos ) != aUsedSelectColumns.end() ) + && ( aFind != aSelectColumns->end() ) + ); } - if(aFind != aCols->end()) + if ( aFind != aSelectColumns->end() ) { (*aFind)->getPropertyValue(PROPERTY_NAME) >>= sName; - aColumnMap.insert(::std::map<OSQLColumns::const_iterator,int>::value_type(aFind,0)); + aUsedSelectColumns.insert( nFoundSelectColumnPos ); aNames.push_back(sName); bFound = sal_True; } } - if ( !bFound ) - { // we can now only look if we found it under the realname propertery - OSQLColumns::const_iterator aRealFind = ::connectivity::findRealName(aCols->begin(),aCols->end(),sName,bCase); - - if ( i <= static_cast< sal_Int32>(aCols->size()) ) - { - if(aRealFind == aCols->end()) - { // here we have to make the assumption that the position is correct - OSQLColumns::iterator aFind2 = aCols->begin() + i-1; - Reference<XPropertySet> xProp(*aFind2,UNO_QUERY); - if(xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME)) + + if ( bFound ) + continue; + + OSQLColumns::const_iterator aRealFind = ::connectivity::findRealName( + aSelectColumns->begin(), aSelectColumns->end(), sName, aCaseCompare ); + + if ( i > static_cast< sal_Int32>( aSelectColumns->size() ) ) { - ::connectivity::parse::OParseColumn* pColumn = new ::connectivity::parse::OParseColumn(xProp,m_xMetaData->supportsMixedCaseQuotedIdentifiers()); + aSelectColumns->push_back( + ::connectivity::parse::OParseColumn::createColumnForResultSet( xResultSetMeta, m_xMetaData, i ) + ); + OSL_ENSURE( aSelectColumns->size() == (size_t)i, "OSingleSelectQueryComposer::getColumns: inconsistency!" ); + } + else if ( aRealFind == aSelectColumns->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::iterator aFind2 = aSelectColumns->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(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))))); pColumn->setAggregateFunction(::comphelper::getBOOL(xProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"))))); @@ -802,39 +854,38 @@ xProp->getPropertyValue(PROPERTY_NAME) >>= sName; - aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(bCase2,sName)); + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sName)); sal_Int32 j = 0; while ( aFindName != aNames.end() ) { sName += ::rtl::OUString::valueOf(++j); - aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(bCase2,sName)); + aFindName = ::std::find_if(aNames.begin(),aNames.end(),::std::bind2nd(aCaseCompareFunctor,sName)); } pColumn->setName(sName); pColumn->setRealName(sRealName); pColumn->setTableName(::comphelper::getString(xProp->getPropertyValue(PROPERTY_TABLENAME))); - (*aCols)[i-1] = pColumn; - aColumnMap.insert(::std::map<OSQLColumns::const_iterator,int>::value_type((*aCols).begin() + i-1,0)); - } - } - aNames.push_back(sName); - } - } - } - ::comphelper::disposeComponent(xStmt); + (*aSelectColumns)[i-1] = pColumn; } else - { - for(OSQLColumns::const_iterator aIter = aCols->begin(); aIter != aCols->end();++aIter) - aNames.push_back(getString((*aIter)->getPropertyValue(PROPERTY_NAME))); + continue; + + aUsedSelectColumns.insert( (size_t)(i - 1) ); + aNames.push_back( sName ); } } - catch(Exception&) + catch(const Exception&) { } - m_aCurrentColumns[SelectColumns] = new OPrivateColumns(aCols,bCase,*this,m_aMutex,aNames); - } + + } while ( false ); + + 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]; } // ------------------------------------------------------------------------- @@ -1020,7 +1071,7 @@ { nPos = pCondition->count()-1; - sal_uInt32 i = pCondition->count() - 2; + sal_Int32 i = pCondition->count() - 2; switch (pCondition->getChild(i)->getNodeType()) { case SQL_NODE_EQUAL: @@ -1056,6 +1107,8 @@ aValue = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<")); aItem.Handle = SQLFilterOperator::LESS; break; + default: + break; } // go backward @@ -1185,7 +1238,7 @@ } else { - ::dbtools::composeTableName(m_xMetaData,aCatalog,aSchema,aTable,aComposedName,sal_False,::dbtools::eInDataManipulation); + 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 @@ -1217,7 +1270,7 @@ } if(pBegin != pEnd) { - ::dbtools::composeTableName(m_xMetaData,aCatalog,aSchema,aTable,sReturn,sal_True,::dbtools::eInDataManipulation); + sReturn = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); sReturn += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); } } @@ -1299,6 +1352,24 @@ return setCurrentColumns( OrderColumns, m_aAdditiveIterator.getOrderColumns() ); } // ----------------------------------------------------------------------------- +::rtl::OUString SAL_CALL OSingleSelectQueryComposer::getQueryWithSubstitution( ) throw (SQLException, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + ::rtl::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; +} +// ----------------------------------------------------------------------------- ::rtl::OUString OSingleSelectQueryComposer::getStatementPart( TGetParseNode& _aGetFunctor, OSQLParseTreeIterator& _rIterator ) { ::rtl::OUString sResult; @@ -1437,7 +1508,7 @@ { ::rtl::OUString aCatlog,aSchema,aTable; ::dbtools::qualifiedNameComponents(m_xMetaData,sTableName,aCatlog,aSchema,aTable,::dbtools::eInDataManipulation); - ::dbtools::composeTableName(m_xMetaData,aCatlog,aSchema,aTable,sTableName,sal_True,::dbtools::eInDataManipulation); + sTableName = ::dbtools::composeTableName( m_xMetaData, aCatlog, aSchema, aTable, sal_True, ::dbtools::eInDataManipulation ); } else sTableName = ::dbtools::quoteName(aQuote,sTableName); @@ -1520,7 +1591,6 @@ aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" TRUE ")); else aSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" FALSE ")); - break; break; case BOOL_COMPARISON_ACCESS: if ( bValue ) --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
