Loading src/adql/db/DBType.java +130 −5 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.db; * 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 - Astronomisches Rechen Institut (ARI) * Copyright 2014-2015 - Astronomisches Rechen Institut (ARI) */ /** Loading @@ -32,7 +32,7 @@ package adql.db; * It is used to set the attribute type/datatype of this class.</p> * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (07/2015) * @since 1.3 */ public class DBType { Loading @@ -41,11 +41,40 @@ public class DBType { * List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD). * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (06/2015) * @since 1.3 */ public static enum DBDatatype{ SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION; SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION, /** @since 1.4 */ UNKNOWN; /** String to return when {@link #toString()} is called. * @since 1.4*/ private String strExp = this.name(); @Override public String toString(){ return strExp; } /** * <p>This function lets define the name of the type as provided * <b>ONLY FOR {@link #UNKNOWN} {@link DBDatatype}</b>.</p> * * <p><i><b>Important:</b> * If this {@link DBDatatype} is not {@link #UNKNOWN} or if the given name is NULL or empty, * this function has no effect. * </i></p> * * @param typeName User type name. * * @since 1.4 */ public void setCustomType(final String typeName){ if (this == UNKNOWN && typeName != null && typeName.trim().length() > 0) strExp = "?" + typeName.trim() + "?"; } } /** Special value in case no length/size is specified. */ Loading Loading @@ -79,6 +108,23 @@ public class DBType { this.length = length; } /** * <p>Tells whether this type is a numeric.</p> * * <p><i>Concerned types: * {@link DBDatatype#SMALLINT SMALLINT}, {@link DBDatatype#INTEGER INTEGER}, {@link DBDatatype#BIGINT BIGINT}, * {@link DBDatatype#REAL REAL}, {@link DBDatatype#DOUBLE DOUBLE}, {@link DBDatatype#BINARY BINARY}, * {@link DBDatatype#VARBINARY VARBINARY} and {@link DBDatatype#BLOB BLOB}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a numeric, <code>false</code> otherwise. */ public boolean isNumeric(){ switch(type){ case SMALLINT: Loading @@ -91,42 +137,121 @@ public class DBType { case BINARY: case VARBINARY: case BLOB: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is a list of bytes.</p> * * <p><i>Concerned types: * {@link DBDatatype#BINARY BINARY}, {@link DBDatatype#VARBINARY VARBINARY} and {@link DBDatatype#BLOB BLOB}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a binary, <code>false</code> otherwise. */ public boolean isBinary(){ switch(type){ case BINARY: case VARBINARY: case BLOB: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is about characters.</p> * * <p><i>Concerned types: * {@link DBDatatype#CHAR CHAR}, {@link DBDatatype#VARCHAR VARCHAR}, {@link DBDatatype#CLOB CLOB} * and {@link DBDatatype#TIMESTAMP TIMESTAMP}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a string, <code>false</code> otherwise. */ public boolean isString(){ switch(type){ case CHAR: case VARCHAR: case CLOB: case TIMESTAMP: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is a geometrical region.</p> * * <p><i>Concerned types: * {@link DBDatatype#POINT POINT} and {@link DBDatatype#REGION REGION}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a geometry, <code>false</code> otherwise. */ public boolean isGeometry(){ return (type == DBDatatype.POINT || type == DBDatatype.REGION); return (type == DBDatatype.POINT || type == DBDatatype.REGION || type == DBDatatype.UNKNOWN); } /** * <p>Tell whether this type has been resolved or not.</p> * * <p><i>Concerned type: * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type has NOT been resolved, <code>false</code> otherwise. * * @since 1.4 */ public boolean isUnknown(){ return type == DBDatatype.UNKNOWN; } /** * <p>Tell whether this {@link DBType} is compatible with the given one.</p> * * <p> * Two {@link DBType}s are said compatible if they are both binary, numeric, geometric or string. * If one of the two types is {@link DBDatatype#UNKNOWN unknown}, this function will consider them * as compatible and will return <code>true</code>. * </p> * * @param t The type to compare to. * * @return <code>true</code> if this type is compatible with the given one, <code>false</code> otherwise. */ public boolean isCompatible(final DBType t){ if (t == null) return false; else if (isUnknown() || t.isUnknown()) return true; 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()) Loading src/adql/db/FunctionDef.java +45 −21 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ import adql.query.operand.function.UserDefinedFunction; * </p> * * @author Grégory Mantelet (ARI) * @version 1.3 (02/2015) * @version 1.4 (07/2015) * * @since 1.3 */ Loading Loading @@ -86,6 +86,14 @@ public class FunctionDef implements Comparable<FunctionDef> { protected final boolean isNumeric; /** Indicate whether the return type is a geometry. */ protected final boolean isGeometry; /** Indicate whether the return type is an unknown type. * <p><i><u>Note:</u> * If <code>true</code>, {@link #isString}, {@link #isNumeric} * and {@link #isGeometry} are <code>false</code>. Otherwise, * at least one of these attributes is set to <code>true</code>. * </i></p> * @since 1.4 */ protected final boolean isUnknown; /** Total number of parameters. */ public final int nbParams; Loading Loading @@ -122,7 +130,7 @@ public class FunctionDef implements Comparable<FunctionDef> { * <p>This definition is composed of two items: the name and the type of the parameter.</p> * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (07/2015) * @since 1.3 */ public static final class FunctionParam { Loading @@ -135,15 +143,13 @@ public class FunctionDef implements Comparable<FunctionDef> { * Create a function parameter. * * @param paramName Name of the parameter to create. <i>MUST NOT be NULL</i> * @param paramType Type of the parameter to create. <i>MUST NOT be NULL</i> * @param paramType Type of the parameter to create. <i>If NULL, an {@link DBDatatype#UNKNOWN UNKNOWN} type will be created and set instead.</i> */ public FunctionParam(final String paramName, final DBType paramType){ if (paramName == null) throw new NullPointerException("Missing name! The function parameter can not be created."); if (paramType == null) throw new NullPointerException("Missing type! The function parameter can not be created."); this.name = paramName; this.type = paramType; this.type = (paramType == null) ? new DBType(DBDatatype.UNKNOWN) : paramType; } } Loading Loading @@ -193,13 +199,11 @@ public class FunctionDef implements Comparable<FunctionDef> { this.nbParams = (params == null) ? 0 : params.length; // Set the return type; this.returnType = returnType; if (returnType != null){ isNumeric = returnType.isNumeric(); isString = returnType.isString(); isGeometry = returnType.isGeometry(); }else isNumeric = isString = isGeometry = false; this.returnType = (returnType != null) ? returnType : new DBType(DBDatatype.UNKNOWN); isUnknown = this.returnType.isUnknown(); isNumeric = isUnknown || this.returnType.isNumeric(); isString = isUnknown || this.returnType.isString(); isGeometry = isUnknown || this.returnType.isGeometry(); // Serialize in Strings (serializedForm and compareForm) this function definition: StringBuffer bufSer = new StringBuffer(name), bufCmp = new StringBuffer(name.toLowerCase()); Loading Loading @@ -244,6 +248,20 @@ public class FunctionDef implements Comparable<FunctionDef> { return isGeometry; } /** * <p>Tell whether this function returns an unknown type.</p> * * <p> * If this function returns <code>true</code>, {@link #isNumeric()}, {@link #isString()} and {@link #isGeometry()} * <b>MUST ALL</b> return <code>false</code>. Otherwise, one of these 3 last functions MUST return <code>true</code>. * </p> * * @return <i>true</i> if this function returns an unknown/unresolved/unsupported type, <i>false</i> otherwise. */ public final boolean isUnknown(){ return isUnknown; } /** * Get the number of parameters required by this function. * Loading Loading @@ -357,8 +375,10 @@ public class FunctionDef implements Comparable<FunctionDef> { DBType returnType = null; if (m.group(3) != null){ returnType = parseType(m.group(5), (m.group(7) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(7))); if (returnType == null) throw new ParseException("Unknown return type: \"" + m.group(4).trim() + "\"!"); if (returnType == null){ returnType = new DBType(DBDatatype.UNKNOWN); returnType.type.setCustomType(m.group(4)); } } // Get the parameters, if any: Loading @@ -384,9 +404,10 @@ public class FunctionDef implements Comparable<FunctionDef> { paramType = parseType(m.group(2), (m.group(4) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(4))); // ...build the parameter definition object: if (paramType == null) throw new ParseException("Unknown type for the parameter \"" + m.group(1) + "\": \"" + m.group(2) + ((m.group(3) == null) ? "" : m.group(3)) + "\"!"); else if (paramType == null){ paramType = new DBType(DBDatatype.UNKNOWN); paramType.type.setCustomType(m.group(2) + ((m.group(3) == null) ? "" : m.group(3))); } params[i] = new FunctionParam(m.group(1), paramType); }else // note: should never happen because we have already check the syntax of the whole parameters list before parsing each individual parameter. Loading @@ -410,7 +431,8 @@ public class FunctionDef implements Comparable<FunctionDef> { * <i>Note: This length will be used only for binary (BINARY and VARBINARY) * and character (CHAR and VARCHAR) types.</i> * * @return The object representation of the specified datatype. * @return The object representation of the specified datatype * or NULL if the specified datatype can not be resolved. */ private static DBType parseType(String datatype, int length){ if (datatype == null) Loading Loading @@ -519,7 +541,9 @@ public class FunctionDef implements Comparable<FunctionDef> { // If equals, compare the parameters' type: if (comp == 0){ for(int i = 0; comp == 0 && i < nbParams && i < fct.getNbParameters(); i++){ if (params[i].type.isNumeric() == fct.getParameter(i).isNumeric()){ if (fct.getParameter(i).isNumeric() && fct.getParameter(i).isString() && fct.getParameter(i).isGeometry()) comp = 0; else if (params[i].type.isNumeric() == fct.getParameter(i).isNumeric()){ if (params[i].type.isString() == fct.getParameter(i).isString()){ if (params[i].type.isGeometry() == fct.getParameter(i).isGeometry()) comp = 0; Loading src/adql/translator/PgSphereTranslator.java +3 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.translator; * 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,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ Loading Loading @@ -48,7 +48,7 @@ import adql.query.operand.function.geometry.PolygonFunction; * The other functions are managed by {@link PostgreSQLTranslator}.</p> * * @author Grégory Mantelet (CDS;ARI) * @version 1.3 (11/2014) * @version 1.4 (07/2015) */ public class PgSphereTranslator extends PostgreSQLTranslator { Loading Loading @@ -202,7 +202,7 @@ public class PgSphereTranslator extends PostgreSQLTranslator { public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; // Put the dbmsTypeName in lower case for the following comparisons: dbmsTypeName = dbmsTypeName.toLowerCase(); Loading src/adql/translator/PostgreSQLTranslator.java +4 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.translator; * 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-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ Loading Loading @@ -50,7 +50,7 @@ import adql.query.operand.function.geometry.RegionFunction; * </i></p> * * @author Grégory Mantelet (CDS;ARI) * @version 1.3 (11/2014) * @version 1.4 (07/2015) * * @see PgSphereTranslator */ Loading Loading @@ -196,7 +196,7 @@ public class PostgreSQLTranslator extends JDBCTranslator { public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; // Put the dbmsTypeName in lower case for the following comparisons: dbmsTypeName = dbmsTypeName.toLowerCase(); Loading Loading @@ -247,7 +247,7 @@ public class PostgreSQLTranslator extends JDBCTranslator { return new DBType(DBDatatype.TIMESTAMP); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; } @Override Loading src/tap/data/ResultSetTableIterator.java +10 −8 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package tap.data; * 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 - Astronomisches Rechen Institut (ARI) * Copyright 2014-2015 - Astronomisches Rechen Institut (ARI) */ import java.sql.ResultSet; Loading @@ -42,7 +42,7 @@ import adql.translator.JDBCTranslator; * </i></p> * * @author Grégory Mantelet (ARI) * @version 2.0 (11/2014) * @version 2.1 (07/2015) * @since 2.0 */ public class ResultSetTableIterator implements TableIterator { Loading Loading @@ -363,7 +363,7 @@ public class ResultSetTableIterator implements TableIterator { if (o instanceof Timestamp) o = ISO8601Format.format(((Timestamp)o).getTime()); // if the column value is a geometrical object, it must be serialized in STC-S: else if (translator != null && colType.isGeometry()){ else if (translator != null && colType != null && colType.isGeometry()){ Region region = translator.translateGeometryFromDB(o); if (region != null) o = region.toSTCS(); Loading Loading @@ -409,7 +409,8 @@ public class ResultSetTableIterator implements TableIterator { * @param dbmsType DBMS column data-type name. * @param dbms Lower-case string which indicates which DBMS the ResultSet is coming from. <i>note: MAY be NULL.</i> * * @return The best suited {@link DBType} object. * @return The best suited {@link DBType} object, * or an {@link DBDatatype#UNKNOWN UNKNOWN} type if none can be found. * * @see JDBCTranslator#convertTypeFromDB(int, String, String, String[]) * @see #defaultTypeConversion(String, String[], String) Loading @@ -417,7 +418,7 @@ public class ResultSetTableIterator implements TableIterator { protected DBType convertType(final int dbmsType, String dbmsTypeName, final String dbms) throws DataReadException{ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); // Extract the type prefix and lower-case it: int startParamIndex = dbmsTypeName.indexOf('('), endParamIndex = dbmsTypeName.indexOf(')'); Loading Loading @@ -468,7 +469,8 @@ public class ResultSetTableIterator implements TableIterator { * @param params The eventual type parameters (e.g. char string length). * @param dbms The targeted DBMS. * * @return The corresponding ADQL/TAP type. <i>NEVER NULL</i> * @return The corresponding ADQL/TAP type. <i>NEVER NULL ; * an {@link DBDatatype#UNKNOWN UNKNOWN} type is returned in case no match can be found.</i> */ protected final DBType defaultTypeConversion(final String dbmsTypeName, final String[] params, final String dbms){ // Get the length parameter (always in first position): Loading @@ -495,7 +497,7 @@ public class ResultSetTableIterator implements TableIterator { return new DBType(DBDatatype.BLOB); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); } // CASE: OTHER DBMS else{ Loading Loading @@ -537,7 +539,7 @@ public class ResultSetTableIterator implements TableIterator { return new DBType(DBDatatype.TIMESTAMP); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); } } Loading Loading
src/adql/db/DBType.java +130 −5 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.db; * 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 - Astronomisches Rechen Institut (ARI) * Copyright 2014-2015 - Astronomisches Rechen Institut (ARI) */ /** Loading @@ -32,7 +32,7 @@ package adql.db; * It is used to set the attribute type/datatype of this class.</p> * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (07/2015) * @since 1.3 */ public class DBType { Loading @@ -41,11 +41,40 @@ public class DBType { * List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD). * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (06/2015) * @since 1.3 */ public static enum DBDatatype{ SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION; SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION, /** @since 1.4 */ UNKNOWN; /** String to return when {@link #toString()} is called. * @since 1.4*/ private String strExp = this.name(); @Override public String toString(){ return strExp; } /** * <p>This function lets define the name of the type as provided * <b>ONLY FOR {@link #UNKNOWN} {@link DBDatatype}</b>.</p> * * <p><i><b>Important:</b> * If this {@link DBDatatype} is not {@link #UNKNOWN} or if the given name is NULL or empty, * this function has no effect. * </i></p> * * @param typeName User type name. * * @since 1.4 */ public void setCustomType(final String typeName){ if (this == UNKNOWN && typeName != null && typeName.trim().length() > 0) strExp = "?" + typeName.trim() + "?"; } } /** Special value in case no length/size is specified. */ Loading Loading @@ -79,6 +108,23 @@ public class DBType { this.length = length; } /** * <p>Tells whether this type is a numeric.</p> * * <p><i>Concerned types: * {@link DBDatatype#SMALLINT SMALLINT}, {@link DBDatatype#INTEGER INTEGER}, {@link DBDatatype#BIGINT BIGINT}, * {@link DBDatatype#REAL REAL}, {@link DBDatatype#DOUBLE DOUBLE}, {@link DBDatatype#BINARY BINARY}, * {@link DBDatatype#VARBINARY VARBINARY} and {@link DBDatatype#BLOB BLOB}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a numeric, <code>false</code> otherwise. */ public boolean isNumeric(){ switch(type){ case SMALLINT: Loading @@ -91,42 +137,121 @@ public class DBType { case BINARY: case VARBINARY: case BLOB: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is a list of bytes.</p> * * <p><i>Concerned types: * {@link DBDatatype#BINARY BINARY}, {@link DBDatatype#VARBINARY VARBINARY} and {@link DBDatatype#BLOB BLOB}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a binary, <code>false</code> otherwise. */ public boolean isBinary(){ switch(type){ case BINARY: case VARBINARY: case BLOB: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is about characters.</p> * * <p><i>Concerned types: * {@link DBDatatype#CHAR CHAR}, {@link DBDatatype#VARCHAR VARCHAR}, {@link DBDatatype#CLOB CLOB} * and {@link DBDatatype#TIMESTAMP TIMESTAMP}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a string, <code>false</code> otherwise. */ public boolean isString(){ switch(type){ case CHAR: case VARCHAR: case CLOB: case TIMESTAMP: case UNKNOWN: return true; default: return false; } } /** * <p>Tells whether this type is a geometrical region.</p> * * <p><i>Concerned types: * {@link DBDatatype#POINT POINT} and {@link DBDatatype#REGION REGION}. * </i></p> * * <p><i><b>Important note</b>: * Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything. * That's why, this function will also returned <code>true</code> if the type is * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type is a geometry, <code>false</code> otherwise. */ public boolean isGeometry(){ return (type == DBDatatype.POINT || type == DBDatatype.REGION); return (type == DBDatatype.POINT || type == DBDatatype.REGION || type == DBDatatype.UNKNOWN); } /** * <p>Tell whether this type has been resolved or not.</p> * * <p><i>Concerned type: * {@link DBDatatype#UNKNOWN UNKNOWN}. * </i></p> * * @return <code>true</code> if this type has NOT been resolved, <code>false</code> otherwise. * * @since 1.4 */ public boolean isUnknown(){ return type == DBDatatype.UNKNOWN; } /** * <p>Tell whether this {@link DBType} is compatible with the given one.</p> * * <p> * Two {@link DBType}s are said compatible if they are both binary, numeric, geometric or string. * If one of the two types is {@link DBDatatype#UNKNOWN unknown}, this function will consider them * as compatible and will return <code>true</code>. * </p> * * @param t The type to compare to. * * @return <code>true</code> if this type is compatible with the given one, <code>false</code> otherwise. */ public boolean isCompatible(final DBType t){ if (t == null) return false; else if (isUnknown() || t.isUnknown()) return true; 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()) Loading
src/adql/db/FunctionDef.java +45 −21 Original line number Diff line number Diff line Loading @@ -49,7 +49,7 @@ import adql.query.operand.function.UserDefinedFunction; * </p> * * @author Grégory Mantelet (ARI) * @version 1.3 (02/2015) * @version 1.4 (07/2015) * * @since 1.3 */ Loading Loading @@ -86,6 +86,14 @@ public class FunctionDef implements Comparable<FunctionDef> { protected final boolean isNumeric; /** Indicate whether the return type is a geometry. */ protected final boolean isGeometry; /** Indicate whether the return type is an unknown type. * <p><i><u>Note:</u> * If <code>true</code>, {@link #isString}, {@link #isNumeric} * and {@link #isGeometry} are <code>false</code>. Otherwise, * at least one of these attributes is set to <code>true</code>. * </i></p> * @since 1.4 */ protected final boolean isUnknown; /** Total number of parameters. */ public final int nbParams; Loading Loading @@ -122,7 +130,7 @@ public class FunctionDef implements Comparable<FunctionDef> { * <p>This definition is composed of two items: the name and the type of the parameter.</p> * * @author Grégory Mantelet (ARI) * @version 1.3 (10/2014) * @version 1.4 (07/2015) * @since 1.3 */ public static final class FunctionParam { Loading @@ -135,15 +143,13 @@ public class FunctionDef implements Comparable<FunctionDef> { * Create a function parameter. * * @param paramName Name of the parameter to create. <i>MUST NOT be NULL</i> * @param paramType Type of the parameter to create. <i>MUST NOT be NULL</i> * @param paramType Type of the parameter to create. <i>If NULL, an {@link DBDatatype#UNKNOWN UNKNOWN} type will be created and set instead.</i> */ public FunctionParam(final String paramName, final DBType paramType){ if (paramName == null) throw new NullPointerException("Missing name! The function parameter can not be created."); if (paramType == null) throw new NullPointerException("Missing type! The function parameter can not be created."); this.name = paramName; this.type = paramType; this.type = (paramType == null) ? new DBType(DBDatatype.UNKNOWN) : paramType; } } Loading Loading @@ -193,13 +199,11 @@ public class FunctionDef implements Comparable<FunctionDef> { this.nbParams = (params == null) ? 0 : params.length; // Set the return type; this.returnType = returnType; if (returnType != null){ isNumeric = returnType.isNumeric(); isString = returnType.isString(); isGeometry = returnType.isGeometry(); }else isNumeric = isString = isGeometry = false; this.returnType = (returnType != null) ? returnType : new DBType(DBDatatype.UNKNOWN); isUnknown = this.returnType.isUnknown(); isNumeric = isUnknown || this.returnType.isNumeric(); isString = isUnknown || this.returnType.isString(); isGeometry = isUnknown || this.returnType.isGeometry(); // Serialize in Strings (serializedForm and compareForm) this function definition: StringBuffer bufSer = new StringBuffer(name), bufCmp = new StringBuffer(name.toLowerCase()); Loading Loading @@ -244,6 +248,20 @@ public class FunctionDef implements Comparable<FunctionDef> { return isGeometry; } /** * <p>Tell whether this function returns an unknown type.</p> * * <p> * If this function returns <code>true</code>, {@link #isNumeric()}, {@link #isString()} and {@link #isGeometry()} * <b>MUST ALL</b> return <code>false</code>. Otherwise, one of these 3 last functions MUST return <code>true</code>. * </p> * * @return <i>true</i> if this function returns an unknown/unresolved/unsupported type, <i>false</i> otherwise. */ public final boolean isUnknown(){ return isUnknown; } /** * Get the number of parameters required by this function. * Loading Loading @@ -357,8 +375,10 @@ public class FunctionDef implements Comparable<FunctionDef> { DBType returnType = null; if (m.group(3) != null){ returnType = parseType(m.group(5), (m.group(7) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(7))); if (returnType == null) throw new ParseException("Unknown return type: \"" + m.group(4).trim() + "\"!"); if (returnType == null){ returnType = new DBType(DBDatatype.UNKNOWN); returnType.type.setCustomType(m.group(4)); } } // Get the parameters, if any: Loading @@ -384,9 +404,10 @@ public class FunctionDef implements Comparable<FunctionDef> { paramType = parseType(m.group(2), (m.group(4) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(4))); // ...build the parameter definition object: if (paramType == null) throw new ParseException("Unknown type for the parameter \"" + m.group(1) + "\": \"" + m.group(2) + ((m.group(3) == null) ? "" : m.group(3)) + "\"!"); else if (paramType == null){ paramType = new DBType(DBDatatype.UNKNOWN); paramType.type.setCustomType(m.group(2) + ((m.group(3) == null) ? "" : m.group(3))); } params[i] = new FunctionParam(m.group(1), paramType); }else // note: should never happen because we have already check the syntax of the whole parameters list before parsing each individual parameter. Loading @@ -410,7 +431,8 @@ public class FunctionDef implements Comparable<FunctionDef> { * <i>Note: This length will be used only for binary (BINARY and VARBINARY) * and character (CHAR and VARCHAR) types.</i> * * @return The object representation of the specified datatype. * @return The object representation of the specified datatype * or NULL if the specified datatype can not be resolved. */ private static DBType parseType(String datatype, int length){ if (datatype == null) Loading Loading @@ -519,7 +541,9 @@ public class FunctionDef implements Comparable<FunctionDef> { // If equals, compare the parameters' type: if (comp == 0){ for(int i = 0; comp == 0 && i < nbParams && i < fct.getNbParameters(); i++){ if (params[i].type.isNumeric() == fct.getParameter(i).isNumeric()){ if (fct.getParameter(i).isNumeric() && fct.getParameter(i).isString() && fct.getParameter(i).isGeometry()) comp = 0; else if (params[i].type.isNumeric() == fct.getParameter(i).isNumeric()){ if (params[i].type.isString() == fct.getParameter(i).isString()){ if (params[i].type.isGeometry() == fct.getParameter(i).isGeometry()) comp = 0; Loading
src/adql/translator/PgSphereTranslator.java +3 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.translator; * 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,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ Loading Loading @@ -48,7 +48,7 @@ import adql.query.operand.function.geometry.PolygonFunction; * The other functions are managed by {@link PostgreSQLTranslator}.</p> * * @author Grégory Mantelet (CDS;ARI) * @version 1.3 (11/2014) * @version 1.4 (07/2015) */ public class PgSphereTranslator extends PostgreSQLTranslator { Loading Loading @@ -202,7 +202,7 @@ public class PgSphereTranslator extends PostgreSQLTranslator { public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; // Put the dbmsTypeName in lower case for the following comparisons: dbmsTypeName = dbmsTypeName.toLowerCase(); Loading
src/adql/translator/PostgreSQLTranslator.java +4 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package adql.translator; * 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-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Copyright 2012-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ Loading Loading @@ -50,7 +50,7 @@ import adql.query.operand.function.geometry.RegionFunction; * </i></p> * * @author Grégory Mantelet (CDS;ARI) * @version 1.3 (11/2014) * @version 1.4 (07/2015) * * @see PgSphereTranslator */ Loading Loading @@ -196,7 +196,7 @@ public class PostgreSQLTranslator extends JDBCTranslator { public DBType convertTypeFromDB(final int dbmsType, final String rawDbmsTypeName, String dbmsTypeName, final String[] params){ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; // Put the dbmsTypeName in lower case for the following comparisons: dbmsTypeName = dbmsTypeName.toLowerCase(); Loading Loading @@ -247,7 +247,7 @@ public class PostgreSQLTranslator extends JDBCTranslator { return new DBType(DBDatatype.TIMESTAMP); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return null; } @Override Loading
src/tap/data/ResultSetTableIterator.java +10 −8 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package tap.data; * 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 - Astronomisches Rechen Institut (ARI) * Copyright 2014-2015 - Astronomisches Rechen Institut (ARI) */ import java.sql.ResultSet; Loading @@ -42,7 +42,7 @@ import adql.translator.JDBCTranslator; * </i></p> * * @author Grégory Mantelet (ARI) * @version 2.0 (11/2014) * @version 2.1 (07/2015) * @since 2.0 */ public class ResultSetTableIterator implements TableIterator { Loading Loading @@ -363,7 +363,7 @@ public class ResultSetTableIterator implements TableIterator { if (o instanceof Timestamp) o = ISO8601Format.format(((Timestamp)o).getTime()); // if the column value is a geometrical object, it must be serialized in STC-S: else if (translator != null && colType.isGeometry()){ else if (translator != null && colType != null && colType.isGeometry()){ Region region = translator.translateGeometryFromDB(o); if (region != null) o = region.toSTCS(); Loading Loading @@ -409,7 +409,8 @@ public class ResultSetTableIterator implements TableIterator { * @param dbmsType DBMS column data-type name. * @param dbms Lower-case string which indicates which DBMS the ResultSet is coming from. <i>note: MAY be NULL.</i> * * @return The best suited {@link DBType} object. * @return The best suited {@link DBType} object, * or an {@link DBDatatype#UNKNOWN UNKNOWN} type if none can be found. * * @see JDBCTranslator#convertTypeFromDB(int, String, String, String[]) * @see #defaultTypeConversion(String, String[], String) Loading @@ -417,7 +418,7 @@ public class ResultSetTableIterator implements TableIterator { protected DBType convertType(final int dbmsType, String dbmsTypeName, final String dbms) throws DataReadException{ // If no type is provided return VARCHAR: if (dbmsTypeName == null || dbmsTypeName.trim().length() == 0) return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); // Extract the type prefix and lower-case it: int startParamIndex = dbmsTypeName.indexOf('('), endParamIndex = dbmsTypeName.indexOf(')'); Loading Loading @@ -468,7 +469,8 @@ public class ResultSetTableIterator implements TableIterator { * @param params The eventual type parameters (e.g. char string length). * @param dbms The targeted DBMS. * * @return The corresponding ADQL/TAP type. <i>NEVER NULL</i> * @return The corresponding ADQL/TAP type. <i>NEVER NULL ; * an {@link DBDatatype#UNKNOWN UNKNOWN} type is returned in case no match can be found.</i> */ protected final DBType defaultTypeConversion(final String dbmsTypeName, final String[] params, final String dbms){ // Get the length parameter (always in first position): Loading @@ -495,7 +497,7 @@ public class ResultSetTableIterator implements TableIterator { return new DBType(DBDatatype.BLOB); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); } // CASE: OTHER DBMS else{ Loading Loading @@ -537,7 +539,7 @@ public class ResultSetTableIterator implements TableIterator { return new DBType(DBDatatype.TIMESTAMP); // Default: else return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); return new DBType(DBDatatype.UNKNOWN); } } Loading