{"record":{"id":"08c28da92a5c73f0","repo":"apache/shardingsphere","slug":"isnullable","errorCode":null,"errorMessage":"isNullable","messagePattern":"isNullable","errorType":"exception","errorClass":"SQLFeatureNotSupportedException","httpStatus":null,"severity":"error","filePath":"jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationParameterMetaData.java","lineNumber":33,"sourceCode":" * limitations under the License.\n */\n\npackage org.apache.shardingsphere.driver.jdbc.unsupported;\n\nimport org.apache.shardingsphere.driver.jdbc.adapter.WrapperAdapter;\n\nimport java.sql.ParameterMetaData;\nimport java.sql.SQLException;\nimport java.sql.SQLFeatureNotSupportedException;\n\n/**\n * Unsupported {@code ParameterMetaData} methods.\n */\npublic abstract class AbstractUnsupportedOperationParameterMetaData extends WrapperAdapter implements ParameterMetaData {\n    \n    @Override\n    public final int isNullable(final int parameter) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isNullable\");\n    }\n    \n    @Override\n    public final boolean isSigned(final int parameter) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"isSigned\");\n    }\n    \n    @Override\n    public final int getPrecision(final int parameter) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getPrecision\");\n    }\n    \n    @Override\n    public final int getScale(final int parameter) throws SQLException {\n        throw new SQLFeatureNotSupportedException(\"getScale\");\n    }\n    \n    @Override","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/jdbc/src/main/java/org/apache/shardingsphere/driver/jdbc/unsupported/AbstractUnsupportedOperationParameterMetaData.java#L15-L51","documentation":"java.sql.SQLFeatureNotSupportedException thrown by ShardingSphere JDBC's AbstractUnsupportedOperationParameterMetaData.isNullable(int). The ShardingSphere driver prepares statements locally (it only parses SQL to route shards), so it never reaches a real backend prepare and cannot know whether a '?' parameter accepts NULL. The concrete ShardingSphereParameterMetaData implements only getParameterCount(); every per-parameter metadata method inherits this final throwing override.","triggerScenarios":"Calling ((ShardingSpherePreparedStatement) ps).getParameterMetaData().isNullable(paramIndex) on a connection whose URL is jdbc:shardingsphere:... . Any library that probes parameter nullability before binding (report writers, generic query builders, JDBC spec-compliance suites) hits it.","commonSituations":"Running MyBatis/Hibernate/Jooq-free generic DAO layers, Spring's SqlParameterSource probing, or BI/report tools (JasperReports, BIRT) on top of sharding-jdbc after adding sharding or encrypt rules; also appears when porting an app from MySQL Connector/J (which supports isNullable) to ShardingSphere.","solutions":["Do not call ParameterMetaData.isNullable through the ShardingSphere driver; derive nullability from your own domain knowledge of the SQL or from table/column metadata of the underlying database.","If you must have per-parameter metadata, execute the statement once and use ResultSetMetaData of the result, or unwrap the real backend PreparedStatement (e.g. via a direct non-sharded DataSource for metadata probes).","Catch SQLFeatureNotSupportedException (before the generic SQLException catch) and fall back to ParameterMetaData.parameterNoNulls/parameterNullableUnknown semantics."],"exampleFix":"// before\nint nullable = ps.getParameterMetaData().isNullable(1);\n\n// after\nint nullable;\ntry {\n    nullable = ps.getParameterMetaData().isNullable(1);\n} catch (final SQLFeatureNotSupportedException e) {\n    nullable = ParameterMetaData.parameterNullableUnknown; // ShardingSphere cannot know pre-execution\n}","handlingStrategy":"try-catch","validationCode":"// Only getParameterCount() is safe on ShardingSphere ParameterMetaData\nboolean isSS;\ntry { isSS = conn.getMetaData().getDriverName().toLowerCase().contains(\"shardingsphere\"); } catch (SQLException e) { isSS = false; }\nif (!isSS) { int n = pmd.isNullable(1); } else { /* skip probe */ }","typeGuard":"static boolean isShardingSphereParameterMetaData(final ParameterMetaData pmd) {\n    return pmd != null && pmd.getClass().getName().startsWith(\"org.apache.shardingsphere.driver.jdbc\");\n}","tryCatchPattern":"try {\n    int nullable = pmd.isNullable(1);\n} catch (final SQLFeatureNotSupportedException e) {\n    nullable = ParameterMetaData.parameterNullableUnknown; // catch BEFORE generic SQLException\n}","preventionTips":["Treat ParameterMetaData from ShardingSphere as count-only metadata","Get nullability from DatabaseMetaData.getColumns of the underlying database","Gate driver-specific metadata probes on conn.getMetaData().getDriverName()"],"tags":["jdbc","shardingsphere","parametermetadata","sql-feature-not-supported"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}