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 @@ -870,7 +870,15 @@ public boolean isLast() throws SQLException {
@Override public boolean absolute(int row) throws SQLException { throw new SQLException("Forward only"); }
@Override public boolean relative(int rows) throws SQLException { throw new SQLException("Forward only"); }
@Override public boolean previous() throws SQLException { throw new SQLException("Forward only"); }
@Override public void setFetchDirection(int direction) throws SQLException {}
@Override
public void setFetchDirection(int direction) throws SQLException {
if (direction != FETCH_FORWARD && direction != FETCH_REVERSE && direction != FETCH_UNKNOWN) {
throw new SQLException(
"Unknown fetch direction "
+ direction
+ ". Must be one of FETCH_FORWARD, FETCH_REVERSE, or FETCH_UNKNOWN");
}
}
@Override public int getFetchDirection() throws SQLException { return FETCH_FORWARD; }
@Override
public void setFetchSize(int rows) throws SQLException {
Expand Down Expand Up @@ -1170,7 +1178,8 @@ private LocalDateTime dateTimeValue(int columnIndex, String targetType) throws S
case Value.Integer i -> epochMillisToLocalDateTime(i.value(), targetType);
case Value.Float f ->
epochMillisToLocalDateTime(julianDayToEpochMillis(f.value()), targetType);
case Value.Text t -> parseSqliteDateTime(t.value(), targetType);
case Value.Text t ->
t.value().isBlank() ? null : parseSqliteDateTime(t.value(), targetType);
case Value.Blob b -> throw new SQLException("Bad value for type " + targetType);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.github.magnusp.libsql.hrana.codec.StmtResult;
import com.github.magnusp.libsql.hrana.codec.Value;

import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
Expand Down Expand Up @@ -533,7 +534,9 @@ public void clearBatch() throws SQLException {
* Executes the batch and reports one update count per step. The generated keys and the update
* count are rebuilt from the step results, so neither can leak from an earlier execution. The
* update count is the total affected rows across the batch; JDBC leaves {@code getUpdateCount}
* unspecified after a batch, and xerial leaves the previous value in place.
* unspecified after a batch, and xerial leaves the previous value in place. A step that returns
* a result set throws {@link BatchUpdateException} with the counts of the steps up to and
* including it, per {@code java.sql}.
*/
@Override
public int[] executeBatch() throws SQLException {
Expand All @@ -545,8 +548,14 @@ public int[] executeBatch() throws SQLException {
int[] updateCounts = new int[results.size()];
long affectedRows = 0;
for (int i = 0; i < results.size(); i++) {
updateCounts[i] = (int) results.get(i).affectedRowCount();
affectedRows += results.get(i).affectedRowCount();
StmtResult result = results.get(i);
if (result.cols() != null && !result.cols().isEmpty()) {
throw new BatchUpdateException(
"batch entry " + i + ": query returns results",
java.util.Arrays.copyOf(updateCounts, i + 1));
}
updateCounts[i] = (int) result.affectedRowCount();
affectedRows += result.affectedRowCount();
}
synchronized (stateLock) {
updateBatchGeneratedKeys(statements, results);
Expand Down Expand Up @@ -641,7 +650,18 @@ public void setQueryTimeout(int seconds) throws SQLException {
public void setCursorName(String name) throws SQLException {
throw new SQLFeatureNotSupportedException("Cursor names are not supported");
}
@Override public void setFetchDirection(int direction) throws SQLException {}
@Override
public void setFetchDirection(int direction) throws SQLException {
if (direction != ResultSet.FETCH_FORWARD
&& direction != ResultSet.FETCH_REVERSE
&& direction != ResultSet.FETCH_UNKNOWN) {
throw new SQLException(
"Unknown fetch direction "
+ direction
+ ". Must be one of FETCH_FORWARD, FETCH_REVERSE, or FETCH_UNKNOWN");
}
}

@Override public int getFetchDirection() throws SQLException { return ResultSet.FETCH_FORWARD; }
@Override
public void setFetchSize(int rows) throws SQLException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,19 @@
assertDateTimeGetters(rs, epochMillis);
}

@Test
void emptyTextDateAndTimeGettersReturnNull() throws SQLException {
LibsqlResultSet rs = resultSet(new Value.Text(""));
assertThat(rs.next()).isTrue();

assertThat(rs.getDate(1)).isNull();
assertThat(rs.getTime(1)).isNull();
assertThat(rs.getTimestamp(1)).isNull();
assertThat(rs.getObject(1, LocalDate.class)).isNull();
assertThat(rs.getObject(1, LocalTime.class)).isNull();
assertThat(rs.getObject(1, LocalDateTime.class)).isNull();
}

@Test
void integerEpochMillisFeedsEveryDateAndTimeGetter() throws SQLException {
LibsqlResultSet rs = resultSet(new Value.Integer(1_700_000_000_000L));
Expand Down Expand Up @@ -365,8 +378,8 @@
List<UnsupportedCall> calls = List.of(
new UnsupportedCall("getAsciiStream(int)", () -> rs.getAsciiStream(1)),
new UnsupportedCall("getAsciiStream(String)", () -> rs.getAsciiStream("c1")),
new UnsupportedCall("getUnicodeStream(int)", () -> rs.getUnicodeStream(1)),

Check warning on line 381 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Xerial Control (reference probe)

getUnicodeStream(int) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated

Check warning on line 381 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 26)

getUnicodeStream(int) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated

Check warning on line 381 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 25)

getUnicodeStream(int) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated
new UnsupportedCall("getUnicodeStream(String)", () -> rs.getUnicodeStream("c1")),

Check warning on line 382 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Xerial Control (reference probe)

getUnicodeStream(java.lang.String) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated

Check warning on line 382 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 26)

getUnicodeStream(java.lang.String) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated

Check warning on line 382 in libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlResultSetTest.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 25)

getUnicodeStream(java.lang.String) in com.github.magnusp.libsql.jdbc.LibsqlResultSet has been deprecated
new UnsupportedCall("getRef(int)", () -> rs.getRef(1)),
new UnsupportedCall("getRef(String)", () -> rs.getRef("c1")),
new UnsupportedCall("getArray(int)", () -> rs.getArray(1)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.github.magnusp.libsql.hrana.codec.Value;
import org.junit.jupiter.api.Test;

import java.sql.BatchUpdateException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
Expand Down Expand Up @@ -141,19 +142,69 @@ void setCursorNameIsNotSupported() {
.hasMessage("Cursor names are not supported");
}

@Test
void setFetchDirectionAcceptsTheJdbcDirections() throws SQLException {
LibsqlStatement statement = new LibsqlStatement(new RecordingConnection(THREE_ROWS));

statement.setFetchDirection(ResultSet.FETCH_FORWARD);
statement.setFetchDirection(ResultSet.FETCH_REVERSE);
statement.setFetchDirection(ResultSet.FETCH_UNKNOWN);
}

@Test
void setFetchDirectionRejectsAnUnknownDirection() {
LibsqlStatement statement = new LibsqlStatement(new RecordingConnection(THREE_ROWS));

assertThatThrownBy(() -> statement.setFetchDirection(999))
.isInstanceOf(SQLException.class)
.hasMessageContaining("999");
}

@Test
void batchThatReturnsResultsThrowsBatchUpdateException() throws SQLException {
StmtResult select = new StmtResult(
List.of(new Col("value", null)),
List.of(new Row(List.of(Value.ofNull()))),
0,
null);
StmtResult insert = new StmtResult(List.of(), List.of(), 1, 1L);
LibsqlStatement statement =
new LibsqlStatement(new RecordingConnection(THREE_ROWS, List.of(insert, select)));

statement.addBatch("insert into t(value) values (1)");
statement.addBatch("select null");

assertThatThrownBy(statement::executeBatch)
.isInstanceOf(BatchUpdateException.class)
.hasMessageContaining("query returns results")
.satisfies(thrown -> assertThat(((BatchUpdateException) thrown).getUpdateCounts())
.containsExactly(1, 0));
}

private static final class RecordingConnection extends LibsqlConnection {
private final StmtResult result;
private final List<StmtResult> batchResults;
private final List<String> executedSql = new ArrayList<>();

private RecordingConnection(StmtResult result) {
this(result, List.of());
}

private RecordingConnection(StmtResult result, List<StmtResult> batchResults) {
super(null, null);
this.result = result;
this.batchResults = batchResults;
}

@Override
public StmtResult executeStatement(Stmt stmt) {
executedSql.add(stmt.sql());
return result;
}

@Override
public List<StmtResult> executeBatchResults(List<Stmt> statements) {
return batchResults;
}
}
}
Loading