Skip to content
Snippets Groups Projects
Commit 3d96c9d9 authored by gmantele's avatar gmantele
Browse files

[ADQL] Put column aliases in lower case while translating into SQL

if the alias is not delimited in ADQL.

This commit fixes the GitHub issue #56
parent 0be32298
No related branches found
No related tags found
No related merge requests found
...@@ -2,20 +2,20 @@ package adql.query; ...@@ -2,20 +2,20 @@ package adql.query;
/* /*
* This file is part of ADQLLibrary. * This file is part of ADQLLibrary.
* *
* ADQLLibrary is free software: you can redistribute it and/or modify * ADQLLibrary is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* ADQLLibrary is distributed in the hope that it will be useful, * ADQLLibrary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>.
* *
* Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2017 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI) * Astronomisches Rechen Institut (ARI)
*/ */
...@@ -45,9 +45,9 @@ import adql.search.ISearchHandler; ...@@ -45,9 +45,9 @@ import adql.search.ISearchHandler;
/** /**
* <p>Object representation of an ADQL query or sub-query.</p> * <p>Object representation of an ADQL query or sub-query.</p>
* <p>The resulting object of the {@link ADQLParser} is an object of this class.</p> * <p>The resulting object of the {@link ADQLParser} is an object of this class.</p>
* *
* @author Gr&eacute;gory Mantelet (CDS;ARI) * @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 1.4 (04/2017) * @version 1.4 (11/2017)
*/ */
public class ADQLQuery implements ADQLObject { public class ADQLQuery implements ADQLObject {
...@@ -87,7 +87,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -87,7 +87,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Builds an ADQL query by copying the given one. * Builds an ADQL query by copying the given one.
* *
* @param toCopy The ADQL query to copy. * @param toCopy The ADQL query to copy.
* @throws Exception If there is an error during the copy. * @throws Exception If there is an error during the copy.
*/ */
...@@ -120,7 +120,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -120,7 +120,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the SELECT clause of this query. * Gets the SELECT clause of this query.
* *
* @return Its SELECT clause. * @return Its SELECT clause.
*/ */
public final ClauseSelect getSelect(){ public final ClauseSelect getSelect(){
...@@ -129,11 +129,11 @@ public class ADQLQuery implements ADQLObject { ...@@ -129,11 +129,11 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its SELECT clause by the given one.</p> * <p>Replaces its SELECT clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newSelect The new SELECT clause. * @param newSelect The new SELECT clause.
* *
* @throws NullPointerException If the given SELECT clause is <i>null</i>. * @throws NullPointerException If the given SELECT clause is <i>null</i>.
*/ */
public void setSelect(ClauseSelect newSelect) throws NullPointerException{ public void setSelect(ClauseSelect newSelect) throws NullPointerException{
...@@ -146,7 +146,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -146,7 +146,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the FROM clause of this query. * Gets the FROM clause of this query.
* *
* @return Its FROM clause. * @return Its FROM clause.
*/ */
public final FromContent getFrom(){ public final FromContent getFrom(){
...@@ -155,11 +155,11 @@ public class ADQLQuery implements ADQLObject { ...@@ -155,11 +155,11 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its FROM clause by the given one.</p> * <p>Replaces its FROM clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newFrom The new FROM clause. * @param newFrom The new FROM clause.
* *
* @throws NullPointerException If the given FROM clause is <i>null</i>. * @throws NullPointerException If the given FROM clause is <i>null</i>.
*/ */
public void setFrom(FromContent newFrom) throws NullPointerException{ public void setFrom(FromContent newFrom) throws NullPointerException{
...@@ -172,7 +172,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -172,7 +172,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the WHERE clause of this query. * Gets the WHERE clause of this query.
* *
* @return Its WHERE clause. * @return Its WHERE clause.
*/ */
public final ClauseConstraints getWhere(){ public final ClauseConstraints getWhere(){
...@@ -181,11 +181,11 @@ public class ADQLQuery implements ADQLObject { ...@@ -181,11 +181,11 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its WHERE clause by the given one.</p> * <p>Replaces its WHERE clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newWhere The new WHERE clause. * @param newWhere The new WHERE clause.
* *
* @throws NullPointerException If the given WHERE clause is <i>null</i>. * @throws NullPointerException If the given WHERE clause is <i>null</i>.
*/ */
public void setWhere(ClauseConstraints newWhere) throws NullPointerException{ public void setWhere(ClauseConstraints newWhere) throws NullPointerException{
...@@ -198,7 +198,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -198,7 +198,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the GROUP BY clause of this query. * Gets the GROUP BY clause of this query.
* *
* @return Its GROUP BY clause. * @return Its GROUP BY clause.
*/ */
public final ClauseADQL<ADQLColumn> getGroupBy(){ public final ClauseADQL<ADQLColumn> getGroupBy(){
...@@ -207,9 +207,9 @@ public class ADQLQuery implements ADQLObject { ...@@ -207,9 +207,9 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its GROUP BY clause by the given one.</p> * <p>Replaces its GROUP BY clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newGroupBy The new GROUP BY clause. * @param newGroupBy The new GROUP BY clause.
* @throws NullPointerException If the given GROUP BY clause is <i>null</i>. * @throws NullPointerException If the given GROUP BY clause is <i>null</i>.
*/ */
...@@ -223,7 +223,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -223,7 +223,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the HAVING clause of this query. * Gets the HAVING clause of this query.
* *
* @return Its HAVING clause. * @return Its HAVING clause.
*/ */
public final ClauseConstraints getHaving(){ public final ClauseConstraints getHaving(){
...@@ -232,9 +232,9 @@ public class ADQLQuery implements ADQLObject { ...@@ -232,9 +232,9 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its HAVING clause by the given one.</p> * <p>Replaces its HAVING clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newHaving The new HAVING clause. * @param newHaving The new HAVING clause.
* @throws NullPointerException If the given HAVING clause is <i>null</i>. * @throws NullPointerException If the given HAVING clause is <i>null</i>.
*/ */
...@@ -248,7 +248,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -248,7 +248,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Gets the ORDER BY clause of this query. * Gets the ORDER BY clause of this query.
* *
* @return Its ORDER BY clause. * @return Its ORDER BY clause.
*/ */
public final ClauseADQL<ADQLOrder> getOrderBy(){ public final ClauseADQL<ADQLOrder> getOrderBy(){
...@@ -257,9 +257,9 @@ public class ADQLQuery implements ADQLObject { ...@@ -257,9 +257,9 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Replaces its ORDER BY clause by the given one.</p> * <p>Replaces its ORDER BY clause by the given one.</p>
* *
* <p><i>note: the position of the query is erased.</i></p> * <p><i>note: the position of the query is erased.</i></p>
* *
* @param newOrderBy The new ORDER BY clause. * @param newOrderBy The new ORDER BY clause.
* @throws NullPointerException If the given ORDER BY clause is <i>null</i>. * @throws NullPointerException If the given ORDER BY clause is <i>null</i>.
*/ */
...@@ -278,7 +278,7 @@ public class ADQLQuery implements ADQLObject { ...@@ -278,7 +278,7 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Set the position of this {@link ADQLQuery} (or sub-query) inside the whole given ADQL query string. * Set the position of this {@link ADQLQuery} (or sub-query) inside the whole given ADQL query string.
* *
* @param position New position of this {@link ADQLQuery}. * @param position New position of this {@link ADQLQuery}.
* @since 1.4 * @since 1.4
*/ */
...@@ -298,9 +298,9 @@ public class ADQLQuery implements ADQLObject { ...@@ -298,9 +298,9 @@ public class ADQLQuery implements ADQLObject {
/** /**
* <p>Gets the list of columns (database metadata) selected by this query.</p> * <p>Gets the list of columns (database metadata) selected by this query.</p>
* *
* <p><i><u>Note:</u> The list is generated on the fly !</i></p> * <p><i><u>Note:</u> The list is generated on the fly !</i></p>
* *
* @return Selected columns metadata. * @return Selected columns metadata.
*/ */
public DBColumn[] getResultingColumns(){ public DBColumn[] getResultingColumns(){
...@@ -324,11 +324,20 @@ public class ADQLQuery implements ADQLObject { ...@@ -324,11 +324,20 @@ public class ADQLQuery implements ADQLObject {
DBColumn col = null; DBColumn col = null;
// ...whose the name will be set with the SELECT item's alias: // ...whose the name will be set with the SELECT item's alias:
if (item.hasAlias()){ if (item.hasAlias()){
// put the alias in lower case if not written between "":
/* Note: This aims to avoid unexpected behavior at execution
* time in the DBMS (i.e. the case sensitivity is
* forced for every references to this column alias). */
String alias = item.getAlias();
if (!item.isCaseSensitive())
alias = alias.toLowerCase();
// create the DBColumn:
if (operand instanceof ADQLColumn && ((ADQLColumn)operand).getDBLink() != null){ if (operand instanceof ADQLColumn && ((ADQLColumn)operand).getDBLink() != null){
col = ((ADQLColumn)operand).getDBLink(); col = ((ADQLColumn)operand).getDBLink();
col = col.copy(col.getDBName(), item.getAlias(), col.getTable()); col = col.copy(col.getDBName(), alias, col.getTable());
}else }else
col = new DefaultDBColumn(item.getAlias(), null); col = new DefaultDBColumn(alias, null);
} }
// ...or whose the name will be the name of the SELECT item: // ...or whose the name will be the name of the SELECT item:
else{ else{
...@@ -374,9 +383,9 @@ public class ADQLQuery implements ADQLObject { ...@@ -374,9 +383,9 @@ public class ADQLQuery implements ADQLObject {
/** /**
* Lets searching ADQL objects into this ADQL query thanks to the given search handler. * Lets searching ADQL objects into this ADQL query thanks to the given search handler.
* *
* @param sHandler A search handler. * @param sHandler A search handler.
* *
* @return An iterator on all ADQL objects found. * @return An iterator on all ADQL objects found.
*/ */
public Iterator<ADQLObject> search(ISearchHandler sHandler){ public Iterator<ADQLObject> search(ISearchHandler sHandler){
......
...@@ -443,7 +443,10 @@ public abstract class JDBCTranslator implements ADQLTranslator { ...@@ -443,7 +443,10 @@ public abstract class JDBCTranslator implements ADQLTranslator {
StringBuffer translation = new StringBuffer(translate(item.getOperand())); StringBuffer translation = new StringBuffer(translate(item.getOperand()));
if (item.hasAlias()){ if (item.hasAlias()){
translation.append(" AS "); translation.append(" AS ");
appendIdentifier(translation, item.getAlias(), item.isCaseSensitive()); if (item.isCaseSensitive())
appendIdentifier(translation, item.getAlias(), true);
else
appendIdentifier(translation, item.getAlias().toLowerCase(), true);
}else{ }else{
translation.append(" AS "); translation.append(" AS ");
appendIdentifier(translation, item.getName(), true); appendIdentifier(translation, item.getName(), true);
......
...@@ -55,7 +55,6 @@ public class TestSubQueries { ...@@ -55,7 +55,6 @@ public class TestSubQueries {
ADQLParser adqlParser = new ADQLParser(new DBChecker(esaTables)); ADQLParser adqlParser = new ADQLParser(new DBChecker(esaTables));
ADQLQuery query = adqlParser.parseQuery("SELECT oid FROM table1 as MyAlias WHERE oid IN (SELECT oid2 FROM table2 WHERE oid2 = myAlias.oid)"); ADQLQuery query = adqlParser.parseQuery("SELECT oid FROM table1 as MyAlias WHERE oid IN (SELECT oid2 FROM table2 WHERE oid2 = myAlias.oid)");
System.out.println((new PostgreSQLTranslator()).translate(query));
assertEquals("SELECT \"myalias\".\"oid\" AS \"oid\"\nFROM \"public\".\"table1\" AS \"myalias\"\nWHERE \"myalias\".\"oid\" IN (SELECT \"public\".\"table2\".\"oid2\" AS \"oid2\"\nFROM \"public\".\"table2\"\nWHERE \"public\".\"table2\".\"oid2\" = \"myalias\".\"oid\")", (new PostgreSQLTranslator()).translate(query)); assertEquals("SELECT \"myalias\".\"oid\" AS \"oid\"\nFROM \"public\".\"table1\" AS \"myalias\"\nWHERE \"myalias\".\"oid\" IN (SELECT \"public\".\"table2\".\"oid2\" AS \"oid2\"\nFROM \"public\".\"table2\"\nWHERE \"public\".\"table2\".\"oid2\" = \"myalias\".\"oid\")", (new PostgreSQLTranslator()).translate(query));
}catch(Exception ex){ }catch(Exception ex){
ex.printStackTrace(System.err); ex.printStackTrace(System.err);
...@@ -63,4 +62,24 @@ public class TestSubQueries { ...@@ -63,4 +62,24 @@ public class TestSubQueries {
} }
} }
@Test
public void testParentRefToMixedCaseColumnAliasInsideSubQueries(){
try{
TableSetParser tsParser = new TableSetParser();
TAPMetadata esaMetaData = tsParser.parse(new File("test/adql/db/subquery_test_tables.xml"));
ArrayList<DBTable> esaTables = new ArrayList<DBTable>(esaMetaData.getNbTables());
Iterator<TAPTable> itTables = esaMetaData.getTables();
while(itTables.hasNext())
esaTables.add(itTables.next());
ADQLParser adqlParser = new ADQLParser(new DBChecker(esaTables));
ADQLQuery query = adqlParser.parseQuery("SELECT t.* FROM (SELECT (ra+ra_error) AS x, (dec+dec_error) AS Y, pmra AS \"ProperMotion\" FROM table2) AS t");
assertEquals("SELECT \"t\".\"x\" AS \"x\",\"t\".\"y\" AS \"y\",\"t\".\"ProperMotion\" AS \"ProperMotion\"\nFROM (SELECT (\"public\".\"table2\".\"ra\"+\"public\".\"table2\".\"ra_error\") AS \"x\" , (\"public\".\"table2\".\"dec\"+\"public\".\"table2\".\"dec_error\") AS \"y\" , \"public\".\"table2\".\"pmra\" AS \"ProperMotion\"\nFROM \"public\".\"table2\") AS \"t\"", (new PostgreSQLTranslator()).translate(query));
}catch(Exception ex){
ex.printStackTrace(System.err);
fail("No error expected! (see console for more details)");
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment