{"record":{"id":"4500bff4b37e5f99","repo":"apache/shardingsphere","slug":"getcharacterstream-4500bf","errorCode":null,"errorMessage":"getCharacterStream","messagePattern":"getCharacterStream","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedDatabaseMetaDataResultSet.java","lineNumber":81,"sourceCode":"    \n    @Override\n    public final InputStream getBinaryStream(final String columnLabel) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getBinaryStream\");\n    }\n    \n    @Override\n    public final SQLWarning getWarnings() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getWarnings\");\n    }\n    \n    @Override\n    public final void clearWarnings() throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"clearWarnings\");\n    }\n    \n    @Override\n    public final Reader getCharacterStream(final int columnIndex) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getCharacterStream\");\n    }\n    \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","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedDatabaseMetaDataResultSet.java#L63-L99","documentation":"java.sql.SQLFeatureNotSupportedException thrown by the Apache ShardingSphere JDBC driver when ResultSet.getCharacterStream(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. getCharacterStream(int columnIndex) is declared final in AbstractUnsupportedDatabaseMetaDataResultSet and always throws, so this is a permanent, intentional limitation, not a version bug.","triggerScenarios":"Calling getCharacterStream(int columnIndex) on the ResultSet returned by ShardingSphereDatabaseMetaData, e.g. connection.getMetaData().getTables(null, null, \"%\", new String[]{\"TABLE\"}\") followed by rs.getCharacterStream(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. ","solutions":["Replace rs.getCharacterStream(int columnIndex) with rs.getString(...), which DatabaseMetaDataResultSet implements, then build the stream/reader yourself (new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII)) or new StringReader(s)).","If binary data was intended, use rs.getBytes(...) instead of a character stream.","If you do not control the calling code (third-party tool), point its metadata introspection at the underlying physical datasource instead of the ShardingSphere datasource.","As a last resort wrap the metadata ResultSet in a delegating adapter that implements the stream getters on top of getString.","Do not wait for a driver upgrade: the throw is final and by design in every ShardingSphere 5.x release."],"exampleFix":"// before - throws SQLFeatureNotSupportedException on ShardingSphere metadata result sets\nInputStream ascii = metaDataRs.getAsciiStream(\"REMARKS\");\nReader reader = metaDataRs.getCharacterStream(\"REMARKS\");\n\n// after - getString is implemented; build the stream/reader yourself\nString remarks = metaDataRs.getString(\"REMARKS\");\nInputStream ascii = remarks == null ? null : new ByteArrayInputStream(remarks.getBytes(StandardCharsets.US_ASCII));\nReader reader = remarks == null ? null : new StringReader(remarks);","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.getCharacterStream(int columnIndex);\n} catch (final SQLFeatureNotSupportedException e) {\n    // ShardingSphere metadata result sets: fall back to the implemented scalar getter\n    final String s = rs.getString(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","stream","reader"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}