{"record":{"id":"2a85c7018b7d8536","repo":"apache/shardingsphere","slug":"previous","errorCode":null,"errorMessage":"previous","messagePattern":"previous","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java","lineNumber":35,"sourceCode":"\npackage org.apache.shardingsphere.driver.jdbc.unsupported;\n\nimport java.io.Reader;\nimport java.sql.NClob;\nimport java.sql.Ref;\nimport java.sql.RowId;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\nimport java.util.Map;\n\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","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationResultSet.java#L17-L53","documentation":"ShardingSphere driver result sets are forward-only (TYPE_FORWARD_ONLY) merge results, so ResultSet.previous() — moving the cursor backward — is final and throws SQLFeatureNotSupportedException. Streaming merged results from multiple shards cannot be rewound without re-execution, hence the hard restriction.","triggerScenarios":"Calling rs.previous() on a ResultSet returned by a query executed through ShardingSphereDataSource, e.g. implementing a two-pass iteration or a bidirectional paginator directly on the ResultSet.","commonSituations":"Report/paging code that iterates once forward then steps back; generic ResultSet wrappers (exporters, CSV writers) that call previous() to peek; frameworks assuming scroll-insensitive result sets because the underlying MySQL/PostgreSQL driver supports them.","solutions":["Restructure to a single forward pass: read everything you need from each row as rs.next() advances.","Buffer rows into a List<Row> (or Apache Commons DbUtils RowSetDynaClass) and navigate the in-memory copy.","If a scrollable cursor is genuinely required, execute the query on a direct (non-sharded) DataSource or via the ShardingSphere Proxy with a client/driver that materializes rows.","Re-execute the query with different OFFSET/FETCH (LIMIT) instead of scrolling backward for pagination."],"exampleFix":"// before\nwhile (rs.next()) { process(rs); }\nif (rs.previous()) { reprocess(rs); } // throws\n\n// after\nList<OrderRow> rows = new ArrayList<>();\nwhile (rs.next()) { rows.add(mapRow(rs)); }\n// navigate 'rows' backward freely","handlingStrategy":"validation","validationCode":"int type = rs.getType();\nif (type == ResultSet.TYPE_FORWARD_ONLY) {\n    // do not call previous(): stream the rows forward or buffer them\n}","typeGuard":null,"tryCatchPattern":"try {\n    rs.previous();\n} catch (SQLFeatureNotSupportedException e) {\n    // re-fetch or use buffered rows instead of scrolling back\n}","preventionTips":["Check rs.getType() == ResultSet.TYPE_FORWARD_ONLY before any cursor API beyond next().","Default to buffering rows when two-directional navigation is needed.","Test cursor-heavy code against the actual sharded datasource, not a passthrough driver."],"tags":["jdbc","resultset","cursor","forward-only","shardingsphere"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}