*/\r
package org.collectionspace.services.common.init;\r
\r
+import java.sql.Connection;\r
+import java.sql.ResultSet;\r
+import java.sql.SQLException;\r
+import java.sql.Statement;\r
+import java.util.List;\r
+\r
import org.collectionspace.services.common.Tools;\r
import org.collectionspace.services.common.service.ServiceBindingType;\r
import org.collectionspace.services.common.service.InitHandler.Params.Field;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
\r
-import java.sql.Connection;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.sql.Statement;\r
-\r
-import java.util.List;\r
-\r
/**\r
* AddIndices, post-init action to add indexes to the database.\r
* \r
String indexName = columnName + INDEX_SUFFIX;\r
try {\r
DatabaseProductType databaseProductType = JDBCTools.getDatabaseProductType();\r
+ if (indexExists(databaseProductType, tableName, indexName)) {\r
+ logger.trace("Index already exists for column " + columnName\r
+ + " in table " + tableName);\r
+ // FIXME: Can add the option to drop and re-create an index here.\r
+ // For example, see MySQL documentation on DROP INDEX.\r
+ return 0;\r
+ }\r
// TODO: Consider refactoring this 'if' statement to a general-purpose\r
// mechanism for retrieving and populating catalog/DDL-type SQL statements\r
// appropriate to a particular database product.\r
if (databaseProductType == DatabaseProductType.MYSQL) {\r
- // If the index already exists, do nothing.\r
- if (indexExists(databaseProductType, tableName, indexName)) {\r
- // FIXME: Can add the option to drop and re-create an index here.\r
- // See MySQL documentation on DROP INDEX.\r
- } else {\r
- sql = "CREATE INDEX " + indexName + " ON " + tableName + " (" + columnName + ")";\r
- }\r
+ logger.trace("Creating index for column " + columnName + " in table " + tableName);\r
+ sql = "CREATE INDEX " + indexName + " ON " + tableName + " (" + columnName + ")";\r
} else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
- if (indexExists(databaseProductType, tableName, indexName)) {\r
- // FIXME: Can add the option to reindex an existing index here.\r
- // See PostgreSQL documentation on REINDEX.\r
- } else {\r
- sql = "CREATE INDEX ON " + tableName + " (" + columnName + ")";\r
- }\r
+ logger.trace("Creating index for column " + columnName + " in table " + tableName);\r
+ sql = "CREATE INDEX ON " + tableName + " (" + columnName + ")";\r
} else {\r
throw new Exception("Unrecognized database system " + databaseProductType);\r
}\r
if (sql != null && ! sql.trim().isEmpty()) {\r
rows = JDBCTools.executeUpdate(sql);\r
- logger.info("Index added to column ("+columnName+") on table ("+tableName+")");\r
+ logger.trace("Index added to column ("+columnName+") on table ("+tableName+")");\r
}\r
return rows;\r
} catch (Throwable e) {\r
- logger.info("Index NOT added to column ("+columnName+") on table ("+tableName+") SQL: "+sql+" ERROR: "+e);\r
+ logger.debug("Index NOT added to column ("+columnName+") on table ("+tableName+") SQL: "+sql+" ERROR: "+e);\r
return -1;\r
}\r
}\r
Connection conn = null;\r
Statement stmt = null;\r
ResultSet rs = null;\r
+\r
+ if (databaseProductType == DatabaseProductType.MYSQL) {\r
+ sql = "SHOW INDEX FROM " + tableName + " WHERE key_name='" + indexName + "'";\r
+ } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
+ // FIXME: Add comparable SQL statement for PostgreSQL.\r
+ }\r
+\r
try {\r
- if (databaseProductType == DatabaseProductType.MYSQL) {\r
- sql = "SHOW INDEX FROM " + tableName + " WHERE key_name='"\r
- + indexName + "'";\r
- conn = JDBCTools.getConnection(JDBCTools.getDefaultRepositoryName());\r
- stmt = conn.createStatement();\r
- rs = stmt.executeQuery(sql);\r
- if (rs.last()) {\r
- rows = rs.getRow();\r
- }\r
- rs.close();\r
- stmt.close();\r
- conn.close();\r
- if (rows > 0) {\r
- indexExists = true;\r
- }\r
- } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
- // FIXME: Add comparable logic for PostgreSQL.\r
+ conn = JDBCTools.getConnection(JDBCTools.getDefaultRepositoryName());\r
+ stmt = conn.createStatement();\r
+ rs = stmt.executeQuery(sql);\r
+ if (rs.last()) {\r
+ rows = rs.getRow();\r
+ }\r
+ rs.close();\r
+ stmt.close();\r
+ conn.close();\r
+ if (rows > 0) {\r
+ indexExists = true;\r
}\r
} catch (Exception e) {\r
logger.debug("Error when identifying whether index exists in table "\r
*/
package org.collectionspace.services.common.init;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
import java.util.List;
+
import org.collectionspace.services.common.service.ServiceBindingType;
import org.collectionspace.services.common.service.InitHandler.Params.Field;
import org.collectionspace.services.common.service.InitHandler.Params.Property;
import org.collectionspace.services.common.storage.DatabaseProductType;
import org.collectionspace.services.common.storage.JDBCTools;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
String datatype = "";
for (Field field : fields) {
datatype = getDatatypeFromLogicalType(databaseProductType, field.getType());
- // TODO: Consider refactoring this 'if' statement to a general-purpose
+ // If the field is already of the desired datatype, skip it.
+ if (fieldHasDesiredDatatype(databaseProductType, field, datatype)) {
+ logger.trace("Field " + field.getTable() + "." + field.getCol()
+ + " is already of desired datatype " + datatype);
+ continue;
+ }
+ // TODO: Consider refactoring this nested 'if' statement to a general-purpose
// mechanism for retrieving and populating catalog/DDL-type SQL statements
// appropriate to a particular database product.
if (databaseProductType == DatabaseProductType.MYSQL) {
+ logger.trace("Modifying field " + field.getTable() + "."
+ + field.getCol() + " to datatype " + datatype);
sql = "ALTER TABLE " + field.getTable() + " MODIFY COLUMN " + field.getCol() + " " + datatype;
} else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
- sql = "ALTER TABLE " + field.getTable() + " ALTER COLUMN " + field.getCol() + " " + datatype;
+ sql = "ALTER TABLE " + field.getTable() + " ALTER COLUMN " + field.getCol() + " " + datatype;
} else {
throw new Exception("Unrecognized database system.");
}
}
}
- // TODO: Refactor this method to a general-purpose mechanism for retrieving
+ // TODO: Consider refactoring this method to a general-purpose mechanism for retrieving
// datatypes appropriate to a particular database product, that corresponds
// to logical datatypes such as "LARGETEXT".
//
}
return datatype;
}
+
+ private boolean fieldHasDesiredDatatype(DatabaseProductType databaseProductType,
+ Field field, String datatype) {
+
+ boolean fieldHasDesiredDatatype = false;
+ int rows = 0;
+ String sql = "";
+ String currentDatatype = "";
+ Connection conn = null;
+ Statement stmt = null;
+ ResultSet rs = null;
+
+ if (databaseProductType == DatabaseProductType.MYSQL) {
+ sql = "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS "
+ + "WHERE TABLE_SCHEMA = '" + getDatabaseName(field) + "'"
+ + " AND TABLE_NAME = '" + getTableName(field) + "'"
+ + " AND COLUMN_NAME = '" + field.getCol() + "'";
+ } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
+ // FIXME: Add comparable SQL statement for PostgreSQL.
+ }
+
+ try {
+ conn = JDBCTools.getConnection(JDBCTools.getDefaultRepositoryName());
+ stmt = conn.createStatement();
+ rs = stmt.executeQuery(sql);
+ while (rs.next()) {
+ currentDatatype = rs.getString(1);
+ }
+ if (datatype.equalsIgnoreCase(currentDatatype)) {
+ fieldHasDesiredDatatype = true;
+ }
+ rs.close();
+ stmt.close();
+ conn.close();
+ } catch (Exception e) {
+ logger.debug("Error when identifying datatype of field " + field.getCol()
+ + " in table " + field.getTable() + ":" + e.getMessage());
+ } finally {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ if (stmt != null) {
+ stmt.close();
+ }
+ if (conn != null) {
+ conn.close();
+ }
+ } catch (SQLException sqle) {
+ logger.debug("SQL Exception closing statement/connection in ModifyFieldDatatypes: " + sqle.getLocalizedMessage());
+ }
+ }
+ return fieldHasDesiredDatatype;
+ }
+
+ // FIXME: Hacks to separate the '.'-delimited database/schema name
+ // from the table name in field.getTable, where that value is
+ // specified in tenant bindings configuration as 'database.table'.
+ //
+ // Even as the current hack, this logic should reside in Field, not here.
+
+ private String getDatabaseName(Field field) {
+ String databaseName = field.getTable();
+ String[] databaseAndTable = databaseName.split("\\.", 2);
+ if (! databaseAndTable[0].isEmpty()) {
+ databaseName = databaseAndTable[0];
+ }
+ return databaseName;
+ }
+
+ private String getTableName(Field field) {
+ String tableName = field.getTable();
+ String[] databaseAndTable = tableName.split("\\.", 2);
+ if (! databaseAndTable[1].isEmpty()) {
+ tableName = databaseAndTable[1];
+ }
+ return tableName;
+ }
}