blob: 193beebf8ddd5b655d39fb37b72fcbff6b0c8772 [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab
package org.mariadb.jdbc.integration;
import static org.junit.jupiter.api.Assertions.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.jupiter.api.Test;
import org.mariadb.jdbc.MariaDbClob;
public class ClobTest extends Common {
private final byte[] bytes = "abc£de🙏fgh".getBytes(StandardCharsets.UTF_8);
@Test
public void length() {
MariaDbClob clob = new MariaDbClob(bytes);
assertEquals(11, clob.length());
MariaDbClob clob2 = new MariaDbClob(bytes, 2, 3);
assertEquals(2, clob2.length());
}
@Test
public void getSubString() throws SQLException {
MariaDbClob clob = new MariaDbClob(bytes);
assertEquals("abc£de🙏", clob.getSubString(1, 8));
assertEquals("abc£de🙏fgh", clob.getSubString(1, 21));
assertEquals("abc£de🙏fgh", clob.getSubString(1, (int) clob.length()));
assertEquals("ab", clob.getSubString(1, 2));
assertEquals("🙏", clob.getSubString(7, 2));
MariaDbClob clob2 = new MariaDbClob(bytes, 6, 6);
assertEquals("e🙏f", clob2.getSubString(1, 20));
assertEquals("🙏f", clob2.getSubString(2, 3));
try {
clob2.getSubString(0, 3);
fail("must have thrown exception, min pos is 1");
} catch (SQLException sqle) {
// normal exception
}
}
@Test
public void getCharacterStream() throws SQLException {
MariaDbClob clob = new MariaDbClob(bytes);
assureReaderEqual("abc£de🙏", clob.getCharacterStream(1, 8));
assureReaderEqual("abc£de🙏fgh", clob.getCharacterStream(1, 11));
try {
assureReaderEqual("abc£de🙏fgh", clob.getCharacterStream(1, 20));
fail("must have throw exception, length > to number of characters");
} catch (SQLException sqle) {
// normal error
}
assureReaderEqual("bc£de🙏", clob.getCharacterStream(2, 7));
MariaDbClob clob2 = new MariaDbClob(bytes, 2, 9);
assureReaderEqual("c£de🙏", clob2.getCharacterStream(1, 6));
try {
assureReaderEqual("c£de🙏fg", clob2.getCharacterStream(1, 20));
fail("must have throw exception, length > to number of characters");
} catch (SQLException sqle) {
// normal error
}
assureReaderEqual("de🙏", clob2.getCharacterStream(3, 4));
}
private void assureReaderEqual(String expectedStr, Reader reader) {
try {
char[] expected = expectedStr.toCharArray();
char[] readArr = new char[expected.length];
assertEquals(expected.length, reader.read(readArr));
assertArrayEquals(expected, readArr);
} catch (IOException ioe) {
ioe.printStackTrace();
fail();
}
}
@Test
public void setCharacterStream() throws SQLException, IOException {
final byte[] bytes = "abcde🙏fgh".getBytes(StandardCharsets.UTF_8);
MariaDbClob clob = new MariaDbClob(bytes);
assureReaderEqual("abcde🙏", clob.getCharacterStream(1, 7));
Writer writer = clob.setCharacterStream(2);
writer.write("tuvxyz", 2, 3);
writer.flush();
assertEquals("avxye🙏", clob.getSubString(1, 7));
clob = new MariaDbClob(bytes);
writer = clob.setCharacterStream(2);
writer.write("1234567890lmnopqrstu", 1, 19);
writer.flush();
assertEquals("a234567890lmnopqrstu", clob.getSubString(1, 100));
}
@Test
public void position() {
MariaDbClob clob = new MariaDbClob(bytes);
assertEquals(5, clob.position("de", 2));
assertEquals(5, clob.position((Clob) new MariaDbClob("de".getBytes()), 2));
clob = new MariaDbClob(bytes, 2, 10);
assertEquals(5, clob.position("🙏", 2));
}
@Test
public void setString() throws SQLException {
final byte[] bytes = "abcd£e🙏fgh".getBytes(StandardCharsets.UTF_8);
final MariaDbClob clob = new MariaDbClob(bytes);
assureReaderEqual("abcd£e🙏", clob.getCharacterStream(1, 8));
clob.setString(2, "zuv");
assertEquals("azuv£e🙏", clob.getSubString(1, 8));
clob.setString(9, "zzz");
assertEquals("azuv£e🙏fzzz", clob.getSubString(1, 12));
MariaDbClob clob2 = new MariaDbClob("abcde🙏fgh".getBytes(StandardCharsets.UTF_8), 2, 9);
assureReaderEqual("cde🙏fg", clob2.getCharacterStream(1, 7));
assertEquals("cde🙏fg", clob2.getSubString(1, 7));
clob2.setString(2, "zg");
assertEquals("czg🙏f", clob2.getSubString(1, 6));
clob2.setString(7, "zzz");
assertEquals("czg🙏fgzzz", clob2.getSubString(1, 12));
Common.assertThrowsContains(
SQLException.class, () -> clob2.setString(2, "abcd", 2, -2), "len must be > 0");
clob2.setString(2, "abcd", 2, 2);
assertEquals("ccd🙏f", clob2.getSubString(1, 6));
clob2.setString(2, "opml", 3, 200);
assertEquals("cld🙏f", clob2.getSubString(1, 6));
clob2.setString(5, "අข\uD800\uDFA2");
assertEquals("cld🙏අข\uD800\uDFA2", clob2.getSubString(1, 20));
assertEquals(9, clob2.length());
clob2.setString(6, "ข\uD800\uDFA2");
assertEquals("cld🙏අข\uD800\uDFA2", clob2.getSubString(1, 20));
clob2.setString(7, "\uD800\uDFA2");
assertEquals("cld🙏අข\uD800\uDFA2", clob2.getSubString(1, 20));
clob2.truncate(9);
assertEquals("cld🙏අข\uD800\uDFA2", clob2.getSubString(1, 20));
clob2.truncate(7);
assertEquals("cld🙏අข", clob2.getSubString(1, 20));
clob2.truncate(6);
assertEquals("cld🙏අ", clob2.getSubString(1, 20));
clob2.truncate(5);
assertEquals("cld🙏", clob2.getSubString(1, 20));
clob2.truncate(3);
assertEquals("cld", clob2.getSubString(1, 20));
Common.assertThrowsContains(
SQLException.class, () -> clob.setString(-1, "7"), "position must be >= 0");
Common.assertThrowsContains(
SQLException.class, () -> clob.setString(1, null), "cannot add null string");
Common.assertThrowsContains(
SQLException.class, () -> clob.setString(-1, null, 1, 2), "cannot add null string");
Common.assertThrowsContains(
SQLException.class, () -> clob.setString(0, "dd", -1, 2), "offset must be >= 0");
Common.assertThrowsContains(
SQLException.class, () -> clob.getSubString(-1, 7), "position must be >= 1");
Common.assertThrowsContains(
SQLException.class, () -> clob.getSubString(1, -7), "length must be > 0");
Common.assertThrowsContains(
SQLException.class, () -> clob.setString(-2, "rrr"), "position must be >= 0");
}
@Test
public void setAsciiStream() throws SQLException, IOException {
final byte[] bytes = "abcde🙏fgh".getBytes(StandardCharsets.UTF_8);
MariaDbClob clob = new MariaDbClob(bytes);
assureReaderEqual("abcde🙏", clob.getCharacterStream(1, 7));
OutputStream stream = clob.setAsciiStream(2);
stream.write("tuvxyz".getBytes(), 2, 3);
stream.flush();
assertEquals("avxye🙏", clob.getSubString(1, 7));
clob = new MariaDbClob(bytes);
stream = clob.setAsciiStream(2);
stream.write("1234567890lmnopqrstu".getBytes(), 1, 19);
stream.flush();
assertEquals("a234567890lmnopqrstu", clob.getSubString(1, 100));
MariaDbClob clob2 = new MariaDbClob(bytes);
InputStream stream2 = clob2.getAsciiStream();
byte[] b = new byte[12];
stream2.read(b);
assertArrayEquals(bytes, b);
}
@Test
public void wrongUtf8() {
final byte[] utf8Wrong2bytes = new byte[] {0x08, (byte) 0xFF, (byte) 0x6F, (byte) 0x6F};
final byte[] utf8Wrong3bytes =
new byte[] {0x07, (byte) 0x0a, (byte) 0xff, (byte) 0x6F, (byte) 0x6F};
final byte[] utf8Wrong4bytes =
new byte[] {0x10, (byte) 0x20, (byte) 0x0a, (byte) 0xff, (byte) 0x6F, (byte) 0x6F};
final byte[] utf8Wrong4bytes2 = new byte[] {-16, (byte) -97, (byte) -103};
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong2bytes).length(),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(new byte[] {(byte) 225}).length(),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong3bytes).length(),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong4bytes).length(),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(new byte[] {(byte) 225}).truncate(2),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong2bytes).truncate(2),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong3bytes).truncate(3),
"invalid UTF8");
Common.assertThrowsContains(
UncheckedIOException.class,
() -> new MariaDbClob(utf8Wrong4bytes2).truncate(4),
"invalid UTF8");
}
@Test
public void setBinaryStream() throws SQLException, IOException {
final byte[] otherBytes = new byte[] {10, 11, 12, 13};
MariaDbClob blob = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5});
OutputStream out = blob.setBinaryStream(2);
out.write(otherBytes);
assertArrayEquals(new byte[] {0, 10, 11, 12, 13, 5}, blob.getBytes(1, 6));
MariaDbClob blob2 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5});
OutputStream out2 = blob2.setBinaryStream(4);
out2.write(otherBytes);
assertArrayEquals(new byte[] {0, 1, 2, 10, 11, 12, 13}, blob2.getBytes(1, 7));
MariaDbClob blob3 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 3);
OutputStream out3 = blob3.setBinaryStream(2);
out3.write(otherBytes);
assertArrayEquals(new byte[] {2, 10, 11, 12, 13, 0, 0}, blob3.getBytes(1, 7));
MariaDbClob blob4 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 3);
OutputStream out4 = blob4.setBinaryStream(4);
out4.write(otherBytes);
assertArrayEquals(new byte[] {2, 3, 4, 10, 11, 12}, blob4.getBytes(1, 6));
try {
MariaDbClob blob5 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 3);
blob5.setBinaryStream(0);
} catch (SQLException sqle) {
// normal exception
}
}
@Test
public void setBinaryStreamOffset() throws SQLException, IOException {
final byte[] otherBytes = new byte[] {10, 11, 12, 13};
MariaDbClob blob = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5});
OutputStream out = blob.setBinaryStream(2);
out.write(otherBytes, 2, 3);
assertArrayEquals(new byte[] {0, 12, 13, 3, 4, 5}, blob.getBytes(1, 6));
MariaDbClob blob2 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5});
OutputStream out2 = blob2.setBinaryStream(4);
out2.write(otherBytes, 3, 2);
assertArrayEquals(new byte[] {0, 1, 2, 13, 4, 5, 0}, blob2.getBytes(1, 7));
MariaDbClob blob3 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 4);
OutputStream out3 = blob3.setBinaryStream(2);
out3.write(otherBytes, 2, 3);
assertArrayEquals(new byte[] {2, 12, 13, 5, 0, 0, 0}, blob3.getBytes(1, 7));
MariaDbClob blob4 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 3);
OutputStream out4 = blob4.setBinaryStream(4);
out4.write(otherBytes, 2, 2);
assertArrayEquals(new byte[] {2, 3, 4, 12, 13, 0}, blob4.getBytes(1, 6));
MariaDbClob blob5 = new MariaDbClob(new byte[] {0, 1, 2, 3, 4, 5}, 2, 3);
OutputStream out5 = blob5.setBinaryStream(4);
out5.write(otherBytes, 2, 20);
assertArrayEquals(new byte[] {2, 3, 4, 12, 13, 0}, blob5.getBytes(1, 6));
}
@Test
public void truncate() throws SQLException {
MariaDbClob clob = new MariaDbClob(bytes);
clob.truncate(20);
assertEquals("abc£de🙏f", clob.getSubString(1, 9));
clob.truncate(8);
assertEquals("abc£de🙏", clob.getSubString(1, 9));
assertEquals("abc£de🙏", clob.getSubString(1, 8));
clob.truncate(7);
assertEquals("abc£de�", clob.getSubString(1, 9));
clob.truncate(6);
assertEquals("abc£de", clob.getSubString(1, 9));
clob.truncate(4);
assertEquals("abc£", clob.getSubString(1, 8));
clob.truncate(3);
assertEquals("abc", clob.getSubString(1, 8));
clob.truncate(0);
assertEquals("", clob.getSubString(1, 8));
MariaDbClob clob2 = new MariaDbClob("abc£de🙏fgh".getBytes(StandardCharsets.UTF_8), 2, 10);
clob2.truncate(20);
assertEquals("c£de🙏f", clob2.getSubString(1, 9));
clob2.truncate(6);
assertEquals("c£de🙏", clob2.getSubString(1, 9));
clob2.truncate(5);
assertEquals("c£de�", clob2.getSubString(1, 9));
clob2.truncate(4);
assertEquals("c£de", clob2.getSubString(1, 9));
clob2.truncate(0);
assertEquals("", clob2.getSubString(1, 7));
}
@Test
public void free() {
MariaDbClob blob = new MariaDbClob(bytes);
blob.free();
assertEquals(0, blob.length());
}
@Test
@SuppressWarnings("checkstyle:AvoidEscapedUnicodeCharacters")
public void clobLength() throws Exception {
Statement stmt = sharedConn.createStatement();
try (ResultSet rs =
stmt.executeQuery("SELECT 'ab$c', 'ab¢c', 'abहc', 'ab\uD801\uDC37c', 'ab𐍈c' from dual")) {
while (rs.next()) {
Clob clob1 = rs.getClob(1);
assertEquals(4, clob1.length());
Clob clob2 = rs.getClob(2);
assertEquals(4, clob2.length());
Clob clob3 = rs.getClob(3);
assertEquals(4, clob3.length());
Clob clob4 = rs.getClob(4);
assertEquals(5, clob4.length());
Clob clob5 = rs.getClob(5);
assertEquals(5, clob5.length());
clob1.truncate(3);
clob2.truncate(3);
clob3.truncate(3);
clob4.truncate(3);
clob5.truncate(3);
assertEquals(3, clob1.length());
assertEquals(3, clob2.length());
assertEquals(3, clob3.length());
assertEquals(3, clob4.length());
assertEquals(3, clob5.length());
assertEquals("ab$", clob1.getSubString(1, 3));
assertEquals("ab¢", clob2.getSubString(1, 3));
assertEquals("abह", clob3.getSubString(1, 3));
assertEquals("ab�", clob4.getSubString(1, 3));
assertEquals("ab�", clob5.getSubString(1, 3));
}
}
}
@Test
public void equal() {
MariaDbClob clob = new MariaDbClob(bytes);
assertEquals(clob, clob);
assertEquals(new MariaDbClob(bytes), clob);
assertFalse(clob.equals(null));
assertFalse(clob.equals(""));
byte[] bytes = "Abc£de🙏fgh".getBytes(StandardCharsets.UTF_8);
assertNotEquals(new MariaDbClob(bytes), clob);
assertNotEquals(new MariaDbClob("Abc".getBytes(StandardCharsets.UTF_8)), clob);
}
}