diff --git a/cadc-tap-schema/build.gradle b/cadc-tap-schema/build.gradle index d290c8b8..5b941c81 100644 --- a/cadc-tap-schema/build.gradle +++ b/cadc-tap-schema/build.gradle @@ -16,7 +16,7 @@ sourceCompatibility = 1.8 group = 'org.opencadc' -version = '1.1.33' +version = '1.2.1' description = 'OpenCADC TAP-1.1 tap schema server library' def git_url = 'https://github.com/opencadc/tap' @@ -34,7 +34,7 @@ dependencies { compile 'org.opencadc:cadc-cdp:[1.2.3,2.0)' compile 'org.opencadc:cadc-gms:[1.0,2.0)' compile 'org.opencadc:cadc-rest:[1.3.1,2.0)' - compile 'org.opencadc:cadc-tap:[1.1,2.0)' + compile 'org.opencadc:cadc-tap:[1.1.17,2.0)' compile 'uk.ac.starlink:jcdf:[1.2.3,2.0)' compile 'uk.ac.starlink:stil:[4.0,5.0)' diff --git a/cadc-tap-schema/src/main/java/ca/nrc/cadc/tap/schema/TapSchemaDAO.java b/cadc-tap-schema/src/main/java/ca/nrc/cadc/tap/schema/TapSchemaDAO.java index 8ad133a8..8f6cd020 100644 --- a/cadc-tap-schema/src/main/java/ca/nrc/cadc/tap/schema/TapSchemaDAO.java +++ b/cadc-tap-schema/src/main/java/ca/nrc/cadc/tap/schema/TapSchemaDAO.java @@ -71,18 +71,12 @@ import ca.nrc.cadc.auth.AuthenticationUtil; import ca.nrc.cadc.auth.IdentityManager; -import ca.nrc.cadc.cred.client.CredUtil; import ca.nrc.cadc.db.DatabaseTransactionManager; import ca.nrc.cadc.net.ResourceNotFoundException; import ca.nrc.cadc.profiler.Profiler; -import ca.nrc.cadc.reg.Standards; -import ca.nrc.cadc.reg.client.LocalAuthority; import ca.nrc.cadc.uws.Job; import java.net.URI; -import java.security.AccessControlException; -import java.security.cert.CertificateExpiredException; -import java.security.cert.CertificateNotYetValidException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -96,9 +90,7 @@ import javax.security.auth.Subject; import javax.sql.DataSource; import org.apache.log4j.Logger; -import org.opencadc.gms.GroupClient; import org.opencadc.gms.GroupURI; -import org.opencadc.gms.GroupUtil; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.RowMapper; @@ -152,6 +144,9 @@ public class TapSchemaDAO { protected static String readWriteCol = "read_write_group"; private static String[] accessControlCols = new String[] { ownerCol, readAnonCol, readOnlyCol, readWriteCol }; + // api_created is in the tables and schemas schema, but not exposed as a tap_schema column + private static String apiCreated = "api_created"; + protected Job job; protected DataSource dataSource; private boolean ordered; @@ -480,7 +475,7 @@ public void put(TableDesc td) { jdbc.update(pts); prof.checkpoint("put-table"); - // add/remove columns not supported so udpate flag is same for the table and + // add/remove columns not supported so update flag is same for the table and // column(s) PutColumnStatement pcs = new PutColumnStatement(update); for (ColumnDesc cd : td.getColumnDescs()) { @@ -783,6 +778,7 @@ public PreparedStatement createPreparedStatement(Connection conn) throws SQLExce StringBuilder sb = new StringBuilder(); sb.append("SELECT ").append(toCommaList(tsSchemaCols, 0)); sb.append(",").append(toCommaList(accessControlCols, 0)); + sb.append(",").append(apiCreated); sb.append(" FROM ").append(tap_schema_tab); if (schemaName != null) { @@ -827,6 +823,7 @@ public PreparedStatement createPreparedStatement(Connection conn) throws SQLExce StringBuilder sb = new StringBuilder(); sb.append("SELECT ").append(toCommaList(tsTablesCols, 0)); sb.append(",").append(toCommaList(accessControlCols, 0)); + sb.append(",").append(apiCreated); sb.append(" FROM ").append(tap_schema_tab); if (tableName != null) { @@ -1106,29 +1103,34 @@ public PreparedStatement createPreparedStatement(Connection conn) throws SQLExce sb.append("UPDATE ").append(schemasTableName); sb.append(" SET ("); sb.append(toCommaList(tsSchemaCols, 1)); + sb.append(",").append(apiCreated); sb.append(") = ("); sb.append(toParamList(tsSchemaCols, 1)); + sb.append(",?"); sb.append(")"); sb.append(" WHERE schema_name=?"); } else { sb.append("INSERT INTO ").append(schemasTableName); sb.append(" ("); sb.append(toCommaList(tsSchemaCols, 0)); + sb.append(",").append(apiCreated); sb.append(") VALUES ("); sb.append(toParamList(tsSchemaCols, 0)); + sb.append(",?"); sb.append(")"); } String sql = sb.toString(); log.debug(sql); PreparedStatement ps = conn.prepareStatement(sql); - // load values: description, utype, schema_index, schema_name + // load values: description, utype, schema_index, schema_name, api_created sb = new StringBuilder(); int col = 1; safeSetString(sb, ps, col++, schema.description); safeSetString(sb, ps, col++, schema.utype); safeSetInteger(sb, ps, col++, schema.schema_index); safeSetString(sb, ps, col++, schema.getSchemaName()); + safeSetBoolean(sb, ps, col++, schema.apiCreated); return ps; } @@ -1153,23 +1155,27 @@ public PreparedStatement createPreparedStatement(Connection conn) throws SQLExce sb.append("UPDATE ").append(tablesTableName); sb.append(" SET ("); sb.append(toCommaList(tsTablesCols, 2)); + sb.append(",").append(apiCreated); sb.append(") = ("); sb.append(toParamList(tsTablesCols, 2)); + sb.append(",?"); sb.append(")"); sb.append(" WHERE schema_name=? AND table_name=?"); } else { sb.append("INSERT INTO ").append(tablesTableName); sb.append(" ("); sb.append(toCommaList(tsTablesCols, 0)); + sb.append(",").append(apiCreated); sb.append(") VALUES ("); sb.append(toParamList(tsTablesCols, 0)); + sb.append(",?"); sb.append(")"); } String sql = sb.toString(); log.debug(sql); PreparedStatement ps = conn.prepareStatement(sql); - // load values: description, utype, schema_name, table_name + // load values: description, utype, schema_name, table_name, api_created sb = new StringBuilder(); int col = 1; safeSetString(sb, ps, col++, table.tableType.getValue()); @@ -1178,6 +1184,7 @@ public PreparedStatement createPreparedStatement(Connection conn) throws SQLExce safeSetInteger(sb, ps, col++, table.tableIndex); safeSetString(sb, ps, col++, table.getSchemaName()); safeSetString(sb, ps, col++, table.getTableName()); + safeSetBoolean(sb, ps, col++, table.apiCreated); return ps; } @@ -1519,6 +1526,7 @@ public Object mapRow(ResultSet rs, int rowNum) throws SQLException { if (tapPermissionsMapper != null) { schemaDesc.tapPermissions = tapPermissionsMapper.mapRow(rs, rowNum); } + schemaDesc.apiCreated = rs.getInt("api_created") == 1; return schemaDesc; } @@ -1546,6 +1554,7 @@ public Object mapRow(ResultSet rs, int rowNum) throws SQLException { if (tapPermissionsMapper != null) { tableDesc.tapPermissions = tapPermissionsMapper.mapRow(rs, rowNum); } + tableDesc.apiCreated = rs.getInt("api_created") == 1; return tableDesc; } diff --git a/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/DeleteAction.java b/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/DeleteAction.java index 226a8cec..a388be07 100644 --- a/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/DeleteAction.java +++ b/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/DeleteAction.java @@ -73,6 +73,7 @@ import ca.nrc.cadc.profiler.Profiler; import ca.nrc.cadc.rest.RestAction; import ca.nrc.cadc.tap.db.TableCreator; +import ca.nrc.cadc.tap.schema.TableDesc; import ca.nrc.cadc.tap.schema.TapSchemaDAO; import java.security.AccessControlException; import javax.sql.DataSource; @@ -118,8 +119,13 @@ public void doAction() throws Exception { // drop table TableCreator tc = new TableCreator(ds); - tc.dropTable(tableName); - prof.checkpoint("delete-table"); + // if the table was created with the API, drop the table, + // otherwise only delete the table from the tap_schema + TableDesc tableDesc = ts.getTable(tableName); + if (tableDesc.apiCreated) { + tc.dropTable(tableName); + prof.checkpoint("delete-table"); + } // remove from tap_schema last to minimise locking ts.delete(tableName); diff --git a/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/PutAction.java b/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/PutAction.java index 0146d85e..f3827b85 100644 --- a/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/PutAction.java +++ b/cadc-tap-schema/src/main/java/ca/nrc/cadc/vosi/actions/PutAction.java @@ -131,6 +131,8 @@ private void createSchema(TapSchemaDAO ts, String schema) throws Exception { s.getPrincipals().add(new HttpPrincipal(owner)); SchemaDesc sd = new SchemaDesc(schema); + // flag schema as created using the TAP API + sd.apiCreated = true; TapPermissions perms = new TapPermissions(); perms.owner = AuthenticationUtil.getIdentityManager().augment(s); @@ -216,6 +218,8 @@ private void createTable(TapSchemaDAO ts, String schemaName, String tableName) t if (td != null) { throw new ResourceAlreadyExistsException("table " + tableName + " already exists"); } + // flag table as created using the API to allow table deletion in the DeleteAction + td.apiCreated = true; Profiler prof = new Profiler(PutAction.class); DatabaseTransactionManager tm = new DatabaseTransactionManager(ds); diff --git a/cadc-tap-schema/src/main/resources/postgresql/tap_schema.upgrade-1.2.1.sql b/cadc-tap-schema/src/main/resources/postgresql/tap_schema.upgrade-1.2.1.sql new file mode 100644 index 00000000..d6edc0fd --- /dev/null +++ b/cadc-tap-schema/src/main/resources/postgresql/tap_schema.upgrade-1.2.1.sql @@ -0,0 +1,6 @@ +-- +-- upgrade from 1.2.0 to 1.2.1 +-- add api_created to flag a table or schema was created using the TAP API + +alter table tap_schema.tables11 add column api_created integer; +alter table tap_schema.schemas11 add column api_created integer; diff --git a/cadc-tap-schema/src/main/resources/postgresql/tap_schema11.sql b/cadc-tap-schema/src/main/resources/postgresql/tap_schema11.sql index c2a5cffd..661680f0 100644 --- a/cadc-tap-schema/src/main/resources/postgresql/tap_schema11.sql +++ b/cadc-tap-schema/src/main/resources/postgresql/tap_schema11.sql @@ -20,6 +20,9 @@ create table tap_schema.schemas11 read_only_group varchar(128), read_write_group varchar(128), +-- extension: flag to indicate if a schema was created using a Tap service API + api_created integer, + primary key (schema_name) ) ; @@ -40,6 +43,9 @@ create table tap_schema.tables11 read_only_group varchar(128), read_write_group varchar(128), +-- extension: flag to indicate if a table was created using a Tap service API + api_created integer, + primary key (table_name), foreign key (schema_name) references tap_schema.schemas11 (schema_name) ) diff --git a/cadc-tap/build.gradle b/cadc-tap/build.gradle index 9e663f23..a0219f47 100644 --- a/cadc-tap/build.gradle +++ b/cadc-tap/build.gradle @@ -15,7 +15,7 @@ apply from: '../opencadc.gradle' sourceCompatibility = 1.8 group = 'org.opencadc' -version = '1.1.16' +version = '1.1.17' description = 'OpenCADC TAP-1.1 tap client library' def git_url = 'https://github.com/opencadc/tap' diff --git a/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/SchemaDesc.java b/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/SchemaDesc.java index 9c9e83d2..75973e88 100644 --- a/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/SchemaDesc.java +++ b/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/SchemaDesc.java @@ -3,7 +3,7 @@ ******************* CANADIAN ASTRONOMY DATA CENTRE ******************* ************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** * - * (c) 2021. (c) 2021. + * (c) 2024. (c) 2021. * Government of Canada Gouvernement du Canada * National Research Council Conseil national de recherches * Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 @@ -76,18 +76,17 @@ * Descriptor class to represent a TAP_SCHEMA.schemas table. * */ -public class SchemaDesc -{ +public class SchemaDesc { private String schemaName; - private final List tableDescs = new ArrayList(); + private final List tableDescs = new ArrayList<>(); public String description; public String utype; public Integer schema_index; public TapPermissions tapPermissions; + public Boolean apiCreated; - public SchemaDesc(String schemaName) - { + public SchemaDesc(String schemaName) { TapSchema.assertNotNull(SchemaDesc.class, "schemaName", schemaName); this.schemaName = schemaName; } @@ -96,22 +95,19 @@ public SchemaDesc(String schemaName) * Setters and getters. * */ - public final String getSchemaName() - { + public final String getSchemaName() { return schemaName; } - public List getTableDescs() - { + public List getTableDescs() { return tableDescs; } - public TableDesc getTable(String name) - { - for (TableDesc td : tableDescs) - { - if (td.getTableName().equalsIgnoreCase(name)) + public TableDesc getTable(String name) { + for (TableDesc td : tableDescs) { + if (td.getTableName().equalsIgnoreCase(name)) { return td; + } } return null; } @@ -120,22 +116,20 @@ public TableDesc getTable(String name) * @return String representation of the Schema. */ @Override - public String toString() - { + public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Schema["); sb.append(schemaName).append(","); sb.append(description == null ? "" : description).append(","); sb.append(utype == null ? "" : utype).append(","); sb.append("tables["); - if (tableDescs != null) - { - for (TableDesc tableDesc : tableDescs) + if (tableDescs != null) { + for (TableDesc tableDesc : tableDescs) { sb.append(tableDesc); + } } sb.append("]]"); return sb.toString(); } - } diff --git a/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/TableDesc.java b/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/TableDesc.java index 34435516..c97d3d20 100644 --- a/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/TableDesc.java +++ b/cadc-tap/src/main/java/ca/nrc/cadc/tap/schema/TableDesc.java @@ -76,18 +76,18 @@ * Descriptor Class to represent a TAP_SCHEMA.tables table. * */ -public class TableDesc -{ +public class TableDesc { private String schemaName; private String tableName; - private final List columnDescs = new ArrayList(); - private final List keyDescs = new ArrayList(); + private final List columnDescs = new ArrayList<>(); + private final List keyDescs = new ArrayList<>(); public String description; public String utype; public Integer tableIndex; public TableType tableType = TableType.TABLE; public TapPermissions tapPermissions; + public Boolean apiCreated; public enum TableType { TABLE("table"), @@ -113,8 +113,7 @@ public String getValue() { } } - public TableDesc(String schemaName, String tableName) - { + public TableDesc(String schemaName, String tableName) { TapSchema.assertNotNull(TableDesc.class, "schemaName", schemaName); TapSchema.assertNotNull(TableDesc.class, "tableName", tableName); this.schemaName = schemaName; @@ -125,8 +124,7 @@ public void setSchemaName(String schemaName) { this.schemaName = schemaName; } - public String getSchemaName() - { + public String getSchemaName() { return schemaName; } @@ -134,33 +132,28 @@ public void setTableName(String tableName) { this.tableName = tableName; } - public String getTableName() - { + public String getTableName() { return tableName; } - public List getColumnDescs() - { + public List getColumnDescs() { return columnDescs; } - public ColumnDesc getColumn(String name) - { - for (ColumnDesc cd : columnDescs) - { - if (cd.getColumnName().equalsIgnoreCase(name)) + public ColumnDesc getColumn(String name) { + for (ColumnDesc cd : columnDescs) { + if (cd.getColumnName().equalsIgnoreCase(name)) { return cd; + } } return null; } - public List getKeyDescs() - { + public List getKeyDescs() { return keyDescs; } - public String toString() - { + public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Table["); sb.append(schemaName == null ? "" : schemaName).append(","); @@ -168,12 +161,14 @@ public String toString() sb.append(description == null ? "" : description).append(","); sb.append(utype == null ? "" : utype).append(","); sb.append("columns["); - for (ColumnDesc col : columnDescs) + for (ColumnDesc col : columnDescs) { sb.append(col).append("|"); + } sb.append("],"); sb.append("keys["); - for (KeyDesc key: keyDescs) + for (KeyDesc key: keyDescs) { sb.append(key).append("|"); + } sb.append("]]"); return sb.toString(); }