/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. The MySQL Connector/J is licensed under the terms of the GPLv2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors. There are special exceptions to the terms and conditions of the GPLv2 as it is applied to this software, see the FLOSS License Exception <http://www.mysql.com/about/legal/licensing/foss-exception.html>. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package testsuite.regression; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.StringReader; import java.sql.Blob; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import testsuite.BaseTestCase; /** * Tests fixes for BLOB handling. * * @author Mark Matthews * @version $Id: BlobRegressionTest.java,v 1.1.2.19 2005/03/09 18:16:16 * mmatthews Exp $ */ public class BlobRegressionTest extends BaseTestCase { /** * Creates a new BlobRegressionTest. * * @param name * name of the test to run */ public BlobRegressionTest(String name) { super(name); } /** * Runs all test cases in this test suite * * @param args */ public static void main(String[] args) { junit.textui.TestRunner.run(BlobRegressionTest.class); } /** * * * @throws Exception * ... */ public void testBug2670() throws Exception { if (!isRunningOnJdk131()) { byte[] blobData = new byte[32]; for (int i = 0; i < blobData.length; i++) { blobData[i] = 1; } createTable("testBug2670", "(blobField LONGBLOB)"); PreparedStatement pStmt = this.conn .prepareStatement("INSERT INTO testBug2670 (blobField) VALUES (?)"); pStmt.setBytes(1, blobData); pStmt.executeUpdate(); this.rs = this.stmt .executeQuery("SELECT blobField FROM testBug2670"); this.rs.next(); Blob blob = this.rs.getBlob(1); // // Test mid-point insertion // blob.setBytes(4, new byte[] { 2, 2, 2, 2 }); byte[] newBlobData = blob.getBytes(1L, (int) blob.length()); assertTrue("Blob changed length", blob.length() == blobData.length); assertTrue("New data inserted wrongly", ((newBlobData[3] == 2) && (newBlobData[4] == 2) && (newBlobData[5] == 2) && (newBlobData[6] == 2))); // // Test end-point insertion // blob.setBytes(32, new byte[] { 2, 2, 2, 2 }); assertTrue("Blob length should be 3 larger", blob.length() == (blobData.length + 3)); } } /** * * http://bugs.mysql.com/bug.php?id=22891 * * @throws Exception * ... */ public void testUpdateLongBlobGT16M() throws Exception { if (versionMeetsMinimum(4, 0)) { byte[] blobData = new byte[18 * 1024 * 1024]; // 18M blob createTable("testUpdateLongBlob", "(blobField LONGBLOB)"); this.stmt .executeUpdate("INSERT INTO testUpdateLongBlob (blobField) VALUES (NULL)"); this.pstmt = this.conn .prepareStatement("UPDATE testUpdateLongBlob SET blobField=?"); this.pstmt.setBytes(1, blobData); try { this.pstmt.executeUpdate(); } catch (SQLException sqlEx) { if (sqlEx.getMessage().indexOf("max_allowed_packet") != -1) { fail("You need to increase max_allowed_packet to at least 18M before running this test!"); } } } } /** * * @throws Exception */ public void testUpdatableBlobsWithCharsets() throws Exception { byte[] smallBlob = new byte[32]; for (byte i = 0; i < smallBlob.length; i++) { smallBlob[i] = i; } createTable("testUpdatableBlobsWithCharsets", "(pk INT NOT NULL PRIMARY KEY, field1 BLOB)"); this.pstmt = this.conn .prepareStatement("INSERT INTO testUpdatableBlobsWithCharsets (pk, field1) VALUES (1, ?)"); this.pstmt.setBinaryStream(1, new ByteArrayInputStream(smallBlob), smallBlob.length); this.pstmt.executeUpdate(); Statement updStmt = this.conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); this.rs = updStmt .executeQuery("SELECT pk, field1 FROM testUpdatableBlobsWithCharsets"); System.out.println(this.rs); this.rs.next(); for (byte i = 0; i < smallBlob.length; i++) { smallBlob[i] = (byte) (i + 32); } this.rs.updateBinaryStream(2, new ByteArrayInputStream(smallBlob), smallBlob.length); this.rs.updateRow(); ResultSet newRs = this.stmt .executeQuery("SELECT field1 FROM testUpdatableBlobsWithCharsets"); newRs.next(); byte[] updatedBlob = newRs.getBytes(1); for (byte i = 0; i < smallBlob.length; i++) { byte origValue = smallBlob[i]; byte newValue = updatedBlob[i]; assertTrue("Original byte at position " + i + ", " + origValue + " != new value, " + newValue, origValue == newValue); } } public void testBug5490() throws Exception { createTable("testBug5490", "(pk INT NOT NULL PRIMARY KEY, blobField BLOB)"); String sql = "insert into testBug5490 values(?,?)"; int blobFileSize = 871; File blobFile = newTempBinaryFile("Bug5490", blobFileSize); this.pstmt = this.conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); this.pstmt.setInt(1, 2); FileInputStream fis = new FileInputStream(blobFile); this.pstmt.setBinaryStream(2, fis, blobFileSize); this.pstmt.execute(); fis.close(); this.pstmt.close(); this.rs = this.stmt.executeQuery("SELECT blobField FROM testBug5490"); this.rs.next(); byte[] returned = this.rs.getBytes(1); assertEquals(blobFileSize, returned.length); } /** * Tests BUG#8096 where emulated locators corrupt binary data when using * server-side prepared statements. * * @throws Exception * if the test fails. */ public void testBug8096() throws Exception { if (!isRunningOnJdk131()) { int dataSize = 256; Properties props = new Properties(); props.setProperty("emulateLocators", "true"); Connection locatorConn = getConnectionWithProps(props); String select = "SELECT ID, 'DATA' AS BLOB_DATA FROM testBug8096 " + "WHERE ID = ?"; String insert = "INSERT INTO testBug8096 (ID, DATA) VALUES (?, '')"; String id = "1"; byte[] testData = new byte[dataSize]; for (int i = 0; i < testData.length; i++) { testData[i] = (byte) i; } createTable("testBug8096", "(ID VARCHAR(10) PRIMARY KEY, DATA LONGBLOB)"); this.pstmt = locatorConn.prepareStatement(insert); this.pstmt.setString(1, id); this.pstmt.execute(); this.pstmt = locatorConn.prepareStatement(select); this.pstmt.setString(1, id); this.rs = this.pstmt.executeQuery(); if (this.rs.next()) { Blob b = rs.getBlob("BLOB_DATA"); b.setBytes(1, testData); } this.rs.close(); this.pstmt.close(); this.pstmt = locatorConn.prepareStatement(select); this.pstmt.setString(1, id); this.rs = this.pstmt.executeQuery(); byte[] result = null; if (this.rs.next()) { Blob b = this.rs.getBlob("BLOB_DATA"); result = b.getBytes(1, dataSize - 1); } this.rs.close(); this.pstmt.close(); assertNotNull(result); for (int i = 0; i < result.length && i < testData.length; i++) { // Will print out all of the values that don't match. // All negative values will instead be replaced with 63. if (result[i] != testData[i]) { assertEquals("At position " + i, testData[i], result[i]); } } } } /** * Tests fix for BUG#9040 - PreparedStatement.addBatch() doesn't work with * server-side prepared statements and streaming BINARY data. * * @throws Exception * if the test fails. */ public void testBug9040() throws Exception { createTable("testBug9040", "(primary_key int not null primary key, data mediumblob)"); this.pstmt = this.conn .prepareStatement("replace into testBug9040 (primary_key, data) values(?,?)"); int primaryKey = 1; byte[] data = "First Row".getBytes(); this.pstmt.setInt(1, primaryKey); this.pstmt.setBinaryStream(2, new ByteArrayInputStream(data), data.length); this.pstmt.addBatch(); primaryKey = 2; data = "Second Row".getBytes(); this.pstmt.setInt(1, primaryKey); this.pstmt.setBinaryStream(2, new ByteArrayInputStream(data), data.length); this.pstmt.addBatch(); this.pstmt.executeBatch(); } public void testBug10850() throws Exception { String tableName = "testBug10850"; createTable(tableName, "(field1 TEXT)"); this.pstmt = this.conn.prepareStatement("INSERT INTO " + tableName + " VALUES (?)"); this.pstmt.setCharacterStream(1, new StringReader(""), 0); this.pstmt.executeUpdate(); assertEquals( "0", getSingleIndexedValueWithQuery(1, "SELECT LENGTH(field1) FROM " + tableName).toString()); this.stmt.executeUpdate("TRUNCATE TABLE " + tableName); this.pstmt.clearParameters(); this.pstmt.setBinaryStream(1, new ByteArrayInputStream(new byte[0]), 0); this.pstmt.executeUpdate(); assertEquals( "0", getSingleIndexedValueWithQuery(1, "SELECT LENGTH(field1) FROM " + tableName).toString()); this.stmt.executeUpdate("TRUNCATE TABLE " + tableName); } public void testBug34677() throws Exception { createTable("testBug34677", "(field1 BLOB)"); this.stmt.executeUpdate("INSERT INTO testBug34677 VALUES ('abc')"); this.rs = this.stmt.executeQuery("SELECT field1 FROM testBug34677"); this.rs.next(); Blob blob = this.rs.getBlob(1); blob.truncate(0L); assertEquals(0, blob.length()); assertEquals(-1, blob.getBinaryStream().read()); } }