From a3bb473e86f755fa3bf0804099b22a07c5bff7a5 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Tue, 1 Nov 2016 17:14:30 +0100 Subject: [PATCH] [#5613] Incorrect deserialisation of deeply nested PostgreSQL ARRAYs / UDTs --- .../java/org/jooq/impl/DefaultBinding.java | 12 +++---- .../org/jooq/util/postgres/PostgresUtils.java | 36 ++++++++++++++----- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 85fb99fb8e..e42abb638e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -2312,18 +2312,16 @@ public class DefaultBinding implements Binding { try { Class component = type.getComponentType(); - String values = string.replaceAll("^\\{(.*)\\}$", "$1"); + List values = PostgresUtils.toPGArray(string); - if ("".equals(values)) { + if (values.isEmpty()) { return (Object[]) java.lang.reflect.Array.newInstance(component, 0); } else { - String[] split = values.split(","); - Object[] result = (Object[]) java.lang.reflect.Array.newInstance(component, split.length); + Object[] result = (Object[]) java.lang.reflect.Array.newInstance(component, values.size()); - for (int i = 0; i < split.length; i++) { - result[i] = pgFromString(type.getComponentType(), split[i]); - } + for (int i = 0; i < values.size(); i++) + result[i] = pgFromString(type.getComponentType(), values.get(i)); return result; } diff --git a/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java b/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java index 2955d2f72e..d6e5bc44d0 100644 --- a/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java +++ b/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java @@ -50,6 +50,7 @@ import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.jooq.Converter; @@ -266,10 +267,27 @@ public class PostgresUtils { } /** - * Tokenize a PGObject input string + * Tokenize a PGObject input string. + */ + public static List toPGArray(String input) { + if ("{}".equals(input)) + return Collections.emptyList(); + + return toPGObjectOrArray(input, '{', '}'); + } + + /** + * Tokenize a PGObject input string. + */ + public static List toPGObject(String input) { + return toPGObjectOrArray(input, '(', ')'); + } + + /** + * Tokenize a PGObject input string. */ @SuppressWarnings("null") - public static List toPGObject(String input) { + private static List toPGObjectOrArray(String input, char open, char close) { List values = new ArrayList(); int i = 0; int state = PG_OBJECT_INIT; @@ -282,8 +300,8 @@ public class PostgresUtils { // Initial state case PG_OBJECT_INIT: - // Consume the opening parenthesis - if (c == '(') { + // Consume the opening bracket + if (c == open) { state = PG_OBJECT_BEFORE_VALUE; } @@ -300,7 +318,7 @@ public class PostgresUtils { } // Consume "empty" - else if (c == ')') { + else if (c == close) { values.add(null); state = PG_OBJECT_END; } @@ -370,8 +388,8 @@ public class PostgresUtils { // A value is being created case PG_OBJECT_UNQUOTED_VALUE: - // Consume the closing parenthesis - if (c == ')') { + // Consume the closing bracket + if (c == close) { values.add(sb.toString()); state = PG_OBJECT_END; } @@ -392,8 +410,8 @@ public class PostgresUtils { // A value was just added case PG_OBJECT_AFTER_VALUE: - // Consume the closing parenthesis - if (c == ')') { + // Consume the closing bracket + if (c == close) { state = PG_OBJECT_END; }