package org.mariadb.jdbc; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import java.io.*; import java.sql.*; import java.util.Arrays; import java.util.Random; import static org.junit.Assert.*; public class BlobTest extends BaseTest { /** * Initialisation. * * @throws SQLException exception */ @BeforeClass() public static void initClass() throws SQLException { createTable("bug716378", "id int not null primary key auto_increment, test longblob, test2 blob, test3 text"); createTable("BlobTeststreamtest2", "id int primary key not null, st varchar(20), strm text", "CHARSET utf8"); createTable("BlobTeststreamtest3", "id int primary key not null, strm text", "CHARSET utf8"); createTable("BlobTestclobtest", "id int not null primary key, strm text", "CHARSET utf8"); createTable("BlobTestclobtest2", "strm text", "CHARSET utf8"); createTable("BlobTestclobtest3", "id int not null primary key, strm text", "CHARSET utf8"); createTable("BlobTestclobtest4", "id int not null primary key, strm text", "CHARSET utf8"); createTable("BlobTestclobtest5", "id int not null primary key, strm text", "CHARSET utf8"); createTable("BlobTestblobtest", "id int not null primary key, strm blob"); createTable("BlobTestblobtest2", "id int not null primary key, strm blob"); createTable("conj77_test", "Name VARCHAR(100) NOT NULL,Archive LONGBLOB, PRIMARY KEY (Name)", "Engine=InnoDB DEFAULT CHARSET utf8"); } @Test public void testPosition() throws SQLException { byte[] blobContent = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; byte[] pattern = new byte[]{3, 4}; Blob blob = new MariaDbBlob(blobContent); assertEquals(3, blob.position(pattern, 1)); pattern = new byte[]{12, 13}; assertEquals(-1, blob.position(pattern, 1)); pattern = new byte[]{11, 12}; assertEquals(11, blob.position(pattern, 1)); pattern = new byte[]{1, 2}; assertEquals(1, blob.position(pattern, 1)); } @Test(expected = SQLException.class) public void testBadStart() throws SQLException { byte[] blobContent = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; byte[] pattern = new byte[]{3, 4}; Blob blob = new MariaDbBlob(blobContent); blob.position(pattern, 0); } @Test(expected = SQLException.class) public void testBadStart2() throws SQLException { byte[] blobContent = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; byte[] pattern = new byte[]{3, 4}; Blob blob = new MariaDbBlob(blobContent); blob.position(pattern, 44); } @Test public void testBug716378() throws SQLException { Statement stmt = sharedConnection.createStatement(); stmt.executeUpdate("insert into bug716378 values(null, 'a','b','c')"); ResultSet rs = stmt.executeQuery("select * from bug716378"); assertTrue(rs.next()); byte[] arr = new byte[0]; assertEquals(arr.getClass(), rs.getObject(2).getClass()); assertEquals(arr.getClass(), rs.getObject(3).getClass()); assertEquals(String.class, rs.getObject(4).getClass()); } @Test public void testCharacterStreamWithMultibyteCharacterAndLength() throws Throwable { String toInsert1 = "\u00D8bbcdefgh\njklmn\""; String toInsert2 = "\u00D8abcdefgh\njklmn\""; PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTeststreamtest2 (id, st, strm) values (?,?,?)"); stmt.setInt(1, 2); stmt.setString(2, toInsert1); Reader reader = new StringReader(toInsert2); stmt.setCharacterStream(3, reader, 5); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTeststreamtest2"); rs.next(); Reader rdr = rs.getCharacterStream("strm"); StringBuilder sb = new StringBuilder(); int ch; while ((ch = rdr.read()) != -1) { sb.append((char) ch); } assertEquals(toInsert1, rs.getString(2)); assertEquals(toInsert2.substring(0, 5), sb.toString()); } @Test public void testCharacterStreamWithMultibyteCharacter() throws Throwable { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTeststreamtest3 (id, strm) values (?,?)"); stmt.setInt(1, 2); String toInsert = "\u00D8abcdefgh\njklmn\""; Reader reader = new StringReader(toInsert); stmt.setCharacterStream(2, reader); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTeststreamtest3"); rs.next(); Reader rdr = rs.getCharacterStream("strm"); StringBuilder sb = new StringBuilder(); int ch; while ((ch = rdr.read()) != -1) { sb.append((char) ch); } assertEquals(toInsert, sb.toString()); } @Test public void testReaderWithLength() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestclobtest5 (id, strm) values (?,?)"); byte[] arr = new byte[32000]; Arrays.fill(arr, (byte) 'b'); stmt.setInt(1, 1); String clob = new String(arr); stmt.setCharacterStream(2, new StringReader(clob), 20000); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestclobtest5"); rs.next(); Reader readStuff = rs.getCharacterStream("strm"); char[] chars = new char[50000]; readStuff.read(chars); byte[] arrResult = new byte[20000]; Arrays.fill(arrResult, (byte) 'b'); for (int i = 0; i < chars.length; i++) { if (i < 20000) { assertEquals(arrResult[i], chars[i]); } else { assertEquals(chars[i], '\u0000'); } } } @Test public void testBlobWithLength() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestblobtest2 (id, strm) values (?,?)"); byte[] arr = new byte[32000]; Random rand = new Random(); rand.nextBytes(arr); InputStream stream = new ByteArrayInputStream(arr); stmt.setInt(1, 1); stmt.setBlob(2, stream, 20000); stmt.execute(); //check what stream not read after length: int remainRead = 0; while (stream.read() >= 0) { remainRead++; } assertEquals(12000, remainRead); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestblobtest2"); rs.next(); InputStream readStuff = rs.getBlob("strm").getBinaryStream(); int pos = 0; int ch; while ((ch = readStuff.read()) != -1) { assertEquals(arr[pos++] & 0xff, ch); } assertEquals(20000, pos); } @Test public void testClobWithLengthAndMultibyteCharacter() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestclobtest (id, strm) values (?,?)"); String clob = "\u00D8clob"; stmt.setInt(1, 1); stmt.setClob(2, new StringReader(clob)); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestclobtest"); if (rs.next()) { Reader readStuff = rs.getClob("strm").getCharacterStream(); char[] chars = new char[5]; readStuff.read(chars); assertEquals(new String(chars), clob); } else { fail(); } } @Test public void testClob3() throws Exception { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestclobtest2 (strm) values (?)"); Clob clob = sharedConnection.createClob(); Writer writer = clob.setCharacterStream(1); writer.write("\u00D8hello", 0, 6); writer.flush(); stmt.setClob(1, clob); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestclobtest2"); rs.next(); assertTrue(rs.getObject(1) instanceof String); String result = rs.getString(1); assertEquals("\u00D8hello", result); } @Test public void testBlob() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestblobtest (id, strm) values (?,?)"); byte[] theBlob = {1, 2, 3, 4, 5, 6}; InputStream stream = new ByteArrayInputStream(theBlob); stmt.setInt(1, 1); stmt.setBlob(2, stream); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestblobtest"); rs.next(); InputStream readStuff = rs.getBlob("strm").getBinaryStream(); int ch; int pos = 0; while ((ch = readStuff.read()) != -1) { assertEquals(theBlob[pos++], ch); } readStuff = rs.getBinaryStream("strm"); pos = 0; while ((ch = readStuff.read()) != -1) { assertEquals(theBlob[pos++], ch); } } @Test public void testClobWithLength() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestclobtest3 (id, strm) values (?,?)"); String clob = "clob"; stmt.setInt(1, 1); stmt.setClob(2, new StringReader(clob)); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestclobtest3"); rs.next(); Reader readStuff = rs.getClob("strm").getCharacterStream(); char[] chars = new char[4]; readStuff.read(chars); Assert.assertEquals(new String(chars), clob); } @Test public void testClob2() throws SQLException, IOException { PreparedStatement stmt = sharedConnection.prepareStatement("insert into BlobTestclobtest4 (id, strm) values (?,?)"); Clob clob = sharedConnection.createClob(); OutputStream ostream = clob.setAsciiStream(1); byte[] bytes = "hello".getBytes(); ostream.write(bytes); stmt.setInt(1, 1); stmt.setClob(2, clob); stmt.execute(); ResultSet rs = sharedConnection.createStatement().executeQuery("select * from BlobTestclobtest4"); rs.next(); assertTrue(rs.getObject(2) instanceof String); assertTrue(rs.getString(2).equals("hello")); } @Test public void blobSerialization() throws Exception { Blob blob = new MariaDbBlob(new byte[]{1, 2, 3}); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(blob); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); MariaDbBlob blob2 = (MariaDbBlob) ois.readObject(); byte[] blobBytes = blob2.getBytes(1, (int) blob2.length()); assertEquals(3, blobBytes.length); assertEquals(1, blobBytes[0]); assertEquals(2, blobBytes[1]); assertEquals(3, blobBytes[2]); Clob clob = new MariaDbClob(new byte[]{1, 2, 3}); baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(clob); ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); MariaDbClob c2 = (MariaDbClob) ois.readObject(); blobBytes = c2.getBytes(1, (int) c2.length()); assertEquals(3, blobBytes.length); assertEquals(1, blobBytes[0]); assertEquals(2, blobBytes[1]); assertEquals(3, blobBytes[2]); } @Test public void conj73() throws Exception { /* CONJ-73: Assertion error: UTF8 length calculation reports invalid ut8 characters */ Clob clob = new MariaDbClob(new byte[]{(byte) 0x10, (byte) 0xD0, (byte) 0xA0, (byte) 0xe0, (byte) 0xa1, (byte) 0x8e}); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(clob); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); MariaDbClob c2 = (MariaDbClob) ois.readObject(); assertEquals(3, c2.length()); } @Test public void conj77() throws Exception { try (Statement sta1 = sharedConnection.createStatement()) { try (PreparedStatement pre = sharedConnection.prepareStatement("INSERT INTO conj77_test (Name,Archive) VALUES (?,?)")) { pre.setString(1, "Empty String"); pre.setBytes(2, "".getBytes()); pre.addBatch(); pre.setString(1, "Data Hello"); pre.setBytes(2, "hello".getBytes()); pre.addBatch(); pre.setString(1, "Empty Data null"); pre.setBytes(2, null); pre.addBatch(); pre.executeBatch(); } } try (Statement sta2 = sharedConnection.createStatement()) { try (ResultSet set = sta2.executeQuery("Select name,archive as text FROM conj77_test")) { while (set.next()) { final Blob blob = set.getBlob("text"); if (blob != null) { try (ByteArrayOutputStream bout = new ByteArrayOutputStream((int) blob.length())) { try (InputStream bin = blob.getBinaryStream()) { final byte[] buffer = new byte[1024 * 4]; for (int read = bin.read(buffer); read != -1; read = bin.read(buffer)) { bout.write(buffer, 0, read); } } } } } } } } @Test public void sendEmptyBlobPreparedQuery() throws SQLException { createTable("emptyBlob", "test longblob, test2 text, test3 text"); try (Connection conn = setConnection()) { PreparedStatement ps = conn.prepareStatement("insert into emptyBlob values(?,?,?)"); ps.setBlob(1, new MariaDbBlob(new byte[0])); ps.setString(2, "a 'a "); ps.setNull(3, Types.VARCHAR); ps.executeUpdate(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select * from emptyBlob"); rs.next(); assertEquals(0, rs.getBytes(1).length); assertEquals("a 'a ", rs.getString(2)); assertNull(rs.getBytes(3)); } } }