diff --git a/src/adql/db/DBChecker.java b/src/adql/db/DBChecker.java index 05c3b005c57202da8cf0f9fab44c963cdadf62b1..cc5fe8dfa653b2f1f447441c678b319a5938c9e8 100644 --- a/src/adql/db/DBChecker.java +++ b/src/adql/db/DBChecker.java @@ -97,7 +97,7 @@ import adql.search.SimpleSearchHandler; * </i></p> * * @author Grégory Mantelet (CDS;ARI) - * @version 1.4 (06/2015) + * @version 1.4 (08/2015) */ public class DBChecker implements QueryChecker { @@ -581,7 +581,7 @@ public class DBChecker implements QueryChecker { return tables.get(0); // but if more than one: ambiguous table name ! else if (tables.size() > 1) - throw new UnresolvedTableException(table, tables.get(0).getADQLSchemaName() + "." + tables.get(0).getADQLName(), tables.get(1).getADQLSchemaName() + "." + tables.get(1).getADQLName()); + throw new UnresolvedTableException(table, (tables.get(0).getADQLSchemaName() == null ? "" : tables.get(0).getADQLSchemaName() + ".") + tables.get(0).getADQLName(), (tables.get(1).getADQLSchemaName() == null ? "" : tables.get(1).getADQLSchemaName() + ".") + tables.get(1).getADQLName()); // otherwise (no match): unknown table ! else throw new UnresolvedTableException(table); diff --git a/src/adql/db/DefaultDBColumn.java b/src/adql/db/DefaultDBColumn.java index a4ed9e3bc557bc8cba391bc68c35e269dbf27ea9..0336e24b865132c42460295f9ec2452f2eeac28c 100644 --- a/src/adql/db/DefaultDBColumn.java +++ b/src/adql/db/DefaultDBColumn.java @@ -16,7 +16,7 @@ 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,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) */ @@ -24,7 +24,7 @@ package adql.db; * Default implementation of {@link DBColumn}. * * @author Grégory Mantelet (CDS;ARI) - * @version 1.3 (10/2014) + * @version 1.4 (08/2015) */ public class DefaultDBColumn implements DBColumn { @@ -96,9 +96,11 @@ public class DefaultDBColumn implements DBColumn { * @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> + * <b>REQUIRED parameter: it must be not NULL.</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> + * <em>If NULL, it will be set to dbName.</em> * @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 @@ -108,8 +110,13 @@ public class DefaultDBColumn implements DBColumn { * @since 1.3 */ public DefaultDBColumn(final String dbName, final String adqlName, final DBType type, final DBTable table){ + + if (dbName == null || dbName.length() == 0) + throw new NullPointerException("Missing DB name!"); + this.dbName = dbName; - this.adqlName = adqlName; + this.adqlName = (adqlName == null) ? dbName : adqlName; + this.type = type; this.table = table; } diff --git a/src/adql/db/DefaultDBTable.java b/src/adql/db/DefaultDBTable.java index ccc3752df7a56eb33715da0eda46ca0f5fc38d81..19762a9c4ef943dae965202d8d322ffc4268a99a 100644 --- a/src/adql/db/DefaultDBTable.java +++ b/src/adql/db/DefaultDBTable.java @@ -16,7 +16,7 @@ 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-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) */ @@ -29,7 +29,7 @@ import java.util.Map; * Default implementation of {@link DBTable}. * * @author Grégory Mantelet (CDS;ARI) - * @version 1.3 (11/2014) + * @version 1.4 (08/2015) */ public class DefaultDBTable implements DBTable { @@ -107,10 +107,13 @@ public class DefaultDBTable implements DBTable { * * @param dbCatName Database catalog name. * @param adqlCatName Catalog name used in ADQL queries. + * <em>If NULL, it will be set to dbCatName.</em> * @param dbSchemName Database schema name. * @param adqlSchemName Schema name used in ADQL queries. + * <em>If NULL, it will be set to dbSchemName.</em> * @param dbName Database table name. * @param adqlName Table name used in ADQL queries. + * <em>If NULL, it will be set to dbName.</em> */ public DefaultDBTable(final String dbCatName, final String adqlCatName, final String dbSchemName, final String adqlSchemName, final String dbName, final String adqlName){ @@ -118,13 +121,13 @@ public class DefaultDBTable implements DBTable { throw new NullPointerException("Missing DB name !"); this.dbName = dbName; - this.adqlName = adqlName; + this.adqlName = (adqlName == null) ? dbName : adqlName; dbSchemaName = dbSchemName; - adqlSchemaName = adqlSchemName; + adqlSchemaName = (adqlSchemName == null) ? dbSchemName : adqlSchemName; dbCatalogName = dbCatName; - adqlCatalogName = adqlCatName; + adqlCatalogName = (adqlCatName == null) ? dbCatName : adqlCatName; } @Override diff --git a/src/adql/db/SearchColumnList.java b/src/adql/db/SearchColumnList.java index b3117d6664ded3589e514f1eefe2b52ccf3fb34d..b403fa51b2fc32a9e9a7b7ffda698760920be577 100644 --- a/src/adql/db/SearchColumnList.java +++ b/src/adql/db/SearchColumnList.java @@ -16,7 +16,7 @@ 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-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) */ @@ -46,7 +46,7 @@ import cds.utils.TextualSearchList; * </i></p> * * @author Grégory Mantelet (CDS;ARI) - * @version 1.3 (02/2015) + * @version 1.4 (08/2015) */ public class SearchColumnList extends TextualSearchList<DBColumn> { private static final long serialVersionUID = 1L; @@ -284,7 +284,10 @@ public class SearchColumnList extends TextualSearchList<DBColumn> { } // test the schema name: - if (schema != null && matchTable.getADQLSchemaName() != null){ + if (schema != null){ + // No schema name (<=> no schema), then this table can not be a good match: + if (matchTable.getADQLSchemaName() == null) + continue; if (IdentifierField.SCHEMA.isCaseSensitive(caseSensitivity)){ if (!matchTable.getADQLSchemaName().equals(schema)) continue; @@ -295,6 +298,9 @@ public class SearchColumnList extends TextualSearchList<DBColumn> { // test the catalog name: if (catalog != null){ + // No catalog name (<=> no catalog), then this table can not be a good match: + if (matchTable.getADQLCatalogName() == null) + continue; if (IdentifierField.CATALOG.isCaseSensitive(caseSensitivity)){ if (!matchTable.getADQLCatalogName().equals(catalog)) continue; diff --git a/src/adql/db/SearchTableList.java b/src/adql/db/SearchTableList.java index 7de6ec59098b7b6f6516627aed856aa64b850cf4..1468218812582cabc2fc62710f6dce3be29e9a71 100644 --- a/src/adql/db/SearchTableList.java +++ b/src/adql/db/SearchTableList.java @@ -16,7 +16,7 @@ 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,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) */ @@ -36,7 +36,7 @@ import cds.utils.TextualSearchList; * </p> * * @author Grégory Mantelet (CDS;ARI) - * @version 1.3 (02/2015) + * @version 1.4 (08/2015) */ public class SearchTableList extends TextualSearchList<DBTable> { private static final long serialVersionUID = 1L; @@ -156,24 +156,28 @@ public class SearchTableList extends TextualSearchList<DBTable> { ArrayList<DBTable> result = new ArrayList<DBTable>(); for(DBTable match : tmpResult){ - if (match.getADQLSchemaName() != null){ - if (IdentifierField.SCHEMA.isCaseSensitive(caseSensitivity)){ - if (!match.getADQLSchemaName().equals(schema)) + // No schema name (<=> no schema), then this table can not be a good match: + if (match.getADQLSchemaName() == null) + continue; + if (IdentifierField.SCHEMA.isCaseSensitive(caseSensitivity)){ + if (!match.getADQLSchemaName().equals(schema)) + continue; + }else{ + if (!match.getADQLSchemaName().equalsIgnoreCase(schema)) + continue; + } + + if (catalog != null){ + // No catalog name (<=> no catalog), then this table can not be a good match: + if (match.getADQLCatalogName() == null) + continue; + if (IdentifierField.CATALOG.isCaseSensitive(caseSensitivity)){ + if (!match.getADQLCatalogName().equals(catalog)) continue; }else{ - if (!match.getADQLSchemaName().equalsIgnoreCase(schema)) + if (!match.getADQLCatalogName().equalsIgnoreCase(catalog)) continue; } - - if (catalog != null && match.getADQLCatalogName() != null){ - if (IdentifierField.CATALOG.isCaseSensitive(caseSensitivity)){ - if (!match.getADQLCatalogName().equals(catalog)) - continue; - }else{ - if (!match.getADQLCatalogName().equalsIgnoreCase(catalog)) - continue; - } - } } result.add(match); diff --git a/test/adql/db/TestDBChecker.java b/test/adql/db/TestDBChecker.java index 64cc5229768233ba168f280e754cee3539680419..b761381b31eb0fe2cc9ddcec2ecea839144c3f2e 100644 --- a/test/adql/db/TestDBChecker.java +++ b/test/adql/db/TestDBChecker.java @@ -42,7 +42,7 @@ public class TestDBChecker { public static void setUpBeforeClass() throws Exception{ tables = new ArrayList<DBTable>(); - DefaultDBTable fooTable = new DefaultDBTable("foo"); + DefaultDBTable fooTable = new DefaultDBTable(null, "aschema", "foo"); DBColumn col = new DefaultDBColumn("colS", new DBType(DBDatatype.VARCHAR), fooTable); fooTable.addColumn(col); col = new DefaultDBColumn("colI", new DBType(DBDatatype.INTEGER), fooTable); @@ -51,6 +51,12 @@ public class TestDBChecker { fooTable.addColumn(col); tables.add(fooTable); + + DefaultDBTable fooTable2 = new DefaultDBTable(null, null, "foo2"); + col = new DefaultDBColumn("oid", new DBType(DBDatatype.BIGINT), fooTable2); + fooTable2.addColumn(col); + + tables.add(fooTable2); } @AfterClass @@ -62,6 +68,73 @@ public class TestDBChecker { @After public void tearDown() throws Exception{} + @Test + public void testSplitTableName(){ + String[] names = DefaultDBTable.splitTableName("foo"); + String[] expected = new String[]{null,null,"foo"}; + assertEquals(expected.length, names.length); + for(int i = 0; i < names.length; i++) + assertEquals(expected[i], names[i]); + + names = DefaultDBTable.splitTableName("aschema.foo"); + expected = new String[]{null,"aschema","foo"}; + assertEquals(expected.length, names.length); + for(int i = 0; i < names.length; i++) + assertEquals(expected[i], names[i]); + + names = DefaultDBTable.splitTableName("acat.aschema.foo"); + expected = new String[]{"acat","aschema","foo"}; + assertEquals(expected.length, names.length); + for(int i = 0; i < names.length; i++) + assertEquals(expected[i], names[i]); + + names = DefaultDBTable.splitTableName("weird.acat.aschema.foo"); + expected = new String[]{"weird.acat","aschema","foo"}; + assertEquals(expected.length, names.length); + for(int i = 0; i < names.length; i++) + assertEquals(expected[i], names[i]); + } + + @Test + public void testQualifiedName(){ + ADQLParser parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0))); + try{ + // Tests with a table whose the schema is specified: + parser.parseQuery("SELECT * FROM foo;"); + parser.parseQuery("SELECT * FROM aschema.foo;"); + parser.parseQuery("SELECT foo.* FROM foo;"); + parser.parseQuery("SELECT aschema.foo.* FROM foo;"); + parser.parseQuery("SELECT aschema.foo.* FROM aschema.foo;"); + parser.parseQuery("SELECT \"colS\" FROM foo;"); + parser.parseQuery("SELECT foo.\"colS\" FROM foo;"); + parser.parseQuery("SELECT foo.\"colS\" FROM aschema.\"foo\";"); + parser.parseQuery("SELECT \"aschema\".\"foo\".\"colS\" FROM foo;"); + + // Tests with a table without schema: + parser.parseQuery("SELECT * FROM foo2;"); + parser.parseQuery("SELECT foo2.* FROM foo2;"); + parser.parseQuery("SELECT foo2.* FROM \"foo2\";"); + parser.parseQuery("SELECT \"foo2\".* FROM \"foo2\";"); + parser.parseQuery("SELECT oid FROM foo2;"); + parser.parseQuery("SELECT \"oid\" FROM \"foo2\";"); + parser.parseQuery("SELECT foo2.oid FROM foo2;"); + parser.parseQuery("SELECT \"foo2\".\"oid\" FROM \"foo2\";"); + }catch(ParseException pe){ + pe.printStackTrace(); + fail(); + } + + // If no schema is specified, then the table is not part of a schema and so, there is no reason a table with a fake schema prefix should work: + try{ + parser.parseQuery("SELECT * FROM noschema.foo2;"); + fail("The table \"foo2\" has no schema specified and so, is not part of a schema. A fake schema prefix should then be forbidden!"); + }catch(ParseException pe){} + try{ + parser.parseQuery("SELECT noschema.foo2.* FROM foo2;"); + fail("The table \"foo2\" has no schema specified and so, is not part of a schema. A fake schema prefix should then be forbidden!"); + }catch(ParseException pe){} + } + @Test public void testNumericOrStringValueExpressionPrimary(){ ADQLParser parser = new ADQLParser();