datatable delete apis should only delete registered datatables

This commit is contained in:
Vishwas Babu AJ
2013-06-25 15:29:15 +05:30
parent 58eda88327
commit fda126474c
@@ -58,13 +58,20 @@ import com.google.gson.reflect.TypeToken;
@Service @Service
public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataService { public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataService {
private final static String DATATABLE_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9]$"; private final static String DATATABLE_NAME_REGEX_PATTERN = "^[a-zA-Z][a-zA-Z0-9\\-_\\s]{0,48}[a-zA-Z0-9]$";
private final static Logger logger = LoggerFactory.getLogger(ReadWriteNonCoreDataServiceImpl.class); private final static Logger logger = LoggerFactory.getLogger(ReadWriteNonCoreDataServiceImpl.class);
private final static HashMap<String, String> apiTypeToMySQL = new HashMap<String, String>() {{ private final static HashMap<String, String> apiTypeToMySQL = new HashMap<String, String>() {
put("String", "VARCHAR"); put("Number", "INT"); put("Decimal", "DECIMAL"); put("Date", "DATE");
put("Text", "TEXT"); put ("Dropdown", "INT"); {
}}; put("String", "VARCHAR");
put("Number", "INT");
put("Decimal", "DECIMAL");
put("Date", "DATE");
put("Text", "TEXT");
put("Dropdown", "INT");
}
};
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
private final DataSource dataSource; private final DataSource dataSource;
@@ -282,20 +289,24 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
} }
} }
private boolean isRegisteredDataTable(final String name) {
// PERMITTED datatables
final String sql = "select if((exists (select 1 from x_registered_table where registered_table_name = ?)) = 1, 'true', 'false')";
final String isRegisteredDataTable = this.jdbcTemplate.queryForObject(sql, String.class, new Object[] { name });
return new Boolean(isRegisteredDataTable);
}
private void validateDatatableName(final String name) { private void validateDatatableName(final String name) {
if (name == null || name.isEmpty()) { if (name == null || name.isEmpty()) {
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.null.name", throw new PlatformDataIntegrityException("error.msg.datatables.datatable.null.name", "Data table name must not be blank.");
"Data table name must not be blank."); } else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) { throw new PlatformDataIntegrityException(
} else if (!name.matches(DATATABLE_NAME_REGEX_PATTERN)) { "error.msg.datatables.datatable.invalid.name.regex", "Invalid data table name.", name); }
throw new PlatformDataIntegrityException("error.msg.datatables.datatable.invalid.name.regex",
"Invalid data table name.", name);
}
} }
private String datatableColumnNameToCodeValueName(final String columnName, final String code) { private String datatableColumnNameToCodeValueName(final String columnName, final String code) {
return (code + "_cd_" + columnName); return (code + "_cd_" + columnName);
} }
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) { private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
@@ -305,373 +316,350 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ
private void parseDatatableColumnObjectForCreate(final JsonObject column, StringBuilder sqlBuilder) { private void parseDatatableColumnObjectForCreate(final JsonObject column, StringBuilder sqlBuilder) {
String name = (column.has("name")) ? column.get("name").getAsString() : null; String name = (column.has("name")) ? column.get("name").getAsString() : null;
String type = (column.has("type")) ? column.get("type").getAsString() : null; String type = (column.has("type")) ? column.get("type").getAsString() : null;
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null; Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false; Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
String code = (column.has("code")) ? column.get("code").getAsString() : null; String code = (column.has("code")) ? column.get("code").getAsString() : null;
if (StringUtils.isNotBlank(code)) { if (StringUtils.isNotBlank(code)) {
name = datatableColumnNameToCodeValueName(name, code); name = datatableColumnNameToCodeValueName(name, code);
} }
String mysqlType = apiTypeToMySQL.get(type); String mysqlType = apiTypeToMySQL.get(type);
sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType); sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType);
if (type != null) if (type != null) {
{ if (type.equals("String")) {
if (type.equals("String")) { sqlBuilder = sqlBuilder.append("(" + length + ")");
sqlBuilder = sqlBuilder.append("(" + length + ")"); } else if (type.equals("Decimal")) {
} else if (type.equals("Decimal")) { sqlBuilder = sqlBuilder.append("(19,6)");
sqlBuilder = sqlBuilder.append("(19,6)"); } else if (type.equals("Dropdown")) {
} else if (type.equals("Dropdown")) { sqlBuilder = sqlBuilder.append("(11)");
sqlBuilder = sqlBuilder.append("(11)"); }
} }
} if (mandatory != null) {
if (mandatory != null) { if (mandatory) {
if (mandatory) { sqlBuilder = sqlBuilder.append(" NOT NULL");
sqlBuilder = sqlBuilder.append(" NOT NULL"); } else {
} else { sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
sqlBuilder = sqlBuilder.append(" DEFAULT NULL"); }
} }
}
sqlBuilder = sqlBuilder.append(", "); sqlBuilder = sqlBuilder.append(", ");
} }
@Transactional @Transactional
@Override @Override
public CommandProcessingResult createDatatable(final JsonCommand command) { public CommandProcessingResult createDatatable(final JsonCommand command) {
String datatableName = null; String datatableName = null;
try { try {
context.authenticatedUser(); context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json()); this.fromApiJsonDeserializer.validateForCreate(command.json());
JsonElement element = this.fromJsonHelper.parse(command.json()); JsonElement element = this.fromJsonHelper.parse(command.json());
JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element); JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element);
datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element); datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element);
String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element); String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element); Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element);
if (multiRow == null) { if (multiRow == null) {
multiRow = false; multiRow = false;
} }
validateDatatableName(datatableName); validateDatatableName(datatableName);
validateAppTable(apptableName); validateAppTable(apptableName);
String fkColumnName = apptableName.substring(2) + "_id"; String fkColumnName = apptableName.substring(2) + "_id";
String fkName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + fkColumnName; String fkName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + fkColumnName;
StringBuilder sqlBuilder = new StringBuilder(); StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` ("); sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` (");
if (multiRow) { if (multiRow) {
sqlBuilder = sqlBuilder sqlBuilder = sqlBuilder.append("`id` BIGINT(20) NOT NULL AUTO_INCREMENT, ").append(
.append("`id` BIGINT(20) NOT NULL AUTO_INCREMENT, ") "`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, "); } else {
} else { sqlBuilder = sqlBuilder.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
sqlBuilder = sqlBuilder }
.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, ");
}
for (JsonElement column : columns) { for (JsonElement column : columns) {
parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder); parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder);
} }
// Remove trailing comma and space // Remove trailing comma and space
sqlBuilder = sqlBuilder.delete(sqlBuilder.length() - 2, sqlBuilder.length()); sqlBuilder = sqlBuilder.delete(sqlBuilder.length() - 2, sqlBuilder.length());
if (multiRow) { if (multiRow) {
sqlBuilder = sqlBuilder sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`id`)")
.append(", PRIMARY KEY (`id`)") .append(", KEY `fk_" + apptableName.substring(2) + "_id` (`" + fkColumnName + "`)")
.append(", KEY `fk_" + apptableName.substring(2) + "_id` (`" + fkColumnName + "`)") .append(", CONSTRAINT `fk_" + fkName + "` ").append("FOREIGN KEY (`" + fkColumnName + "`) ")
.append(", CONSTRAINT `fk_" + fkName + "` ") .append("REFERENCES `" + apptableName + "` (`id`)");
.append("FOREIGN KEY (`" + fkColumnName + "`) ") } else {
.append("REFERENCES `" + apptableName + "` (`id`)"); sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`" + fkColumnName + "`)").append(", CONSTRAINT `fk_" + fkName + "` ")
} else { .append("FOREIGN KEY (`" + fkColumnName + "`) ").append("REFERENCES `" + apptableName + "` (`id`)");
sqlBuilder = sqlBuilder }
.append(", PRIMARY KEY (`" + fkColumnName + "`)")
.append(", CONSTRAINT `fk_" + fkName + "` ")
.append("FOREIGN KEY (`" + fkColumnName + "`) ")
.append("REFERENCES `" + apptableName + "` (`id`)");
}
sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;");
this.jdbcTemplate.execute(sqlBuilder.toString()); this.jdbcTemplate.execute(sqlBuilder.toString());
registerDatatable(datatableName, apptableName); registerDatatable(datatableName, apptableName);
} catch (SQLGrammarException e) { } catch (SQLGrammarException e) {
Throwable realCause = e.getCause(); Throwable realCause = e.getCause();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
if (realCause.getMessage().toLowerCase().contains("duplicate column name")) { if (realCause.getMessage().toLowerCase().contains("duplicate column name")) {
baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name"); baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name");
} else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) { } else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
baseDataValidator.reset().parameter("datatableName").value(datatableName) baseDataValidator.reset().parameter("datatableName").value(datatableName).failWithCode("datatable.already.exists");
.failWithCode("datatable.already.exists"); }
}
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
return new CommandProcessingResultBuilder() return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withResourceIdAsString(datatableName).build();
.withCommandId(command.commandId())
.withResourceIdAsString(datatableName)
.build();
} }
private void parseDatatableColumnForUpdate(final JsonObject column, private void parseDatatableColumnForUpdate(final JsonObject column,
final Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition, StringBuilder sqlBuilder) { final Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition, StringBuilder sqlBuilder) {
String name = (column.has("name")) ? column.get("name").getAsString() : null; String name = (column.has("name")) ? column.get("name").getAsString() : null;
String lengthStr = (column.has("length")) ? column.get("length").getAsString() : null; String lengthStr = (column.has("length")) ? column.get("length").getAsString() : null;
Integer length = (StringUtils.isNotBlank(lengthStr)) ? Integer.parseInt(lengthStr) : null; Integer length = (StringUtils.isNotBlank(lengthStr)) ? Integer.parseInt(lengthStr) : null;
String newName = (column.has("newName")) ? column.get("newName").getAsString() : name; String newName = (column.has("newName")) ? column.get("newName").getAsString() : name;
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false; Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
String after = (column.has("after")) ? column.get("after").getAsString() : null; String after = (column.has("after")) ? column.get("after").getAsString() : null;
String code = (column.has("code")) ? column.get("code").getAsString() : null; String code = (column.has("code")) ? column.get("code").getAsString() : null;
String newCode = (column.has("newCode")) ? column.get("newCode").getAsString() : null; String newCode = (column.has("newCode")) ? column.get("newCode").getAsString() : null;
if (StringUtils.isNotBlank(code)) { if (StringUtils.isNotBlank(code)) {
name = datatableColumnNameToCodeValueName(name, code); name = datatableColumnNameToCodeValueName(name, code);
if (StringUtils.isNotBlank(newCode)) { if (StringUtils.isNotBlank(newCode)) {
newName = datatableColumnNameToCodeValueName(newName, newCode); newName = datatableColumnNameToCodeValueName(newName, newCode);
} else { } else {
newName = datatableColumnNameToCodeValueName(newName, code); newName = datatableColumnNameToCodeValueName(newName, code);
} }
} }
if (!mapColumnNameDefinition.containsKey(name)) { if (!mapColumnNameDefinition.containsKey(name)) { throw new PlatformDataIntegrityException(
throw new PlatformDataIntegrityException("error.msg.datatable.column.missing.update.parse", "error.msg.datatable.column.missing.update.parse", "Column " + name + " does not exist.", name); }
"Column " + name + " does not exist.", name);
}
String type = mapColumnNameDefinition.get(name).getColumnType(); String type = mapColumnNameDefinition.get(name).getColumnType();
if (length == null && type.toLowerCase().equals("varchar")) { if (length == null && type.toLowerCase().equals("varchar")) {
length = mapColumnNameDefinition.get(name).getColumnLength().intValue(); length = mapColumnNameDefinition.get(name).getColumnLength().intValue();
} }
sqlBuilder = sqlBuilder.append(", CHANGE `" + name + "` `" + newName + "` " + type); sqlBuilder = sqlBuilder.append(", CHANGE `" + name + "` `" + newName + "` " + type);
if (length != null && length > 0) { if (length != null && length > 0) {
if (type.toLowerCase().equals("decimal")) { if (type.toLowerCase().equals("decimal")) {
sqlBuilder.append("(19,6)"); sqlBuilder.append("(19,6)");
} else if (type.toLowerCase().equals("varchar")) { } else if (type.toLowerCase().equals("varchar")) {
sqlBuilder.append("(" + length + ")"); sqlBuilder.append("(" + length + ")");
} }
} }
if (mandatory != null) { if (mandatory != null) {
if (mandatory) { if (mandatory) {
sqlBuilder = sqlBuilder.append(" NOT NULL"); sqlBuilder = sqlBuilder.append(" NOT NULL");
} else { } else {
sqlBuilder = sqlBuilder.append(" DEFAULT NULL"); sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
} }
} }
if (after != null) { if (after != null) {
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`"); sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
} }
} }
private void parseDatatableColumnForAdd(final JsonObject column, StringBuilder sqlBuilder) { private void parseDatatableColumnForAdd(final JsonObject column, StringBuilder sqlBuilder) {
String name = (column.has("name")) ? column.get("name").getAsString() : null; String name = (column.has("name")) ? column.get("name").getAsString() : null;
String type = (column.has("type")) ? column.get("type").getAsString() : null; String type = (column.has("type")) ? column.get("type").getAsString() : null;
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null; Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false; Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
String after = (column.has("after")) ? column.get("after").getAsString() : null; String after = (column.has("after")) ? column.get("after").getAsString() : null;
String code = (column.has("code")) ? column.get("code").getAsString() : null; String code = (column.has("code")) ? column.get("code").getAsString() : null;
if (StringUtils.isNotBlank(code)) { if (StringUtils.isNotBlank(code)) {
name = datatableColumnNameToCodeValueName(name, code); name = datatableColumnNameToCodeValueName(name, code);
} }
String mysqlType = apiTypeToMySQL.get(type); String mysqlType = apiTypeToMySQL.get(type);
sqlBuilder = sqlBuilder.append(", ADD `" + name + "` " + mysqlType); sqlBuilder = sqlBuilder.append(", ADD `" + name + "` " + mysqlType);
if (type != null) { if (type != null) {
if (type.equals("String") && length != null) { if (type.equals("String") && length != null) {
sqlBuilder = sqlBuilder.append("(" + length + ")"); sqlBuilder = sqlBuilder.append("(" + length + ")");
} else if (type.equals("Decimal")) { } else if (type.equals("Decimal")) {
sqlBuilder = sqlBuilder.append("(19,6)"); sqlBuilder = sqlBuilder.append("(19,6)");
} else if (type.equals("Dropdown")) { } else if (type.equals("Dropdown")) {
sqlBuilder = sqlBuilder.append("(11)"); sqlBuilder = sqlBuilder.append("(11)");
} }
} }
if (mandatory != null) { if (mandatory != null) {
if (mandatory) { if (mandatory) {
sqlBuilder = sqlBuilder.append(" NOT NULL"); sqlBuilder = sqlBuilder.append(" NOT NULL");
} else { } else {
sqlBuilder = sqlBuilder.append(" DEFAULT NULL"); sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
} }
} }
if (after != null) { if (after != null) {
sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`"); sqlBuilder = sqlBuilder.append(" AFTER `" + after + "`");
} }
} }
private void parseDatatableColumnForDrop(final JsonObject column, StringBuilder sqlBuilder) { private void parseDatatableColumnForDrop(final JsonObject column, StringBuilder sqlBuilder) {
String name = (column.has("name")) ? column.get("name").getAsString() : null; String name = (column.has("name")) ? column.get("name").getAsString() : null;
sqlBuilder = sqlBuilder.append(", DROP COLUMN `" + name + "`"); sqlBuilder = sqlBuilder.append(", DROP COLUMN `" + name + "`");
} }
@Transactional @Transactional
@Override @Override
public void updateDatatable(final String datatableName, final JsonCommand command) { public void updateDatatable(final String datatableName, final JsonCommand command) {
try { try {
context.authenticatedUser(); context.authenticatedUser();
this.fromApiJsonDeserializer.validateForUpdate(command.json()); this.fromApiJsonDeserializer.validateForUpdate(command.json());
JsonElement element = this.fromJsonHelper.parse(command.json()); JsonElement element = this.fromJsonHelper.parse(command.json());
JsonArray changeColumns = this.fromJsonHelper.extractJsonArrayNamed("changeColumns", element); JsonArray changeColumns = this.fromJsonHelper.extractJsonArrayNamed("changeColumns", element);
JsonArray addColumns = this.fromJsonHelper.extractJsonArrayNamed("addColumns", element); JsonArray addColumns = this.fromJsonHelper.extractJsonArrayNamed("addColumns", element);
JsonArray dropColumns = this.fromJsonHelper.extractJsonArrayNamed("dropColumns", element); JsonArray dropColumns = this.fromJsonHelper.extractJsonArrayNamed("dropColumns", element);
String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element); String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element);
validateDatatableName(datatableName); validateDatatableName(datatableName);
List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService.fillResultsetColumnHeaders(datatableName); List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService.fillResultsetColumnHeaders(datatableName);
Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = new HashMap<String, ResultsetColumnHeaderData>(); Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = new HashMap<String, ResultsetColumnHeaderData>();
for (ResultsetColumnHeaderData columnHeader : columnHeaderData) { for (ResultsetColumnHeaderData columnHeader : columnHeaderData) {
mapColumnNameDefinition.put(columnHeader.getColumnName(), columnHeader); mapColumnNameDefinition.put(columnHeader.getColumnName(), columnHeader);
} }
if (!StringUtils.isBlank(apptableName)) { if (!StringUtils.isBlank(apptableName)) {
validateAppTable(apptableName); validateAppTable(apptableName);
String oldApptableName = this.queryForApplicationTableName(datatableName); String oldApptableName = this.queryForApplicationTableName(datatableName);
if (!StringUtils.equals(oldApptableName, apptableName)) { if (!StringUtils.equals(oldApptableName, apptableName)) {
String oldFKName = oldApptableName.substring(2) + "_id"; String oldFKName = oldApptableName.substring(2) + "_id";
String newFKName = apptableName.substring(2) + "_id"; String newFKName = apptableName.substring(2) + "_id";
String oldConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + oldFKName; String oldConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + oldFKName;
String newConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + newFKName; String newConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + newFKName;
StringBuilder sqlBuilder = new StringBuilder(); StringBuilder sqlBuilder = new StringBuilder();
if (mapColumnNameDefinition.containsKey("id")) { if (mapColumnNameDefinition.containsKey("id")) {
sqlBuilder = sqlBuilder sqlBuilder = sqlBuilder.append("ALTER TABLE `" + datatableName + "` ").append("DROP KEY `fk_" + oldFKName + "`,")
.append("ALTER TABLE `" + datatableName + "` ") .append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
.append("DROP KEY `fk_" + oldFKName + "`,") .append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,") .append("ADD KEY `fk_" + newFKName + "` (`" + newFKName + "`),")
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,") .append("ADD CONSTRAINT `fk_" + newConstraintName + "` ").append("FOREIGN KEY (`" + newFKName + "`) ")
.append("ADD KEY `fk_" + newFKName + "` (`" + newFKName + "`),") .append("REFERENCES `" + apptableName + "` (`id`)");
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ") } else {
.append("FOREIGN KEY (`" + newFKName + "`) ") sqlBuilder = sqlBuilder.append("ALTER TABLE `" + datatableName + "` ")
.append("REFERENCES `" + apptableName + "` (`id`)"); .append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
} else { .append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
sqlBuilder = sqlBuilder .append("ADD CONSTRAINT `fk_" + newConstraintName + "` ").append("FOREIGN KEY (`" + newFKName + "`) ")
.append("ALTER TABLE `" + datatableName + "` ") .append("REFERENCES `" + apptableName + "` (`id`)");
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,") }
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ")
.append("FOREIGN KEY (`" + newFKName + "`) ")
.append("REFERENCES `" + apptableName + "` (`id`)");
}
this.jdbcTemplate.execute(sqlBuilder.toString()); this.jdbcTemplate.execute(sqlBuilder.toString());
deregisterDatatable(datatableName); deregisterDatatable(datatableName);
registerDatatable(datatableName, apptableName); registerDatatable(datatableName, apptableName);
} }
} }
if (changeColumns == null && addColumns == null && dropColumns == null) { if (changeColumns == null && addColumns == null && dropColumns == null) { return; }
return;
}
if (dropColumns != null) { if (dropColumns != null) {
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`"); StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
for (JsonElement column : dropColumns) { for (JsonElement column : dropColumns) {
parseDatatableColumnForDrop(column.getAsJsonObject(), sqlBuilder); parseDatatableColumnForDrop(column.getAsJsonObject(), sqlBuilder);
} }
// Remove the first comma, right after ALTER TABLE `datatable` // Remove the first comma, right after ALTER TABLE `datatable`
int indexOfFirstComma = sqlBuilder.indexOf(","); int indexOfFirstComma = sqlBuilder.indexOf(",");
if (indexOfFirstComma != -1) { if (indexOfFirstComma != -1) {
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma); sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
} }
this.jdbcTemplate.execute(sqlBuilder.toString()); this.jdbcTemplate.execute(sqlBuilder.toString());
} }
if (addColumns != null) { if (addColumns != null) {
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`"); StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
for (JsonElement column : addColumns) { for (JsonElement column : addColumns) {
parseDatatableColumnForAdd(column.getAsJsonObject(), sqlBuilder); parseDatatableColumnForAdd(column.getAsJsonObject(), sqlBuilder);
} }
// Remove the first comma, right after ALTER TABLE `datatable` // Remove the first comma, right after ALTER TABLE `datatable`
int indexOfFirstComma = sqlBuilder.indexOf(","); int indexOfFirstComma = sqlBuilder.indexOf(",");
if (indexOfFirstComma != -1) { if (indexOfFirstComma != -1) {
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma); sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
} }
this.jdbcTemplate.execute(sqlBuilder.toString()); this.jdbcTemplate.execute(sqlBuilder.toString());
} }
if (changeColumns != null) { if (changeColumns != null) {
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`"); StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
for (JsonElement column : changeColumns) { for (JsonElement column : changeColumns) {
parseDatatableColumnForUpdate(column.getAsJsonObject(), mapColumnNameDefinition, sqlBuilder); parseDatatableColumnForUpdate(column.getAsJsonObject(), mapColumnNameDefinition, sqlBuilder);
} }
// Remove the first comma, right after ALTER TABLE `datatable` // Remove the first comma, right after ALTER TABLE `datatable`
int indexOfFirstComma = sqlBuilder.indexOf(","); int indexOfFirstComma = sqlBuilder.indexOf(",");
if (indexOfFirstComma != -1) { if (indexOfFirstComma != -1) {
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma); sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
} }
this.jdbcTemplate.execute(sqlBuilder.toString()); this.jdbcTemplate.execute(sqlBuilder.toString());
} }
} catch (SQLGrammarException e) { } catch (SQLGrammarException e) {
Throwable realCause = e.getCause(); Throwable realCause = e.getCause();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable"); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
if (realCause.getMessage().toLowerCase().contains("unknown column")) { if (realCause.getMessage().toLowerCase().contains("unknown column")) {
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist"); baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
} else if (realCause.getMessage().toLowerCase().contains("can't drop")) { } else if (realCause.getMessage().toLowerCase().contains("can't drop")) {
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist"); baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
} else if (realCause.getMessage().toLowerCase().contains("duplicate column")) { } else if (realCause.getMessage().toLowerCase().contains("duplicate column")) {
baseDataValidator.reset().parameter("name").failWithCode("column.already.exists"); baseDataValidator.reset().parameter("name").failWithCode("column.already.exists");
} }
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
} }
@Transactional @Transactional
@Override @Override
public void deleteDatatable(final String datatableName) { public void deleteDatatable(final String datatableName) {
try { try {
context.authenticatedUser(); context.authenticatedUser();
if (!isRegisteredDataTable(datatableName)) { throw new DatatableNotFoundException(datatableName); }
validateDatatableName(datatableName);
deregisterDatatable(datatableName);
String sql = "DROP TABLE `" + datatableName + "`";
this.jdbcTemplate.execute(sql);
} catch (SQLGrammarException e) {
Throwable realCause = e.getCause();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
if (realCause.getMessage().contains("Unknown table")) {
baseDataValidator.reset().parameter("datatableName").failWithCode("does.not.exist");
}
validateDatatableName(datatableName); throwExceptionIfValidationWarningsExist(dataValidationErrors);
deregisterDatatable(datatableName); }
String sql = "DROP TABLE `" + datatableName + "`";
this.jdbcTemplate.execute(sql);
} catch (SQLGrammarException e) {
Throwable realCause = e.getCause();
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
if (realCause.getMessage().contains("Unknown table")) {
baseDataValidator.reset().parameter("datatableName").failWithCode("does.not.exist");
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
} }
@Transactional @Transactional