#2328 - Postgres JSONB dirty checking - trim json

This commit is contained in:
rbygrave committed 2021-08-24 15:58:29 +12:00
1 parent 3bfb6dbc20
commit 60db0b0999
3 files changed
+65 -1

No files matched your search

@@ -0,0 +1,33 @@
package io.ebeaninternal.server.type;
/**
* Helper that removes whitespace from JSON. Used to normalise Postgres JSONB content.
*/
final class JsonTrim {
/**
* Return JSON with whitespace trimmed.
*/
static String trim(String json) {
if (json == null) {
return null;
}
int len = json.length();
StringBuilder builder = new StringBuilder(len);
boolean escaped = false;
boolean quoted = false;
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"') {
if (!escaped) quoted = !quoted;
else escaped = false;
} else if (quoted && c == '\\') {
escaped = true;
}
if (quoted || !Character.isWhitespace(c)) {
builder.append(c);
}
}
return builder.toString();
}
}
@@ -39,7 +39,11 @@ final class ScalarTypeJsonObjectMapper {
return new GenericObject(jsonManager, field, dbType, docType);
}
// using the global default MutationDetection mode (defaults to HASH)
prop.setMutationDetection(jsonManager.mutationDetection());
final MutationDetection defaultMode = jsonManager.mutationDetection();
prop.setMutationDetection(defaultMode);
if (MutationDetection.NONE == defaultMode) {
return new NoMutationDetection(jsonManager, field, dbType, docType);
}
return new GenericObject(jsonManager, field, dbType, docType);
}
@@ -68,8 +72,11 @@ final class ScalarTypeJsonObjectMapper {
*/
private static final class GenericObject extends Base<Object> {
private final boolean jsonb;
GenericObject(TypeJsonManager jsonManager, AnnotatedField field, int dbType, DocPropertyType docType) {
super(Object.class, jsonManager, field, dbType, docType);
this.jsonb = "jsonb".equals(pgType);
}
@Override
@@ -80,6 +87,9 @@ final class ScalarTypeJsonObjectMapper {
@Override
public Object read(DataReader reader) throws SQLException {
String json = reader.getString();
if (jsonb) {
json = JsonTrim.trim(json);
}
// pushJson such that we MD5 and store on EntityBeanIntercept later
reader.pushJson(json);
if (json == null || json.isEmpty()) {