Skip to content
Snippets Groups Projects
Commit 225c49e1 authored by gmantele's avatar gmantele
Browse files

[ADQL] Grouping by a SELECTed item's alias was not possible any more

since the commit 8e2fa9ff.
parent 42cb5bb2
No related branches found
No related tags found
No related merge requests found
......@@ -42,6 +42,7 @@ import adql.parser.QueryChecker;
import adql.query.ADQLIterator;
import adql.query.ADQLObject;
import adql.query.ADQLQuery;
import adql.query.ClauseADQL;
import adql.query.ClauseSelect;
import adql.query.ColumnReference;
import adql.query.IdentifierField;
......@@ -615,7 +616,7 @@ public class DBChecker implements QueryChecker {
ISearchHandler sHandler;
// Check the existence of all columns:
sHandler = new SearchColumnHandler();
sHandler = new SearchColumnOutsideGroupByHandler();
sHandler.search(query);
for(ADQLObject result : sHandler){
try{
......@@ -630,12 +631,30 @@ public class DBChecker implements QueryChecker {
}
}
// Check the GROUP BY items:
ClauseSelect select = query.getSelect();
sHandler = new SearchColumnHandler();
sHandler.search(query.getGroupBy());
for(ADQLObject result : sHandler){
try{
ADQLColumn adqlColumn = (ADQLColumn)result;
// resolve the column:
DBColumn dbColumn = checkGroupByItem(adqlColumn, select, list);
// link with the matched DBColumn:
if (dbColumn != null){
adqlColumn.setDBLink(dbColumn);
adqlColumn.setAdqlTable(mapTables.get(dbColumn.getTable()));
}
}catch(ParseException pe){
errors.addException(pe);
}
}
// Check the correctness of all column references (= references to selected columns):
/* Note: no need to provide the father tables when resolving column references,
* because no father column can be used in ORDER BY. */
sHandler = new SearchColReferenceHandler();
sHandler.search(query);
ClauseSelect select = query.getSelect();
for(ADQLObject result : sHandler){
try{
ColumnReference colRef = (ColumnReference)result;
......@@ -695,6 +714,38 @@ public class DBChecker implements QueryChecker {
}
}
/**
* Check whether the given column corresponds to a selected item's alias or to an existing column.
*
* @param col The column to check.
* @param select The SELECT clause of the ADQL query.
* @param dbColumns The list of all available columns.
*
* @return The corresponding {@link DBColumn} if this column corresponds to an existing column,
* <i>NULL</i> otherwise.
*
* @throws ParseException An {@link UnresolvedColumnException} if the given column can't be resolved
* or an {@link UnresolvedTableException} if its table reference can't be resolved.
*
* @see ClauseSelect#searchByAlias(String)
* @see #resolveColumn(ADQLColumn, SearchColumnList, Stack)
*
* @since 1.4
*/
protected DBColumn checkGroupByItem(final ADQLColumn col, final ClauseSelect select, final SearchColumnList dbColumns) throws ParseException{
/* If the column name is not qualified, it may be a SELECT-item's alias.
* So, try resolving the name as an alias.
* If it fails, perform the normal column resolution.*/
if (col.getTableName() == null){
ArrayList<SelectItem> founds = select.searchByAlias(col.getColumnName(), col.isCaseSensitive(IdentifierField.COLUMN));
if (founds.size() == 1)
return null;
else if (founds.size() > 1)
throw new UnresolvedColumnException(col, founds.get(0).getAlias(), founds.get(1).getAlias());
}
return resolveColumn(col, dbColumns, null);
}
/**
* Check whether the given column reference corresponds to a selected item (column or an expression with an alias)
* or to an existing column.
......@@ -1245,6 +1296,26 @@ public class DBChecker implements QueryChecker {
/* *************** */
/* SEARCH HANDLERS */
/* *************** */
/**
* Lets searching all {@link ADQLColumn} in the given object, EXCEPT in the GROUP BY clause.
*
* <p>
* {@link ADQLColumn}s of the GROUP BY may be aliases and so, they can not be checked
* exactly as a normal column.
* </p>
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 1.4 (04/2017)
* @since 1.4
*/
private static class SearchColumnOutsideGroupByHandler extends SearchColumnHandler {
@Override
protected boolean goInto(final ADQLObject obj){
return !(obj instanceof ClauseADQL<?> && ((ClauseADQL<?>)obj).getName().equalsIgnoreCase("GROUP BY")) && super.goInto(obj);
}
}
/**
* Lets searching all tables.
*
......
......@@ -106,6 +106,8 @@ public class TestDBChecker {
parser.parseQuery("SELECT foo.colI, COUNT(*) AS cnt FROM foo GROUP BY foo.colI");
// Qualified with the table alias:
parser.parseQuery("SELECT f.colI, COUNT(*) AS cnt FROM foo AS f GROUP BY f.colI");
// With the SELECT item alias:
parser.parseQuery("SELECT colI AS mycol, COUNT(*) AS cnt FROM foo GROUP BY mycol");
}catch(ParseException pe){
pe.printStackTrace();
fail();
......@@ -156,9 +158,15 @@ public class TestDBChecker {
public void testColRefWithDottedAlias(){
ADQLParser parser = new ADQLParser(new DBChecker(tables));
try{
// ORDER BY
ADQLQuery adql = parser.parseQuery("SELECT colI AS \"col.I\" FROM aschema.foo ORDER BY \"col.I\"");
assertNotNull(adql);
assertEquals("SELECT \"aschema\".\"foo\".\"colI\" AS \"col.I\"\nFROM \"aschema\".\"foo\"\nORDER BY \"col.I\" ASC", (new PostgreSQLTranslator()).translate(adql));
// GROUP BY
adql = parser.parseQuery("SELECT colI AS \"col.I\" FROM aschema.foo GROUP BY \"col.I\"");
assertNotNull(adql);
assertEquals("SELECT \"aschema\".\"foo\".\"colI\" AS \"col.I\"\nFROM \"aschema\".\"foo\"\nGROUP BY \"col.I\"", (new PostgreSQLTranslator()).translate(adql));
}catch(ParseException pe){
pe.printStackTrace();
fail();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment