{"record":{"id":"94b176f90d22d98b","repo":"apache/shardingsphere","slug":"getblob","errorCode":null,"errorMessage":"getBlob","messagePattern":"getBlob","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedDatabaseMetaDataResultSet.java","lineNumber":101,"sourceCode":"    \n    @Override\n    public final Reader getCharacterStream(final String columnLabel) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getCharacterStream\");\n    }\n    \n    @Override\n    public final Array getArray(final int columnIndex) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getArray\");\n    }\n    \n    @Override\n    public final Array getArray(final String columnLabel) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getArray\");\n    }\n    \n    @Override\n    public final Blob getBlob(final int columnIndex) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getBlob\");\n    }\n    \n    @Override\n    public final Blob getBlob(final String columnLabel) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getBlob\");\n    }\n    \n    @Override\n    public final Clob getClob(final int columnIndex) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getClob\");\n    }\n    \n    @Override\n    public final Clob getClob(final String columnLabel) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getClob\");\n    }\n    \n    @Override","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedDatabaseMetaDataResultSet.java#L83-L119","documentation":"java.sql.SQLFeatureNotSupportedException thrown by the Apache ShardingSphere JDBC driver when ResultSet.getBlob(int columnIndex) is called on a DatabaseMetaData result set. Metadata calls such as Connection.getMetaData().getTables()/getColumns()/getIndexInfo()/getPrimaryKeys() on a jdbc:shardingsphere: URL return a synthesized DatabaseMetaDataResultSet that buffers every row as plain Java objects, so only scalar getters (getString, getInt, getBytes, single-arg getDate/getTime/getTimestamp, ...) are implemented. getBlob(int columnIndex) is declared final in AbstractUnsupportedDatabaseMetaDataResultSet and always throws, so this is a permanent, intentional limitation, not a version bug.","triggerScenarios":"Calling getBlob(int columnIndex) on the ResultSet returned by ShardingSphereDatabaseMetaData, e.g. connection.getMetaData().getTables(null, null, \"%\", new String[]{\"TABLE\"}\") followed by rs.getBlob(1)) where connection was opened with the org.apache.shardingsphere.driver JDBC URL (jdbc:shardingsphere:classpath:sharding.yaml or jdbc:shardingsphere:...). Both the int-columnIndex and String-columnLabel overloads of every listed getter throw; the methods are final so no subclass can override them.","commonSituations":"Code that ran unchanged against the native MySQL/PostgreSQL/OpenGauss driver and is repointed to the ShardingSphere driver URL, so the same metadata loop now hits the stubbed getter; generic schema tooling that enumerates JDBC metadata with feature-rich getters (DBeaver, Squirrel SQL, Liquibase/Hibernate/Flyway schema validators, code generators, DBDiff tools); hand-written metadata loops that defensively call getWarnings()/clearWarnings() or use the Calendar overloads to pin a timezone. LOB getters are a common reflex when columns look binary/large even though metadata columns are short catalog strings.","solutions":["Replace rs.getBlob(int columnIndex) with rs.getBytes(...), which DatabaseMetaDataResultSet implements; metadata catalogs only contain short scalar values (names, types, remarks).","For java.sql.Blob/Clob objects you need for an API, construct SerialBlob/SerialClob (com.sun.rowset or javax.sql.rowset.serial) from the byte[]/String you read.","If you need real LOB columns of actual user tables, SELECT them through a normal sharded Statement (whose ResultSet is a ShardingResultSet with full getter support), not through DatabaseMetaData.","If you do not control the calling code (third-party tool), run its metadata introspection against the physical datasource.","Do not wait for a driver upgrade: the throw is final and by design."],"exampleFix":"// before - throws SQLFeatureNotSupportedException on ShardingSphere metadata result sets\nBlob blob = metaDataRs.getBlob(1);\n\n// after - getBytes is implemented; wrap only if a Blob-typed value is required\nbyte[] bytes = metaDataRs.getBytes(1);\nBlob blob = bytes == null ? null : new SerialBlob(bytes);","handlingStrategy":"try-catch","validationCode":"// Run BEFORE using exotic getters: detect a ShardingSphere-synthesized metadata ResultSet\nstatic boolean isShardingSphereMetaDataResultSet(final ResultSet rs) {\n    return rs != null && \"org.apache.shardingsphere.driver.jdbc.core.resultset.DatabaseMetaDataResultSet\"\n            .equals(rs.getClass().getName());\n}\n\nstatic boolean supportsMetaDataGetter(final Connection c) throws SQLException {\n    // jdbc:shardingsphere: URLs return the synthesized metadata result set\n    return c != null && !c.getMetaData().getURL().startsWith(\"jdbc:shardingsphere:\");\n}","typeGuard":"private static boolean isUnsupportedMetaDataResultSet(final ResultSet rs) {\n    return rs != null && rs.getClass().getName().startsWith(\"org.apache.shardingsphere.driver.jdbc.core.resultset.DatabaseMetaDataResultSet\");\n}","tryCatchPattern":"try {\n    return rs.getBlob(int columnIndex);\n} catch (final SQLFeatureNotSupportedException e) {\n    // ShardingSphere metadata result sets: fall back to the implemented scalar getter\n    final byte[] bytes = rs.getBytes(col);\n}","preventionTips":["Never assume a JDBC driver implements every ResultSet getter; DatabaseMetaData results are the most commonly stubbed surface.","When adding ShardingSphere in front of an existing datasource, smoke-test the metadata paths your frameworks use (getTables/getColumns loops) before shipping.","Prefer the simplest getter (getString/getObject/getBytes) and convert in application code; it is portable across drivers.","Treat SQLFeatureNotSupportedException (an SQLException subclass) as a signal about capability, not a transient failure - never retry it."],"tags":["jdbc","shardingsphere","database-metadata","blob"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}