You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-user@db.apache.org by Mikael <mi...@telia.com> on 2007/09/21 16:51:08 UTC

PreparedStatement problem with big BLOBS

Hi !

I have a pretty weird problem, I use a Derby 10.3.1.4 with the ClientDriver and I run the code below:

    // Data is a byte[] vector
    ByteArrayInputStream is = new ByteArrayInputStream( data);    
    String sql = "UPDATE MyTable SET FContents=? WHERE FName='" + name + "'";
    PreparedStatement ps = conn.prepareStatement( sql);
    ps.setBinaryStream( 1, is, data.length);
    
    if( ps.executeUpdate() == 0)
    {
        // it throws an exception here if the data array us larger then around 32750 bytes!!!
    }

Connection is "jdbc:derby://localhost/mydb;create=true;"

java.sql.SQLException: A network protocol error was encountered and the connection has been terminated: A PROTOCOL Data Stream Syntax Error was detected.  Reason: 0x0. Plaintext connection attempt to an SSL enabled server?
        at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
        at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
        at org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source)

The table is defined as:
    CREATE TABLE MyTable (FName varchar(300) NOT NULL,FContents BLOB(16M) NOT NULL)

I do not understand why it only works with small BLOB contents, as soon as I pass 32750 bytes or so the above happens,
when data is 32750 or smaller it works just fine.

Re: PreparedStatement problem with big BLOBS

Posted by Mikael <mi...@telia.com>.
That is correct, no SSL involved at all.

----- Original Message ----- 
From: "Bernt M. Johnsen" <Be...@Sun.COM>
To: "Derby Discussion" <de...@db.apache.org>
Sent: Monday, September 24, 2007 3:45 PM
Subject: Re: PreparedStatement problem with big BLOBS



Re: PreparedStatement problem with big BLOBS

Posted by "Bernt M. Johnsen" <Be...@Sun.COM>.
>>>>>>>>>>>> Kathey Marsden wrote (2007-09-21 09:14:50):
> Mikael wrote:
> >Hi !
> > 
> >I have a pretty weird problem, I use a Derby 10.3.1.4 with the 
> >ClientDriver and I run the code below:
> > 
> >    // Data is a byte[] vector
> >    ByteArrayInputStream is = new ByteArrayInputStream( data);    
> >    String sql = "UPDATE MyTable SET FContents=? WHERE FName='" + name 
> >+ "'";
> >    PreparedStatement ps = conn.prepareStatement( sql);
> >    ps.setBinaryStream( 1, is, data.length);
> >    
> >    if( ps.executeUpdate() == 0)
> >    {
> >        // it throws an exception here if the data array us larger 
> >then around 32750 bytes!!!
> >    }
> > 
> >Connection is "jdbc:derby://localhost/mydb;create=true;"
> >
> >java.sql.SQLException: A network protocol error was encountered and 
> >the connection has been terminated: A PROTOCOL Data Stream Syntax 
> >Error was detected.  Reason: 0x0. Plaintext connection attempt to an 
> >SSL enabled server?
> >        at 
> >org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown 
> >Source)
> >        at 
> >org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
> >        at 
> >org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source)
> >The table is defined as:
> >    CREATE TABLE MyTable (FName varchar(300) NOT NULL,FContents 
> >BLOB(16M) NOT NULL)
> > 
> >I do not understand why it only works with small BLOB contents, as 
> >soon as I pass 32750 bytes or so the above happens,
> >when data is 32750 or smaller it works just fine.
> > 
> Hello Mikal.   The error seems related to an SSL enabled server, but it 
> would seem that you would get that error at connection time, not when 
> inserting into the table.  I tried the following program just starting 
> network server normally java org.apache.derby.drda.NetworkServerControl 
> start and it seemed to run ok.  Can you tell me how to modify this 
> program or the way I started the server to reproduce your error?

The client error message "A network protocol error was encountered and 
the connection has been terminated: A PROTOCOL Data Stream Syntax 
Error was detected.  Reason: 0x0. Plaintext connection attempt to an 
SSL enabled server?" will be thrown in 3 possible cases
1) A buggy DRDA data stream was sent from the server
2) A plaintext client tries to connect to an SSL enabled server
3) A plaintext client tries to connect to any other server which does
not talk DRDA.

So that's why the question mark is there. I assume Mikael hits case
#1 and no SSL is involved.

