JDBC checkin fixing the following bugs:

Fixed support in the driver for notifications (added PGConnection.getNotifications()) - problem reported by Benjamin.Feinstein@guardent.com
  Worked around server problems with int8/int2 and constants; quote values when they are intended to bind to an int8/int2 column - reported by many
  Fixed bug in the Array interface with string parsing not handling escaped characters correctly - reported by devajx@yahoo.com
  Added workaround to support 'infinity' and '-infinity' for dates - reported bydmitry@openratings.com
  Fixed some performance issues with setBlob - reported by d.wall@computer.org
  Added support for using new prepared statements functionality in 7.3 (added PGStatement.setUseServerPrepare() and isUseServerPrepare() methods)

 Modified Files:
 	jdbc/org/postgresql/PGConnection.java
 	jdbc/org/postgresql/PGStatement.java
 	jdbc/org/postgresql/core/QueryExecutor.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Connection.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java
 	jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
 	jdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java
 	jdbc/org/postgresql/jdbc2/Array.java
 Added Files:
 	jdbc/org/postgresql/PGNotification.java
 	jdbc/org/postgresql/core/Notification.java
This commit is contained in:
Barry Lind 2002-09-02 03:07:36 +00:00
parent 97ac103289
commit 2232172e44
10 changed files with 242 additions and 39 deletions

View File

@ -7,7 +7,7 @@ import org.postgresql.core.Encoding;
import org.postgresql.fastpath.Fastpath;
import org.postgresql.largeobject.LargeObjectManager;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.2 2002/09/02 03:07:36 barry Exp $
* This interface defines PostgreSQL extentions to the java.sql.Connection interface.
* Any java.sql.Connection object returned by the driver will also implement this
* interface
@ -68,5 +68,14 @@ public interface PGConnection
*/
public Object getObject(String type, String value) throws SQLException;
/*
* This method returns any notifications that have been received
* since the last call to this method.
* Returns null if there have been no notifications.
*/
public PGNotification[] getNotifications();
}

View File

@ -0,0 +1,20 @@
package org.postgresql;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGNotification.java,v 1.1 2002/09/02 03:07:36 barry Exp $
* This interface defines PostgreSQL extention for Notifications
*/
public interface PGNotification
{
/*
* Returns name of this notification
*/
public String getName();
/*
* Returns the process id of the backend process making this notification
*/
public int getPID();
}

View File

@ -3,7 +3,7 @@ package org.postgresql;
import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.3 2002/07/23 03:59:55 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.4 2002/09/02 03:07:36 barry Exp $
* This interface defines PostgreSQL extentions to the java.sql.Statement interface.
* Any java.sql.Statement object returned by the driver will also implement this
* interface
@ -18,4 +18,8 @@ public interface PGStatement
*/
public long getLastOID() throws SQLException;
public void setUseServerPrepare(boolean flag);
public boolean isUseServerPrepare();
}

View File

@ -0,0 +1,32 @@
package org.postgresql.core;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Notification.java,v 1.1 2002/09/02 03:07:36 barry Exp $
* This is the implementation of the PGNotification interface
*/
public class Notification implements org.postgresql.PGNotification
{
public Notification(String p_name, int p_pid) {
m_name = p_name;
m_pid = p_pid;
}
/*
* Returns name of this notification
*/
public String getName() {
return m_name;
}
/*
* Returns the process id of the backend process making this notification
*/
public int getPID() {
return m_pid;
}
private String m_name;
private int m_pid;
}

View File

@ -13,7 +13,7 @@ import org.postgresql.util.PSQLException;
* <p>The lifetime of a QueryExecutor object is from sending the query
* until the response has been received from the backend.
*
* $Id: QueryExecutor.java,v 1.14 2002/08/23 20:45:49 barry Exp $
* $Id: QueryExecutor.java,v 1.15 2002/09/02 03:07:36 barry Exp $
*/
public class QueryExecutor
@ -75,6 +75,7 @@ public class QueryExecutor
case 'A': // Asynchronous Notify
int pid = pg_stream.ReceiveInteger(4);
String msg = pg_stream.ReceiveString(connection.getEncoding());
connection.addNotification(new org.postgresql.core.Notification(msg, pid));
break;
case 'B': // Binary Data Transfer
receiveTuple(true);

View File

