Commit cda98f33 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added arraysize support, set multicolumn layout in addable modals

parent 78f330b0
......@@ -79,14 +79,14 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
public final DBBroker getSourceDBBroker() {
if (sourceDBBroker == null) {
sourceDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getSourceDataSourceWrapper());
sourceDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getSourceDataSourceWrapper(), tapSchemaVersion);
}
return sourceDBBroker;
}
public final DBBroker getTapSchemaDBBroker() {
if (tapSchemaDBBroker == null) {
tapSchemaDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper());
tapSchemaDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper(), tapSchemaVersion);
}
return tapSchemaDBBroker;
}
......@@ -464,6 +464,8 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable {
SchemaModel ivoaSchemaModel = getIvoaSchemaModel();
broker.createIvoaSchemaStructure(ivoaSchemaModel);
// Initializing ivoa schema slot in schemata maps
schemas.put(ivoaSchemaModel.getName(), null);
// Add ivoa schema into TAP_SCHEMA
addEntireSchema(ivoaSchemaModel.getName());
......
......@@ -24,7 +24,6 @@ package it.inaf.ia2.tsm;
import it.inaf.ia2.tsm.model.PropertyModel;
import it.inaf.ia2.tsm.model.TableModel;
import it.inaf.ia2.tsm.model.TypesMapping;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
......
......@@ -31,13 +31,13 @@ import it.inaf.ia2.tsm.datalayer.pgsql.PostgresDBBroker;
*/
public class DBBrokerFactory {
public static DBBroker getDBBroker(DataSourceWrapper dataSourceWrapper) {
public static DBBroker getDBBroker(DataSourceWrapper dataSourceWrapper, String tapSchemaVersion) {
switch (dataSourceWrapper.getDatabaseType()) {
case MYSQL:
return new MySQLDBBroker(dataSourceWrapper.getDataSource());
return new MySQLDBBroker(dataSourceWrapper.getDataSource(), tapSchemaVersion);
default:
String pgDatabase = dataSourceWrapper.getCredentials().getDatabase();
return new PostgresDBBroker(dataSourceWrapper.getDataSource(), pgDatabase);
return new PostgresDBBroker(dataSourceWrapper.getDataSource(), pgDatabase, tapSchemaVersion);
}
}
}
......@@ -62,10 +62,12 @@ public abstract class DBBrokerTemplate implements DBBroker {
protected final DataSource dataSource;
private final char escapeCharacter;
private final String tapSchemaVersion;
public DBBrokerTemplate(DataSource dataSource, char escapeCharacter) {
public DBBrokerTemplate(DataSource dataSource, char escapeCharacter, String tapSchemaVersion) {
this.dataSource = dataSource;
this.escapeCharacter = escapeCharacter;
this.tapSchemaVersion = tapSchemaVersion;
}
protected List<String> getAllItemsNames(String query) throws SQLException {
......@@ -110,7 +112,7 @@ public abstract class DBBrokerTemplate implements DBBroker {
sb.append(String.format("(%s)", size));
}
protected abstract void createTable(String tapSchemaName, TableModel tableModel, Connection conn) throws SQLException;
protected abstract void createTable(String schemaName, TableModel tableModel, Connection conn) throws SQLException;
protected abstract String getAddPrimaryKeyQuery(String tapSchemaName, String tableName, String[] keyColumns);
......@@ -764,4 +766,8 @@ public abstract class DBBrokerTemplate implements DBBroker {
LOG.debug("{} columns found", allColumns.size());
return allColumns;
}
protected String getTapSchemaVersion() {
return tapSchemaVersion;
}
}
......@@ -50,8 +50,8 @@ public class MySQLDBBroker extends DBBrokerTemplate {
private static final Logger LOG = LoggerFactory.getLogger(MySQLDBBroker.class);
public MySQLDBBroker(DataSource dataSource) {
super(dataSource, '`');
public MySQLDBBroker(DataSource dataSource, String tapSchemaVersion) {
super(dataSource, '`', tapSchemaVersion);
}
@Override
......@@ -74,7 +74,7 @@ public class MySQLDBBroker extends DBBrokerTemplate {
if (beginIndex != -1) {
int endIndex = typeWithSize.indexOf(')');
if (endIndex != -1) {
Integer.parseInt(typeWithSize.substring(beginIndex + 1, endIndex));
return Integer.parseInt(typeWithSize.substring(beginIndex + 1, endIndex));
}
}
return null;
......@@ -111,14 +111,26 @@ public class MySQLDBBroker extends DBBrokerTemplate {
cm.put(Column.INDEXED_KEY, indexed);
// Datatype and Size
String type = resultSet.getString("Type").toLowerCase();
String datatype = TypesMapping.getADQLTypeFromMySQLType(type);
String type = resultSet.getString("Type").toUpperCase();
String datatype = TypesMapping.getADQLTypeFromMySQLType(type, getTapSchemaVersion());
Integer size = getSize(type);
if (size != null && size > 0 && !datatype.contains("(")) {
// Adding size at the end of datatype
datatype += String.format("(%s)", size);
}
cm.put(Column.DATATYPE_KEY, datatype);
cm.put(Column.SIZE_KEY, size);
Integer arraySize = null; // TODO (v 1.1)
String arraySize = null;
if (size != null) {
arraySize = String.valueOf(size);
// variable length columns must have a "*" symbol on arraysize
if (datatype.startsWith(ADQL.VARCHAR.name())) {
arraySize += "*";
}
}
cm.put(Column.ARRAYSIZE_KEY, arraySize);
allColumnsMetadata.put(columnName, cm);
}
......@@ -128,12 +140,12 @@ public class MySQLDBBroker extends DBBrokerTemplate {
}
@Override
protected void createTable(String tapSchemaName, TableModel tableModel, Connection conn) throws SQLException {
protected void createTable(String schemaName, TableModel tableModel, Connection conn) throws SQLException {
StringBuilder querySb = new StringBuilder();
querySb.append("CREATE TABLE IF NOT EXISTS ");
querySb.append(escape(tapSchemaName));
querySb.append(escape(schemaName));
querySb.append(".");
querySb.append(escape(tableModel.getName()));
querySb.append(" (\n");
......
......@@ -53,17 +53,17 @@ public class PostgresDBBroker extends DBBrokerTemplate {
private final String pgDatabaseName;
public PostgresDBBroker(DataSource dataSource, String pgDatabaseName) {
super(dataSource, '"');
public PostgresDBBroker(DataSource dataSource, String pgDatabaseName, String tapSchemaVersion) {
super(dataSource, '"', tapSchemaVersion);
this.pgDatabaseName = pgDatabaseName;
}
@Override
protected void createTable(String tapSchemaName, TableModel tableModel, Connection conn) throws SQLException {
protected void createTable(String schemaName, TableModel tableModel, Connection conn) throws SQLException {
StringBuilder querySb = new StringBuilder();
querySb.append("CREATE TABLE IF NOT EXISTS ");
querySb.append(escape(tapSchemaName));
querySb.append(escape(schemaName));
querySb.append(".");
querySb.append(escape(tableModel.getName()));
querySb.append(" (\n");
......@@ -131,6 +131,21 @@ public class PostgresDBBroker extends DBBrokerTemplate {
return String.format("SELECT tablename FROM pg_catalog.pg_tables where schemaname = '%s'", schemaName);
}
/**
* Example: 5x5x4 is approximated to *x*x*, because it seems there is no
* easy way to retrieve that numbers.
*/
private String formatArraySize(int arrayDimension) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arrayDimension; i++) {
if (i > 0) {
sb.append("x");
}
sb.append("*");
}
return sb.toString();
}
@Override
public Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName) throws SQLException {
......@@ -138,10 +153,11 @@ public class PostgresDBBroker extends DBBrokerTemplate {
StringBuilder querySb = new StringBuilder();
querySb.append("SELECT c.column_name, c.data_type, r.contype AS column_type, c.character_maximum_length, c.numeric_precision\n"); //, c.numeric_precision_radix
querySb.append("SELECT c.column_name, c.data_type, pg_catalog.format_type(a.atttypid, a.atttypmod), r.contype AS column_type, c.character_maximum_length, c.numeric_precision, a.attndims AS arraydim\n");
querySb.append("FROM information_schema.columns c\n");
querySb.append("JOIN pg_catalog.pg_tables t ON c.table_schema = t.schemaname AND c.table_name = t.tablename\n");
querySb.append("LEFT JOIN pg_catalog.pg_constraint r ON c.ordinal_position = ANY(r.conkey) AND r.conrelid = (t.schemaname || '.' || t.tablename)::regclass::oid\n");
querySb.append("LEFT JOIN pg_catalog.pg_attribute a ON a.attrelid = (t.schemaname || '.' || t.tablename)::regclass::oid and a.attname = c.column_name\n");
querySb.append("WHERE t.schemaname = '");
querySb.append(schemaName);
querySb.append("' AND t.tablename = '");
......@@ -178,19 +194,46 @@ public class PostgresDBBroker extends DBBrokerTemplate {
cm.put(Column.PRIMARY_KEY, primaryKey);
cm.put(Column.INDEXED_KEY, indexed);
int size = 0;
Integer size = null;
int arraydimension = 0;
String datatype;
String type = resultSet.getString("data_type");
datatype = TypesMapping.getADQLTypeFromPostgresType(type);
if (datatype.equals(ADQL.VARCHAR.name()) || datatype.equals(ADQL.CHAR.name())) {
String type = resultSet.getString("data_type").toUpperCase();
boolean isArray = false;
if ("ARRAY".equals(type)) {
isArray = true;
// example: integer array has data_type ARRAY and format_type integer[]
type = resultSet.getString("format_type").toUpperCase();
// example: an array defined as integer[5][5] has arraydim = 2
// unfortunately it seems there is no easy way to get also the
// numbers inside brakets, so this case will be approximated to *x*
arraydimension = resultSet.getInt("arraydim");
}
datatype = TypesMapping.getADQLTypeFromPostgresType(type, getTapSchemaVersion());
if (!isArray && (datatype.equals(ADQL.VARCHAR.name()) || datatype.equals(ADQL.CHAR.name()))) {
size = resultSet.getInt("character_maximum_length");
}
if (size != null && size > 0 && !datatype.contains("(")) {
// Adding size at the end of datatype
datatype += String.format("(%s)", size);
}
cm.put(Column.DATATYPE_KEY, datatype);
cm.put(Column.SIZE_KEY, size);
Integer arraySize = null; // TODO (v 1.1)
String arraySize = null;
if (isArray) {
arraySize = formatArraySize(arraydimension);
} else if (size != null) {
arraySize = String.valueOf(size);
// variable length columns must have a "*" symbol on arraysize
if (datatype.startsWith(ADQL.VARCHAR.name())) {
arraySize += "*";
}
}
cm.put(Column.ARRAYSIZE_KEY, arraySize);
allColumnsMetadata.put(columnName, cm);
}
......
......@@ -46,11 +46,11 @@ public class TypeMapping {
}
@XmlElement(name = "mysql")
public String getMysqlType() {
public String getMySQLType() {
return mysqlType;
}
public void setMysqlType(String mysqlType) {
public void setMySQLType(String mysqlType) {
this.mysqlType = mysqlType;
}
......
......@@ -28,7 +28,6 @@ import java.io.InputStream;
import java.util.List;
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
......@@ -38,6 +37,9 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
public class TypesMapping {
// For older TAP_SCHEMA versions
private static final String ADQL_PREFIX = "adql:";
@XmlRootElement(name = "sql_type_mapping")
static class TypesWrapper {
......@@ -76,36 +78,55 @@ public class TypesMapping {
throw new IllegalArgumentException("Unable to retrieve mapping for ADQL type " + adqlType);
}
/**
* returns an ADQL type String compatible with older TAP_SCHEMA versions
* (for older versions "adql:" prefix is needed).
*/
private static String getCompatibleADQLType(String adqlType, String tapSchemaVersion) {
if (tapSchemaVersion.startsWith("1.0")) {
return ADQL_PREFIX + adqlType;
}
return adqlType;
}
public static Class getClassFromAdqlType(String adqlType) {
return getTypeMappingFromADQLType(adqlType).getJavaType();
}
public static String getMySQLTypeFromADQLType(String adqlType) {
return getTypeMappingFromADQLType(adqlType).getMysqlType();
return getTypeMappingFromADQLType(adqlType).getMySQLType();
}
public static String getPostgresSQLTypeFromADQLType(String adqlType) {
return getTypeMappingFromADQLType(adqlType).getPgsqlType();
}
public static String getADQLTypeFromPostgresType(String pgsqlType) {
private static String getADQLTypeFromPostgresType(String pgsqlType) {
for (TypeMapping typeMapping : TYPES) {
if (typeMapping.getPgsqlType().startsWith(pgsqlType)) {
if (pgsqlType.toUpperCase().startsWith(typeMapping.getPgsqlType().toUpperCase())) {
return typeMapping.getAdqlType();
}
}
return ADQL.getDataType(pgsqlType);
}
public static String getADQLTypeFromMySQLType(String mysqlType) {
public static String getADQLTypeFromPostgresType(String pgsqlType, String tapSchemaVersion) {
return getCompatibleADQLType(getADQLTypeFromPostgresType(pgsqlType), tapSchemaVersion);
}
private static String getADQLTypeFromMySQLType(String mysqlType) {
for (TypeMapping typeMapping : TYPES) {
if (typeMapping.getPgsqlType().startsWith(mysqlType)) {
if (mysqlType.toUpperCase().startsWith(typeMapping.getMySQLType().toUpperCase())) {
return typeMapping.getAdqlType();
}
}
return ADQL.getDataType(mysqlType);
}
public static String getADQLTypeFromMySQLType(String mysqlType, String tapSchemaVersion) {
return getCompatibleADQLType(getADQLTypeFromMySQLType(mysqlType), tapSchemaVersion);
}
public static Object parseDefaultValue(String defaultValue, String type) {
return parseDefaultValue(defaultValue, ADQL.valueOf(type));
}
......
......@@ -39,12 +39,14 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
<type>VARCHAR</type>
<updatable>false</updatable>
<key>arraysize</key>
<size>255</size>
<standard>true</standard>
</property>
<property>
<name>xtype</name>
<type>VARCHAR</type>
<updatable>true</updatable>
<size>255</size>
<standard>true</standard>
</property>
<property>
......
......@@ -92,7 +92,7 @@ public class TestAll {
settings = new TapSchemaSettings();
settings.setTapSchemaName("test_tap_schema");
settings.setTapSchemaVersion("1.0");
settings.setTapSchemaVersion("1.1");
settings.setHasObscore(true);
settings.setObscoreVersion("1.1");
......@@ -166,9 +166,11 @@ public class TestAll {
switch (dbType) {
case MYSQL:
stat.executeUpdate("DROP DATABASE IF EXISTS test_tap_schema");
stat.executeUpdate("DROP DATABASE IF EXISTS ivoa");
break;
case POSTGRES:
stat.executeUpdate("DROP SCHEMA IF EXISTS test_tap_schema CASCADE");
stat.executeUpdate("DROP SCHEMA IF EXISTS ivoa CASCADE");
break;
default:
throw new UnsupportedOperationException("Database type " + dbType + " not supported");
......@@ -457,10 +459,16 @@ public class TestAll {
operations = new UpdateOperations(tapSchema);
assertFalse(operations.getHasOperations());
// Checking size and arraysize detection
Column descriptionColumn = tapSchema.getChild(tapSchema.getName()).getChild("columns").getChild("description");
assertEquals("VARCHAR(255)", descriptionColumn.getProperty("datatype").getValue(String.class));
assertEquals(255, descriptionColumn.getProperty("size").getValue(Integer.class));
assertEquals("255*", descriptionColumn.getProperty("arraysize").getValue(String.class));
// reloading
LOG.debug("----- Reloading saved TAP_SCHEMA -----");
tapSchema = new TapSchema(dbWrapper, settings, true);
assertEquals("1.0", tapSchema.getTapSchemaDBBroker().detectVersion(tapSchema.getName()));
assertEquals("1.1", tapSchema.getTapSchemaDBBroker().detectVersion(tapSchema.getName()));
LOG.debug(tapSchema.toString());
assertNotNull(sch0 = tapSchema.getChild("sch0", Status.ADDED_PERSISTED));
......
......@@ -79,7 +79,7 @@ public class TapSchemaLoader implements Serializable {
dbWrapper.testConnections();
// Searching for TAP_SCHEMA name
DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper());
DBBroker broker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper(), tapCredentials.getTapSchemaVersion());
boolean tapSchemaExists = false;
for (String schemaName : broker.getAllSchemaNames()) {
if (schemaName.equals(tapCredentials.getTapSchemaName())) {
......
......@@ -218,4 +218,16 @@ table input+label {
#users-list-wrapper li a:hover {
text-decoration: none;
}
/* CSS3 multicolumn layout */
#addablesModal .modal-body {
-webkit-column-count: 3;
-moz-column-count: 3;
column-count: 3;
}
/* Margin fix for multicolumn layout */
#addablesModal .checkbox:first-child {
margin-top: 0;
}
\ No newline at end of file
......@@ -259,10 +259,14 @@
</div>
</div>
<div class="col-xs-6">
<div class="form-group">
<h:panelGroup class="form-group" layout="block" rendered="#{tapSchemaEditing.selectedColumn.getProperty('arraysize') eq null}">
<label for="size" class="control-label">Size:</label>
<span>#{tapSchemaEditing.selectedColumn.getProperty('size').value}</span>
</div>
</h:panelGroup>
<h:panelGroup class="form-group" layout="block" rendered="#{tapSchemaEditing.selectedColumn.getProperty('arraysize') ne null}">
<label for="arraysize" class="control-label">Arraysize:</label>
<span>#{tapSchemaEditing.selectedColumn.getProperty('arraysize').value}</span>
</h:panelGroup>
</div>
</div>
<div class="row">
......@@ -375,9 +379,8 @@
</h:panelGroup>
<div class="modal fade" tabindex="-1" role="dialog" id="addablesModal">
<div class="modal-dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<div class="pull-right">
<h:commandLink class="btn btn-default btn-sm" action="#{tapSchemaEditing.checkAllEntities(false)}">
......@@ -396,8 +399,6 @@
<h4 class="modal-title">Add</h4>
</div>
<div class="modal-body">
<div class="clearfix">
</div>
<div class="addables">
<h:panelGroup id="addables_modal_content">
<h:panelGroup rendered="#{tapSchemaEditing.currentAddingContainer ne null}">
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment