diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 5270ce346b..65e5f24bda 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -41,7 +41,6 @@ package org.jooq.impl; import static java.lang.Boolean.TRUE; -import static java.lang.Integer.toOctalString; import static java.util.Arrays.asList; // ... // ... @@ -62,11 +61,11 @@ import static org.jooq.SQLDialect.SQLITE; // ... // ... import static org.jooq.conf.ParamType.INLINED; +import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.using; import static org.jooq.impl.DefaultExecuteContext.localTargetConnection; import static org.jooq.impl.Utils.needsBackslashEscaping; -import static org.jooq.tools.StringUtils.leftPad; import static org.jooq.tools.jdbc.JDBCUtils.safeClose; import static org.jooq.tools.jdbc.JDBCUtils.safeFree; import static org.jooq.tools.jdbc.JDBCUtils.wasNull; @@ -479,7 +478,7 @@ public class DefaultBinding implements Binding { } else if (family == POSTGRES) { render.sql("E'") - .sql(convertBytesToPostgresOctal(binary)) + .sql(PostgresUtils.toPGString(binary)) .keyword("'::bytea"); } @@ -631,6 +630,10 @@ public class DefaultBinding implements Binding { render.sql(')'); } + else if (family == POSTGRES) { + render.visit(inline(PostgresUtils.toPGArrayString((Object[]) val))); + } + // By default, render HSQLDB / POSTGRES syntax else { render.keyword("ARRAY"); @@ -747,22 +750,6 @@ public class DefaultBinding implements Binding { return new String(buff); } - /** - * Postgres uses octals instead of hex encoding - */ - private static final String convertBytesToPostgresOctal(byte[] binary) { - StringBuilder sb = new StringBuilder(); - - for (byte b : binary) { - - // [#3924] Beware of signed vs unsigned bytes! - sb.append("\\\\"); - sb.append(leftPad(toOctalString(b & 0x000000ff), 3, '0')); - } - - return sb.toString(); - } - @Override public void register(BindingRegisterContext ctx) throws SQLException { Configuration configuration = ctx.configuration(); 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 9665e8af44..acdb7579b5 100644 --- a/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java +++ b/jOOQ/src/main/java/org/jooq/util/postgres/PostgresUtils.java @@ -40,6 +40,8 @@ */ package org.jooq.util.postgres; +import static java.lang.Integer.toOctalString; +import static org.jooq.tools.StringUtils.leftPad; import static org.jooq.tools.reflect.Reflect.on; import java.io.ByteArrayOutputStream; @@ -50,6 +52,7 @@ import java.io.StringReader; import java.util.ArrayList; import java.util.List; +import org.jooq.Record; import org.jooq.exception.DataTypeException; import org.jooq.tools.reflect.Reflect; import org.jooq.types.DayToSecond; @@ -420,19 +423,81 @@ public class PostgresUtils { sb.append(separator); // [#753] null must be set as a literal - if (o == null) { + if (o == null) sb.append(o); - } - else { - sb.append("\""); - sb.append(o.toString().replace("\\", "\\\\").replace("\"", "\\\"")); - sb.append("\""); - } + else if (o instanceof byte[]) + sb.append(toPGString((byte[]) o)); + else + sb.append("\"") + .append(toPGString(o).replace("\\", "\\\\").replace("\"", "\\\"")) + .append("\""); - separator = ", "; + separator = ","; } sb.append("}"); return sb.toString(); } + + /** + * Create a PostgreSQL string representation of any object. + */ + public static String toPGString(Object o) { + if (o instanceof byte[]) { + return toPGString((byte[]) o); + } + else if (o instanceof Object[]) { + return toPGArrayString((Object[]) o); + } + else if (o instanceof Record) { + return toPGString((Record) o); + } + else { + return "" + o; + } + } + + /** + * Create a PostgreSQL string representation of a record. + */ + public static String toPGString(Record r) { + StringBuilder sb = new StringBuilder(); + sb.append("("); + + String separator = ""; + for (Object a : r.intoArray()) { + sb.append(separator); + + // [#753] null must not be set as a literal + if (a != null) { + if (a instanceof byte[]) + sb.append(toPGString((byte[]) a)); + else + sb.append("\"") + .append(toPGString(a).replace("\\", "\\\\").replace("\"", "\\\"")) + .append("\""); + } + + separator = ","; + } + + sb.append(")"); + return sb.toString(); + } + + /** + * Create a PostgreSQL string representation of a binary. + */ + public static String toPGString(byte[] binary) { + StringBuilder sb = new StringBuilder(); + + for (byte b : binary) { + + // [#3924] Beware of signed vs unsigned bytes! + sb.append("\\\\"); + sb.append(leftPad(toOctalString(b & 0x000000ff), 3, '0')); + } + + return sb.toString(); + } }