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 @@ -19,8 +19,9 @@

public class LibsqlResultSetMetaData implements ResultSetMetaData {

private static final Pattern COLUMN_TYPENAME = Pattern.compile("([^\\(]*)");
private static final Pattern COLUMN_TYPECAST =
Pattern.compile("(?i)cast\\(.*?\\s+as\\s+(.*?)\\s*\\)");
Pattern.compile("cast\\(.*?\\s+as\\s+(.*?)\\s*\\)");
private static final Pattern COLUMN_PRECISION = Pattern.compile(".*?\\((.*?)\\)");

private final List<Col> cols;
Expand Down Expand Up @@ -119,18 +120,8 @@ public int isNullable(int column) throws SQLException {

@Override
public boolean isSigned(int column) throws SQLException {
return switch (getColumnType(column)) {
case Types.TINYINT,
Types.SMALLINT,
Types.INTEGER,
Types.BIGINT,
Types.NUMERIC,
Types.DECIMAL,
Types.REAL,
Types.FLOAT,
Types.DOUBLE -> true;
default -> false;
};
String typeName = getColumnTypeName(column);
return "NUMERIC".equals(typeName) || "INTEGER".equals(typeName) || "REAL".equals(typeName);
}

@Override
Expand Down Expand Up @@ -163,14 +154,7 @@ public int getPrecision(int column) throws SQLException {
return 0;
}
Matcher matcher = COLUMN_PRECISION.matcher(declType);
if (!matcher.find()) {
return 0;
}
try {
return Integer.parseInt(matcher.group(1).split(",")[0].trim());
} catch (NumberFormatException e) {
return 0;
}
return matcher.find() ? Integer.parseInt(matcher.group(1).split(",")[0].trim()) : 0;
}

@Override
Expand All @@ -183,11 +167,7 @@ public int getScale(int column) throws SQLException {
if (matcher.find()) {
String[] parts = matcher.group(1).split(",");
if (parts.length == 2) {
try {
return Integer.parseInt(parts[1].trim());
} catch (NumberFormatException e) {
return 0;
}
return Integer.parseInt(parts[1].trim());
}
}
return 0;
Expand Down Expand Up @@ -302,13 +282,9 @@ public String getColumnTypeName(int column) throws SQLException {
getCol(column);
String declType = declType(column);
if (declType != null) {
int paren = declType.indexOf('(');
String name = (paren >= 0 ? declType.substring(0, paren) : declType)
.trim()
.toUpperCase(Locale.ENGLISH);
if (!name.isEmpty()) {
return name;
}
Matcher matcher = COLUMN_TYPENAME.matcher(declType);
matcher.find();
return matcher.group(1).toUpperCase(Locale.ENGLISH);
}
return switch (sampleType(column)) {
case INTEGER -> "INTEGER";
Expand Down Expand Up @@ -362,17 +338,14 @@ private static String className(Value value) {
private String declType(int column) throws SQLException {
Col col = getCol(column);
String declType = col.decltype();
if (declType != null && !declType.isBlank()) {
return declType;
}
String name = col.name();
if (name != null) {
Matcher matcher = COLUMN_TYPECAST.matcher(name);
if (matcher.find()) {
return matcher.group(1);
if (declType == null) {
String name = col.name();
if (name != null) {
Matcher matcher = COLUMN_TYPECAST.matcher(name);
declType = matcher.find() ? matcher.group(1) : null;
}
}
return null;
return declType;
}

private String columnName(int column) throws SQLException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class LibsqlResultSetMetaDataTest {

Expand Down Expand Up @@ -210,6 +211,87 @@ void usesDeclaredTypesForEmptyResultSet() throws SQLException {
assertDeclaredTypes(metadata);
}

@Test
void isSignedMatchesXerialNarrowTypeNameSet() throws SQLException {
LibsqlResultSetMetaData metadata = new LibsqlResultSetMetaData(
List.of(
new Col("bi", "BIGINT"),
new Col("sm", "SMALLINT"),
new Col("dec", "DECIMAL(10,5)"),
new Col("f", "FLOAT"),
new Col("d", "DOUBLE"),
new Col("num", "NUMERIC"),
new Col("i", "INTEGER"),
new Col("r", "REAL")),
List.of(),
"SELECT 1",
null);

assertThat(metadata.isSigned(1)).as("BIGINT").isFalse();
assertThat(metadata.isSigned(2)).as("SMALLINT").isFalse();
assertThat(metadata.isSigned(3)).as("DECIMAL(10,5)").isFalse();
assertThat(metadata.isSigned(4)).as("FLOAT").isFalse();
assertThat(metadata.isSigned(5)).as("DOUBLE").isFalse();
assertThat(metadata.isSigned(6)).as("NUMERIC").isTrue();
assertThat(metadata.isSigned(7)).as("INTEGER").isTrue();
assertThat(metadata.isSigned(8)).as("REAL").isTrue();
}

@Test
void matchesCastOnlyInLowerCase() throws SQLException {
LibsqlResultSetMetaData metadata = new LibsqlResultSetMetaData(
List.of(new Col("CAST(1 AS BOOLEAN)", null), new Col("cast(1 as BOOLEAN)", null)),
List.of(new Row(List.of(Value.of(1L), Value.of(1L)))),
"SELECT CAST(1 AS BOOLEAN), cast(1 as BOOLEAN)",
null);

assertThat(metadata.getColumnTypeName(1)).as("uppercase CAST").isEqualTo("INTEGER");
assertThat(metadata.getColumnType(1)).as("uppercase CAST").isEqualTo(Types.INTEGER);
assertThat(metadata.isSigned(1)).as("uppercase CAST").isTrue();

assertThat(metadata.getColumnTypeName(2)).as("lowercase cast").isEqualTo("BOOLEAN");
assertThat(metadata.getColumnType(2)).as("lowercase cast").isEqualTo(Types.BOOLEAN);
assertThat(metadata.isSigned(2)).as("lowercase cast").isFalse();
}

@Test
void preservesWhitespaceInDeclaredTypeNames() throws SQLException {
LibsqlResultSetMetaData metadata = new LibsqlResultSetMetaData(
List.of(new Col("c", "BIG INT"), new Col("g", " NUMERIC ")),
List.of(new Row(List.of(Value.of(1L), Value.of(1L)))),
"SELECT c, g FROM q",
null);

assertThat(metadata.getColumnTypeName(1)).isEqualTo("BIG INT");
assertThat(metadata.getColumnType(1)).isEqualTo(Types.INTEGER);
assertThat(metadata.isSigned(1)).isFalse();

assertThat(metadata.getColumnTypeName(2)).isEqualTo(" NUMERIC ");
assertThat(metadata.getColumnType(2)).isEqualTo(Types.INTEGER);
assertThat(metadata.isSigned(2)).isFalse();
}

@Test
void throwsNumberFormatExceptionForMalformedPrecision() throws SQLException {
LibsqlResultSetMetaData metadata = new LibsqlResultSetMetaData(
List.of(new Col("e", "DECIMAL(abc)")), List.of(), "SELECT e FROM q", null);

assertThat(metadata.getColumnTypeName(1)).isEqualTo("DECIMAL");
assertThatThrownBy(() -> metadata.getPrecision(1))
.isInstanceOf(NumberFormatException.class)
.hasMessageContaining("abc");
assertThat(metadata.getScale(1)).isZero();
}

@Test
void reportsPrecisionAndScaleFromParenthesizedType() throws SQLException {
LibsqlResultSetMetaData metadata = new LibsqlResultSetMetaData(
List.of(new Col("d", "DECIMAL(10,5)")), List.of(), "SELECT d FROM m", null);

assertThat(metadata.getPrecision(1)).isEqualTo(10);
assertThat(metadata.getScale(1)).isEqualTo(5);
}

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