Description:
If updating a blob field such that the blob will increase in size above the max_allowed_packet (but the update itself is less than max_allowed_packet) the value for the blob will be removed and replaced with a NULL value.
How to repeat:
E.g. Create a table with a blob. Set max_allowed_packet to 1MB. Update the Blob 4 times with byte array size of 512KB. Check blob value in the database. It will be NULL.
I have attached some Java code that demostrates the bug:
------>
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.sql.rowset.serial.SerialBlob;
/*
* Created on Jan 8, 2005
*
*/
/**
* Demonstrates MySQL Blob bug. Assumes max_allowed_packet is
* set to 1MB in the MySQL configuration file.
*
* @author Michael Barker
*
*/
public class MySQLBlobBug
{
public static void main(String[] args) throws Exception
{
int DATA_SIZE = 512 * 1024; // 512KB
String CREATE_TABLE = "CREATE TABLE BLOB_TEST (ID VARCHAR(10) PRIMARY KEY, DATA LONGBLOB)";
String SELECT = "SELECT ID, 'DATA' AS BLOB_DATA FROM BLOB_TEST WHERE ID = ?";
String INSERT = "INSERT INTO BLOB_TEST (ID, DATA) VALUES (?, ?)";
String URL = "jdbc:mysql://localhost/test?emulateLocators=true";
String USER = "root";
// Set this value in order to test.
String PASS = "xxxxxxx";
String DRIVER = "com.mysql.jdbc.Driver";
String ID = "1";
byte[] TEST_DATA = new byte[DATA_SIZE];
for (int i = 0; i < TEST_DATA.length; i++)
{
TEST_DATA[i] = (byte) ((i % 26) + 97);
}
DriverManager.registerDriver((Driver) Class.forName(DRIVER).newInstance());
// Create a table with a blob.
Connection con = DriverManager.getConnection(URL, USER, PASS);
Statement stmt = con.createStatement();
boolean result = stmt.execute(CREATE_TABLE);
stmt.close();
con.close();
// Insert an empty blob.
con = DriverManager.getConnection(URL, USER, PASS);
PreparedStatement ps = con.prepareStatement(INSERT);
ps.setString(1, ID);
ps.setBlob(2, new SerialBlob(new byte[0]));
result = ps.execute();
ps.close();
con.close();
// Write 2MB to the blob
con = DriverManager.getConnection(URL, USER, PASS);
ps = con.prepareStatement(SELECT);
ps.setString(1, ID);
ResultSet rs = ps.executeQuery();
if (rs.next())
{
Blob b = rs.getBlob("BLOB_DATA");
for (int i = 0; i < 4; i++)
{
b.setBytes((i * TEST_DATA.length) + 1, TEST_DATA);
}
}
rs.close();
ps.close();
con.close();
// Read the data from the blob
con = DriverManager.getConnection(URL, USER, PASS);
ps = con.prepareStatement(SELECT);
ps.setString(1, ID);
rs = ps.executeQuery();
if (rs.next())
{
Blob b = rs.getBlob("BLOB_DATA");
// This will result in a null being returned, when it should be
// a valid byte array.
byte[] data = b.getBytes(1, DATA_SIZE);
if (data == null)
{
System.out.println("Result from data base is null, this should be a valid byte array");
}
}
rs.close();
ps.close();
con.close();
}
}
<-------------
Description: If updating a blob field such that the blob will increase in size above the max_allowed_packet (but the update itself is less than max_allowed_packet) the value for the blob will be removed and replaced with a NULL value. How to repeat: E.g. Create a table with a blob. Set max_allowed_packet to 1MB. Update the Blob 4 times with byte array size of 512KB. Check blob value in the database. It will be NULL. I have attached some Java code that demostrates the bug: ------> import java.sql.Blob; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import javax.sql.rowset.serial.SerialBlob; /* * Created on Jan 8, 2005 * */ /** * Demonstrates MySQL Blob bug. Assumes max_allowed_packet is * set to 1MB in the MySQL configuration file. * * @author Michael Barker * */ public class MySQLBlobBug { public static void main(String[] args) throws Exception { int DATA_SIZE = 512 * 1024; // 512KB String CREATE_TABLE = "CREATE TABLE BLOB_TEST (ID VARCHAR(10) PRIMARY KEY, DATA LONGBLOB)"; String SELECT = "SELECT ID, 'DATA' AS BLOB_DATA FROM BLOB_TEST WHERE ID = ?"; String INSERT = "INSERT INTO BLOB_TEST (ID, DATA) VALUES (?, ?)"; String URL = "jdbc:mysql://localhost/test?emulateLocators=true"; String USER = "root"; // Set this value in order to test. String PASS = "xxxxxxx"; String DRIVER = "com.mysql.jdbc.Driver"; String ID = "1"; byte[] TEST_DATA = new byte[DATA_SIZE]; for (int i = 0; i < TEST_DATA.length; i++) { TEST_DATA[i] = (byte) ((i % 26) + 97); } DriverManager.registerDriver((Driver) Class.forName(DRIVER).newInstance()); // Create a table with a blob. Connection con = DriverManager.getConnection(URL, USER, PASS); Statement stmt = con.createStatement(); boolean result = stmt.execute(CREATE_TABLE); stmt.close(); con.close(); // Insert an empty blob. con = DriverManager.getConnection(URL, USER, PASS); PreparedStatement ps = con.prepareStatement(INSERT); ps.setString(1, ID); ps.setBlob(2, new SerialBlob(new byte[0])); result = ps.execute(); ps.close(); con.close(); // Write 2MB to the blob con = DriverManager.getConnection(URL, USER, PASS); ps = con.prepareStatement(SELECT); ps.setString(1, ID); ResultSet rs = ps.executeQuery(); if (rs.next()) { Blob b = rs.getBlob("BLOB_DATA"); for (int i = 0; i < 4; i++) { b.setBytes((i * TEST_DATA.length) + 1, TEST_DATA); } } rs.close(); ps.close(); con.close(); // Read the data from the blob con = DriverManager.getConnection(URL, USER, PASS); ps = con.prepareStatement(SELECT); ps.setString(1, ID); rs = ps.executeQuery(); if (rs.next()) { Blob b = rs.getBlob("BLOB_DATA"); // This will result in a null being returned, when it should be // a valid byte array. byte[] data = b.getBytes(1, DATA_SIZE); if (data == null) { System.out.println("Result from data base is null, this should be a valid byte array"); } } rs.close(); ps.close(); con.close(); } } <-------------