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)

Change-Id: I6725dfda36b09429a78262bff6f3d3e3dd9032b6
This commit is contained in:
Lionel Elie Mamane
2013-07-11 16:53:23 +02:00
parent ad1049716a
commit 40370f759c
5 changed files with 95 additions and 35 deletions

View File

@@ -1868,7 +1868,9 @@ OUString OSQLParseTreeIterator::getUniqueColumnName(const OUString & rColumnName
void OSQLParseTreeIterator::setOrderByColumnName(const OUString & rColumnName, OUString & rTableRange, sal_Bool bAscending)
{
SAL_INFO( "connectivity.parse", "parse Ocke.Janssen@sun.com 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
@@ -2045,6 +2047,30 @@ const OSQLParseNode* OSQLParseTreeIterator::getSimpleHavingTree() const
return pNode ? pNode->getChild(1) : NULL;
}
// -----------------------------------------------------------------------------
Reference< XPropertySet > OSQLParseTreeIterator::findSelectColumn( const OUString & rColumnName )
{
SAL_INFO( "connectivity.parse", "parse lionel@mamane.lu 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 )
{

View File

@@ -456,7 +456,7 @@ void SAL_CALL OSingleSelectQueryComposer::appendFilterByColumn( const Reference<
setConditionByColumn(column,andCriteria,F_tmp,filterOperator);
}
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);
@@ -471,17 +471,18 @@ OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< X
throw SQLException(DBACORE_RESSTRING(RID_STR_COLUMN_NOT_VALID),*this,SQLSTATE_GENERAL,1000,makeAny(aErr) );
}
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) )
{
OUString sError(DBACORE_RESSTRING(RID_STR_COLUMN_MUST_VISIBLE));
throw SQLException(sError.replaceAll("%name", aName),*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) )
{
@@ -491,7 +492,7 @@ OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< X
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
OSL_ENSURE(xColumn->getPropertySetInfo()->hasPropertyByName("Function"),"Property FUNCTION not available!");
OUString sRealName,sTableName;
OUString sRealName, sTableName;
xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
xColumn->getPropertyValue(PROPERTY_TABLENAME) >>= sTableName;
sal_Bool bFunction = sal_False;
@@ -525,11 +526,43 @@ OUString OSingleSelectQueryComposer::impl_getColumnName_throw(const Reference< X
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)
{
SAL_INFO("dbaccess", "OSingleSelectQueryComposer::appendOrderByColumn" );
::osl::MutexGuard aGuard( m_aMutex );
OUString sColumnName( impl_getColumnName_throw(column) );
OUString sColumnName( impl_getColumnName_throw(column, true) );
OUString sOrder = getOrder();
if ( !(sOrder.isEmpty() || sColumnName.isEmpty()) )
sOrder += COMMA;
@@ -544,7 +577,7 @@ void SAL_CALL OSingleSelectQueryComposer::appendGroupByColumn( const Reference<
{
SAL_INFO("dbaccess", "OSingleSelectQueryComposer::appendGroupByColumn" );
::osl::MutexGuard aGuard( m_aMutex );
OUString sColumnName( impl_getColumnName_throw(column) );
OUString sColumnName( impl_getColumnRealName_throw(column, true) );
OrderCreator aComposer;
aComposer.append( getGroup() );
aComposer.append( sColumnName );

View File

@@ -180,9 +180,25 @@ namespace dbaccess
*/
OUString composeStatementFromParts( const ::std::vector< 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_getColumnName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column);
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.
*/
OUString impl_getColumnName_throw(const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& column, bool bOrderBy);
protected:
virtual ~OSingleSelectQueryComposer();

View File

@@ -234,30 +234,7 @@ OUString DlgOrderCrit::GetOrderList( ) const
sOrder += OUString(",");
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) )
{
OUString sRealName;
xColumn->getPropertyValue(PROPERTY_REALNAME) >>= sRealName;
sName = sRealName;
static OUString sFunction("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

View File

@@ -111,6 +111,14 @@ namespace connectivity
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > findColumn(
const OUString & rColumnName, 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 OUString & rColumnName,const OUString & rColumnAlias, const 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 OUString& _rTableAlias,const OSQLTable& _rTable);