{"record":{"id":"d3f8f6b93d781d45","repo":"apache/shardingsphere","slug":"expected-blr-end","errorCode":null,"errorMessage":"Expected blr_end","messagePattern":"Expected blr_end","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/batch/FirebirdParseBatchBlr.java","lineNumber":97,"sourceCode":"        int version = buffer.readUnsignedByte();\n        if (BlrConstants.blr_version4 != version && BlrConstants.blr_version5 != version) {\n            throw new IllegalArgumentException(\"Unsupported BLR version: \" + version);\n        }\n        if (BlrConstants.blr_begin != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_begin\");\n        }\n        if (BlrConstants.blr_message != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_message\");\n        }\n        buffer.skipBytes(1);\n        FirebirdParseBatchBlr result = parseFormat(buffer);\n        validateTermination(buffer, startReaderIndex, blrLength);\n        return result;\n    }\n    \n    private static void validateTermination(final ByteBuf buffer, final int startReaderIndex, final int blrLength) {\n        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_end != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_end\");\n        }\n        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_eoc != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_eoc\");\n        }\n        if (0 != remainingWithinBlr(buffer, startReaderIndex, blrLength)) {\n            throw new IllegalArgumentException(\"Unexpected trailing bytes in BLR\");\n        }\n    }\n    \n    private static int remainingWithinBlr(final ByteBuf buffer, final int startReaderIndex, final int blrLength) {\n        return blrLength - (buffer.readerIndex() - startReaderIndex);\n    }\n    \n    private static void validateSupported(final List<FirebirdBatchColumnDescriptor> fields) {\n        for (FirebirdBatchColumnDescriptor each : fields) {\n            if (FirebirdBinaryColumnType.BLOB == each.getType()) {\n                // TODO Implement BATCH_REGBLOB, BATCH_BLOB_STREAM and BATCH_SET_BPB before accepting BLOB fields.\n                throw new FirebirdProtocolException(\"BLOB fields are not supported in Firebird batch operations\");","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/batch/FirebirdParseBatchBlr.java#L79-L115","documentation":"SQLFeatureNotSupportedException thrown by updateBlob(int, InputStream, long) on SQL federation ResultSets. The length-parameterized stream overload is one of the six updateBlob signatures, all final and throwing in AbstractUnsupportedUpdateOperationSQLFederationResultSet. Because federated ResultSets are read-only, the length hint never matters: the operation is refused before the stream is touched. This mirrors the JDBC 3-era pattern of bounded BLOB writes, which federation simply does not offer.","triggerScenarios":"Calling rs.updateBlob(columnIndex, inputStream, length) on a federation ResultSet then rs.updateRow(). Encountered in code that knows the exact byte count (e.g. a staged temp file) and uses the bounded API.","commonSituations":"Upload code migrated from older drivers where the bounded overload was the only stream option; batch importers writing known-size binaries in place; ShardingSphere introduced into an existing stack without a cursor-usage audit.","solutions":["Use UPDATE with ps.setBinaryStream(index, stream, length) to preserve the bounded-write semantics","Check getConcurrency() before planning cursor edits; fall back to DML when CONCUR_READ_ONLY","Re-route the query away from federation if in-place edits are a hard requirement"],"exampleFix":"// before\nrs.updateBlob(2, in, fileSize); // SQLFeatureNotSupportedException\n\n// after\ntry (PreparedStatement ps = conn.prepareStatement(\"UPDATE files SET content = ? WHERE id = ?\")) {\n    ps.setBinaryStream(1, in, fileSize);\n    ps.setLong(2, rs.getLong(\"id\"));\n    ps.executeUpdate();\n}","handlingStrategy":"try-catch","validationCode":"if (rs.getConcurrency() != ResultSet.CONCUR_UPDATABLE) {\n    // bounded stream write unsupported: use UPDATE + setBinaryStream(1, in, length)\n}","typeGuard":null,"tryCatchPattern":"try {\n    rs.updateBlob(columnIndex, inputStream, length);\n} catch (SQLFeatureNotSupportedException e) {\n    // fall back to bounded setBinaryStream via DML\n}","preventionTips":["Prefer modern length-less overloads via DML where possible","Check concurrency before bounded writes","Keep staged-file uploads on the DML path"],"tags":["jdbc","resultset","sql-federation","read-only","blob","streaming"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}