@ -6,6 +6,7 @@ import java.net.ConnectException;
import java.sql.*;
import java.util.*;
import org.postgresql.Driver;
import org.postgresql.PGNotification;
import org.postgresql.PG_Stream;
import org.postgresql.core.*;
import org.postgresql.fastpath.Fastpath;
@ -13,7 +14,7 @@ import org.postgresql.largeobject.LargeObjectManager;
import org.postgresql.util.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.6 2002/09/01 23:56:13 davec Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Connection.java,v 1.7 2002/09/02 03:07:36 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Connection which adds the jdbc2
* methods. The real Connection class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Connection
@ -34,6 +35,8 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
protected int pid;
protected int ckey;
private Vector m_notifications;
/*
The encoding to use for this connection.
*/
@ -1309,7 +1312,22 @@ public abstract class AbstractJdbc1Connection implements org.postgresql.PGConnec
Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP
};
//Methods to support postgres notifications
public void addNotification(org.postgresql.PGNotification p_notification) {
if (m_notifications == null)
m_notifications = new Vector();
m_notifications.addElement(p_notification);
}
public PGNotification[] getNotifications() {
PGNotification[] l_return = null;
if (m_notifications != null) {
l_return = new PGNotification[m_notifications.size()];
m_notifications.copyInto(l_return);
}
m_notifications = null;
return l_return;
}
}

View File

