mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-31 13:54:27 +01:00
Merge 'Implement wasNull tracking in ResultSet getter methods' from 김민석
## Summary Implemented comprehensive wasNull tracking and refactored getter methods in JDBC4ResultSet to ensure JDBC specification compliance and improve code maintainability. ### Changes Added wasNull tracking to all getter methods: Covers primitive types, objects, dates/times, streams, and BigDecimal Refactored columnLabel getters to use delegation pattern: Eliminates code duplication and ensures consistent wasNull behavior ### Bug Fixes & Code Quality - Fixed getString(String) to return null instead of empty string for null values - Added @Nullable annotation to getBytes(String) to fix NullAway error - Preserved String parsing in getDate(String) for TEXT-formatted dates - Extracted timezone offset calculation to helper method ### Testing Added comprehensive tests for wasNull tracking, columnLabel getters, stream methods, and null handling Closes #3838
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package tech.turso.jdbc4;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
@@ -32,6 +33,7 @@ import tech.turso.core.TursoResultSet;
|
||||
public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
|
||||
private final TursoResultSet resultSet;
|
||||
private boolean wasNull = false;
|
||||
|
||||
/**
|
||||
* Creates a new JDBC4ResultSet.
|
||||
@@ -54,13 +56,14 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
|
||||
@Override
|
||||
public boolean wasNull() throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return wasNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getString(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -70,6 +73,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public boolean getBoolean(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -79,6 +83,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public byte getByte(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -88,6 +93,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public short getShort(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -97,6 +103,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public int getInt(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -106,6 +113,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public long getLong(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -115,6 +123,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public float getFloat(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -124,6 +133,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
public double getDouble(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -135,6 +145,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Nullable
|
||||
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -147,6 +158,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Nullable
|
||||
public byte[] getBytes(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -157,6 +169,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Nullable
|
||||
public Date getDate(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -177,6 +190,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@SkipNullableCheck
|
||||
public Time getTime(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -197,6 +211,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@SkipNullableCheck
|
||||
public Timestamp getTimestamp(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -216,81 +231,116 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getAsciiStream(int columnIndex) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return wrapTypeConversion(
|
||||
() -> {
|
||||
if (result instanceof String) {
|
||||
return new ByteArrayInputStream(((String) result).getBytes("US-ASCII"));
|
||||
} else if (result instanceof byte[]) {
|
||||
return new ByteArrayInputStream((byte[]) result);
|
||||
}
|
||||
throw new SQLException("Cannot convert to ASCII stream: " + result.getClass());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getUnicodeStream(int columnIndex) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return wrapTypeConversion(
|
||||
() -> {
|
||||
if (result instanceof String) {
|
||||
return new ByteArrayInputStream(((String) result).getBytes("UTF-8"));
|
||||
} else if (result instanceof byte[]) {
|
||||
return new ByteArrayInputStream((byte[]) result);
|
||||
}
|
||||
throw new SQLException("Cannot convert to Unicode stream: " + result.getClass());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getBinaryStream(int columnIndex) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
return wrapTypeConversion(
|
||||
() -> {
|
||||
if (result instanceof byte[]) {
|
||||
return new ByteArrayInputStream((byte[]) result);
|
||||
}
|
||||
throw new SQLException("Cannot convert to binary stream: " + result.getClass());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getString(String columnLabel) throws SQLException {
|
||||
final Object result = this.resultSet.get(columnLabel);
|
||||
if (result == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return wrapTypeConversion(() -> (String) result);
|
||||
return getString(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getBoolean(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getByte(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getShort(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getInt(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getLong(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getFloat(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getDouble(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getBigDecimal(findColumn(columnLabel), scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public byte[] getBytes(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getBytes(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Date getDate(String columnLabel) throws SQLException {
|
||||
final Object result = resultSet.get(columnLabel);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -314,7 +364,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public Time getTime(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getTime(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,19 +376,19 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getAsciiStream(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getAsciiStream(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getUnicodeStream(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getUnicodeStream(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public InputStream getBinaryStream(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getBinaryStream(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -364,13 +414,15 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
|
||||
@Override
|
||||
public Object getObject(int columnIndex) throws SQLException {
|
||||
return resultSet.get(columnIndex);
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SkipNullableCheck
|
||||
public Object getObject(String columnLabel) throws SQLException {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
return getObject(findColumn(columnLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -392,6 +444,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@SkipNullableCheck
|
||||
public Reader getCharacterStream(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -408,6 +461,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
@Nullable
|
||||
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
|
||||
final Object result = resultSet.get(columnIndex);
|
||||
wasNull = result == null;
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -830,15 +884,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
if (date == null || cal == null) {
|
||||
return date;
|
||||
}
|
||||
|
||||
final Calendar localCal = Calendar.getInstance();
|
||||
localCal.setTime(date);
|
||||
|
||||
final long offset =
|
||||
cal.getTimeZone().getOffset(date.getTime())
|
||||
- localCal.getTimeZone().getOffset(date.getTime());
|
||||
|
||||
return new Date(date.getTime() + offset);
|
||||
return new Date(date.getTime() + calculateTimezoneOffset(date.getTime(), cal));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -854,15 +900,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
if (time == null || cal == null) {
|
||||
return time;
|
||||
}
|
||||
|
||||
final Calendar localCal = Calendar.getInstance();
|
||||
localCal.setTime(time);
|
||||
|
||||
final long offset =
|
||||
cal.getTimeZone().getOffset(time.getTime())
|
||||
- localCal.getTimeZone().getOffset(time.getTime());
|
||||
|
||||
return new Time(time.getTime() + offset);
|
||||
return new Time(time.getTime() + calculateTimezoneOffset(time.getTime(), cal));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -878,15 +916,7 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
if (timestamp == null || cal == null) {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
final Calendar localCal = Calendar.getInstance();
|
||||
localCal.setTime(timestamp);
|
||||
|
||||
final long offset =
|
||||
cal.getTimeZone().getOffset(timestamp.getTime())
|
||||
- localCal.getTimeZone().getOffset(timestamp.getTime());
|
||||
|
||||
return new Timestamp(timestamp.getTime() + offset);
|
||||
return new Timestamp(timestamp.getTime() + calculateTimezoneOffset(timestamp.getTime(), cal));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1334,6 +1364,12 @@ public final class JDBC4ResultSet implements ResultSet, ResultSetMetaData {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
private long calculateTimezoneOffset(long timeMillis, Calendar targetCal) {
|
||||
Calendar localCal = Calendar.getInstance();
|
||||
return targetCal.getTimeZone().getOffset(timeMillis)
|
||||
- localCal.getTimeZone().getOffset(timeMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface for result set value suppliers.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@ package tech.turso.jdbc4;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@@ -869,4 +870,285 @@ class JDBC4ResultSetTest {
|
||||
|
||||
assertNotNull(timestamp);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_wasNull() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_was_null (id INTEGER, name TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_was_null VALUES (1, 'test');");
|
||||
stmt.executeUpdate("INSERT INTO test_was_null VALUES (NULL, NULL);");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_was_null");
|
||||
|
||||
// First row - non-null values
|
||||
assertTrue(resultSet.next());
|
||||
int id = resultSet.getInt(1);
|
||||
assertFalse(resultSet.wasNull());
|
||||
String name = resultSet.getString(2);
|
||||
assertFalse(resultSet.wasNull());
|
||||
|
||||
// Second row - null values
|
||||
assertTrue(resultSet.next());
|
||||
int nullInt = resultSet.getInt(1);
|
||||
assertTrue(resultSet.wasNull());
|
||||
assertEquals(0, nullInt);
|
||||
String nullString = resultSet.getString(2);
|
||||
assertTrue(resultSet.wasNull());
|
||||
assertNull(nullString);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_columnLabel_getters() throws Exception {
|
||||
stmt.executeUpdate(
|
||||
"CREATE TABLE test_column_label ("
|
||||
+ "bool_col INTEGER, "
|
||||
+ "byte_col INTEGER, "
|
||||
+ "short_col INTEGER, "
|
||||
+ "int_col INTEGER, "
|
||||
+ "long_col BIGINT, "
|
||||
+ "float_col REAL, "
|
||||
+ "double_col REAL, "
|
||||
+ "bytes_col BLOB);");
|
||||
|
||||
stmt.executeUpdate(
|
||||
"INSERT INTO test_column_label VALUES ("
|
||||
+ "1, 127, 32767, 2147483647, 9223372036854775807, 3.14, 2.718281828, X'48656C6C6F');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_column_label");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
// Test columnLabel-based getters
|
||||
assertTrue(resultSet.getBoolean("bool_col"));
|
||||
assertEquals(127, resultSet.getByte("byte_col"));
|
||||
assertEquals(32767, resultSet.getShort("short_col"));
|
||||
assertEquals(2147483647, resultSet.getInt("int_col"));
|
||||
assertEquals(9223372036854775807L, resultSet.getLong("long_col"));
|
||||
assertEquals(3.14f, resultSet.getFloat("float_col"), 0.001);
|
||||
assertEquals(2.718281828, resultSet.getDouble("double_col"), 0.000001);
|
||||
assertArrayEquals("Hello".getBytes(), resultSet.getBytes("bytes_col"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getObject_with_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_object (id INTEGER, name TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_object VALUES (42, 'test');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_object");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
Object idObj = resultSet.getObject("id");
|
||||
assertEquals(42L, idObj);
|
||||
assertFalse(resultSet.wasNull());
|
||||
|
||||
Object nameObj = resultSet.getObject("name");
|
||||
assertEquals("test", nameObj);
|
||||
assertFalse(resultSet.wasNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBigDecimal_with_scale_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_decimal (amount REAL);");
|
||||
stmt.executeUpdate("INSERT INTO test_decimal VALUES (123.456789);");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_decimal");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
BigDecimal result = resultSet.getBigDecimal("amount", 2);
|
||||
assertEquals(new BigDecimal("123.46"), result); // Should be rounded to 2 decimal places
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getTime_with_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_time (time_col BLOB);");
|
||||
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
byte[] timeBytes = ByteBuffer.allocate(Long.BYTES).putLong(timeMillis).array();
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : timeBytes) {
|
||||
hexString.append(String.format("%02X", b));
|
||||
}
|
||||
stmt.executeUpdate("INSERT INTO test_time VALUES (X'" + hexString + "');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_time");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
Time time = resultSet.getTime("time_col");
|
||||
assertNotNull(time);
|
||||
assertEquals(timeMillis, time.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getAsciiStream() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_ascii (text_col TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_ascii VALUES ('Hello ASCII');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_ascii");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getAsciiStream(1);
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[11];
|
||||
int bytesRead = stream.read(buffer);
|
||||
assertEquals(11, bytesRead);
|
||||
assertEquals("Hello ASCII", new String(buffer, "US-ASCII"));
|
||||
assertFalse(resultSet.wasNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getAsciiStream_with_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_ascii (text_col TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_ascii VALUES ('Test');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_ascii");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getAsciiStream("text_col");
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[4];
|
||||
stream.read(buffer);
|
||||
assertEquals("Test", new String(buffer, "US-ASCII"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBinaryStream() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_binary (binary_col BLOB);");
|
||||
byte[] data = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : data) {
|
||||
hexString.append(String.format("%02X", b));
|
||||
}
|
||||
stmt.executeUpdate("INSERT INTO test_binary VALUES (X'" + hexString + "');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_binary");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getBinaryStream(1);
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[5];
|
||||
int bytesRead = stream.read(buffer);
|
||||
assertEquals(5, bytesRead);
|
||||
assertArrayEquals(data, buffer);
|
||||
assertFalse(resultSet.wasNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getBinaryStream_with_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_binary (data BLOB);");
|
||||
byte[] data = {0x0A, 0x0B, 0x0C};
|
||||
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : data) {
|
||||
hexString.append(String.format("%02X", b));
|
||||
}
|
||||
stmt.executeUpdate("INSERT INTO test_binary VALUES (X'" + hexString + "');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_binary");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getBinaryStream("data");
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[3];
|
||||
stream.read(buffer);
|
||||
assertArrayEquals(data, buffer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getUnicodeStream() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_unicode (text_col TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_unicode VALUES ('Hello minseok');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_unicode");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getUnicodeStream(1);
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead = stream.read(buffer);
|
||||
String result = new String(buffer, 0, bytesRead, "UTF-8");
|
||||
assertEquals("Hello minseok", result);
|
||||
assertFalse(resultSet.wasNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getUnicodeStream_with_columnLabel() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_unicode (text_col TEXT);");
|
||||
stmt.executeUpdate("INSERT INTO test_unicode VALUES ('Unicode 테스트');");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_unicode");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
InputStream stream = resultSet.getUnicodeStream("text_col");
|
||||
assertNotNull(stream);
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead = stream.read(buffer);
|
||||
String result = new String(buffer, 0, bytesRead, "UTF-8");
|
||||
assertEquals("Unicode 테스트", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_stream_methods_return_null_on_null() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_null_stream (text_col TEXT, binary_col BLOB);");
|
||||
stmt.executeUpdate("INSERT INTO test_null_stream VALUES (NULL, NULL);");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_null_stream");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
assertNull(resultSet.getAsciiStream(1));
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
assertNull(resultSet.getUnicodeStream(1));
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
assertNull(resultSet.getBinaryStream(2));
|
||||
assertTrue(resultSet.wasNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_getMetaData_column_count() throws Exception {
|
||||
stmt.executeUpdate("CREATE TABLE test_meta (col1 INTEGER, col2 TEXT, col3 REAL);");
|
||||
stmt.executeUpdate("INSERT INTO test_meta VALUES (1, 'test', 3.14);");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_meta");
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
|
||||
assertEquals(3, metaData.getColumnCount());
|
||||
assertEquals("col1", metaData.getColumnName(1));
|
||||
assertEquals("col2", metaData.getColumnName(2));
|
||||
assertEquals("col3", metaData.getColumnName(3));
|
||||
assertEquals("col1", metaData.getColumnLabel(1));
|
||||
assertEquals(Integer.MAX_VALUE, metaData.getColumnDisplaySize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_wasNull_consistency_across_types() throws Exception {
|
||||
stmt.executeUpdate(
|
||||
"CREATE TABLE test_null_types ("
|
||||
+ "int_col INTEGER, "
|
||||
+ "text_col TEXT, "
|
||||
+ "real_col REAL, "
|
||||
+ "blob_col BLOB);");
|
||||
stmt.executeUpdate("INSERT INTO test_null_types VALUES (NULL, NULL, NULL, NULL);");
|
||||
|
||||
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test_null_types");
|
||||
assertTrue(resultSet.next());
|
||||
|
||||
// Test wasNull for various getter methods
|
||||
resultSet.getInt(1);
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
resultSet.getString(2);
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
resultSet.getDouble(3);
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
resultSet.getBytes(4);
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
resultSet.getObject(1);
|
||||
assertTrue(resultSet.wasNull());
|
||||
|
||||
resultSet.getBigDecimal(3);
|
||||
assertTrue(resultSet.wasNull());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user