This sub-version fixes also few (but quite important) bugs and adds a better support for STC-S expressions and UDFs.
STC-S expressions like a region definition or a coordinate system, as restricted by the TAP protocol (see 6. Use of STC-S in TAP (informative)) are now checked by the library. A syntax mistake will be notified with a ParserException.
DBChecker has been modified in order to be also able to check whether the used
geometrical functions, coordinate systems and User Defined Functions are allowed. For that, a list of allowed items may be provided
in the constructor. For geometries, each item of the list must be a function name (e.g. AREA, COORDSYS, BOX, CIRCLE). For coordinate
system, a kind of regular expression (e.g.
ICRS * *) is expected for each item. But for UDFs, each item must be an
instance of FunctionDef in which a
UserDefinedFunction may be provided in order to
specify how to translate the function.
Warning: The possibility to list coordinate systems directly in the parser has been removed. Now, verification of coordinate systems must be done afterwards using a QueryChecker (see A.3. Checker to see how).
Actually, it is not really about a new translator. JDBCTranslator is an abstract class between the interface ADQLTranslator and the concrete translator PostgreSQLTranslator. The idea is to use this abstract class for any other translator into SQL language. Indeed, the translation into SQL is very similar in all DBMS. So in this abstract translator all common instructions in ADQL and SQL are already translated ; only functions related to geometrical functions and column types are left for implementation. Thus, a huge work can be avoided while willing to support a new SQL-based translator.
Before this fix,
NOT BETWEEN were translated by
BETWEEN. So, the negation
was forgotten. This grave mistake is now fixed!
table.* was translated as provided...which is a grave mistake in case the TAP table content is different
from the database table. This should be translated by replacing this "joker" by the full list of columns as described in the TAP
metadata. It is actually the behavior of the general "joker"
A string like
'foo\'bar\'' contains twice the same escaped character:
'. However, this escaped string
is not interpreted as one by Postgres by default. To specify a string may contain escaped characters, it must be prefixed by
E (in upper- or lower-case). The library was not doing so before this version 1.3 which is now prefixing string
constants only when at least one \ is detected:
When no alias is specified for a SELECT item, the library is adding one automatically. Thus, the alias of a column is the name of the column and the alias of a function is the function name. For a concatenation or mathematical operations, the sign of the operation is used as alias. However, before this new sub-version, double quotes were not surrounding those aliases. That is a problem for mathematical operations which were then interpreted as a real operation rather than just an alias: a SQL error were then returned by the DBMS.
This bug is now fixed: automatic aliases are always surrounded by double quotes.
The DEBUG mode of the parser was enabled by default...meaning that all grammar rules were listed when parsing a query. This mode is still possible but now disabled by default.
This sub-version is just a correction of several bugs often encountered. Here are the major bugs fixed (the list is not exhaustive):
Parse exceptions about columns inside the clauses ORDER and GROUP BY had no information about the position in the query. This is now fixed!
Brackets in mathematical or logical operations had no effect when translating the query in SQL. The notion of priority was well read and represented in the object tree, but it was not used during the SQL translation.
For instance, the following ADQL query:
SELECT oid AS oid FROM A WHERE oid = 1 AND (colTxtB = 'toto' or colC*(colA-colB) > colD);
...was translated in SQL:
SELECT oid AS oid FROM A WHERE oid = 1 AND colTxtB = 'toto' OR colC*colA-colB > colD
In conformity with the IVOA definition, these two functions must have either 1 or 2 parameters. Before, the library was allowing just one parameter. Now, both are allowed.
The query checker was not allowing subqueries to use columns of the parent/main query.
SELECT oid, colA, colB FROM A WHERE ... AND (SELECT COUNT(*) FROM B WHERE B.oid = A.oid) > 1;
After 3-4 NATURAL joins or joins using the keyword USING, the query checker was lost and returned wrong errors. Columns which were supposed to be joined were not seen like that by the checker. Now they are!
For example: let's suppose that we have 3 tables (A, B and C) and all of them have a column with the same name: oid. The following query:
SELECT oid FROM A NATURAL JOIN B NATURAL JOIN C; -- which more or less equivalent to: SELECT oid FROM A JOIN B USING(oid) JOIN C USING(oid);
With the version 1.1, we get the following error:
((X)) 1 unresolved identifiers ! * [l.1 c.8 - l.1 c.11] - Ambiguous column name "oid" ! It may be (at least) "A.oid" or "B.oid".
When creating your own user defined function with some parameters using DefaultUDF, you may have had an ArrayIndexOutOfBoundsException. This bug is now fixed!
Before this correction, the alias of a sub-query in the clause FROM was not taken into account when checking the query with DBChecker.
For instance, the following query:
SELECT q.flux, q.filter, p.oid, p.ra, p.dec FROM (SELECT flux, filter, oidref FROM flux WHERE flux BETWEEN 0 AND 10) AS q INNER JOIN basic ON q.oidref = p.oid;
In this case, the following error was returned:
((X)) 7 unresolved identifiers ! * [l.1 c.8 - l.1 c.14] - Unknown column "q.flux" ! * [l.1 c.16 - l.1 c.24] - Unknown column "q.filter" ! * [l.1 c.26 - l.1 c.31] - Unknown column "p.oid" ! * [l.1 c.33 - l.1 c.37] - Unknown column "p.ra" ! * [l.1 c.39 - l.1 c.44] - Unknown column "p.dec" ! * [l.2 c.99 - l.2 c.107] - Unknown column "q.oidref" ! * [l.2 c.110 - l.2 c.115] - Unknown column "p.oid" ! adql.db.exception.UnresolvedIdentifiersException: 7 unresolved identifiers ! at adql.db.DBChecker.check(DBChecker.java:170) at adql.parser.ADQLParser.QueryExpression(ADQLParser.java:539) at adql.parser.ADQLParser.Query(ADQLParser.java:473) at adql.parser.ADQLParser.parseQuery(ADQLParser.java:269) at adql.demo.ADQLDemo.main(ADQLDemo.java:125)
The problem has been fixed by setting a default description of the sub-query into the
ADQLTable which describes it.
See the following correction for more details.
This method builds a DefaultDBTable object describing the table returned by the represented sub-query.