@ -13,7 +13,7 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.4 2002/08/16 17:51:38 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.5 2002/09/02 03:07:36 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2
* methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet
@ -934,6 +934,15 @@ public abstract class AbstractJdbc1ResultSet
}
else
{
if (slen == 8 && s.equals("infinity"))
//java doesn't have a concept of postgres's infinity
//so set to an arbitrary future date
s = "9999-01-01";
if (slen == 9 && s.equals("-infinity"))
//java doesn't have a concept of postgres's infinity
//so set to an arbitrary old date
s = "0001-01-01";
// We must just have a date. This case is
// needed if this method is called on a date
// column

View File

@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.5 2002/08/23 20:45:49 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.6 2002/09/02 03:07:36 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
* methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
@ -44,7 +44,13 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
//Used by the preparedstatement style methods
protected String[] m_sqlFragments;
private String[] m_origSqlFragments;
private String[] m_executeSqlFragments;
protected Object[] m_binds = new Object[0];
private String[] m_bindTypes = new String[0];
private String m_statementName = null;
private boolean m_useServerPrepare = false;
private static int m_preparedCount = 1;
//Used by the callablestatement style methods
private static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";
@ -102,11 +108,13 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
m_sqlFragments = new String[v.size()];
m_binds = new String[v.size() - 1];
m_bindTypes = new String[v.size() - 1];
//BJL why if binds is new???
clearParameters();
for (i = 0 ; i < m_sqlFragments.length; ++i)
m_sqlFragments[i] = (String)v.elementAt(i);
}
@ -207,6 +215,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
throw new PSQLException("postgresql.call.noreturntype");
if (isFunction) { // set entry 1 to dummy entry..
m_binds[0] = ""; // dummy entry which ensured that no one overrode
m_bindTypes[0] = PG_TEXT;
// and calls to setXXX (2,..) really went to first arg in a function call..
}
@ -220,6 +229,53 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
rs.close();
}
//Use server prepared statements if directed
if (m_useServerPrepare) {
if (m_statementName == null) {
m_statementName = "JDBC_STATEMENT_" + m_preparedCount++;
m_origSqlFragments = new String[m_sqlFragments.length];
m_executeSqlFragments = new String[m_sqlFragments.length];
System.arraycopy(m_sqlFragments, 0, m_origSqlFragments, 0, m_sqlFragments.length);
m_executeSqlFragments[0] = "EXECUTE " + m_statementName;
if (m_sqlFragments.length > 1) {
m_executeSqlFragments[0] = m_executeSqlFragments[0] + "(";
for(int i = 1; i < m_bindTypes.length; i++) {
m_executeSqlFragments[i] = ", ";
}
m_executeSqlFragments[m_bindTypes.length] = ")";
}
synchronized (sbuf) {
sbuf.setLength(0);
sbuf.append("PREPARE ");
sbuf.append(m_statementName);
if (m_origSqlFragments.length > 1) {
sbuf.append("(");
for(int i = 0; i < m_bindTypes.length - 1; i++) {
sbuf.append(m_bindTypes[i]);
sbuf.append(", ");
}
sbuf.append(m_bindTypes[m_bindTypes.length - 1]);
sbuf.append(")");
}
sbuf.append(" AS ");
sbuf.append(m_origSqlFragments[0]);
for(int i = 1; i < m_origSqlFragments.length; i++) {
sbuf.append(" $");
sbuf.append(i);
sbuf.append(" ");
sbuf.append(m_origSqlFragments[i]);
}
sbuf.append("; ");
sbuf.append(m_executeSqlFragments[0]);
m_sqlFragments[0] = sbuf.toString();
System.arraycopy(m_executeSqlFragments, 1, m_sqlFragments, 1, m_sqlFragments.length - 1);
}
} else {
m_sqlFragments = m_executeSqlFragments;
}
}
// New in 7.1, pass Statement so that ExecSQL can customise to it
result = ((AbstractJdbc1Connection)connection).ExecSQL(m_sqlFragments, m_binds, (java.sql.Statement)this);
@ -618,7 +674,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setNull(int parameterIndex, int sqlType) throws SQLException
{
set(parameterIndex, "null");
bind(parameterIndex, "null", PG_TEXT);
}
/*
@ -631,7 +687,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setBoolean(int parameterIndex, boolean x) throws SQLException
{
set(parameterIndex, x ? "'t'" : "'f'");
bind(parameterIndex, x ? "'t'" : "'f'", PG_BOOLEAN);
}
/*
@ -644,7 +700,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setByte(int parameterIndex, byte x) throws SQLException
{
set(parameterIndex, Integer.toString(x));
bind(parameterIndex, Integer.toString(x), PG_TEXT);
}
/*
@ -657,7 +713,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setShort(int parameterIndex, short x) throws SQLException
{
set(parameterIndex, Integer.toString(x));
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex,"'" + Integer.toString(x) +"'", PG_INT2);
}
/*
@ -670,7 +729,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setInt(int parameterIndex, int x) throws SQLException
{
set(parameterIndex, Integer.toString(x));
bind(parameterIndex, Integer.toString(x), PG_INTEGER);
}
/*
@ -683,7 +742,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setLong(int parameterIndex, long x) throws SQLException
{
set(parameterIndex, Long.toString(x));
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex, "'"+Long.toString(x)+"'", PG_INT8);
}
/*
@ -696,7 +758,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setFloat(int parameterIndex, float x) throws SQLException
{
set(parameterIndex, Float.toString(x));
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex, "'"+Float.toString(x)+"'", PG_FLOAT);
}
/*
@ -709,7 +774,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
*/
public void setDouble(int parameterIndex, double x) throws SQLException
{
set(parameterIndex, Double.toString(x));
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex, "'"+Double.toString(x)+"'", PG_DOUBLE);
}
/*
@ -727,7 +795,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
setNull(parameterIndex, Types.OTHER);
else
{
set(parameterIndex, x.toString());
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex, "'"+x.toString()+"'", PG_NUMERIC);
}
}
@ -742,6 +813,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
* @exception SQLException if a database access error occurs
*/
public void setString(int parameterIndex, String x) throws SQLException
{
setString(parameterIndex, x, PG_TEXT);
}
public void setString(int parameterIndex, String x, String type) throws SQLException
{
// if the passed string is null, then set this column to null
if (x == null)
@ -765,7 +841,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
sbuf.append(c);
}
sbuf.append('\'');
set(parameterIndex, sbuf.toString());
bind(parameterIndex, sbuf.toString(), type);
}
}
}
@ -795,7 +871,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
else
{
setString(parameterIndex, PGbytea.toPGString(x));
setString(parameterIndex, PGbytea.toPGString(x), PG_TEXT);
}
}
else
@ -826,7 +902,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
else
{
set(parameterIndex, "'" + x.toString() + "'");
bind(parameterIndex, "'" + x.toString() + "'", PG_DATE);
}
}
@ -846,7 +922,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
else
{
set(parameterIndex, "'" + x.toString() + "'");
bind(parameterIndex, "'" + x.toString() + "'", PG_TIME);
}
}
@ -932,7 +1008,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
sbuf.append(l_minos);
}
sbuf.append("'");
set(parameterIndex, sbuf.toString());
bind(parameterIndex, sbuf.toString(), PG_TIMESTAMPTZ);
}
}
@ -969,7 +1045,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
char[] l_chars = new char[length];
int l_charsRead = l_inStream.read(l_chars, 0, length);
setString(parameterIndex, new String(l_chars, 0, l_charsRead));
setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT);
}
catch (UnsupportedEncodingException l_uee)
{
@ -1018,7 +1094,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
char[] l_chars = new char[length];
int l_charsRead = l_inStream.read(l_chars, 0, length);
setString(parameterIndex, new String(l_chars, 0, l_charsRead));
setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT);
}
catch (UnsupportedEncodingException l_uee)
{
@ -1130,8 +1206,10 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
{
int i;
for (i = 0 ; i < m_binds.length ; i++)
for (i = 0 ; i < m_binds.length ; i++) {
m_binds[i] = null;
m_bindTypes[i] = null;
}
}
/*
@ -1162,9 +1240,11 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
switch (targetSqlType)
{
case Types.INTEGER:
bind(parameterIndex, x.toString(), PG_INTEGER);
break;
case Types.TINYINT:
case Types.SMALLINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.REAL:
case Types.FLOAT:
@ -1172,9 +1252,12 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
case Types.DECIMAL:
case Types.NUMERIC:
if (x instanceof Boolean)
set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
bind(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0", PG_BOOLEAN);
else
set(parameterIndex, x.toString());
//Note this should be fixed
//as soon as the backend correctly supports int8 type
//comparisons
bind(parameterIndex, "'"+x.toString()+"'", PG_NUMERIC);
break;
case Types.CHAR:
case Types.VARCHAR:
@ -1193,7 +1276,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
case Types.BIT:
if (x instanceof Boolean)
{
set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
bind(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE", PG_TEXT);
}
else
{
@ -1205,7 +1288,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
setObject(parameterIndex, x);
break;
case Types.OTHER:
setString(parameterIndex, ((PGobject)x).getValue());
setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
break;
default:
throw new PSQLException("postgresql.prep.type");
@ -1255,7 +1338,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
else if (x instanceof Boolean)
setBoolean(parameterIndex, ((Boolean)x).booleanValue());
else if (x instanceof PGobject)
setString(parameterIndex, ((PGobject)x).getValue());
setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
else
// Try to store java object in database
setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
@ -1579,13 +1662,14 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
* @param s a string to be stored
* @exception SQLException if something goes wrong
*/
protected void set(int paramIndex, String s) throws SQLException
protected void bind(int paramIndex, Object s, String type) throws SQLException
{
if (paramIndex < 1 || paramIndex > m_binds.length)
throw new PSQLException("postgresql.prep.range");
if (paramIndex == 1 && isFunction) // need to registerOut instead
throw new PSQLException ("postgresql.call.funcover");
m_binds[paramIndex - 1] = s;
m_bindTypes[paramIndex - 1] = type;
}
/*
@ -1607,7 +1691,7 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
// This cannot be just a plain OID because then there would be ambiguity
// between when you want the oid itself and when you want the object
// an oid references.
set(parameterIndex, Long.toString(x) + "::" + tablename );
bind(parameterIndex, Long.toString(x) + "::" + tablename, PG_TEXT );
}
/**
@ -1675,4 +1759,27 @@ public abstract class AbstractJdbc1Statement implements org.postgresql.PGStateme
}
public void setUseServerPrepare(boolean flag) {
m_useServerPrepare = flag;
}
public boolean isUseServerPrepare() {
return m_useServerPrepare;
}
private static final String PG_TEXT = "text";
private static final String PG_INTEGER = "integer";
private static final String PG_INT2 = "int2";
private static final String PG_INT8 = "int8";
private static final String PG_NUMERIC = "numeric";
private static final String PG_FLOAT = "float";
private static final String PG_DOUBLE = "double";
private static final String PG_BOOLEAN = "boolean";
private static final String PG_DATE = "date";
private static final String PG_TIME = "time";
private static final String PG_TIMESTAMPTZ = "timestamptz";
}

View File

@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.4 2002/08/23 20:45:49 barry Exp $
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.5 2002/09/02 03:07:36 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
@ -172,23 +172,23 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
public void setBlob(int i, Blob x) throws SQLException
{
InputStream l_inStream = x.getBinaryStream();
int l_length = (int) x.length();
LargeObjectManager lom = connection.getLargeObjectAPI();
int oid = lom.create();
LargeObject lob = lom.open(oid);
OutputStream los = lob.getOutputStream();
byte[] buf = new byte[4096];
try
{
// could be buffered, but then the OutputStream returned by LargeObject
// is buffered internally anyhow, so there would be no performance
// boost gained, if anything it would be worse!
int c = l_inStream.read();
int p = 0;
while (c > -1 && p < l_length)
int bytesRemaining = (int)x.length();
int numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining));
while (numRead != -1 && bytesRemaining > 0)
{
los.write(c);
c = l_inStream.read();
p++;
bytesRemaining -= numRead;
los.write(buf,0,numRead);
numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining));
}
los.close();
}

View File

@ -88,6 +88,9 @@ public class Array implements java.sql.Array
boolean insideString = false;
for ( int i = 0; i < chars.length; i++ )
{
if ( chars[i] == '\\' )
//escape character that we need to skip
i++;
if ( chars[i] == '{' )
{
if ( foundOpen ) // Only supports 1-D arrays for now