package adql.query; 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; 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.constraint.Comparison; 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.CentroidFunction; import adql.query.operand.function.geometry.CircleFunction; import adql.query.operand.function.geometry.GeometryFunction; import adql.query.operand.function.geometry.GeometryFunction.GeometryValue; 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; import adql.search.SimpleReplaceHandler; public class TestADQLQuery { private ADQLQuery query = null; private List<ADQLColumn> columns = new ArrayList<ADQLColumn>(8); private List<ADQLColumn> typeObjColumns = new ArrayList<ADQLColumn>(3); @Before public void setUp(){ query = new ADQLQuery(); columns.clear(); typeObjColumns.clear(); columns.add(new ADQLColumn("O", "nameObj")); // 0 = O.nameObj columns.add(new ADQLColumn("O", "typeObj")); // 1 = O.typeObj columns.add(new ADQLColumn("O", "ra")); // 2 = O.ra columns.add(new ADQLColumn("O", "dec")); // 3 = O.dec columns.add(new ADQLColumn("ra")); // 4 = ra columns.add(new ADQLColumn("dec")); // 5 = dec columns.add(new ADQLColumn("typeObj")); // 6 = typeObj columns.add(new ADQLColumn("typeObj")); // 7 = typeObj typeObjColumns.add(columns.get(1)); typeObjColumns.add(columns.get(6)); typeObjColumns.add(columns.get(7)); // SELECT: ClauseSelect select = query.getSelect(); Concatenation concatObj = new Concatenation(); concatObj.add(columns.get(0)); // O.nameObj concatObj.add(new StringConstant(" (")); concatObj.add(columns.get(1)); // O.typeObj concatObj.add(new StringConstant(")")); select.add(new SelectItem(new WrappedOperand(concatObj), "Nom objet")); select.add(columns.get(2)); // O.ra select.add(columns.get(3)); // O.dec // FROM: ADQLTable table = new ADQLTable("truc.ObsCore"); table.setAlias("O"); // table.setJoin(new ADQLJoin(JoinType.INNER, new ADQLTable("VO"))); query.setFrom(table); // WHERE: ClauseConstraints where = query.getWhere(); // ra/dec > 1 where.add(new Comparison(new Operation(columns.get(4), OperationType.DIV, columns.get(5)), ComparisonOperator.GREATER_THAN, new NumericConstant("1"))); ConstraintsGroup constOr = new ConstraintsGroup(); // AND (typeObj == 'Star' constOr.add(new Comparison(columns.get(6), ComparisonOperator.EQUAL, new StringConstant("Star"))); // OR typeObj LIKE 'Galaxy*') constOr.add("OR", new Comparison(columns.get(7), ComparisonOperator.LIKE, new StringConstant("Galaxy*"))); where.add("AND", constOr); // ORDER BY: ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); orderBy.add(new ADQLOrder(1, true)); } @Test public void testADQLQuery(){ assertEquals("SELECT (O.nameObj || ' (' || O.typeObj || ')') AS Nom objet , O.ra , O.dec\nFROM truc.ObsCore AS O\nWHERE ra/dec > 1 AND (typeObj = 'Star' OR typeObj LIKE 'Galaxy*')\nORDER BY 1 DESC", query.toADQL()); } @Test public void testSearch(){ ISearchHandler sHandler = new SearchColumnHandler(false); Iterator<ADQLObject> results = query.search(sHandler); assertEquals(columns.size(), sHandler.getNbMatch()); for(ADQLColumn expectedCol : columns) assertEquals(expectedCol, results.next()); } @Test public void testReplace(){ IReplaceHandler sHandler = new SimpleReplaceHandler(false, false){ @Override protected boolean match(ADQLObject obj){ return (obj instanceof ADQLColumn) && (((ADQLColumn)obj).getColumnName().equalsIgnoreCase("typeObj")); } @Override public ADQLObject getReplacer(ADQLObject objToReplace) throws UnsupportedOperationException{ return new ADQLColumn("NewTypeObj"); } }; sHandler.searchAndReplace(query); assertEquals(typeObjColumns.size(), sHandler.getNbMatch()); assertEquals(sHandler.getNbMatch(), sHandler.getNbReplacement()); Iterator<ADQLObject> results = sHandler.iterator(); for(ADQLColumn expectedCol : typeObjColumns) 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"))); select.add(new CentroidFunction(new GeometryValue<GeometryFunction>(new ADQLColumn("aRegion")))); assertEquals(2, query.getResultingColumns().length); for(int i = 0; i < 2; i++) assertEquals(DBDatatype.POINT, query.getResultingColumns()[i].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); } }