{"record":{"id":"02410cbf6bed5213","repo":"tursodatabase/turso","slug":"turso-only-supports-close-cursors-at-commit","errorCode":null,"errorMessage":"turso only supports CLOSE_CURSORS_AT_COMMIT","messagePattern":"turso only supports CLOSE_CURSORS_AT_COMMIT","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"warning","filePath":"bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java","lineNumber":180,"sourceCode":"\n  @Override\n  public void setTypeMap(Map<String, Class<?>> map) throws SQLException {\n    synchronized (this) {\n      this.typeMap = map;\n    }\n  }\n\n  @Override\n  public int getHoldability() throws SQLException {\n    connection.checkOpen();\n    return ResultSet.CLOSE_CURSORS_AT_COMMIT;\n  }\n\n  @Override\n  public void setHoldability(int holdability) throws SQLException {\n    connection.checkOpen();\n    if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {\n      throw new SQLException(\"turso only supports CLOSE_CURSORS_AT_COMMIT\");\n    }\n  }\n\n  @Override\n  @SkipNullableCheck\n  public Savepoint setSavepoint() throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n\n  @Override\n  @SkipNullableCheck\n  public Savepoint setSavepoint(String name) throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");\n  }\n\n  @Override\n  public void rollback(Savepoint savepoint) throws SQLException {\n    throw new SQLFeatureNotSupportedException(\"Savepoints are not supported by Turso\");","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/java/src/main/java/tech/turso/jdbc4/JDBC4Connection.java#L162-L198","documentation":"The Turso JDBC connection only supports ResultSet.CLOSE_CURSORS_AT_COMMIT holdability, mirroring SQLite semantics where cursors are not held open across commits. setHoldability throws a plain SQLException for any other value, including HOLD_CURSORS_OVER_COMMIT, which is ironically the JDBC specification default.","triggerScenarios":"conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); connection pools that apply a configured defaultHoldability (DBCP2, commons-dbcp); frameworks or app servers that set holdability during connection setup; ported code that assumes the JDBC default holdability is accepted.","commonSituations":"Migrating an app from PostgreSQL/MySQL drivers where holdable cursors work; DBCP2 basicDataSource.setDefaultHoldability(...) left at a non-default; libraries like JasperReports or reporting tools that explicitly request holdable cursors to keep result sets across commits.","solutions":["Remove the setHoldability call entirely; the driver's default is already CLOSE_CURSORS_AT_COMMIT.","If holdability must be set, pass exactly ResultSet.CLOSE_CURSORS_AT_COMMIT.","Set the pool's defaultHoldability to CLOSE_CURSORS_AT_COMMIT (or remove the pool property) so the pool never applies the JDBC default on its behalf.","Refactor code that relies on reading a ResultSet after commit; consume result sets before committing."],"exampleFix":"// before\nconn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); // throws\n\n// after\n// Option 1: do not call setHoldability at all (default is already correct).\n// Option 2: if forced, use the only supported value:\nconn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);","handlingStrategy":"validation","validationCode":"if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {\n    holdability = ResultSet.CLOSE_CURSORS_AT_COMMIT; // or reject with a clear config error\n}\nconn.setHoldability(holdability);","typeGuard":"private static boolean isSupportedHoldability(int holdability) {\n    return holdability == ResultSet.CLOSE_CURSORS_AT_COMMIT;\n}","tryCatchPattern":"try {\n    conn.setHoldability(requested);\n} catch (SQLException e) {\n    // driver only supports CLOSE_CURSORS_AT_COMMIT; fall back to the default\n    LOG.info(\"holdability {} not supported; using CLOSE_CURSORS_AT_COMMIT\", requested);\n}","preventionTips":["Do not call setHoldability on this driver; its default is already the only supported value.","Set pools (e.g., DBCP2 defaultHoldability) to CLOSE_CURSORS_AT_COMMIT or remove the property.","Consume result sets before commit instead of relying on holdable cursors.","Centralize connection configuration in one factory method so unsupported settings surface immediately."],"tags":["java","jdbc","holdability","connection-config","unsupported-feature"],"backgroundTag":"unsupported-holdability","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}