Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -342,58 +342,23 @@ public boolean isDefinitelyWritable(int column) throws SQLException {
@Override
public String getColumnClassName(int column) throws SQLException {
getCol(column);
Value sample = sampleValue(column);
if (sample != null) {
return switch (sample) {
case Value.Integer i -> integerClassName(column);
case Value.Float f -> Double.class.getName();
case Value.Text t -> String.class.getName();
case Value.Blob b -> Object.class.getName();
case Value.Null n -> Object.class.getName();
};
}
if (!rows.isEmpty()) {
return Object.class.getName();
}
return switch (getColumnType(column)) {
case Types.TINYINT, Types.SMALLINT, Types.INTEGER -> Integer.class.getName();
case Types.BIGINT -> Long.class.getName();
case Types.FLOAT, Types.REAL, Types.DOUBLE, Types.NUMERIC, Types.DECIMAL -> Double.class.getName();
case Types.CHAR, Types.VARCHAR, Types.CLOB -> String.class.getName();
case Types.BOOLEAN -> Boolean.class.getName();
default -> Object.class.getName();
};
return className(runtimeValue(column));
}

private String integerClassName(int column) {
Value firstNonInteger = null;
boolean outsideIntRange = false;
for (Row row : rows) {
List<Value> values = row.values();
if (values == null || column < 1 || column > values.size()) {
continue;
}
Value value = values.get(column - 1);
if (value instanceof Value.Integer) {
if (!isIntInRange(value)) {
outsideIntRange = true;
}
} else if (value != null
&& !(value instanceof Value.Null)
&& firstNonInteger == null) {
firstNonInteger = value;
}
private static String className(Value value) {
if (value instanceof Value.Integer i) {
long val = i.value();
return val > Integer.MAX_VALUE || val < Integer.MIN_VALUE
? Long.class.getName()
: Integer.class.getName();
}
if (firstNonInteger instanceof Value.Float) {
if (value instanceof Value.Float) {
return Double.class.getName();
}
if (firstNonInteger instanceof Value.Text) {
if (value instanceof Value.Text) {
return String.class.getName();
}
if (firstNonInteger != null) {
return Object.class.getName();
}
return outsideIntRange ? Long.class.getName() : Integer.class.getName();
return Object.class.getName();
}

private String declType(int column) throws SQLException {
Expand Down Expand Up @@ -458,12 +423,6 @@ private static SampleType storageType(Value value) {
return SampleType.NULL;
}

private static boolean isIntInRange(Value value) {
return value instanceof Value.Integer i
&& i.value() >= Integer.MIN_VALUE
&& i.value() <= Integer.MAX_VALUE;
}

private TableInfo resolveTableContext() throws SQLException {
if (!tableContextResolved) {
TableInfo resolved = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,85 @@ void usesDeclaredTypesForEmptyResultSet() throws SQLException {
assertDeclaredTypes(metadata);
}

@Test
void reportsObjectClassNameForEmptyResultSet() throws SQLException {
StmtResult result = new StmtResult(
List.of(
new Col("i", "INTEGER"),
new Col("big", "BIGINT"),
new Col("txt", "TEXT"),
new Col("b", "BLOB"),
new Col("flag", "BOOLEAN"),
new Col("real", "REAL"),
new Col("untyped", null)),
List.of(),
0,
null);
LibsqlResultSet resultSet = new LibsqlResultSet(null, result);
ResultSetMetaData metadata = resultSet.getMetaData();

for (int column = 1; column <= metadata.getColumnCount(); column++) {
assertThat(metadata.getColumnClassName(column))
.as("column %d before the first row", column)
.isEqualTo(Object.class.getName());
}

assertThat(resultSet.next()).isFalse();

for (int column = 1; column <= metadata.getColumnCount(); column++) {
assertThat(metadata.getColumnClassName(column))
.as("column %d after the last row", column)
.isEqualTo(Object.class.getName());
}
}

@Test
void reportsCurrentRowClassNameForMixedTypeColumn() throws SQLException {
StmtResult result = new StmtResult(
List.of(new Col("x", null)),
List.of(new Row(List.of(Value.of(1L))), new Row(List.of(Value.of("a")))),
0,
null);
LibsqlResultSet resultSet = new LibsqlResultSet(null, result);
ResultSetMetaData metadata = resultSet.getMetaData();

assertThat(metadata.getColumnClassName(1))
.as("before the first row")
.isEqualTo(Integer.class.getName());

assertThat(resultSet.next()).isTrue();
assertThat(metadata.getColumnClassName(1))
.as("on the integer row")
.isEqualTo(Integer.class.getName());

assertThat(resultSet.next()).isTrue();
assertThat(metadata.getColumnClassName(1))
.as("on the text row")
.isEqualTo(String.class.getName());

assertThat(resultSet.next()).isFalse();
assertThat(metadata.getColumnClassName(1))
.as("after the last row")
.isEqualTo(Object.class.getName());
}

@Test
void reportsClassNameForCurrentRowOutsideIntRange() throws SQLException {
StmtResult result = new StmtResult(
List.of(new Col("x", null)),
List.of(new Row(List.of(Value.of(1L))), new Row(List.of(Value.of(5_000_000_000L)))),
0,
null);
LibsqlResultSet resultSet = new LibsqlResultSet(null, result);
ResultSetMetaData metadata = resultSet.getMetaData();

assertThat(resultSet.next()).isTrue();
assertThat(metadata.getColumnClassName(1)).isEqualTo(Integer.class.getName());

assertThat(resultSet.next()).isTrue();
assertThat(metadata.getColumnClassName(1)).isEqualTo(Long.class.getName());
}

@Test
void reflectsStorageClassChangesBetweenRows() throws SQLException {
StmtResult result = new StmtResult(
Expand Down
Loading