Commit 496e769c authored by gmantele's avatar gmantele
Browse files

[ADQL,TAP] Add STC-S and UDFs support in the ADQL parser. Now, it is possible...

[ADQL,TAP] Add STC-S and UDFs support in the ADQL parser. Now, it is possible to provide a list of allowed UDFs, regions and coordinate systems. The ServiceConnection of TAP is now able to provide these lists and to propagate them to the ADQLExecutor. UDFs and allowed regions are now listed automatically in the /capabilities resource of TAP. The type 'geometry' is now fully supported in ADQL. That's why the new function 'isGeometry()' has been added to all ADQLOperand extensions. Now the DBChecker is also able to check roughly types of columns and UDFs (unknown when parsing syntactically a query). The syntax of STC-S regions (expressed in the REGION function) are now checked by DBChecker. However, for the moment, geometries are not serialized in STC-S in the output....but it should be possible in some way in the next commit(s).
parent 3938d99d
Loading
Loading
Loading
Loading
+1071 −143

File changed.

Preview size limit exceeded, changes collapsed.

+17 −3
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@ package adql.db;
 * You should have received a copy of the GNU Lesser General Public License
 * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2011 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
 * Copyright 2011,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
 *                       Astronomisches Rechen Institut (ARI)
 */

/**
@@ -27,8 +28,8 @@ package adql.db;
 * 	and corresponds to a real column in the "database" with its DB name ({@link #getDBName()}).
 * </p>
 * 
 * @author Gr&eacute;gory Mantelet (CDS)
 * @version 08/2011
 * @author Gr&eacute;gory Mantelet (CDS;ARI)
 * @version 1.3 (10/2014)
 */