-- 
Bernt Marius Johnsen, Database Technology Group, 
Staff Engineer, Derby/Java DB
Sun Microsystems, Trondheim, Norway

Re: PreparedStatement problem with big BLOBS

Posted by Kathey Marsden <km...@sbcglobal.net>.
Mikael wrote:
> Hi !
>  
> I have a pretty weird problem, I use a Derby 10.3.1.4 with the 
> ClientDriver and I run the code below:
>  
>     // Data is a byte[] vector
>     ByteArrayInputStream is = new ByteArrayInputStream( data);    
>     String sql = "UPDATE MyTable SET FContents=? WHERE FName='" + name 
> + "'";
>     PreparedStatement ps = conn.prepareStatement( sql);
>     ps.setBinaryStream( 1, is, data.length);
>     
>     if( ps.executeUpdate() == 0)
>     {
>         // it throws an exception here if the data array us larger 
> then around 32750 bytes!!!
>     }
>  
> Connection is "jdbc:derby://localhost/mydb;create=true;"
>
> java.sql.SQLException: A network protocol error was encountered and 
> the connection has been terminated: A PROTOCOL Data Stream Syntax 
> Error was detected.  Reason: 0x0. Plaintext connection attempt to an 
> SSL enabled server?
>         at 
> org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown 
> Source)
>         at 
> org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
>         at 
> org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source)
> The table is defined as:
>     CREATE TABLE MyTable (FName varchar(300) NOT NULL,FContents 
> BLOB(16M) NOT NULL)
>  
> I do not understand why it only works with small BLOB contents, as 
> soon as I pass 32750 bytes or so the above happens,
> when data is 32750 or smaller it works just fine.
>  
Hello Mikal.   The error seems related to an SSL enabled server, but it 
would seem that you would get that error at connection time, not when 
inserting into the table.  I tried the following program just starting 
network server normally java org.apache.derby.drda.NetworkServerControl 
start and it seemed to run ok.  Can you tell me how to modify this 
program or the way I started the server to reproduce your error?

Thanks

Kathey



import java.sql.*;
import java.io.*;

public class TestBlob {

    public static void main(String args[]) throws Exception {
    Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();
    Connection conn = 
DriverManager.getConnection("jdbc:derby://localhost:1527/wombat;create=true");
    Statement s = conn.createStatement();
    try {
        s.executeUpdate("drop table MyTable");
    } catch (SQLException se) {}
    s.executeUpdate("create table MyTable (Contents BLOB(2G))");
    s.executeUpdate("insert into MyTable VALUES NULL");
    byte[] data = new byte[40000];
    for (int i = 0; i < 40000; i++)
        data[i] = 'a';
    ByteArrayInputStream is = new ByteArrayInputStream( data);   
    String sql = "UPDATE MyTable SET Contents=?";
    PreparedStatement ps = conn.prepareStatement( sql);
    ps.setBinaryStream( 1, is, data.length);
    ps.executeUpdate();  
    ps.close();
    conn.close();
    }
}



Re: PreparedStatement problem with big BLOBS

Posted by Kathey Marsden <km...@sbcglobal.net>.
Kathey Marsden wrote:
> I was able to reproduce the exception with your reproduction.


Looks like this regressed with revision 438478 of DERBY-1559
http://svn.apache.org/viewvc?view=rev&revision=438478



Re: PreparedStatement problem with big BLOBS

Posted by Kathey Marsden <km...@sbcglobal.net>.
Mikael wrote:
> Here is a modified version of the SimpleApp that comes with Derby, if 
> you run it without any argument (embedded mode) it works just fine, 
> but if you add the argument "derbyclient" to run it in client mode it 
> throws the exception,
Thanks Mikael,

I was able to reproduce the exception with your reproduction.  It also 
reproduced with 10.2, but with a generic protocol message.  The program 
was successful with 10.1 so this is a regression in 10.2.
Could you file an issue and mark it as a regression.

http://db.apache.org/derby/DerbyBugGuidelines.html


Thanks for finding this problem.

Kathey



Re: PreparedStatement problem with big BLOBS

