{"record":{"id":"cb73793b9236312b","repo":"apache/shardingsphere","slug":"updatebigdecimal","errorCode":null,"errorMessage":"updateBigDecimal","messagePattern":"updateBigDecimal","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedUpdateOperationSQLFederationResultSet.java","lineNumber":124,"sourceCode":"    \n    @Override\n    public final void updateFloat(final String columnLabel, final float x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateFloat\");\n    }\n    \n    @Override\n    public final void updateDouble(final int columnIndex, final double x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateDouble\");\n    }\n    \n    @Override\n    public final void updateDouble(final String columnLabel, final double x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateDouble\");\n    }\n    \n    @Override\n    public final void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateBigDecimal\");\n    }\n    \n    @Override\n    public final void updateBigDecimal(final String columnLabel, final BigDecimal x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateBigDecimal\");\n    }\n    \n    @Override\n    public final void updateString(final int columnIndex, final String x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateString\");\n    }\n    \n    @Override\n    public final void updateString(final String columnLabel, final String x) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"updateString\");\n    }\n    \n    @Override","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/resultset/AbstractUnsupportedUpdateOperationSQLFederationResultSet.java#L106-L142","documentation":"AbstractUnsupportedUpdateOperationSQLFederationResultSet defines the update contract for every SQL federation ResultSet in ShardingSphere: each updateXxx method unconditionally throws SQLFeatureNotSupportedException, with the message naming the method ('updateBigDecimal'). Federated results are in-memory computed rows without an updatable cursor, so BigDecimal writes by column index always fail fast rather than silently no-op.","triggerScenarios":"Calling ResultSet.updateBigDecimal(int columnIndex, BigDecimal x) on the ResultSet of a federation-executed statement (cross-shard join/subquery under an enabled sql_federation rule). Encountered in financial/billing code that patches monetary columns in place, or generic row-edit frameworks.","commonSituations":"Money-handling code that assumed CONCUR_UPDATABLE on the underlying MySQL/Oracle driver and now runs against ShardingSphere federation; sqlFederation turned on during a sharding migration, silently routing previously normal queries through the federation engine; reusable JDBC utilities that call updateXxx on every ResultSet they process.","solutions":["Move the write out of the cursor: read with getBigDecimal(columnIndex), then execute a PreparedStatement UPDATE setting the BigDecimal by setBigDecimal, keyed on the primary key.","Pre-check rs.getConcurrency() and branch to UPDATE statements when the set is read-only; optionally assert DatabaseMetaData.supportsResultSetConcurrency(TYPE_FORWARD_ONLY, CONCUR_UPDATABLE) is true before relying on cursor updates.","Scope the sql_federation rule so this query is not federated and the backend driver's native ResultSet semantics apply."],"exampleFix":"// before\nrs.updateBigDecimal(4, new BigDecimal(\"123.45\"));  // SQLFeatureNotSupportedException: updateBigDecimal\nrs.updateRow();\n\n// after\ntry (PreparedStatement upd = conn.prepareStatement(\"UPDATE ledger SET amount = ? WHERE id = ?\")) {\n    upd.setBigDecimal(1, new BigDecimal(\"123.45\"));\n    upd.setLong(2, rs.getLong(1));\n    upd.executeUpdate();\n}","handlingStrategy":"try-catch","validationCode":"if (rs.getConcurrency() != ResultSet.CONCUR_UPDATABLE) {\n    // monetary writes must go through UPDATE + setBigDecimal\n}","typeGuard":"private static boolean supportsRowUpdates(final ResultSet rs) throws SQLException {\n    return rs.getConcurrency() == ResultSet.CONCUR_UPDATABLE;\n}","tryCatchPattern":"try {\n    rs.updateBigDecimal(4, amount);\n} catch (final SQLFeatureNotSupportedException ignored) {\n    try (PreparedStatement upd = conn.prepareStatement(\"UPDATE ledger SET amount = ? WHERE id = ?\")) {\n        upd.setBigDecimal(1, amount);\n        upd.setLong(2, rs.getLong(1));\n        upd.executeUpdate();\n    }\n}","preventionTips":["Never patch monetary columns through the ResultSet cursor on ShardingSphere.","Branch on rs.getConcurrency() in financial code paths and fail loudly to an UPDATE strategy.","Keep federation usage documented per statement so read-only behavior is expected."],"tags":["jdbc","resultset","sql-federation","read-only","shardingsphere","bigdecimal"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}