Skip to content
Snippets Groups Projects
Commit 0003e343 authored by gmantele's avatar gmantele
Browse files

[ADQL] Set a type to a query's resulting column when it is not originally a column.

This is easily possible for concatenations, string constants and User Defined
Functions having a FunctionDef. A new special datatype was needed for
numeric functions and operations: UNKNOWN_NUMERIC. This special type
can not be set with FunctionDef.parse(...) and it behaves exactly like the type
UNKNOWN, except that DBType.isNumeric() returns true (as .isUnknown()).
Thus, while writing the metadata of a result in TAP, nothing changes:
an UNKNOWN_NUMERIC type will be processed similarly as an UNKNOWN type:
to use the type returned from the database ResultSet or to set VARCHAR.
(no modification of TAP was needed for that)
parent 475fcb65
No related branches found
No related tags found
No related merge requests found
......@@ -16,11 +16,10 @@ 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-2015 - Astronomisches Rechen Institut (ARI)
* Copyright 2014-2016 - Astronomisches Rechen Institut (ARI)
*/
/**
*
* <p>
* 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).
......@@ -32,7 +31,7 @@ package adql.db;
* It is used to set the attribute type/datatype of this class.</p>
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 1.4 (08/2015)
* @version 1.4 (03/2016)
* @since 1.3
*/
public class DBType {
......@@ -41,13 +40,21 @@ public class DBType {
* List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD).
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 1.4 (06/2015)
* @version 1.4 (03/2016)
* @since 1.3
*/
public static enum DBDatatype{
SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION,
/** @since 1.4 */
UNKNOWN;
/** Type to use when the precise datatype is unknown.
* @since 1.4 */
UNKNOWN,
/** <p>Type to use when the type is known as numeric but there is no precise datatype
* (e.g. double, float, integer, ...).</p>
* <p>It is particularly used when creating a {@link DefaultDBColumn} from an ADQL function
* or operation while listing resulting columns of a sub-query.</p>
* <p>This type is similar to {@link #UNKNOWN}.</p>
* @since 1.4 */
UNKNOWN_NUMERIC;
/** String to return when {@link #toString()} is called.
* @since 1.4*/
......@@ -60,11 +67,11 @@ public class DBType {
/**
* <p>This function lets define the name of the type as provided
* <b>ONLY FOR {@link #UNKNOWN} {@link DBDatatype}</b>.</p>
* <b>ONLY FOR {@link #UNKNOWN} and {@link #UNKNOWN_NUMERIC} {@link DBDatatype}s</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.
* If this {@link DBDatatype} is not {@link #UNKNOWN} or {@link #UNKNOWN_NUMERIC} or
* if the given name is NULL or empty, this function has no effect.
* </i></p>
*
* @param typeName User type name.
......@@ -72,7 +79,7 @@ public class DBType {
* @since 1.4
*/
public void setCustomType(final String typeName){
if (this == UNKNOWN && typeName != null && typeName.trim().length() > 0)
if ((this == UNKNOWN || this == UNKNOWN_NUMERIC) && typeName != null && typeName.trim().length() > 0)
strExp = "?" + typeName.trim() + "?";
}
}
......@@ -121,7 +128,8 @@ public class DBType {
* Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything.
* But, in order to avoid incorrect operation while expecting a numeric although the type is unknown
* and is in fact not really a numeric, this function will return <code>false</code> if the type is
* {@link DBDatatype#UNKNOWN UNKNOWN}.
* {@link DBDatatype#UNKNOWN UNKNOWN} <b>BUT</b> <code>true</code> if
* {@link DBDatatype#UNKNOWN_NUMERIC UNKNOWN_NUMERIC}.
* </i></p>
*
* @return <code>true</code> if this type is a numeric, <code>false</code> otherwise.
......@@ -138,6 +146,7 @@ public class DBType {
case BINARY:
case VARBINARY:
case BLOB:
case UNKNOWN_NUMERIC:
return true;
default:
return false;
......@@ -155,7 +164,7 @@ public class DBType {
* Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything.
* But, in order to avoid incorrect operation while expecting a binary although the type is unknown
* and is in fact not really a binary, this function will return <code>false</code> if the type is
* {@link DBDatatype#UNKNOWN UNKNOWN}.
* {@link DBDatatype#UNKNOWN UNKNOWN} or {@link DBDatatype#UNKNOWN_NUMERIC UNKNOWN_NUMERIC}.
* </i></p>
*
* @return <code>true</code> if this type is a binary, <code>false</code> otherwise.
......@@ -183,7 +192,7 @@ public class DBType {
* Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything.
* But, in order to avoid incorrect operation while expecting a string although the type is unknown
* and is in fact not really a string, this function will return <code>false</code> if the type is
* {@link DBDatatype#UNKNOWN UNKNOWN}.
* {@link DBDatatype#UNKNOWN UNKNOWN} or {@link DBDatatype#UNKNOWN_NUMERIC UNKNOWN_NUMERIC}
* </i></p>
*
* @return <code>true</code> if this type is a string, <code>false</code> otherwise.
......@@ -211,7 +220,7 @@ public class DBType {
* Since {@link DBDatatype#UNKNOWN UNKNOWN} is an unresolved type, it can potentially be anything.
* But, in order to avoid incorrect operation while expecting a geometry although the type is unknown
* and is in fact not really a geometry, this function will return <code>false</code> if the type is
* {@link DBDatatype#UNKNOWN UNKNOWN}.
* {@link DBDatatype#UNKNOWN UNKNOWN} or {@link DBDatatype#UNKNOWN_NUMERIC UNKNOWN_NUMERIC}.
* </i></p>
*
* @return <code>true</code> if this type is a geometry, <code>false</code> otherwise.
......@@ -223,8 +232,8 @@ public class DBType {
/**
* <p>Tell whether this type has been resolved or not.</p>
*
* <p><i>Concerned type:
* {@link DBDatatype#UNKNOWN UNKNOWN}.
* <p><i>Concerned types:
* {@link DBDatatype#UNKNOWN UNKNOWN} and {@link DBDatatype#UNKNOWN_NUMERIC UNKNOWN_NUMERIC}.
* </i></p>
*
* @return <code>true</code> if this type has NOT been resolved, <code>false</code> otherwise.
......@@ -232,7 +241,7 @@ public class DBType {
* @since 1.4
*/
public boolean isUnknown(){
return type == DBDatatype.UNKNOWN;
return type == DBDatatype.UNKNOWN || type == DBDatatype.UNKNOWN_NUMERIC;
}
/**
......@@ -240,8 +249,8 @@ public class DBType {
*
* <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>.
* If one of the two types is {@link DBDatatype#UNKNOWN unknown} or {@link DBDatatype#UNKNOWN_NUMERIC unknown_numeric},
* this function will consider them as compatible and will return <code>true</code>.
* </p>
*
* @param t The type to compare to.
......
......@@ -59,7 +59,7 @@ public class FunctionDef implements Comparable<FunctionDef> {
/** Rough regular expression for a function return type or a parameter type.
* The exact type is not checked here ; just the type name syntax is tested, not its value.
* This regular expression allows a type to have exactly one parameter (which is generally the length of a character or binary string. */
protected final static String typeRegExp = "([a-zA-Z]+[ 0-9a-zA-Z]*)(\\(\\s*([0-9]+)\\s*\\))?";
protected final static String typeRegExp = "([a-zA-Z_]+[ 0-9a-zA-Z_]*)(\\(\\s*([0-9]+)\\s*\\))?";
/** Rough regular expression for a function parameters' list. */
protected final static String fctParamsRegExp = "\\s*[^,]+\\s*(,\\s*[^,]+\\s*)*";
/** Rough regular expression for a function parameter: a name (see {@link #regularIdentifierRegExp}) and a type (see {@link #typeRegExp}). */
......@@ -350,7 +350,7 @@ public class FunctionDef implements Comparable<FunctionDef> {
* <p>
* <em>This function must be able to parse functions as defined by TAPRegExt (section 2.3).</em>
* Hence, allowed parameter types and return types should be one of the types listed by the UPLOAD section of the TAP recommendation document.
* These types are listed in the enumeration object {@link DBType}.
* These types are listed in the enumeration object {@link DBDatatype}.
* However, other types should be accepted like the common database types...but it should be better to not rely on that
* since the conversion of those types to TAP types should not be exactly what is expected (because depending from the used DBMS);
* a default interpretation of database types is nevertheless processed by this parser.
......
......@@ -16,7 +16,7 @@ package adql.query;
* 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-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -25,12 +25,20 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
import adql.db.DBColumn;
import adql.db.DBType;
import adql.db.DBType.DBDatatype;
import adql.db.DefaultDBColumn;
import adql.parser.ADQLParser;
import adql.parser.ParseException;
import adql.query.from.FromContent;
import adql.query.operand.ADQLColumn;
import adql.query.operand.ADQLOperand;
import adql.query.operand.function.DefaultUDF;
import adql.query.operand.function.geometry.BoxFunction;
import adql.query.operand.function.geometry.CircleFunction;
import adql.query.operand.function.geometry.PointFunction;
import adql.query.operand.function.geometry.PolygonFunction;
import adql.query.operand.function.geometry.RegionFunction;
import adql.search.ISearchHandler;
/**
......@@ -38,7 +46,7 @@ import adql.search.ISearchHandler;
* <p>The resulting object of the {@link ADQLParser} is an object of this class.</p>
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 1.4 (06/2015)
* @version 1.4 (03/2016)
*/
public class ADQLQuery implements ADQLObject {
......@@ -311,19 +319,50 @@ public class ADQLQuery implements ADQLObject {
// Here, this error should not occur any more, since it must have been caught by the DBChecker!
}
}else{
// Create the DBColumn:
DBColumn col = null;
// ...whose the name will be set with the SELECT item's alias:
if (item.hasAlias()){
if (operand instanceof ADQLColumn && ((ADQLColumn)operand).getDBLink() != null){
col = ((ADQLColumn)operand).getDBLink();
col = col.copy(col.getDBName(), item.getAlias(), col.getTable());
}else
col = new DefaultDBColumn(item.getAlias(), null);
}else{
}
// ...or whose the name will be the name of the SELECT item:
else{
if (operand instanceof ADQLColumn && ((ADQLColumn)operand).getDBLink() != null)
col = ((ADQLColumn)operand).getDBLink();
if (col == null)
col = new DefaultDBColumn(item.getName(), null);
}
/* For columns created by default (from functions and operations generally),
* set the adequate type if known: */
// CASE: Well-defined UDF
if (operand instanceof DefaultUDF && ((DefaultUDF)operand).getDefinition() != null){
DBType type = ((DefaultUDF)operand).getDefinition().returnType;
((DefaultDBColumn)col).setDatatype(type);
}
// CASE: Point type:
else if (operand instanceof PointFunction)
((DefaultDBColumn)col).setDatatype(new DBType(DBDatatype.POINT));
// CASE: Region type:
else if (operand instanceof RegionFunction || operand instanceof CircleFunction || operand instanceof BoxFunction || operand instanceof PolygonFunction)
((DefaultDBColumn)col).setDatatype(new DBType(DBDatatype.REGION));
// CASE: String and numeric types
else if (col instanceof DefaultDBColumn && col.getDatatype() == null && operand.isNumeric() != operand.isString()){
// CASE: String types
if (operand.isString())
((DefaultDBColumn)col).setDatatype(new DBType(DBDatatype.VARCHAR));
// CASE: Numeric types:
/* Note: a little special case here since a numeric could be a real, double, integer, or anything
* else and that we don't know precisely here. So we set the special UNKNOWN NUMERIC type. */
else
((DefaultDBColumn)col).setDatatype(new DBType(DBDatatype.UNKNOWN_NUMERIC));
}
// Add the new column to the list:
columns.add(col);
}
}
......
......@@ -16,7 +16,7 @@ package adql.query.operand;
* 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-2015 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
......@@ -32,7 +32,7 @@ import adql.query.from.ADQLTable;
* Represents the complete (literal) reference to a column ({schema(s)}.{table}.{column}).
*
* @author Gr&eacute;gory Mantelet (CDS;ARI)
* @version 1.4 (06/2015)
* @version 1.4 (03/2016)
*/
public class ADQLColumn implements ADQLOperand, UnknownType {
......@@ -469,17 +469,17 @@ public class ADQLColumn implements ADQLOperand, UnknownType {
@Override
public boolean isNumeric(){
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isUnknown() || dbLink.getDatatype().isNumeric());
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isNumeric() || dbLink.getDatatype().isUnknown());
}
@Override
public boolean isString(){
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isUnknown() || dbLink.getDatatype().isString());
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isString() || (dbLink.getDatatype().isUnknown() && !dbLink.getDatatype().isNumeric()));
}
@Override
public boolean isGeometry(){
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isUnknown() || dbLink.getDatatype().isGeometry());
return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isGeometry() || (dbLink.getDatatype().isUnknown() && !dbLink.getDatatype().isNumeric()));
}
@Override
......
package adql;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Iterator;
......@@ -9,6 +11,9 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import adql.db.DBType;
import adql.db.DBType.DBDatatype;
import adql.db.FunctionDef;
import adql.query.ADQLObject;
import adql.query.ADQLOrder;
import adql.query.ADQLQuery;
......@@ -21,12 +26,23 @@ import adql.query.constraint.ComparisonOperator;
import adql.query.constraint.ConstraintsGroup;
import adql.query.from.ADQLTable;
import adql.query.operand.ADQLColumn;
import adql.query.operand.ADQLOperand;
import adql.query.operand.Concatenation;
import adql.query.operand.NumericConstant;
import adql.query.operand.Operation;
import adql.query.operand.OperationType;
import adql.query.operand.StringConstant;
import adql.query.operand.WrappedOperand;
import adql.query.operand.function.DefaultUDF;
import adql.query.operand.function.MathFunction;
import adql.query.operand.function.MathFunctionType;
import adql.query.operand.function.SQLFunction;
import adql.query.operand.function.SQLFunctionType;
import adql.query.operand.function.geometry.BoxFunction;
import adql.query.operand.function.geometry.CircleFunction;
import adql.query.operand.function.geometry.PointFunction;
import adql.query.operand.function.geometry.PolygonFunction;
import adql.query.operand.function.geometry.RegionFunction;
import adql.search.IReplaceHandler;
import adql.search.ISearchHandler;
import adql.search.SearchColumnHandler;
......@@ -124,4 +140,103 @@ public class TestADQLQuery {
assertEquals(expectedCol, results.next());
assertEquals("SELECT (O.nameObj || ' (' || NewTypeObj || ')') AS Nom objet , O.ra , O.dec\nFROM truc.ObsCore AS O\nWHERE ra/dec > 1 AND (NewTypeObj = 'Star' OR NewTypeObj LIKE 'Galaxy*')\nORDER BY 1 DESC", query.toADQL());
}
@Test
public void testTypeResultingColumns(){
ADQLQuery query = new ADQLQuery();
query.setFrom(new ADQLTable("foo"));
ClauseSelect select = new ClauseSelect();
query.setSelect(select);
// Test with a numeric constant:
select.add(new NumericConstant(2.3));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.UNKNOWN_NUMERIC, query.getResultingColumns()[0].getDatatype().type);
// Test with a math operation:
select.clear();
select.add(new Operation(new Operation(new NumericConstant(2), OperationType.MULT, new NumericConstant(3.14)), OperationType.DIV, new NumericConstant(5)));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.UNKNOWN_NUMERIC, query.getResultingColumns()[0].getDatatype().type);
// Test with a math function:
try{
select.clear();
select.add(new MathFunction(MathFunctionType.SQRT, new ADQLColumn("col1")));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.UNKNOWN_NUMERIC, query.getResultingColumns()[0].getDatatype().type);
}catch(Exception ex){
ex.printStackTrace();
fail("The mathematical function SQRT is well defined. This error should have occurred.");
}
// Test with an aggregation function:
select.clear();
select.add(new SQLFunction(SQLFunctionType.SUM, new ADQLColumn("col1")));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.UNKNOWN_NUMERIC, query.getResultingColumns()[0].getDatatype().type);
// Test with a string constant:
select.clear();
select.add(new StringConstant("blabla"));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.VARCHAR, query.getResultingColumns()[0].getDatatype().type);
// Test with a concatenation:
select.clear();
Concatenation concat = new Concatenation();
concat.add(new StringConstant("super "));
concat.add(new ADQLColumn("foo", "col"));
select.add(concat);
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.VARCHAR, query.getResultingColumns()[0].getDatatype().type);
// Test with a POINT:
try{
select.clear();
select.add(new PointFunction(new StringConstant(""), new ADQLColumn("ra"), new ADQLColumn("dec")));
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.POINT, query.getResultingColumns()[0].getDatatype().type);
}catch(Exception ex){
ex.printStackTrace();
fail("The POINT function is well defined. This error should have occurred.");
}
// Test with a REGION (CIRCLE, BOX, POLYGON and REGION functions):
try{
select.clear();
select.add(new CircleFunction(new StringConstant(""), new ADQLColumn("ra"), new ADQLColumn("dec"), new NumericConstant(1)));
select.add(new BoxFunction(new StringConstant(""), new ADQLColumn("ra"), new ADQLColumn("dec"), new NumericConstant(10), new NumericConstant(20)));
ADQLOperand[] points = new ADQLOperand[6];
points[0] = new ADQLColumn("point1");
points[1] = new ADQLColumn("point2");
points[2] = new ADQLColumn("point3");
points[3] = new ADQLColumn("point4");
points[4] = new ADQLColumn("point5");
points[5] = new ADQLColumn("point6");
select.add(new PolygonFunction(new StringConstant(""), points));
select.add(new RegionFunction(new StringConstant("CIRCLE '' ra dec 2.3")));
assertEquals(4, query.getResultingColumns().length);
for(int i = 0; i < 4; i++)
assertEquals(DBDatatype.REGION, query.getResultingColumns()[i].getDatatype().type);
}catch(Exception ex){
ex.printStackTrace();
fail("The geometrical functions are well defined. This error should have occurred.");
}
// Test with a UDF having no definition:
select.clear();
select.add(new DefaultUDF("foo", new ADQLOperand[0]));
assertEquals(1, query.getResultingColumns().length);
assertNull(query.getResultingColumns()[0].getDatatype());
// Test with a UDF having a definition:
select.clear();
DefaultUDF udf = new DefaultUDF("foo", new ADQLOperand[0]);
udf.setDefinition(new FunctionDef("foo", new DBType(DBDatatype.INTEGER)));
select.add(udf);
assertEquals(1, query.getResultingColumns().length);
assertEquals(DBDatatype.INTEGER, query.getResultingColumns()[0].getDatatype().type);
}
}
......@@ -10,6 +10,7 @@ import org.junit.Test;
import adql.db.DBType.DBDatatype;
import adql.db.FunctionDef.FunctionParam;
import adql.parser.ParseException;
import adql.query.operand.ADQLColumn;
import adql.query.operand.ADQLOperand;
import adql.query.operand.NumericConstant;
import adql.query.operand.StringConstant;
......@@ -62,6 +63,7 @@ public class TestFunctionDef {
case UNKNOWN:
assertFalse(new FunctionDef("foo", new DBType(type)).isNumeric);
break;
case UNKNOWN_NUMERIC:
default:
assertTrue(new FunctionDef("foo", new DBType(type)).isNumeric);
}
......@@ -338,6 +340,18 @@ public class TestFunctionDef {
e.printStackTrace();
fail();
}
// Test with an UNKNOWN numeric type:
// TEST :: "fct0(foo)", where foo is a simple UNKNOWN [EQUAL]
FunctionDef def0 = new FunctionDef("fct0", null, new FunctionParam[]{new FunctionParam("whatever", new DBType(DBDatatype.VARCHAR))});
DefaultDBColumn dbcol = new DefaultDBColumn("foo", new DefaultDBTable("toto"));
dbcol.setDatatype(new DBType(DBDatatype.UNKNOWN));
ADQLColumn col = new ADQLColumn("foo");
col.setDBLink(dbcol);
assertEquals(0, def0.compareTo(new DefaultUDF("fct0", new ADQLOperand[]{col})));
// TEST :: "fct0(foo)", where foo is an UNKNOWN NUMERIC [LESS]
dbcol.setDatatype(new DBType(DBDatatype.UNKNOWN_NUMERIC));
assertEquals(-1, def0.compareTo(new DefaultUDF("fct0", new ADQLOperand[]{col})));
}
}
......@@ -70,7 +70,7 @@ public class UnknownTypes {
@Test
public void testForColumns(){
final String QUERY_TXT = "SELECT FOO(C1), FOO(C2), C1, C2, C3 FROM T1";
final String QUERY_TXT = "SELECT FOO(C1), FOO(C2), FOO(C4), C1, C2, C3, C4 FROM T1";
try{
// Create the parser:
......@@ -81,6 +81,7 @@ public class UnknownTypes {
table1.addColumn(new DefaultDBColumn("C1", table1));
table1.addColumn(new DefaultDBColumn("C2", new DBType(DBDatatype.UNKNOWN), table1));
table1.addColumn(new DefaultDBColumn("C3", new DBType(DBDatatype.VARCHAR), table1));
table1.addColumn(new DefaultDBColumn("C4", new DBType(DBDatatype.UNKNOWN_NUMERIC), table1));
Collection<DBTable> tList = Arrays.asList(new DBTable[]{table1});
// Check the type of the column T1.C1:
......@@ -98,6 +99,16 @@ public class UnknownTypes {
assertFalse(col.getDatatype().isGeometry());
assertEquals("UNKNOWN", col.getDatatype().toString());
// Check the type of the column T1.C4:
col = table1.getColumn("C4", true);
assertNotNull(col);
assertNotNull(col.getDatatype());
assertTrue(col.getDatatype().isUnknown());
assertTrue(col.getDatatype().isNumeric());
assertFalse(col.getDatatype().isString());
assertFalse(col.getDatatype().isGeometry());
assertEquals("UNKNOWN_NUMERIC", col.getDatatype().toString());
// Define a UDF, and allow all geometrical functions and coordinate systems:
FunctionDef udf1 = FunctionDef.parse("FOO(x INTEGER) -> INTEGER");
Collection<FunctionDef> udfList = Arrays.asList(new FunctionDef[]{udf1});
......@@ -122,18 +133,26 @@ public class UnknownTypes {
assertTrue(pq.getSelect().get(1).getOperand().isNumeric());
assertFalse(pq.getSelect().get(1).getOperand().isString());
assertFalse(pq.getSelect().get(1).getOperand().isGeometry());
// isNumeric() = isString() = isGeometry() for C1
// isNumeric() = true for FOO(C4), but false for the others
assertTrue(pq.getSelect().get(2).getOperand().isNumeric());
assertTrue(pq.getSelect().get(2).getOperand().isString());
assertTrue(pq.getSelect().get(2).getOperand().isGeometry());
// isNumeric() = isString() = isGeometry() for C2
assertFalse(pq.getSelect().get(2).getOperand().isString());
assertFalse(pq.getSelect().get(2).getOperand().isGeometry());
// isNumeric() = isString() = isGeometry() for C1
assertTrue(pq.getSelect().get(3).getOperand().isNumeric());
assertTrue(pq.getSelect().get(3).getOperand().isString());
assertTrue(pq.getSelect().get(3).getOperand().isGeometry());
// isString() = true for C3, but false for the others
assertFalse(pq.getSelect().get(4).getOperand().isNumeric());
// isNumeric() = isString() = isGeometry() for C2
assertTrue(pq.getSelect().get(4).getOperand().isNumeric());
assertTrue(pq.getSelect().get(4).getOperand().isString());
assertFalse(pq.getSelect().get(4).getOperand().isGeometry());
assertTrue(pq.getSelect().get(4).getOperand().isGeometry());
// isString() = true for C3, but false for the others
assertFalse(pq.getSelect().get(5).getOperand().isNumeric());
assertTrue(pq.getSelect().get(5).getOperand().isString());
assertFalse(pq.getSelect().get(5).getOperand().isGeometry());
// isString() = true for C4, but false for the others
assertTrue(pq.getSelect().get(6).getOperand().isNumeric());
assertFalse(pq.getSelect().get(6).getOperand().isString());
assertFalse(pq.getSelect().get(6).getOperand().isGeometry());
}catch(Exception ex){
ex.printStackTrace(System.err);
fail("The construction, configuration and usage of the parser are correct. Nothing should have failed here. (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