connectivity/inc/connectivity/sqliterator.hxx | 8 ++ connectivity/source/parse/sqliterator.cxx | 30 ++++++++- dbaccess/source/core/api/SingleSelectQueryComposer.cxx | 53 +++++++++++++---- dbaccess/source/core/inc/SingleSelectQueryComposer.hxx | 19 +++++- dbaccess/source/ui/dlg/queryorder.cxx | 25 -------- 5 files changed, 98 insertions(+), 37 deletions(-)
New commits: commit 6fb427e8d233f7adf416d7ac48c7afb4435518d4 Author: Lionel Elie Mamane <[email protected]> Date: Thu Jul 11 16:53:23 2013 +0200 ORDER BY columns are prioritarily *SELECT* columns as opposed to *table* columns, and notwithstanding HSQLDB 1.8 (our embedded database) bugs. Actually, supporting ORDER BY on non-select (but table) columns is OPTIONAL for DBMSs (but quite common) Conflicts: connectivity/source/parse/sqliterator.cxx Change-Id: I6725dfda36b09429a78262bff6f3d3e3dd9032b6 Reviewed-on: https://gerrit.libreoffice.org/4846 Reviewed-by: David Tardon <[email protected]> Tested-by: David Tardon <[email protected]> diff --git a/connectivity/inc/connectivity/sqliterator.hxx b/connectivity/inc/connectivity/sqliterator.hxx index 5da60c2..a18809d 100644 --- a/connectivity/inc/connectivity/sqliterator.hxx +++ b/connectivity/inc/connectivity/sqliterator.hxx @@ -112,6 +112,14 @@ namespace connectivity ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn( const ::rtl::OUString & rColumnName, ::rtl::OUString & rTableRange, bool _bLookInSubTables ); + /** finds a column with a given name among the select columns + @param rColumnName + the column name to look for + @return + */ + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findSelectColumn( + const OUString & rColumnName ); + protected: void setSelectColumnName(::rtl::Reference<OSQLColumns>& _rColumns,const ::rtl::OUString & rColumnName,const ::rtl::OUString & rColumnAlias, const ::rtl::OUString & rTableRange,sal_Bool bFkt=sal_False,sal_Int32 _nType = com::sun::star::sdbc::DataType::VARCHAR,sal_Bool bAggFkt=sal_False); void appendColumns(::rtl::Reference<OSQLColumns>& _rColumns,const ::rtl::OUString& _rTableAlias,const OSQLTable& _rTable); diff --git a/connectivity/source/parse/sqliterator.cxx b/connectivity/source/parse/sqliterator.cxx index 7967683..97122d1 100644 --- a/connectivity/source/parse/sqliterator.cxx +++ b/connectivity/source/parse/sqliterator.cxx @@ -1912,7 +1912,9 @@ void OSQLParseTreeIterator::setSelectColumnName(::rtl::Reference<OSQLColumns>& _ void OSQLParseTreeIterator::setOrderByColumnName(const ::rtl::OUString & rColumnName, ::rtl::OUString & rTableRange, sal_Bool bAscending) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "[email protected]", "OSQLParseTreeIterator::setOrderByColumnName" ); - Reference<XPropertySet> xColumn = findColumn( rColumnName, rTableRange, false ); + Reference<XPropertySet> xColumn = findSelectColumn( rColumnName ); + if ( !xColumn.is() ) + xColumn = findColumn ( rColumnName, rTableRange, false ); if ( xColumn.is() ) m_aOrderColumns->get().push_back(new OOrderColumn( xColumn, rTableRange, isCaseSensitive(), bAscending ) ); else @@ -2090,7 +2092,31 @@ const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const } // ----------------------------------------------------------------------------- -Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const ::rtl::OUString & rColumnName, ::rtl::OUString & rTableRange, bool _bLookInSubTables ) +Reference< XPropertySet > OSQLParseTreeIterator::findSelectColumn( const OUString & rColumnName ) +{ + SAL_INFO( "connectivity.parse", "parse [email protected] OSQLParseTreeIterator::findSelectColumn" ); + for ( OSQLColumns::Vector::const_iterator lookupColumn = m_aSelectColumns->get().begin(); + lookupColumn != m_aSelectColumns->get().end(); + ++lookupColumn ) + { + Reference< XPropertySet > xColumn( *lookupColumn ); + try + { + OUString sName, sTableName; + xColumn->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= sName; + if ( sName == rColumnName ) + return xColumn; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + return NULL; +} + +// ----------------------------------------------------------------------------- +Reference< XPropertySet > OSQLParseTreeIterator::findColumn( const OUString & rColumnName, OUString & rTableRange, bool _bLookInSubTables ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "parse", "[email protected]", "OSQLParseTreeIterator::findColumn" ); Reference< XPropertySet > xColumn = findColumn( *m_pImpl->m_pTables, rColumnName, rTableRange ); diff --git a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx index 8d67b87..a06d44b 100644 --- a/dbaccess/source/core/api/SingleSelectQueryComposer.cxx +++ b/dbaccess/source/core/api/SingleSelectQueryComposer.cxx @@ -467,7 +467,7 @@ void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< setConditionByColumn(column,andCriteria,F_tmp,filterOperator); } -::rtl::OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column) +OUString OSingleSelectQueryComposer::impl_getColumnRealName_throw(const Reference< XPropertySet >& column, bool bGroupBy) { ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); @@ -483,19 +483,20 @@ void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) ); } - ::rtl::OUString aName,aNewName; + OUString aName, aNewName; column->getPropertyValue(PROPERTY_NAME) >>= aName; - if ( !m_xMetaData->supportsOrderByUnrelated() && m_aCurrentColumns[SelectColumns] && !m_aCurrentColumns[SelectColumns]->hasByName(aName)) + if ( bGroupBy && + !m_xMetaData->supportsGroupByUnrelated() && + 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 - ::rtl::OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + OUString aQuote = m_xMetaData->getIdentifierQuoteString(); if ( m_aCurrentColumns[SelectColumns]->hasByName(aName) ) { Reference<XPropertySet> xColumn; @@ -504,7 +505,7 @@ void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!"); OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Function"))),"Property FUNCTION not available!"); - ::rtl::OUString sRealName,sTableName; + OUString sRealName, sTableName; xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName; sal_Bool bFunction = sal_False; @@ -538,12 +539,44 @@ void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference< return aNewName; } +OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< XPropertySet >& column, bool bOrderBy) +{ + ::connectivity::checkDisposed(OSubComponent::rBHelper.bDisposed); + + getColumns(); + if ( !column.is() + || !m_aCurrentColumns[SelectColumns] + || !column->getPropertySetInfo()->hasPropertyByName(PROPERTY_NAME) + ) + { + OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_UNKNOWN_PROP)); + SQLException aErr(sError.replaceAll("%value", OUString(PROPERTY_NAME)),*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 ( bOrderBy && + !m_xMetaData->supportsOrderByUnrelated() && + m_aCurrentColumns[SelectColumns] && + !m_aCurrentColumns[SelectColumns]->hasByName(aName) ) + { + OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE)); + throw SQLException(sError.replaceAll("%name", aName),*this,SQLSTATE_GENERAL,1000,Any() ); + } + + const OUString aQuote = m_xMetaData->getIdentifierQuoteString(); + aNewName = ::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", "[email protected]", "OSingleSelectQueryComposer::appendOrderByColumn" ); ::osl::MutexGuard aGuard( m_aMutex ); - ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); - ::rtl::OUString sOrder = getOrder(); + OUString sColumnName( impl_getColumnName_throw(column, true) ); + OUString sOrder = getOrder(); if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) ) sOrder += COMMA; sOrder += sColumnName; @@ -557,7 +590,7 @@ void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference< { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "[email protected]", "OSingleSelectQueryComposer::appendGroupByColumn" ); ::osl::MutexGuard aGuard( m_aMutex ); - ::rtl::OUString sColumnName( impl_getColumnName_throw(column) ); + OUString sColumnName( impl_getColumnRealName_throw(column, true) ); OrderCreator aComposer; aComposer.append( getGroup() ); aComposer.append( sColumnName ); diff --git a/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx index 34166c2..6ea8b80 100644 --- a/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx +++ b/dbaccess/source/core/inc/SingleSelectQueryComposer.hxx @@ -179,9 +179,26 @@ namespace dbaccess */ ::rtl::OUString composeStatementFromParts( const ::std::vector< ::rtl::OUString >& _rParts ); - /** return the name of the column. + /** return the name of the column in the *source* *table*. + + That is, for (SELECT a AS b FROM t), it returns A or "t"."A", as appropriate. + + Use e.g. for WHERE, GROUP BY and HAVING clauses. + + @param bGroupBy: for GROUP BY clause? In that case, throw exception if trying to use an unrelated column and the database does not support that. + */ + OUString impl_getColumnRealName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, bool bGroupBy); + + /** return the name of the column in the *query* + + That is, for (SELECT a AS b FROM t), it returns "b" + + Use e.g. for ORDER BY clause. + + @param bOrderBy: for ORDER BY clause? In that case, throw exception if trying to use an unrelated column and the database does not support that. */ ::rtl::OUString impl_getColumnName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column); + OUString impl_getColumnName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, bool bOrderBy); protected: virtual ~OSingleSelectQueryComposer(); diff --git a/dbaccess/source/ui/dlg/queryorder.cxx b/dbaccess/source/ui/dlg/queryorder.cxx index 6721690..b4c4bb7 100644 --- a/dbaccess/source/ui/dlg/queryorder.cxx +++ b/dbaccess/source/ui/dlg/queryorder.cxx @@ -234,30 +234,7 @@ void DlgOrderCrit::EnableLines() sOrder += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(",")); String sName = m_aColumnList[i]->GetSelectEntry(); - try - { - sal_Bool bFunction = sal_False; - Reference< XPropertySet > xColumn; - if ( xColumns.is() && xColumns->hasByName( sName ) && (xColumns->getByName( sName ) >>= xColumn) && xColumn.is() ) - { - if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) ) - { - ::rtl::OUString sRealName; - xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName; - sName = sRealName; - static ::rtl::OUString sFunction(RTL_CONSTASCII_USTRINGPARAM("Function")); - if ( xColumn->getPropertySetInfo()->hasPropertyByName(sFunction) ) - xColumn->getPropertyValue(sFunction) >>= bFunction; - } - } - if ( bFunction ) - sOrder += sName; - else - sOrder += ::dbtools::quoteName(sQuote,sName); - } - catch(const Exception&) - { - } + sOrder += ::dbtools::quoteName(sQuote,sName); if(m_aValueList[i]->GetSelectEntryPos()) sOrder += sDESC; else _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
