diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java index 7c461d100473a4538140dbedbbd4fced4dca0576..7ddf18ea9166c26ac8bee457df72324ace06e652 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java @@ -48,6 +48,7 @@ public class Column extends ChildEntity<Table> { public final static String UNIT_KEY = "unit"; public final static String COLUMN_INDEX = "column_index"; // TAP version >= 1.1 public final static String DBNAME = "dbname"; + public final static String XTYPE_KEY = "xtype"; /** * Original datatype (computed from information_schema data), used for diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java index 1e6ee1f96dc6b839f68ad99353f8e7d2e8163505..a91bf3dd6519241009bd8f6c989da8e5ffbc57d1 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java @@ -43,7 +43,9 @@ public enum ADQL { BINARY, VARBINARY, REGION, - POINT; + POINT, + CIRCLE, + POLYGON; /** * Returns a string representing a datatype which can't be interpreted as an @@ -64,4 +66,12 @@ public enum ADQL { public static boolean isVariable(ADQL adql) { return adql.equals(VARCHAR) || adql.equals(VARBINARY) || adql.equals(CLOB) || adql.equals(BLOB); } + + public static ADQL parse(String adqlStr) { + try { + return ADQL.valueOf(adqlStr); + } catch (IllegalArgumentException e) { + return null; + } + } } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java index d5f2d89cf82594de6a4bb5e17708db5d2248e073..286ec90fdf4b65326834c94e3c736a3ae2151a2c 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java @@ -30,6 +30,7 @@ import it.inaf.ia2.tsm.datalayer.DBBrokerTemplate; import it.inaf.ia2.tsm.datalayer.DataTypeMode; import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; +import it.inaf.ia2.tsm.model.TypeMapping; import it.inaf.ia2.tsm.model.TypesMapping; import java.sql.Connection; import java.sql.PreparedStatement; @@ -268,7 +269,7 @@ public class PostgresDBBroker extends DBBrokerTemplate { int arraydimension = 0; String dbType = resultSet.getString("data_type").toUpperCase(); - boolean isArray = false; + boolean isArray = false, userDefinedType = false; if ("ARRAY".equals(dbType)) { isArray = true; // example: integer array has data_type ARRAY and format_type integer[] @@ -277,10 +278,25 @@ public class PostgresDBBroker extends DBBrokerTemplate { // 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"); + } else if ("USER-DEFINED".equals(dbType)) { + dbType = resultSet.getString("format_type"); + userDefinedType = true; } + String arraySize = null; + ADQL adqlType = TypesMapping.getADQLFromPostgresType(dbType); String datatype = TypesMapping.getDataTypeFromPostgresType(dbType, getDataTypeMode()); + if (userDefinedType && adqlType != null) { + // ADQL type must be used for the following search, because it is the most specific (a POINT is a double using VOTable syntax). + TypeMapping mapping = TypesMapping.getTypeMapping(adqlType.toString(), DataTypeMode.ADQL); + if (mapping.getArraysize() != null) { + arraySize = mapping.getArraysize(); + } + if (mapping.getXtype() != null) { + cm.put(Column.XTYPE_KEY, mapping.getXtype()); + } + } if (!isArray && (ADQL.VARCHAR.equals(adqlType) || ADQL.CHAR.equals(adqlType))) { size = resultSet.getInt("character_maximum_length"); @@ -292,11 +308,12 @@ public class PostgresDBBroker extends DBBrokerTemplate { cm.put(Column.DATATYPE_KEY, datatype); cm.put(Column.SIZE_KEY, size); - String arraySize; - if (isArray) { - arraySize = formatArraySize(arraydimension); - } else { - arraySize = getArraysize(adqlType, size); + if (arraySize == null) { + if (isArray) { + arraySize = formatArraySize(arraydimension); + } else { + arraySize = getArraysize(adqlType, size); + } } cm.put(Column.ARRAYSIZE_KEY, arraySize); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypeMapping.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypeMapping.java index c260e68281211f1ce43304d30d89ee315e095e30..342a844e828c4caf010acfedf39fb28ed2393781 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypeMapping.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypeMapping.java @@ -36,6 +36,8 @@ public class TypeMapping { private String adqlType; private String voTableType; + private String xtype; + private String arraysize; private DBTypeMapping mysqlMapping; private DBTypeMapping pgsqlMapping; private String javaTypeString; @@ -54,6 +56,33 @@ public class TypeMapping { return voTableType; } + /** + * Returns the default xtype for this datatype. This value can be null. + */ + @XmlElement(name = "xtype") + public String getXtype() { + return xtype; + } + + public void setXtype(String xtype) { + this.xtype = xtype; + } + + /** + * Returns the arraysize defined for this datatype. This is necessary for + * some special datatypes (e.g. {@code POINT}, {@code CIRCLE}) having an + * arraysize defined by their semantic and not by the database metadata. + * This value is null for all the other data types. + */ + @XmlElement(name = "arraysize") + public String getArraysize() { + return arraysize; + } + + public void setArraysize(String arraysize) { + this.arraysize = arraysize; + } + public void setVoTableType(String voTableType) { this.voTableType = voTableType; } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java index 4185534bafa68bf79725f098dc5042f0bf2c209b..90be35c6c96d7a639e92d4ccc1387381661313d1 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java @@ -245,11 +245,7 @@ public class TypesMapping { * @param mysqlDBType the datatype, as read from MySQL information_schema. */ public static ADQL getADQLFromMySQLType(String mysqlDBType) { - try { - return ADQL.valueOf(getDataTypeFromMySQLType(mysqlDBType, DataTypeMode.ADQL)); - } catch (IllegalArgumentException e) { - return null; - } + return ADQL.parse(getDataTypeFromMySQLType(mysqlDBType, DataTypeMode.ADQL)); } /** @@ -259,11 +255,7 @@ public class TypesMapping { * information_schema. */ public static ADQL getADQLFromPostgresType(String postgresDBType) { - try { - return ADQL.valueOf(getDataTypeFromPostgresType(postgresDBType, DataTypeMode.ADQL)); - } catch (IllegalArgumentException e) { - return null; - } + return ADQL.parse(getDataTypeFromPostgresType(postgresDBType, DataTypeMode.ADQL)); } /** diff --git a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml index c3470b537abe146db6b728c6981c40d1c2210142..6a6f8d5d0f8e51fff8406a034113c3043322ef05 100644 --- a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml +++ b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml @@ -39,6 +39,7 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <column name="xtype"> <type>VARCHAR</type> <updatable>true</updatable> + <key>xtype</key> <standard>true</standard> </column> <column name="column_index"> diff --git a/TASMAN-core/src/main/resources/sql_type_mapping.xml b/TASMAN-core/src/main/resources/sql_type_mapping.xml index 83e05ab3f4368f984943ce158e871540e4216061..5e1e4599f20875f2fd740057800db7f25842bb41 100644 --- a/TASMAN-core/src/main/resources/sql_type_mapping.xml +++ b/TASMAN-core/src/main/resources/sql_type_mapping.xml @@ -133,6 +133,7 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <type> <adql>CLOB</adql> <votable>char</votable> + <xtype>adql:clob</xtype> <mysql inverse="true"> <type>LONGTEXT</type> <type>MEDIUMTEXT</type> @@ -147,6 +148,7 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <type> <adql>BLOB</adql> <votable>unsignedByte</votable> + <xtype>adql:blob</xtype> <mysql inverse="true"> <type>BLOB</type> </mysql> @@ -159,6 +161,7 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <type> <adql>TIMESTAMP</adql> <votable>char</votable> + <xtype>timestamp</xtype> <mysql inverse="true"> <type>DATETIME</type> <type>DATE</type> @@ -203,8 +206,9 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <type> <adql>REGION</adql> <votable>char</votable> + <xtype>adql:region</xtype> <mysql> - <type>VARCHAR</type> + <type>TEXT</type> </mysql> <pgsql> <type>character varying</type> @@ -214,12 +218,45 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <type> <adql>POINT</adql> - <votable>char</votable> + <votable>double</votable> + <!--<votable>float</votable>--> + <xtype>point</xtype> + <arraysize>2</arraysize> <mysql> <type>VARCHAR</type> </mysql> - <pgsql> - <type>character varying</type> + <pgsql inverse="true"> + <type>spoint</type> + </pgsql> + <java>java.lang.String</java> + </type> + + <type> + <adql>CIRCLE</adql> + <votable>double</votable> + <!--<votable>float</votable>--> + <xtype>circle</xtype> + <arraysize>3</arraysize> + <mysql> + <type>VARCHAR</type> + </mysql> + <pgsql inverse="true"> + <type>scircle</type> + </pgsql> + <java>java.lang.String</java> + </type> + + <type> + <adql>POLYGON</adql> + <votable>double</votable> + <!--<votable>float</votable>--> + <xtype>polygon</xtype> + <arraysize>*</arraysize> + <mysql> + <type>VARCHAR</type> + </mysql> + <pgsql inverse="true"> + <type>spoly</type> </pgsql> <java>java.lang.String</java> </type> diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java index 26e4c36a28300aa8243da12d721cb3653ae83462..bedb38c1a299bc708ac1b1390df456aecaead3b4 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java @@ -145,11 +145,14 @@ public class TapSchemaEditingBean implements Serializable { return sb.toString(); } - public boolean isShowWarningOnDataType() { + public boolean isShowWarning(String key) { if (selectedColumn == null) { return false; } - EntityProperty dataTypeProp = selectedColumn.getProperty("datatype"); + EntityProperty dataTypeProp = selectedColumn.getProperty(key); + if (dataTypeProp.getDefaultValue() == null) { + return false; + } return !Objects.equals(dataTypeProp.getDefaultValue(), dataTypeProp.getValue()); } diff --git a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml index 8269f8f84e1def0d4a56654e58fda7b9c21966a3..e2518753d926460bf6b41d44b949ddf56448b8f3 100644 --- a/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml +++ b/TASMAN-webapp/src/main/webapp/tapSchemaEditing.xhtml @@ -329,7 +329,7 @@ <f:ajax event="keyup" execute="@form" render=":main:datatype-warning" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'datatype')}" onevent="TSM.textInputChanged" /> </h:inputText> <h:panelGroup id="datatype-warning"> - <h:panelGroup class="text-warning" rendered="#{tapSchemaEditing.showWarningOnDataType}"> + <h:panelGroup class="text-warning" rendered="#{tapSchemaEditing.isShowWarning('datatype')}"> <small> <span class="glyphicon glyphicon-warning-sign"></span> Suggested value: #{tapSchemaEditing.selectedColumn.getProperty('datatype').defaultValue} @@ -425,8 +425,16 @@ class="form-control #{tapSchemaEditing.selectedColumn.isChanged('xtype') ? 'changed' : ''}" value="#{tapSchemaEditing.selectedColumn.getProperty('xtype').value}"> <f:converter converterId="it.inaf.ia2.NullOrEmptyConverter" /> - <f:ajax event="keyup" execute="@form" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'xtype')}" onevent="TSM.textInputChanged" /> + <f:ajax event="keyup" execute="@form" render=":main:xtype-warning" listener="#{tapSchemaEditing.textInputChanged(tapSchemaEditing.selectedColumn, 'xtype')}" onevent="TSM.textInputChanged" /> </h:inputText> + <h:panelGroup id="xtype-warning"> + <h:panelGroup class="text-warning" rendered="#{tapSchemaEditing.isShowWarning('xtype')}"> + <small> + <span class="glyphicon glyphicon-warning-sign"></span> + Suggested value: #{tapSchemaEditing.selectedColumn.getProperty('xtype').defaultValue} + </small> + </h:panelGroup> + </h:panelGroup> </h:panelGroup> </h:panelGroup> </h:panelGroup>