datatable delete apis should only delete registered datatables
This commit is contained in:
+296
-308
@@ -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,396 +289,377 @@ 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) {
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||||
"Validation errors exist.", dataValidationErrors); }
|
"Validation errors exist.", dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
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 type = (column.has("type")) ? column.get("type").getAsString() : null;
|
|
||||||
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
|
||||||
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
|
||||||
String code = (column.has("code")) ? column.get("code").getAsString() : null;
|
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(code)) {
|
String name = (column.has("name")) ? column.get("name").getAsString() : null;
|
||||||
name = datatableColumnNameToCodeValueName(name, code);
|
String type = (column.has("type")) ? column.get("type").getAsString() : null;
|
||||||
}
|
Integer length = (column.has("length")) ? column.get("length").getAsInt() : null;
|
||||||
|
Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false;
|
||||||
|
String code = (column.has("code")) ? column.get("code").getAsString() : null;
|
||||||
|
|
||||||
String mysqlType = apiTypeToMySQL.get(type);
|
if (StringUtils.isNotBlank(code)) {
|
||||||
sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType);
|
name = datatableColumnNameToCodeValueName(name, code);
|
||||||
|
}
|
||||||
|
|
||||||
if (type != null)
|
String mysqlType = apiTypeToMySQL.get(type);
|
||||||
{
|
sqlBuilder = sqlBuilder.append("`" + name + "` " + mysqlType);
|
||||||
if (type.equals("String")) {
|
|
||||||
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
|
||||||
} else if (type.equals("Decimal")) {
|
|
||||||
sqlBuilder = sqlBuilder.append("(19,6)");
|
|
||||||
} else if (type.equals("Dropdown")) {
|
|
||||||
sqlBuilder = sqlBuilder.append("(11)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mandatory != null) {
|
|
||||||
if (mandatory) {
|
|
||||||
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
|
||||||
} else {
|
|
||||||
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlBuilder = sqlBuilder.append(", ");
|
if (type != null) {
|
||||||
|
if (type.equals("String")) {
|
||||||
|
sqlBuilder = sqlBuilder.append("(" + length + ")");
|
||||||
|
} else if (type.equals("Decimal")) {
|
||||||
|
sqlBuilder = sqlBuilder.append("(19,6)");
|
||||||
|
} else if (type.equals("Dropdown")) {
|
||||||
|
sqlBuilder = sqlBuilder.append("(11)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mandatory != null) {
|
||||||
|
if (mandatory) {
|
||||||
|
sqlBuilder = sqlBuilder.append(" NOT NULL");
|
||||||
|
} else {
|
||||||
|
sqlBuilder = sqlBuilder.append(" DEFAULT NULL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
} catch (SQLGrammarException e) {
|
||||||
|
Throwable realCause = e.getCause();
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||||
|
|
||||||
|
if (realCause.getMessage().toLowerCase().contains("duplicate column name")) {
|
||||||
|
baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name");
|
||||||
|
} else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
|
||||||
|
baseDataValidator.reset().parameter("datatableName").value(datatableName).failWithCode("datatable.already.exists");
|
||||||
|
}
|
||||||
|
|
||||||
registerDatatable(datatableName, apptableName);
|
|
||||||
} catch (SQLGrammarException e) {
|
|
||||||
Throwable realCause = e.getCause();
|
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
|
||||||
|
|
||||||
if (realCause.getMessage().toLowerCase().contains("duplicate column name")) {
|
|
||||||
baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name");
|
|
||||||
} else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) {
|
|
||||||
baseDataValidator.reset().parameter("datatableName").value(datatableName)
|
|
||||||
.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);
|
|
||||||
Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = new HashMap<String, ResultsetColumnHeaderData>();
|
|
||||||
for (ResultsetColumnHeaderData columnHeader : columnHeaderData) {
|
|
||||||
mapColumnNameDefinition.put(columnHeader.getColumnName(), columnHeader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!StringUtils.isBlank(apptableName)) {
|
List<ResultsetColumnHeaderData> columnHeaderData = this.genericDataService.fillResultsetColumnHeaders(datatableName);
|
||||||
validateAppTable(apptableName);
|
Map<String, ResultsetColumnHeaderData> mapColumnNameDefinition = new HashMap<String, ResultsetColumnHeaderData>();
|
||||||
|
for (ResultsetColumnHeaderData columnHeader : columnHeaderData) {
|
||||||
|
mapColumnNameDefinition.put(columnHeader.getColumnName(), columnHeader);
|
||||||
|
}
|
||||||
|
|
||||||
String oldApptableName = this.queryForApplicationTableName(datatableName);
|
if (!StringUtils.isBlank(apptableName)) {
|
||||||
if (!StringUtils.equals(oldApptableName, apptableName)) {
|
validateAppTable(apptableName);
|
||||||
String oldFKName = oldApptableName.substring(2) + "_id";
|
|
||||||
String newFKName = apptableName.substring(2) + "_id";
|
|
||||||
String oldConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + oldFKName;
|
|
||||||
String newConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + newFKName;
|
|
||||||
StringBuilder sqlBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
if (mapColumnNameDefinition.containsKey("id")) {
|
|
||||||
sqlBuilder = sqlBuilder
|
|
||||||
.append("ALTER TABLE `" + datatableName + "` ")
|
|
||||||
.append("DROP KEY `fk_" + oldFKName + "`,")
|
|
||||||
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
|
|
||||||
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
|
|
||||||
.append("ADD KEY `fk_" + newFKName + "` (`" + newFKName + "`),")
|
|
||||||
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ")
|
|
||||||
.append("FOREIGN KEY (`" + newFKName + "`) ")
|
|
||||||
.append("REFERENCES `" + apptableName + "` (`id`)");
|
|
||||||
} else {
|
|
||||||
sqlBuilder = sqlBuilder
|
|
||||||
.append("ALTER TABLE `" + datatableName + "` ")
|
|
||||||
.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());
|
|
||||||
|
|
||||||
deregisterDatatable(datatableName);
|
|
||||||
registerDatatable(datatableName, apptableName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeColumns == null && addColumns == null && dropColumns == null) {
|
String oldApptableName = this.queryForApplicationTableName(datatableName);
|
||||||
return;
|
if (!StringUtils.equals(oldApptableName, apptableName)) {
|
||||||
}
|
String oldFKName = oldApptableName.substring(2) + "_id";
|
||||||
|
String newFKName = apptableName.substring(2) + "_id";
|
||||||
|
String oldConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + oldFKName;
|
||||||
|
String newConstraintName = datatableName.toLowerCase().replaceAll("\\s", "_") + "_" + newFKName;
|
||||||
|
StringBuilder sqlBuilder = new StringBuilder();
|
||||||
|
|
||||||
if (dropColumns != null) {
|
if (mapColumnNameDefinition.containsKey("id")) {
|
||||||
|
sqlBuilder = sqlBuilder.append("ALTER TABLE `" + datatableName + "` ").append("DROP KEY `fk_" + oldFKName + "`,")
|
||||||
|
.append("DROP FOREIGN KEY `fk_" + oldConstraintName + "`,")
|
||||||
|
.append("CHANGE COLUMN `" + oldFKName + "` `" + newFKName + "` BIGINT(20) NOT NULL,")
|
||||||
|
.append("ADD KEY `fk_" + newFKName + "` (`" + newFKName + "`),")
|
||||||
|
.append("ADD CONSTRAINT `fk_" + newConstraintName + "` ").append("FOREIGN KEY (`" + newFKName + "`) ")
|
||||||
|
.append("REFERENCES `" + apptableName + "` (`id`)");
|
||||||
|
} else {
|
||||||
|
sqlBuilder = sqlBuilder.append("ALTER TABLE `" + datatableName + "` ")
|
||||||
|
.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`)");
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||||
|
|
||||||
for (JsonElement column : dropColumns) {
|
deregisterDatatable(datatableName);
|
||||||
parseDatatableColumnForDrop(column.getAsJsonObject(), sqlBuilder);
|
registerDatatable(datatableName, apptableName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the first comma, right after ALTER TABLE `datatable`
|
if (changeColumns == null && addColumns == null && dropColumns == null) { return; }
|
||||||
int indexOfFirstComma = sqlBuilder.indexOf(",");
|
|
||||||
if (indexOfFirstComma != -1) {
|
|
||||||
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
if (dropColumns != 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 : dropColumns) {
|
||||||
parseDatatableColumnForAdd(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());
|
|
||||||
}
|
|
||||||
if (changeColumns != null) {
|
|
||||||
|
|
||||||
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||||
|
}
|
||||||
|
if (addColumns != null) {
|
||||||
|
|
||||||
for (JsonElement column : changeColumns) {
|
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
||||||
parseDatatableColumnForUpdate(column.getAsJsonObject(), mapColumnNameDefinition, sqlBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the first comma, right after ALTER TABLE `datatable`
|
for (JsonElement column : addColumns) {
|
||||||
int indexOfFirstComma = sqlBuilder.indexOf(",");
|
parseDatatableColumnForAdd(column.getAsJsonObject(), sqlBuilder);
|
||||||
if (indexOfFirstComma != -1) {
|
}
|
||||||
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.jdbcTemplate.execute(sqlBuilder.toString());
|
// Remove the first comma, right after ALTER TABLE `datatable`
|
||||||
}
|
int indexOfFirstComma = sqlBuilder.indexOf(",");
|
||||||
} catch (SQLGrammarException e) {
|
if (indexOfFirstComma != -1) {
|
||||||
Throwable realCause = e.getCause();
|
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
|
||||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
}
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
|
||||||
|
|
||||||
if (realCause.getMessage().toLowerCase().contains("unknown column")) {
|
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||||
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
}
|
||||||
} else if (realCause.getMessage().toLowerCase().contains("can't drop")) {
|
if (changeColumns != null) {
|
||||||
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
|
||||||
} else if (realCause.getMessage().toLowerCase().contains("duplicate column")) {
|
|
||||||
baseDataValidator.reset().parameter("name").failWithCode("column.already.exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
StringBuilder sqlBuilder = new StringBuilder("ALTER TABLE `" + datatableName + "`");
|
||||||
}
|
|
||||||
|
for (JsonElement column : changeColumns) {
|
||||||
|
parseDatatableColumnForUpdate(column.getAsJsonObject(), mapColumnNameDefinition, sqlBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the first comma, right after ALTER TABLE `datatable`
|
||||||
|
int indexOfFirstComma = sqlBuilder.indexOf(",");
|
||||||
|
if (indexOfFirstComma != -1) {
|
||||||
|
sqlBuilder = sqlBuilder.deleteCharAt(indexOfFirstComma);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.jdbcTemplate.execute(sqlBuilder.toString());
|
||||||
|
}
|
||||||
|
} catch (SQLGrammarException e) {
|
||||||
|
Throwable realCause = e.getCause();
|
||||||
|
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("datatable");
|
||||||
|
|
||||||
|
if (realCause.getMessage().toLowerCase().contains("unknown column")) {
|
||||||
|
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
||||||
|
} else if (realCause.getMessage().toLowerCase().contains("can't drop")) {
|
||||||
|
baseDataValidator.reset().parameter("name").failWithCode("does.not.exist");
|
||||||
|
} else if (realCause.getMessage().toLowerCase().contains("duplicate column")) {
|
||||||
|
baseDataValidator.reset().parameter("name").failWithCode("column.already.exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user