{"record":{"id":"36c76939bfa27933","repo":"apache/shardingsphere","slug":"setsavepoint-name","errorCode":null,"errorMessage":"setSavepoint name","messagePattern":"setSavepoint name","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java","lineNumber":119,"sourceCode":"    }\n    \n    @Override\n    public void rollback() {\n    }\n    \n    @Override\n    public void rollback(final Savepoint savepoint) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"rollback savepoint\");\n    }\n    \n    @Override\n    public Savepoint setSavepoint() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"setSavepoint\");\n    }\n    \n    @Override\n    public Savepoint setSavepoint(final String name) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"setSavepoint name\");\n    }\n    \n    @Override\n    public void releaseSavepoint(final Savepoint savepoint) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"releaseSavepoint\");\n    }\n    \n    @Override\n    public void setHoldability(final int holdability) {\n    }\n    \n    @Override\n    public int getHoldability() {\n        return 0;\n    }\n    \n    @Override\n    public PreparedStatement prepareStatement(final String sql) {","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/state/circuit/connection/CircuitBreakerConnection.java#L101-L137","documentation":"CircuitBreakerConnection.setSavepoint(String name) throws SQLFeatureNotSupportedException(\"setSavepoint name\") whenever the ShardingSphere data source is circuit-broken. Like its no-arg sibling, a named savepoint cannot be created without a live backend transaction, so the stub refuses rather than returning a fake Savepoint that later code would rely on.","triggerScenarios":"Calling conn.setSavepoint(\"CHECKPOINT_1\") on a Connection whose data source is in the OPEN circuit state — typically code that names its savepoints for logging or multi-checkpoint logic.","commonSituations":"Named-savepoint batch jobs running when the database fails over; frameworks emitting named checkpoints (e.g. custom retry scopes); the same PROPAGATION_NESTED scenario with named savepoints.","solutions":["Check the circuit/data-source state and getMetaData().supportsSavepoints() before creating named savepoints.","Restore backend availability so the circuit breaker returns to CLOSED and real connections resume.","Refactor named-checkpoint logic to full-transaction boundaries that tolerate a stubbed Connection.","Catch SQLFeatureNotSupportedException and degrade to rollback()/commit() without the named checkpoint."],"exampleFix":"// before\nSavepoint sp = conn.setSavepoint(\"before_bulk_step\");\n\n// after\nif (metaData.supportsSavepoints()) {\n    Savepoint sp = conn.setSavepoint(\"before_bulk_step\");\n} else {\n    logger.warn(\"savepoints unavailable; running step without checkpoint\");\n}","handlingStrategy":"validation","validationCode":"if (conn.getMetaData().supportsSavepoints()) {\n    sp = conn.setSavepoint(\"step_\" + n);\n} else {\n    sp = null; // degraded mode\n}","typeGuard":null,"tryCatchPattern":"try {\n    sp = conn.setSavepoint(\"checkpoint\");\n} catch (final SQLFeatureNotSupportedException ex) {\n    LOGGER.warn(\"named savepoint unavailable (circuit open); continuing without\");\n}","preventionTips":["Treat named checkpoints as optional decorations, never correctness requirements.","Verify connection health/state before beginning multi-step checkpointed transactions."],"tags":["jdbc","circuit-breaker","savepoint"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}