Posted by Mikael <mi...@telia.com>.
Here is a modified version of the SimpleApp that comes with Derby, 
if you run it without any argument (embedded mode) it works just 
fine, but if you add the argument "derbyclient" to run it in client mode 
it throws the exception, the modified code is marked with comments
and look's like this:

   byte[] data = new byte[ 38000];
   ByteArrayInputStream is = new ByteArrayInputStream( data);   
   String sql = "UPDATE testing SET contents=? WHERE num=1";
   PreparedStatement ps = conn.prepareStatement( sql);
   ps.setBinaryStream( 1, is, data.length);
    
   int x = ps.executeUpdate(); // Throws exception here
 
----- Original Message ----- 
From: "Bryan Pendleton" <bp...@amberpoint.com>
To: "Derby Discussion" <de...@db.apache.org>
Sent: Friday, September 21, 2007 6:05 PM
Subject: Re: PreparedStatement problem with big BLOBS


>> I do not understand why it only works with small BLOB contents, as soon 
>> as I pass 32750 bytes or so the above happens,
>> when data is 32750 or smaller it works just fine.
> 
> This sounds like a bug to me. The DRDA client/server protocol
> tends to divide data at 32K boundaries, so it's possible that
> there is a bug in that implementation that you have encountered.
> 
> Can you provide a test program that reproduces this problem?
> 
> thanks,
> 
> bryan
> 
>

Re: PreparedStatement problem with big BLOBS

Posted by Bryan Pendleton <bp...@amberpoint.com>.
> I do not understand why it only works with small BLOB contents, as soon 
> as I pass 32750 bytes or so the above happens,
> when data is 32750 or smaller it works just fine.

This sounds like a bug to me. The DRDA client/server protocol
tends to divide data at 32K boundaries, so it's possible that
there is a bug in that implementation that you have encountered.

Can you provide a test program that reproduces this problem?

thanks,

bryan



Re: PreparedStatement problem with big BLOBS

Posted by Kathey Marsden <km...@sbcglobal.net>.
Kathey Marsden wrote:
> Mikael wrote:
>
>>
>>     ps.setBinaryStream( 1, is, data.length);
> [snip rest of the program]
>
> A workaround seems to be to use ps.setBinaryStream without the length 
> parameter.
> ps.setBinaryStream( 1, is);
>
Sorry, I was wrong about the workaround. Please ignore my last mail.

Kathey



Re: PreparedStatement problem with big BLOBS

Posted by Kathey Marsden <km...@sbcglobal.net>.
Mikael wrote:

>
>     ps.setBinaryStream( 1, is, data.length);
[snip rest of the program]

A workaround seems to be to use ps.setBinaryStream without the length 
parameter.
ps.setBinaryStream( 1, is);

Here is the old error output  at revision 438478 before SSL was added 
which was more helpful: (I don't know if maybe we have an issue with the 
message we are getting with protocol errors in 10.3)

[C:/kmarsden/repro/bigblob] java TestBlob
Exception in thread "main" java.sql.SQLException: Network protocol 
error: end of stream prematurely reached, parameter #
1.  Remaining data has been padded with 0x0.
        at 
org.apache.derby.client.am.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:46)
        at 
org.apache.derby.client.am.SqlException.getSQLException(SqlException.java:345)
        at 
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:389)
        at TestBlob.main(TestBlob.java:28)
Caused by: org.apache.derby.client.am.SqlException: Network protocol 
error: end of stream prematurely reached, parameter
 #1.  Remaining data has been padded with 0x0.
        at 
org.apache.derby.client.net.Request.writePlainScalarStream(Request.java:467)
        at 
org.apache.derby.client.net.Request.writeScalarStream(Request.java:242)
        at 
org.apache.derby.client.net.NetStatementRequest.buildEXTDTA(NetStatementRequest.java:855)
        at 
org.apache.derby.client.net.NetStatementRequest.writeExecute(NetStatementRequest.java:145)
        at 
org.apache.derby.client.net.NetPreparedStatement.writeExecute_(NetPreparedStatement.java:172)
        at 
org.apache.derby.client.am.PreparedStatement.writeExecute(PreparedStatement.java:1557)
        at 
org.apache.derby.client.am.PreparedStatement.flowExecute(PreparedStatement.java:1803)
        at 
org.apache.derby.client.am.PreparedStatement.executeUpdateX(PreparedStatement.java:394)
        at 
org.apache.derby.client.am.PreparedStatement.executeUpdate(PreparedStatement.java:380)
        ... 1 more

This sounds kind of similar to DERBY-2017, but in this case the length 
is actually correct so I think this is a separate issue.

Kathey