{"record":{"id":"ccfb097aeddcc561","repo":"apache/shardingsphere","slug":"isafterlast","errorCode":null,"errorMessage":"isAfterLast","messagePattern":"isAfterLast","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java","lineNumber":45,"sourceCode":"\n/**\n * Unsupported {@code ResultSet} methods.\n */\npublic abstract class AbstractUnsupportedOperationResultSet extends AbstractUnsupportedUpdateOperationResultSet {\n    \n    @Override\n    public final boolean previous() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"previous\");\n    }\n    \n    @Override\n    public final boolean isBeforeFirst() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isBeforeFirst\");\n    }\n    \n    @Override\n    public final boolean isAfterLast() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isAfterLast\");\n    }\n    \n    @Override\n    public final boolean isFirst() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isFirst\");\n    }\n    \n    @Override\n    public final boolean isLast() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isLast\");\n    }\n    \n    @Override\n    public final void beforeFirst() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"beforeFirst\");\n    }\n    \n    @Override","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java#L27-L63","documentation":"isAfterLast() is unsupported on ShardingSphere result sets: the class makes it final and throws SQLFeatureNotSupportedException. A forward-only streaming merge never exposes an 'after last' position to user code — the iteration simply ends when next() returns false — so the driver forbids the probe.","triggerScenarios":"Calling rs.isAfterLast() on a query result from ShardingSphereDataSource, e.g. loop guards like while (!rs.isAfterLast()) instead of while (rs.next()).","commonSituations":"Iteration idioms ported from scroll-insensitive cursors; frameworks that verify iteration completion with position predicates; code generated by tools that emit the JDBC tutorial-style position checks.","solutions":["Use while (rs.next()) as the loop condition; next()==false already means the cursor is past the last row.","Materialize rows into a List if you need arbitrary position checks afterward.","For row counts, issue a separate COUNT query or accumulate a counter during iteration.","Shield third-party callers by handing them a CachedRowSet built from the forward-only result."],"exampleFix":"// before\nwhile (!rs.isAfterLast()) { rs.next(); process(rs); } // throws\n\n// after\nwhile (rs.next()) { process(rs); }","handlingStrategy":"validation","validationCode":"if (rs.getType() == ResultSet.TYPE_FORWARD_ONLY) {\n    // terminate loops with rs.next(), not !rs.isAfterLast()\n}","typeGuard":null,"tryCatchPattern":"try {\n    while (!rs.isAfterLast()) { rs.next(); }\n} catch (SQLFeatureNotSupportedException e) {\n    while (rs.next()) { }\n}","preventionTips":["Always use while (rs.next()) — it is the only supported loop idiom here.","Reject code-review patterns that call isAfterLast/isBeforeFirst in loop conditions.","Buffer rows when end-position knowledge is required."],"tags":["jdbc","resultset","cursor","position-check","iteration"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}