Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for setBinaryStream with unknown length #220

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.xml
Expand Up @@ -108,7 +108,7 @@
</patternset>

<artifact:dependencies pathId="dependency.classpath" useScope="test">
<dependency groupId="junit" artifactId="junit" version="4.0" scope="test"/>
<dependency groupId="junit" artifactId="junit" version="4.11" scope="test"/>
</artifact:dependencies>

<target name="check_versions">
Expand Down
11 changes: 11 additions & 0 deletions org/postgresql/core/ParameterList.java
Expand Up @@ -120,6 +120,17 @@ public interface ParameterList {
*/
void setBytea(int index, InputStream stream, int length) throws SQLException;

/**
* Binds a binary bytea value stored as an InputStream. The
* parameter's type is implicitly set to 'bytea'. The stream should
* remain valid until query execution has completed.
*
* @param index the 1-based parameter index to bind.
* @param stream a stream containing the parameter data.
* @throws SQLException on error or if <code>index</code> is out of range
*/
void setBytea(int index, InputStream stream) throws SQLException;

/**
* Binds given byte[] value to a parameter. The bytes must already
* be in correct format matching the OID.
Expand Down
8 changes: 8 additions & 0 deletions org/postgresql/core/v2/FastpathParameterList.java
Expand Up @@ -86,6 +86,14 @@ public void setBytea(int index, final InputStream stream, final int length) thro
paramValues[index - 1] = new StreamWrapper(stream, length);
}

public void setBytea(int index, InputStream stream) throws SQLException
{
if (index < 1 || index > paramValues.length)
throw new PSQLException(GT.tr("The column index is out of range: {0}, number of columns: {1}.", new Object[]{new Integer(index), new Integer(paramValues.length)}), PSQLState.INVALID_PARAMETER_VALUE );

paramValues[index - 1] = new StreamWrapper(stream);
}

public void setNull(int index, int oid) throws SQLException {
throw new IllegalArgumentException("can't setNull() on a v2 fastpath parameter");
}
Expand Down
8 changes: 8 additions & 0 deletions org/postgresql/core/v2/SimpleParameterList.java
Expand Up @@ -85,6 +85,14 @@ public void setBytea(int index, final InputStream stream, final int length) thro
paramValues[index - 1] = new StreamWrapper(stream, length);
}

public void setBytea(int index, InputStream stream) throws SQLException
{
if (index < 1 || index > paramValues.length)
throw new PSQLException(GT.tr("The column index is out of range: {0}, number of columns: {1}.", new Object[]{new Integer(index), new Integer(paramValues.length)}), PSQLState.INVALID_PARAMETER_VALUE );

paramValues[index - 1] = new StreamWrapper(stream);
}

public void setNull(int index, int oid) throws SQLException {
if (index < 1 || index > paramValues.length)
throw new PSQLException(GT.tr("The column index is out of range: {0}, number of columns: {1}.", new Object[]{new Integer(index), new Integer(paramValues.length)}), PSQLState.INVALID_PARAMETER_VALUE );
Expand Down
6 changes: 6 additions & 0 deletions org/postgresql/core/v3/CompositeParameterList.java
Expand Up @@ -97,6 +97,12 @@ public void setBytea(int index, InputStream stream, int length) throws SQLExcept
subparams[sub].setBytea(index - offsets[sub], stream, length);
}

public void setBytea(int index, InputStream stream) throws SQLException
{
int sub = findSubParam(index);
subparams[sub].setBytea(index - offsets[sub], stream);
}

public void setNull(int index, int oid) throws SQLException {
int sub = findSubParam(index);
subparams[sub].setNull(index - offsets[sub], oid);
Expand Down
5 changes: 5 additions & 0 deletions org/postgresql/core/v3/SimpleParameterList.java
Expand Up @@ -130,6 +130,11 @@ public void setBytea(int index, InputStream stream, int length) throws SQLExcept
bind(index, new StreamWrapper(stream, length), Oid.BYTEA, BINARY);
}

public void setBytea(int index, InputStream stream) throws SQLException
{
bind(index, new StreamWrapper(stream), Oid.BYTEA, BINARY);
}

public void setNull(int index, int oid) throws SQLException {

int binaryTransfer = TEXT;
Expand Down
2 changes: 1 addition & 1 deletion org/postgresql/jdbc4/AbstractJdbc4Statement.java
Expand Up @@ -132,7 +132,7 @@ public void setBinaryStream(int parameterIndex, InputStream value, long length)

public void setBinaryStream(int parameterIndex, InputStream value) throws SQLException
{
throw org.postgresql.Driver.notImplemented(this.getClass(), "setBinaryStream(int, InputStream)");
preparedParameters.setBytea(parameterIndex, value);
}

public void setAsciiStream(int parameterIndex, InputStream value, long length) throws SQLException
Expand Down
183 changes: 183 additions & 0 deletions org/postgresql/test/jdbc4/BinaryStreamTest.java
@@ -0,0 +1,183 @@
package org.postgresql.test.jdbc4;

import java.io.ByteArrayInputStream;
import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Random;

import junit.framework.TestCase;

import org.junit.Assert;
import org.postgresql.test.TestUtil;

public class BinaryStreamTest extends TestCase
{

private Connection _conn;

private ByteBuffer _testData;

protected void setUp() throws Exception
{
_conn = TestUtil.openDB();
TestUtil.createTable(_conn, "images", "img bytea");

Random random = new Random(31459);
_testData = ByteBuffer.allocate(200 * 1024);
while (_testData.remaining() > 0)
{
_testData.putLong(random.nextLong());
}
}

protected void tearDown() throws SQLException
{
TestUtil.dropTable(_conn, "images");
TestUtil.closeDB(_conn);
}

private void insertStreamKownLength(byte[] data)
throws Exception
{
PreparedStatement updatePS = _conn.prepareStatement(TestUtil.insertSQL("images", "img", "?"));
try
{
updatePS.setBinaryStream(1, new ByteArrayInputStream(data), data.length);
updatePS.executeUpdate();
}
finally
{
updatePS.close();
}
}

private void insertStreamUnkownLength(byte[] data)
throws Exception
{
PreparedStatement updatePS = _conn.prepareStatement(TestUtil.insertSQL("images", "img", "?"));
try
{
updatePS.setBinaryStream(1, new ByteArrayInputStream(data));
updatePS.executeUpdate();
}
finally
{
updatePS.close();
}
}

private void validateContent(byte[] data)
throws Exception
{
PreparedStatement selectPS = _conn.prepareStatement(TestUtil.selectSQL("images", "img"));
try
{
ResultSet rs = selectPS.executeQuery();
try
{
rs.next();
byte[] actualData = rs.getBytes(1);
Assert.assertArrayEquals("Sent and received data are not the same", data, actualData);
}
finally
{
rs.close();
}
}
finally
{
selectPS.close();
}

PreparedStatement deletePS = _conn.prepareStatement("DELETE FROM images");
try
{
deletePS.executeUpdate();
}
finally
{
deletePS.close();
}
}

private byte[] getTestData(int size)
{
_testData.rewind();
byte[] data = new byte[size];
_testData.get(data);
return data;
}

public void testKnownLengthEmpty() throws Exception
{
byte[] data = new byte[0];
insertStreamKownLength(data);
validateContent(data);
}

public void testKnownLength2Kb() throws Exception
{
byte[] data = getTestData(2 * 1024);
insertStreamKownLength(data);
validateContent(data);
}

public void testKnownLength10Kb() throws Exception
{
byte[] data = getTestData(10 * 1024);
insertStreamKownLength(data);
validateContent(data);
}

public void testKnownLength100Kb() throws Exception
{
byte[] data = getTestData(100 * 1024);
insertStreamKownLength(data);
validateContent(data);
}

public void testKnownLength200Kb() throws Exception
{
byte[] data = getTestData(200 * 1024);
insertStreamKownLength(data);
validateContent(data);
}

public void testUnknownLengthEmpty() throws Exception
{
byte[] data = getTestData(2 * 1024);
insertStreamUnkownLength(data);
validateContent(data);
}

public void testUnknownLength2Kb() throws Exception
{
byte[] data = getTestData(2 * 1024);
insertStreamUnkownLength(data);
validateContent(data);
}

public void testUnknownLength10Kb() throws Exception
{
byte[] data = getTestData(10 * 1024);
insertStreamUnkownLength(data);
validateContent(data);
}

public void testUnknownLength100Kb() throws Exception
{
byte[] data = getTestData(100 * 1024);
insertStreamUnkownLength(data);
validateContent(data);
}

public void testUnknownLength200Kb() throws Exception
{
byte[] data = getTestData(200 * 1024);
insertStreamUnkownLength(data);
validateContent(data);
}
}
1 change: 1 addition & 0 deletions org/postgresql/test/jdbc4/Jdbc4TestSuite.java
Expand Up @@ -35,6 +35,7 @@ public static TestSuite suite() throws Exception
suite.addTestSuite(IsValidTest.class);
suite.addTestSuite(ClientInfoTest.class);
suite.addTestSuite(PGCopyInputStreamTest.class);
suite.addTestSuite(BinaryStreamTest.class);

Connection connection = TestUtil.openDB();
try
Expand Down
1 change: 1 addition & 0 deletions org/postgresql/util/PSQLState.java
Expand Up @@ -97,6 +97,7 @@ public PSQLState(String state)
public final static PSQLState OBJECT_NOT_IN_STATE = new PSQLState("55000");

public final static PSQLState SYSTEM_ERROR = new PSQLState("60000");
public final static PSQLState IO_ERROR = new PSQLState("58030");

public final static PSQLState UNEXPECTED_ERROR = new PSQLState("99999");

Expand Down