public interface DBColumn {

@@ -46,6 +47,19 @@ public interface DBColumn {
	 */
	public String getDBName();

	/**
	 * <p>Get the type of this column (as closed as possible from the "database" type).</p>
	 * 
	 * <p><i>Note:
	 * 	The returned type should be as closed as possible from a type listed by the IVOA in the TAP protocol description into the section UPLOAD.
	 * </i></p>
	 * 
	 * @return	Its type.
	 * 
	 * @since 1.3
	 */
	public DBType getDatatype();

	/**
	 * Gets the table which contains this {@link DBColumn}.
	 * 
+14 −4
Original line number Diff line number Diff line
@@ -16,12 +16,13 @@ package adql.db;
 * You should have received a copy of the GNU Lesser General Public License
 * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2014 - Astronomishes Rechen Institut (ARI)
 * Copyright 2014 - Astronomisches Rechen Institut (ARI)
 */

import java.util.ArrayList;
import java.util.Iterator;

import adql.db.exception.UnresolvedJoin;
import adql.query.ADQLQuery;

/**
@@ -33,7 +34,7 @@ import adql.query.ADQLQuery;
 * in case of several JOINs.
 * 
 * @author Gr&eacute;gory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de
 * @version 1.2 (11/2013)
 * @version 1.3 (10/2014)
 * @since 1.2
 */
public class DBCommonColumn implements DBColumn {
@@ -54,8 +55,13 @@ public class DBCommonColumn implements DBColumn {
	 * 
	 * @param leftCol	Column of the left join table. May be a {@link DBCommonColumn}.
	 * @param rightCol	Column of the right join table. May be a {@link DBCommonColumn}.
	 * 
	 * @throws UnresolvedJoin	If the type of the two given columns are not roughly (just testing numeric, string or geometry) compatible.
	 */
	public DBCommonColumn(final DBColumn leftCol, final DBColumn rightCol){
	public DBCommonColumn(final DBColumn leftCol, final DBColumn rightCol) throws UnresolvedJoin{
		// Test whether type of both columns are compatible:
		if (leftCol.getDatatype() != null && rightCol.getDatatype() != null && !leftCol.getDatatype().isCompatible(rightCol.getDatatype()))
			throw new UnresolvedJoin("JOIN impossible: incompatible column types when trying to join the columns " + leftCol.getADQLName() + " (" + leftCol.getDatatype() + ") and " + rightCol.getADQLName() + " (" + rightCol.getDatatype() + ")!");

		// LEFT COLUMN:
		if (leftCol instanceof DBCommonColumn){
@@ -83,7 +89,6 @@ public class DBCommonColumn implements DBColumn {
			// add the table to cover:
			addCoveredTable(rightCol.getTable());
		}

	}

	/**
@@ -112,6 +117,11 @@ public class DBCommonColumn implements DBColumn {
		return generalColumnDesc.getDBName();
	}

	@Override
	public final DBType getDatatype(){
		return generalColumnDesc.getDatatype();
	}

	@Override
	public final DBTable getTable(){
		return null;
+76 −27
Original line number Diff line number Diff line
package tap.metadata;
package adql.db;

/*
 * This file is part of TAPLibrary.
 * This file is part of ADQLLibrary.
 * 
 * TAPLibrary 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
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * TAPLibrary 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
@@ -16,35 +16,35 @@ package tap.metadata;
 * You should have received a copy of the GNU Lesser General Public License
 * along with TAPLibrary.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2014 - Astronomishes Rechen Institut (ARI)
 * Copyright 2014 - Astronomisches Rechen Institut (ARI)
 */

/**
 * 
 * <p>
 * 	Describe a full TAP column type as it is described in the IVOA document.
 * 	Describe a full column type as it is described in the IVOA document of TAP.
 * 	Thus, this object contains 2 attributes: <code>type</code> (or datatype) and <code>length</code> (or size).
 * </p>
 * 
 * <p>The length/size may be not defined ; in this case, its value is set to {@link #NO_LENGTH} or is negative or null.</p>
 * 
 * <p>All datatypes declared in the IVOA recommendation document of TAP are listed in an enumeration type: {@link TAPDatatype}.
 * <p>All datatypes declared in the IVOA recommendation document of TAP are listed in an enumeration type: {@link DBDatatype}.
 * It is used to set the attribute type/datatype of this class.</p>
 *  
 * @author Gr&eacute;gory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de
 * @version 2.0 (06/2014)
 * @since 2.0
 * @author Gr&eacute;gory Mantelet (ARI)
 * @version 1.3 (10/2014)
 * @since 1.3
 */
public class TAPType {
public class DBType {

	/**
	 * List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD).
	 * 
	 * @author Gr&eacute;gory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de
	 * @version 2.0 (06/2014)
	 * @since 2.0
	 * @author Gr&eacute;gory Mantelet (ARI)
	 * @version 1.3 (10/2014)
	 * @since 1.3
	 */
	public static enum TAPDatatype{
	public static enum DBDatatype{
		SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION;
	}

@@ -52,7 +52,7 @@ public class TAPType {
	public static final int NO_LENGTH = -1;

	/** Datatype of a column. */
	public final TAPDatatype type;
	public final DBDatatype type;

	/** The length parameter (only few datatypes need this parameter: char, varchar, binary and varbinary). */
	public final int length;
@@ -62,7 +62,7 @@ public class TAPType {
	 * 
	 * @param datatype	Column datatype.
	 */
	public TAPType(final TAPDatatype datatype){
	public DBType(final DBDatatype datatype){
		this(datatype, NO_LENGTH);
	}

@@ -72,22 +72,71 @@ public class TAPType {
	 * @param datatype	Column datatype.
	 * @param length	Length of the column value (needed only for datatypes like char, varchar, binary and varbinary).
	 */
	public TAPType(final TAPDatatype datatype, final int length){
	public DBType(final DBDatatype datatype, final int length){
		if (datatype == null)
			throw new NullPointerException("Missing TAP column datatype !");
		this.type = datatype;
		this.length = length;
	}

	/**
	 * Convert this TAP column type into a VOTable field type.
	 * 
	 * @return	The corresponding VOTable field type.
	 * 
	 * @see VotType#VotType(TAPType)
	 */
	public VotType toVotType(){
		return new VotType(this);
	public boolean isNumeric(){
		switch(type){
			case SMALLINT:
			case INTEGER:
			case BIGINT:
			case REAL:
			case DOUBLE:
				/* Note: binaries are also included here because they can also be considered as Numeric,
				 * but not for JOINs. */
			case BINARY:
			case VARBINARY:
			case BLOB:
				return true;
			default:
				return false;
		}
	}

	public boolean isBinary(){
		switch(type){
			case BINARY:
			case VARBINARY:
			case BLOB:
				return true;
			default:
				return false;
		}
	}

	public boolean isString(){
		switch(type){
			case CHAR:
			case VARCHAR:
			case CLOB:
			case TIMESTAMP:
				return true;
			default:
				return false;
		}
	}

	public boolean isGeometry(){
		return (type == DBDatatype.POINT || type == DBDatatype.REGION);
	}

	public boolean isCompatible(final DBType t){
		if (t == null)
			return false;
		else if (isBinary() == t.isBinary())
			return (type == DBDatatype.BLOB && t.type == DBDatatype.BLOB) || (type != DBDatatype.BLOB && t.type != DBDatatype.BLOB);
		else if (isNumeric() == t.isNumeric())
			return true;
		else if (isGeometry() == t.isGeometry())
			return (type == t.type);
		else if (isString())
			return (type == DBDatatype.CLOB && t.type == DBDatatype.CLOB) || (type != DBDatatype.CLOB && t.type != DBDatatype.CLOB);
		else
			return (type == t.type);
	}

	@Override
+88 −7
Original line number Diff line number Diff line
@@ -16,20 +16,27 @@ package adql.db;
 * You should have received a copy of the GNU Lesser General Public License
 * along with ADQLLibrary.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2012 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
 * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
 *                       Astronomisches Rechen Institut (ARI)
 */

/**
 * Default implementation of {@link DBColumn}.
 * 
 * @author Gr&eacute;gory Mantelet (CDS)
 * @version 08/2011
 * @author Gr&eacute;gory Mantelet (CDS;ARI)
 * @version 1.3 (10/2014)
 */
public class DefaultDBColumn implements DBColumn {

	/** Name of the column in the "database". */
	protected String dbName;
	/** Type of the column in the "database".
	 * <i>Note: This should be one of the types listed by the IVOA in the TAP description.</i>
	 * @since 1.3 */
	protected DBType type;
	/** Table in which this column exists. */
	protected DBTable table;

	/** Name that this column must have in ADQL queries. */
	protected String adqlName = null;

	/**
@@ -40,10 +47,30 @@ public class DefaultDBColumn implements DBColumn {
	 * 					if a whole column reference is given, no split will be done.</b>
	 * @param table		DB table which contains this column.
	 * 
	 * @see #DefaultDBColumn(String, String, DBTable)
	 * @see #DefaultDBColumn(String, String, DBType, DBTable)
	 */
	public DefaultDBColumn(final String dbName, final DBTable table){
		this(dbName, dbName, table);
		this(dbName, dbName, null, table);
	}

	/**
	 * Builds a default {@link DBColumn} with the given DB name and DB table.
	 * 
	 * @param dbName	Database column name (it will be also used for the ADQL name).
	 * 					<b>Only the column name is expected. Contrary to {@link DefaultDBTable},
	 * 					if a whole column reference is given, no split will be done.</b>
	 * @param type		Type of the column.
	 *            		<i>Note: there is no default value. Consequently if this parameter is NULL,
	 *            		the type should be considered as unknown. It means that any comparison with
	 *            		any type will always return 'true'.</i>
	 * @param table		DB table which contains this column.
	 * 
	 * @see #DefaultDBColumn(String, String, DBType, DBTable)
	 * 
	 * @since 1.3
	 */
	public DefaultDBColumn(final String dbName, final DBType type, final DBTable table){
		this(dbName, dbName, type, table);
	}

	/**
@@ -56,13 +83,38 @@ public class DefaultDBColumn implements DBColumn {
	 * 					<b>Only the column name is expected. Contrary to {@link DefaultDBTable},
	 * 					if a whole column reference is given, no split will be done.</b>
	 * @param table		DB table which contains this column.
	 * 
	 * @see #DefaultDBColumn(String, String, DBType, DBTable)
	 */
	public DefaultDBColumn(final String dbName, final String adqlName, final DBTable table){
		this(dbName, adqlName, null, table);
	}

	/**
	 * Builds a default {@link DBColumn} with the given DB name, DB table and ADQL name.
	 * 
	 * @param dbName	Database column name.
	 * 					<b>Only the column name is expected. Contrary to {@link DefaultDBTable},
	 * 					if a whole column reference is given, no split will be done.</b>
	 * @param adqlName	Column name used in ADQL queries.
	 * 					<b>Only the column name is expected. Contrary to {@link DefaultDBTable},
	 * 					if a whole column reference is given, no split will be done.</b>
	 * @param type		Type of the column.
	 *            		<i>Note: there is no default value. Consequently if this parameter is NULL,
	 *            		the type should be considered as unknown. It means that any comparison with
	 *            		any type will always return 'true'.</i>
	 * @param table		DB table which contains this column.
	 * 
	 * @since 1.3
	 */
	public DefaultDBColumn(final String dbName, final String adqlName, final DBType type, final DBTable table){
		this.dbName = dbName;
		this.adqlName = adqlName;
		this.type = type;
		this.table = table;
	}

	@Override
	public final String getADQLName(){
		return adqlName;
	}
@@ -72,10 +124,38 @@ public class DefaultDBColumn implements DBColumn {
			this.adqlName = adqlName;
	}

	@Override
	public final DBType getDatatype(){
		return type;
	}

	/**
	 * <p>Set the type of this column.</p>
	 * 
	 * <p><i>Note 1:
	 * 	The given type should be as closed as possible from a type listed by the IVOA in the TAP protocol description into the section UPLOAD.
	 * </i></p>
	 * 
	 * <p><i>Note 2:
	 * 	there is no default value. Consequently if this parameter is NULL,
	 * 	the type should be considered as unknown. It means that any comparison with
	 * 	any type will always return 'true'.
	 * </i></p>
	 * 
	 * @param type	New type of this column.
	 * 
	 * @since 1.3
	 */
	public final void setDatatype(final DBType type){
		this.type = type;
	}

	@Override
	public final String getDBName(){
		return dbName;
	}

	@Override
	public final DBTable getTable(){
		return table;
	}
@@ -84,8 +164,9 @@ public class DefaultDBColumn implements DBColumn {
		this.table = table;
	}

	@Override
	public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable){
		return new DefaultDBColumn(dbName, adqlName, dbTable);
		return new DefaultDBColumn(dbName, adqlName, type, dbTable);
	}

}
Loading