package org.postgresql.jdbc;
import org.postgresql.core.BaseConnection;
import org.postgresql.core.BaseStatement;
import org.postgresql.core.Encoding;
import org.postgresql.core.Field;
import org.postgresql.core.Oid;
import org.postgresql.jdbc2.ArrayAssistant;
import org.postgresql.jdbc2.ArrayAssistantRegistry;
import org.postgresql.util.ByteConverter;
import org.postgresql.util.GT;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
public class PgArray implements java.sql.Array {
static {
ArrayAssistantRegistry.register(Oid.UUID, new UUIDArrayAssistant());
ArrayAssistantRegistry.register(Oid.UUID_ARRAY, new UUIDArrayAssistant());
}
private static class PgArrayList extends ArrayList<Object> {
private static final long serialVersionUID = 2052783752654562677L;
int dimensionsCount = 1;
}
protected BaseConnection connection = null;
private int oid;
protected String fieldString = null;
private final boolean useObjects;
protected PgArrayList arrayList;
protected byte[] fieldBytes;
private PgArray(BaseConnection connection, int oid) throws SQLException {
this.connection = connection;
this.oid = oid;
this.useObjects = true;
}
public PgArray(BaseConnection connection, int oid, String fieldString) throws SQLException {
this(connection, oid);
this.fieldString = fieldString;
}
public PgArray(BaseConnection connection, int oid, byte[] fieldBytes) throws SQLException {
this(connection, oid);
this.fieldBytes = fieldBytes;
}
public Object getArray() throws SQLException {
return getArrayImpl(1, 0, null);
}
public Object getArray(long index, int count) throws SQLException {
return getArrayImpl(index, count, null);
}
public Object getArrayImpl(Map<String, Class<?>> map) throws SQLException {
return getArrayImpl(1, 0, map);
}
public Object getArray(Map<String, Class<?>> map) throws SQLException {
return getArrayImpl(map);
}
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
return getArrayImpl(index, count, map);
}
public Object getArrayImpl(long index, int count, Map<String, Class<?>> map) throws SQLException {
if (map != null && !map.isEmpty()) {
throw org.postgresql.Driver.notImplemented(this.getClass(), "getArrayImpl(long,int,Map)");
}
if (index < 1) {
throw new PSQLException(GT.tr("The array index is out of range: {0}", index),
PSQLState.DATA_ERROR);
}
if (fieldBytes != null) {
return readBinaryArray((int) index, count);
}
if (fieldString == null) {
return null;
}
buildArrayList();
if (count == 0) {
count = arrayList.size();
}
if ((--index) + count > arrayList.size()) {
throw new PSQLException(
GT.tr("The array index is out of range: {0}, number of elements: {1}.",
index + count, (long) arrayList.size()),
PSQLState.DATA_ERROR);
}
return buildArray(arrayList, (int) index, count);
}
private Object readBinaryArray(int index, int count) throws SQLException {
int dimensions = ByteConverter.int4(fieldBytes, 0);
int elementOid = ByteConverter.int4(fieldBytes, 8);
int pos = 12;
int[] dims = new int[dimensions];
for (int d = 0; d < dimensions; ++d) {
dims[d] = ByteConverter.int4(fieldBytes, pos);
pos += 4;
pos += 4;
}
if (dimensions == 0) {
return java.lang.reflect.Array.newInstance(elementOidToClass(elementOid), 0);
}
if (count > 0) {
dims[0] = Math.min(count, dims[0]);
}
Object arr = java.lang.reflect.Array.newInstance(elementOidToClass(elementOid), dims);
try {
storeValues((Object[]) arr, elementOid, dims, pos, 0, index);
} catch (IOException ioe) {
throw new PSQLException(
GT.tr(
"Invalid character data was found. This is most likely caused by stored data containing characters that are invalid for the character set the database was created in. The most common example of this is storing 8bit data in a SQL_ASCII database."),
PSQLState.DATA_ERROR, ioe);
}
return arr;
}
private int storeValues(final Object[] arr, int elementOid, final int[] dims, int pos,
final int thisDimension, int index) throws SQLException, IOException {
if (thisDimension == dims.length - 1) {
for (int i = 1; i < index; ++i) {
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len != -1) {
pos += len;
}
}
for (int i = 0; i < dims[thisDimension]; ++i) {
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len == -1) {
continue;
}
switch (elementOid) {
case Oid.INT2:
arr[i] = ByteConverter.int2(fieldBytes, pos);
break;
case Oid.INT4:
arr[i] = ByteConverter.int4(fieldBytes, pos);
break;
case Oid.INT8:
arr[i] = ByteConverter.int8(fieldBytes, pos);
break;
case Oid.FLOAT4:
arr[i] = ByteConverter.float4(fieldBytes, pos);
break;
case Oid.FLOAT8:
arr[i] = ByteConverter.float8(fieldBytes, pos);
break;
case Oid.TEXT:
case Oid.VARCHAR:
Encoding encoding = connection.getEncoding();
arr[i] = encoding.decode(fieldBytes, pos, len);
break;
case Oid.BOOL:
arr[i] = ByteConverter.bool(fieldBytes, pos);
break;
default:
ArrayAssistant arrAssistant = ArrayAssistantRegistry.getAssistant(elementOid);
if (arrAssistant != null) {
arr[i] = arrAssistant.buildElement(fieldBytes, pos, len);
}
}
pos += len;
}
} else {
for (int i = 0; i < dims[thisDimension]; ++i) {
pos = storeValues((Object[]) arr[i], elementOid, dims, pos, thisDimension + 1, 0);
}
}
return pos;
}
private ResultSet readBinaryResultSet(int index, int count) throws SQLException {
int dimensions = ByteConverter.int4(fieldBytes, 0);
int elementOid = ByteConverter.int4(fieldBytes, 8);
int pos = 12;
int[] dims = new int[dimensions];
for (int d = 0; d < dimensions; ++d) {
dims[d] = ByteConverter.int4(fieldBytes, pos);
pos += 4;
pos += 4;
}
if (count > 0 && dimensions > 0) {
dims[0] = Math.min(count, dims[0]);
}
List<byte[][]> rows = new ArrayList<byte[][]>();
Field[] fields = new Field[2];
storeValues(rows, fields, elementOid, dims, pos, 0, index);
BaseStatement stat = (BaseStatement) connection
.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
return stat.createDriverResultSet(fields, rows);
}
private int storeValues(List<byte[][]> rows, Field[] fields, int elementOid, final int[] dims,
int pos, final int thisDimension, int index) throws SQLException {
if (dims.length == 0) {
fields[0] = new Field("INDEX", Oid.INT4);
fields[0].setFormat(Field.BINARY_FORMAT);
fields[1] = new Field("VALUE", elementOid);
fields[1].setFormat(Field.BINARY_FORMAT);
for (int i = 1; i < index; ++i) {
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len != -1) {
pos += len;
}
}
} else if (thisDimension == dims.length - 1) {
fields[0] = new Field("INDEX", Oid.INT4);
fields[0].setFormat(Field.BINARY_FORMAT);
fields[1] = new Field("VALUE", elementOid);
fields[1].setFormat(Field.BINARY_FORMAT);
for (int i = 1; i < index; ++i) {
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len != -1) {
pos += len;
}
}
for (int i = 0; i < dims[thisDimension]; ++i) {
byte[][] rowData = new byte[2][];
rowData[0] = new byte[4];
ByteConverter.int4(rowData[0], 0, i + index);
rows.add(rowData);
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len == -1) {
continue;
}
rowData[1] = new byte[len];
System.arraycopy(fieldBytes, pos, rowData[1], 0, rowData[1].length);
pos += len;
}
} else {
fields[0] = new Field("INDEX", Oid.INT4);
fields[0].setFormat(Field.BINARY_FORMAT);
fields[1] = new Field("VALUE", oid);
fields[1].setFormat(Field.BINARY_FORMAT);
int nextDimension = thisDimension + 1;
int dimensionsLeft = dims.length - nextDimension;
for (int i = 1; i < index; ++i) {
pos = calcRemainingDataLength(dims, pos, elementOid, nextDimension);
}
for (int i = 0; i < dims[thisDimension]; ++i) {
byte[][] rowData = new byte[2][];
rowData[0] = new byte[4];
ByteConverter.int4(rowData[0], 0, i + index);
rows.add(rowData);
int dataEndPos = calcRemainingDataLength(dims, pos, elementOid, nextDimension);
int dataLength = dataEndPos - pos;
rowData[1] = new byte[12 + 8 * dimensionsLeft + dataLength];
ByteConverter.int4(rowData[1], 0, dimensionsLeft);
System.arraycopy(fieldBytes, 4, rowData[1], 4, 8);
System.arraycopy(fieldBytes, 12 + nextDimension * 8, rowData[1], 12, dimensionsLeft * 8);
System.arraycopy(fieldBytes, pos, rowData[1], 12 + dimensionsLeft * 8, dataLength);
pos = dataEndPos;
}
}
return pos;
}
private int calcRemainingDataLength(int[] dims, int pos, int elementOid, int thisDimension) {
if (thisDimension == dims.length - 1) {
for (int i = 0; i < dims[thisDimension]; ++i) {
int len = ByteConverter.int4(fieldBytes, pos);
pos += 4;
if (len == -1) {
continue;
}
pos += len;
}
} else {
pos = calcRemainingDataLength(dims, elementOid, pos, thisDimension + 1);
}
return pos;
}
private Class<?> elementOidToClass(int oid) throws SQLException {
switch (oid) {
case Oid.INT2:
return Short.class;
case Oid.INT4:
return Integer.class;
case Oid.INT8:
return Long.class;
case Oid.FLOAT4:
return Float.class;
case Oid.FLOAT8:
return Double.class;
case Oid.TEXT:
case Oid.VARCHAR:
return String.class;
case Oid.BOOL:
return Boolean.class;
default:
ArrayAssistant arrElemBuilder = ArrayAssistantRegistry.getAssistant(oid);
if (arrElemBuilder != null) {
return arrElemBuilder.baseType();
}
throw org.postgresql.Driver.notImplemented(this.getClass(), "readBinaryArray(data,oid)");
}
}
private synchronized void buildArrayList() throws SQLException {
if (arrayList != null) {
return;
}
arrayList = new PgArrayList();
char delim = connection.getTypeInfo().getArrayDelimiter(oid);
if (fieldString != null) {
char[] chars = fieldString.toCharArray();
StringBuilder buffer = null;
boolean insideString = false;
boolean wasInsideString = false;
List<PgArrayList> dims = new ArrayList<PgArrayList>();
PgArrayList curArray = arrayList;
int startOffset = 0;
{
if (chars[0] == '[') {
while (chars[startOffset] != '=') {
startOffset++;
}
startOffset++;
}
}
for (int i = startOffset; i < chars.length; i++) {
if (chars[i] == '\\') {
i++;
} else if (!insideString && chars[i] == '{') {
if (dims.isEmpty()) {
dims.add(arrayList);
} else {
PgArrayList a = new PgArrayList();
PgArrayList p = dims.get(dims.size() - 1);
p.add(a);
dims.add(a);
}
curArray = dims.get(dims.size() - 1);
{
for (int t = i + 1; t < chars.length; t++) {
if (Character.isWhitespace(chars[t])) {
continue;
} else if (chars[t] == '{') {
curArray.dimensionsCount++;
} else {
break;
}
}
}
buffer = new StringBuilder();
continue;
} else if (chars[i] == '"') {
insideString = !insideString;
wasInsideString = true;
continue;
} else if (!insideString && Character.isWhitespace(chars[i])) {
continue;
} else if ((!insideString && (chars[i] == delim || chars[i] == '}'))
|| i == chars.length - 1) {
if (chars[i] != '"' && chars[i] != '}' && chars[i] != delim && buffer != null) {
buffer.append(chars[i]);
}
String b = buffer == null ? null : buffer.toString();
if (b != null && (!b.isEmpty() || wasInsideString)) {
curArray.add(!wasInsideString && b.equals("NULL") ? null : b);
}
wasInsideString = false;
buffer = new StringBuilder();
if (chars[i] == '}') {
dims.remove(dims.size() - 1);
if (!dims.isEmpty()) {
curArray = dims.get(dims.size() - 1);
}
buffer = null;
}
continue;
}
if (buffer != null) {
buffer.append(chars[i]);
}
}
}
}
private Object buildArray(PgArrayList input, int index, int count) throws SQLException {
if (count < 0) {
count = input.size();
}
Object ret = null;
int dims = input.dimensionsCount;
int[] dimsLength = dims > 1 ? new int[dims] : null;
if (dims > 1) {
for (int i = 0; i < dims; i++) {
dimsLength[i] = (i == 0 ? count : 0);
}
}
int length = 0;
final int type =
connection.getTypeInfo().getSQLType(connection.getTypeInfo().getPGArrayElement(oid));
if (type == Types.BIT) {
boolean[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret = oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Boolean.class : boolean.class, dimsLength)
: new Boolean[count]);
} else {
ret = pa = new boolean[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : BooleanTypeUtil.castToBoolean((String) o));
} else {
pa[length++] = o == null ? false : BooleanTypeUtil.castToBoolean((String) o);
}
}
} else if (type == Types.SMALLINT) {
short[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret =
oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Short.class : short.class, dimsLength)
: new Short[count]);
} else {
ret = pa = new short[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : PgResultSet.toShort((String) o));
} else {
pa[length++] = o == null ? 0 : PgResultSet.toShort((String) o);
}
}
} else if (type == Types.INTEGER) {
int[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret =
oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Integer.class : int.class, dimsLength)
: new Integer[count]);
} else {
ret = pa = new int[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : PgResultSet.toInt((String) o));
} else {
pa[length++] = o == null ? 0 : PgResultSet.toInt((String) o);
}
}
} else if (type == Types.BIGINT) {
long[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret =
oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Long.class : long.class, dimsLength)
: new Long[count]);
} else {
ret = pa = new long[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : PgResultSet.toLong((String) o));
} else {
pa[length++] = o == null ? 0L : PgResultSet.toLong((String) o);
}
}
} else if (type == Types.NUMERIC) {
Object[] oa = null;
ret = oa =
(dims > 1 ? (Object[]) java.lang.reflect.Array.newInstance(BigDecimal.class, dimsLength)
: new BigDecimal[count]);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = dims > 1 && v != null ? buildArray((PgArrayList) v, 0, -1)
: (v == null ? null : PgResultSet.toBigDecimal((String) v));
}
} else if (type == Types.REAL) {
float[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret =
oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Float.class : float.class, dimsLength)
: new Float[count]);
} else {
ret = pa = new float[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : PgResultSet.toFloat((String) o));
} else {
pa[length++] = o == null ? 0f : PgResultSet.toFloat((String) o);
}
}
} else if (type == Types.DOUBLE) {
double[] pa = null;
Object[] oa = null;
if (dims > 1 || useObjects) {
ret = oa = (dims > 1
? (Object[]) java.lang.reflect.Array
.newInstance(useObjects ? Double.class : double.class, dimsLength)
: new Double[count]);
} else {
ret = pa = new double[count];
}
for (; count > 0; count--) {
Object o = input.get(index++);
if (dims > 1 || useObjects) {
oa[length++] = o == null ? null
: (dims > 1 ? buildArray((PgArrayList) o, 0, -1) : PgResultSet.toDouble((String) o));
} else {
pa[length++] = o == null ? 0d : PgResultSet.toDouble((String) o);
}
}
} else if (type == Types.CHAR || type == Types.VARCHAR || oid == Oid.JSONB_ARRAY) {
Object[] oa = null;
ret =
oa = (dims > 1 ? (Object[]) java.lang.reflect.Array.newInstance(String.class, dimsLength)
: new String[count]);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = dims > 1 && v != null ? buildArray((PgArrayList) v, 0, -1) : v;
}
} else if (type == Types.DATE) {
Object[] oa = null;
ret = oa = (dims > 1
? (Object[]) java.lang.reflect.Array.newInstance(java.sql.Date.class, dimsLength)
: new java.sql.Date[count]);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = dims > 1 && v != null ? buildArray((PgArrayList) v, 0, -1)
: (v == null ? null : connection.getTimestampUtils().toDate(null, (String) v));
}
} else if (type == Types.TIME) {
Object[] oa = null;
ret = oa = (dims > 1
? (Object[]) java.lang.reflect.Array.newInstance(java.sql.Time.class, dimsLength)
: new java.sql.Time[count]);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = dims > 1 && v != null ? buildArray((PgArrayList) v, 0, -1)
: (v == null ? null : connection.getTimestampUtils().toTime(null, (String) v));
}
} else if (type == Types.TIMESTAMP) {
Object[] oa = null;
ret = oa = (dims > 1
? (Object[]) java.lang.reflect.Array.newInstance(java.sql.Timestamp.class, dimsLength)
: new java.sql.Timestamp[count]);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = dims > 1 && v != null ? buildArray((PgArrayList) v, 0, -1)
: (v == null ? null : connection.getTimestampUtils().toTimestamp(null, (String) v));
}
} else if (ArrayAssistantRegistry.getAssistant(oid) != null) {
ArrayAssistant arrAssistant = ArrayAssistantRegistry.getAssistant(oid);
Object[] oa = null;
ret = oa = (dims > 1)
? (Object[]) java.lang.reflect.Array.newInstance(arrAssistant.baseType(), dimsLength)
: (Object[]) java.lang.reflect.Array.newInstance(arrAssistant.baseType(), count);
for (; count > 0; count--) {
Object v = input.get(index++);
oa[length++] = (dims > 1 && v != null) ? buildArray((PgArrayList) v, 0, -1)
: (v == null ? null : arrAssistant.buildElement((String) v));
}
} else if (dims == 1) {
Object[] oa = new Object[count];
String typeName = getBaseTypeName();
for (; count > 0; count--) {
Object v = input.get(index++);
if (v instanceof String) {
oa[length++] = connection.getObject(typeName, (String) v, null);
} else if (v instanceof byte[]) {
oa[length++] = connection.getObject(typeName, null, (byte[]) v);
} else if (v == null) {
oa[length++] = null;
} else {
throw org.postgresql.Driver.notImplemented(this.getClass(), "getArrayImpl(long,int,Map)");
}
}
ret = oa;
} else {
connection.getLogger().log(Level.FINEST, "getArrayImpl(long,int,Map) with {0}", getBaseTypeName());
throw org.postgresql.Driver.notImplemented(this.getClass(), "getArrayImpl(long,int,Map)");
}
return ret;
}
public int getBaseType() throws SQLException {
return connection.getTypeInfo().getSQLType(getBaseTypeName());
}
public String getBaseTypeName() throws SQLException {
buildArrayList();
int elementOID = connection.getTypeInfo().getPGArrayElement(oid);
return connection.getTypeInfo().getPGType(elementOID);
}
public java.sql.ResultSet getResultSet() throws SQLException {
return getResultSetImpl(1, 0, null);
}
public java.sql.ResultSet getResultSet(long index, int count) throws SQLException {
return getResultSetImpl(index, count, null);
}
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
return getResultSetImpl(map);
}
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map)
throws SQLException {
return getResultSetImpl(index, count, map);
}
public ResultSet getResultSetImpl(Map<String, Class<?>> map) throws SQLException {
return getResultSetImpl(1, 0, map);
}
public ResultSet getResultSetImpl(long index, int count, Map<String, Class<?>> map)
throws SQLException {
if (map != null && !map.isEmpty()) {
throw org.postgresql.Driver.notImplemented(this.getClass(), "getResultSetImpl(long,int,Map)");
}
if (index < 1) {
throw new PSQLException(GT.tr("The array index is out of range: {0}", index),
PSQLState.DATA_ERROR);
}
if (fieldBytes != null) {
return readBinaryResultSet((int) index, count);
}
buildArrayList();
if (count == 0) {
count = arrayList.size();
}
if ((--index) + count > arrayList.size()) {
throw new PSQLException(
GT.tr("The array index is out of range: {0}, number of elements: {1}.",
index + count, (long) arrayList.size()),
PSQLState.DATA_ERROR);
}
List<byte[][]> rows = new ArrayList<byte[][]>();
Field[] fields = new Field[2];
if (arrayList.dimensionsCount <= 1) {
final int baseOid = connection.getTypeInfo().getPGArrayElement(oid);
fields[0] = new Field("INDEX", Oid.INT4);
fields[1] = new Field("VALUE", baseOid);
for (int i = 0; i < count; i++) {
int offset = (int) index + i;
byte[][] t = new byte[2][0];
String v = (String) arrayList.get(offset);
t[0] = connection.encodeString(Integer.toString(offset + 1));
t[1] = v == null ? null : connection.encodeString(v);
rows.add(t);
}
} else {
fields[0] = new Field("INDEX", Oid.INT4);
fields[1] = new Field("VALUE", oid);
for (int i = 0; i < count; i++) {
int offset = (int) index + i;
byte[][] t = new byte[2][0];
Object v = arrayList.get(offset);
t[0] = connection.encodeString(Integer.toString(offset + 1));
t[1] = v == null ? null : connection.encodeString(toString((PgArrayList) v));
rows.add(t);
}
}
BaseStatement stat = (BaseStatement) connection
.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
return stat.createDriverResultSet(fields, rows);
}
public String toString() {
if (fieldString == null && fieldBytes != null) {
try {
Object array = readBinaryArray(1, 0);
final PrimitiveArraySupport arraySupport = PrimitiveArraySupport.getArraySupport(array);
if (arraySupport != null) {
fieldString =
arraySupport.toArrayString(connection.getTypeInfo().getArrayDelimiter(oid), array);
} else {
java.sql.Array tmpArray = connection.createArrayOf(getBaseTypeName(), (Object[]) array);
fieldString = tmpArray.toString();
}
} catch (SQLException e) {
fieldString = "NULL";
}
}
return fieldString;
}
private String toString(PgArrayList list) throws SQLException {
if (list == null) {
return "NULL";
}
StringBuilder b = new StringBuilder().append('{');
char delim = connection.getTypeInfo().getArrayDelimiter(oid);
for (int i = 0; i < list.size(); i++) {
Object v = list.get(i);
if (i > 0) {
b.append(delim);
}
if (v == null) {
b.append("NULL");
} else if (v instanceof PgArrayList) {
b.append(toString((PgArrayList) v));
} else {
escapeArrayElement(b, (String) v);
}
}
b.append('}');
return b.toString();
}
public static void escapeArrayElement(StringBuilder b, String s) {
b.append('"');
for (int j = 0; j < s.length(); j++) {
char c = s.charAt(j);
if (c == '"' || c == '\\') {
b.append('\\');
}
b.append(c);
}
b.append('"');
}
public boolean isBinary() {
return fieldBytes != null;
}
public byte[] toBytes() {
return fieldBytes;
}
public void free() throws SQLException {
connection = null;
fieldString = null;
fieldBytes = null;
arrayList = null;
}
}