[#4162] Malformed record literal when using PostgreSQL array of user-defined types
This commit is contained in:
parent
a251b1e8da
commit
97a58e9d72
@ -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<T, U> implements Binding<T, U> {
|
||||
}
|
||||
else if (family == POSTGRES) {
|
||||
render.sql("E'")
|
||||
.sql(convertBytesToPostgresOctal(binary))
|
||||
.sql(PostgresUtils.toPGString(binary))
|
||||
.keyword("'::bytea");
|
||||
}
|
||||
|
||||
@ -631,6 +630,10 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
|
||||
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<T, U> implements Binding<T, U> {
|
||||
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<U> ctx) throws SQLException {
|
||||
Configuration configuration = ctx.configuration();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user