From c96980c457d4f45e631d201f17d3d6f39a3dee48 Mon Sep 17 00:00:00 2001 From: emmanuel Date: Wed, 3 Sep 2014 11:39:28 +0200 Subject: [PATCH] commit for 'MIFOSX-1145': updating datatable throws 'Data truncation: Invalid use of NULL value' SQL error --- .../ReadWriteNonCoreDataServiceImpl.java | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java index 5175bd27b..8cc21dd3d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java @@ -769,6 +769,47 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ } } + + /** + * Update data table, set column value to empty string where current value is NULL. + * Run update SQL only if the "mandatory" property is set to true + * + * @param datatableName Name of data table + * @param column JSON encoded array of column properties + * @see https://mifosforge.jira.com/browse/MIFOSX-1145 + **/ + private void removeNullValuesFromColumn(final String datatableName, final JsonObject column, + final Map mapColumnNameDefinition) { + final Boolean mandatory = (column.has("mandatory")) ? column.get("mandatory").getAsBoolean() : false; + final String name = (column.has("name")) ? column.get("name").getAsString() : ""; + final String type = (mapColumnNameDefinition.containsKey(name)) ? mapColumnNameDefinition.get(name).getColumnType() : ""; + final List stringDataTypes = new ArrayList(); + + // =========== STRING DATA TYPES ============= + // For string types other than ENUM, the default value is an empty string. + // No errors are thrown when the value is set to an empty string. + // For ENUM, the default is the first enumeration value. + stringDataTypes.add("char"); + stringDataTypes.add("varchar"); + stringDataTypes.add("blob"); + stringDataTypes.add("text"); + stringDataTypes.add("tinyblob"); + stringDataTypes.add("tinytext"); + stringDataTypes.add("mediumblob"); + stringDataTypes.add("mediumtext"); + stringDataTypes.add("longblob"); + stringDataTypes.add("longtext"); + // ============================================= + + if(StringUtils.isNotEmpty(type)) { + if(mandatory && stringDataTypes.contains(type.toLowerCase())) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("UPDATE `" + datatableName + "` SET `" + name + "` = '' WHERE `" + name + "` IS NULL"); + + this.jdbcTemplate.update(sqlBuilder.toString()); + } + } + } @Transactional @Override @@ -874,6 +915,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ final Map codeMappings = new HashMap<>(); final List removeMappings = new ArrayList<>(); for (final JsonElement column : changeColumns) { + // remove NULL values from column where mandatory is true + removeNullValuesFromColumn(datatableName, column.getAsJsonObject(), mapColumnNameDefinition); + parseDatatableColumnForUpdate(column.getAsJsonObject(), mapColumnNameDefinition, sqlBuilder, datatableName, constrainBuilder, codeMappings, removeMappings, isConstraintApproach); } @@ -891,7 +935,15 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ } catch (final GenericJDBCException e) { if (e.getMessage().contains("Error on rename")) { throw new PlatformServiceUnavailableException( "error.msg.datatable.column.update.not.allowed", "One of the column name modification not allowed"); } - } + } catch (final Exception e) { + // handle all other exceptions in here + + // check if exception message contains the "invalid use of null value" SQL exception message + // throw a 503 HTTP error - PlatformServiceUnavailableException + if (e.getMessage().toLowerCase().contains("invalid use of null value")) { throw new PlatformServiceUnavailableException( + "error.msg.datatable.column.update.not.allowed", "One of the data table columns contains null values"); + } + } } } catch (final SQLGrammarException e) { final Throwable realCause = e.getCause(); @@ -1470,7 +1522,9 @@ public class ReadWriteNonCoreDataServiceImpl implements ReadWriteNonCoreDataServ String paramValue = pValue; if (columnHeader.isDateDisplayType() || columnHeader.isIntegerDisplayType() || columnHeader.isDecimalDisplayType()) { - paramValue = paramValue.trim(); + // only trim if string is not empty and is not null. + // throws a NULL pointer exception if the check below is not applied + paramValue = StringUtils.isNotEmpty(paramValue) ? paramValue.trim() : paramValue; } if (StringUtils.isEmpty(paramValue) && columnHeader.isMandatory()) {