Skip to content

DatabaseMetaData.getIndexInfo() now returns a ResultSet that throws when next() is called after it previously returned false #2758

@labkey-adam

Description

@labkey-adam

Driver version

13.2.0.jre11

SQL Server version

Microsoft SQL Server 2022 (RTM-CU20-GDR) (KB5063814) - 16.0.4210.1 (X64) Jul 11 2025 13:04:02 Copyright (C) 2022 Microsoft Corporation Developer Edition (64-bit) on Windows 10 Pro 10.0 (Build 26100: ) (Hypervisor)

Client Operating System

Microsoft Windows 11

JAVA/JVM version

Eclipse Adoptium OpenJDK 17.0.16+8

Table schema

N/A

Problem description

The ResultSet returned from DatabaseMetaData.getIndexInfo() now throws if rs.next() is called after the ResultSet has been enumerated. No other metadata method we've used (in this driver or any other JDBC driver) returns a ResultSet that exhibits this behavior. This is a behavior change in 13.2.0, possibly related to the rewrite of getIndexInfo() for this version of the driver: #2598

An abbreviated excerpt from our code illustrates the problem. Our metadata retrieval code calls conn.getMetaData().getIndexInfo(...) and passes the returned ResultSet to our standard cached ResultSet implementation, which includes:

while (list.size() < maxRows && rs.next())
   list.add(factory.getRowMap(rs));

boolean isComplete = !rs.next();

(In other scenarios involving paging, the query selects an extra row (e.g., SELECT TOP 101) and this code reliably determines whether maxRows limited the results or not... without unnecessarily handling the extra row.)

If needed, a working example can be provided.

Expected behavior

Calling next() after next() returns false should simply return false.

Actual behavior

Calling next() after next() returns false throws a SQLException: Invalid cursor position

Error message/stack trace

java.sql.SQLException: Invalid cursor position
	at java.sql.rowset/com.sun.rowset.CachedRowSetImpl.next(CachedRowSetImpl.java:1474) ~[java.sql.rowset:?]
	at org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:1166) ~[tomcat-dbcp-10.1.44.jar:10.1.44]
	at org.apache.tomcat.dbcp.dbcp2.DelegatingResultSet.next(DelegatingResultSet.java:1166) ~[tomcat-dbcp-10.1.44.jar:10.1.44]
	at org.labkey.api.data.ResultSetWrapper.next(ResultSetWrapper.java:59) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.LoggingResultSetWrapper.next(LoggingResultSetWrapper.java:47) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.ResultSetImpl.next(ResultSetImpl.java:148) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.ResultSetWrapper.next(ResultSetWrapper.java:59) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.LoggingResultSetWrapper.next(LoggingResultSetWrapper.java:47) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.CachedResultSets.create(CachedResultSets.java:64) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.api.data.CachedResultSets.create(CachedResultSets.java:37) ~[api-25.10-SNAPSHOT.jar:?]
	at org.labkey.query.controllers.QueryController$RawTableMetaDataAction.getView(QueryController.java:1766) ~[query-25.10-SNAPSHOT.jar:?]
	at org.labkey.query.controllers.QueryController$RawTableMetaDataAction.getView(QueryController.java:1681) ~[query-25.10-SNAPSHOT.jar:?]

Any other details that can be helpful

JDBC trace logs

Provide the JDBC driver trace logs. Instructions can be found here: https://docs.microsoft.com/sql/connect/jdbc/tracing-driver-operation

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions