{"record":{"id":"bdd954f356451575","repo":"apache/shardingsphere","slug":"statement-class-is-not-supported","errorCode":null,"errorMessage":"Statement class is not supported.","messagePattern":"Statement class is not supported\\.","errorType":"exception","errorClass":"StatementClassNotSupportedException","httpStatus":null,"severity":"error","filePath":"mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPJdbcStatementExecutor.java","lineNumber":251,"sourceCode":"        boolean hasResultSet = statement.execute(classificationResult.getNormalizedSql());\n        switch (classificationResult.getStatementClass()) {\n            case QUERY:\n            case EXPLAIN:\n                if (!hasResultSet) {\n                    throw new QueryDidNotReturnResultSetException();\n                }\n                return createResultSetResult(statement.getResultSet(), executionRequest, classificationResult);\n            case DML:\n                return hasResultSet\n                        ? createResultSetResult(statement.getResultSet(), executionRequest, classificationResult)\n                        : SQLExecutionResult.updateCount(classificationResult.getStatementClass(), classificationResult.getStatementType(), statement.getUpdateCount(),\n                                executionRequest.getMaxRows(), executionRequest.getTimeoutMs(), classificationResult.getNormalizedSql());\n            case DDL:\n            case DCL:\n                return SQLExecutionResult.statementAck(classificationResult.getStatementClass(), classificationResult.getStatementType(),\n                        executionRequest.getMaxRows(), executionRequest.getTimeoutMs(), classificationResult.getNormalizedSql());\n            default:\n                throw new StatementClassNotSupportedException();\n        }\n    }\n    \n    private SQLExecutionResult createResultSetResult(final ResultSet resultSet, final SQLExecutionRequest executionRequest, final ClassificationResult classificationResult) throws SQLException {\n        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();\n        LinkedList<SQLExecutionColumnDefinition> columns = new LinkedList<>();\n        for (int index = 1; index <= resultSetMetaData.getColumnCount(); index++) {\n            columns.add(new SQLExecutionColumnDefinition(resultSetMetaData.getColumnLabel(index), resultSetMetaData.getColumnTypeName(index),\n                    resultSetMetaData.getColumnTypeName(index), ResultSetMetaData.columnNoNulls != resultSetMetaData.isNullable(index)));\n        }\n        LinkedList<List<Object>> rows = new LinkedList<>();\n        boolean truncated = false;\n        int effectiveMaxRows = 0 >= executionRequest.getMaxRows() ? Integer.MAX_VALUE : executionRequest.getMaxRows();\n        while (resultSet.next()) {\n            if (rows.size() >= effectiveMaxRows) {\n                truncated = true;\n                break;\n            }","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPJdbcStatementExecutor.java#L233-L269","documentation":"The default arm of the statement-class switch in MCPJdbcStatementExecutor: after execution, a classification whose StatementClass is not QUERY, EXPLAIN, DML, DDL, or DCL (e.g. TCL, SAVEPOINT, TRANSACTION_CONTROL, or an unknown class) reaches StatementClassNotSupportedException. QUERY/EXPLAIN require a result set, DML returns rows or an update count, DDL/DCL return an ack; anything else means the classifier and executor disagree about supported classes.","triggerScenarios":"A statement classified as a class the JDBC executor does not handle reaching the generic statement executor — normally transaction-control statements routed to the wrong executor path, or a future/unknown StatementClass enum value after a version skew between analyzer and executor.","commonSituations":"BEGIN/COMMIT/ROLLBACK/SAVEPOINT SQL sent through execute_query or execute_update instead of the transaction tools; mixed version jars on the classpath where a newer analyzer produces classes an older executor cannot switch on.","solutions":["Send transaction-control SQL (BEGIN/COMMIT/ROLLBACK/SAVEPOINT) through the dedicated transaction statement path/tool, not execute_query/execute_update.","Align versions of the mcp core modules so StatementClass enum values agree between analyzer and executor.","Capture the failing SQL and its reported statement class and report it if it is a plain QUERY/DML/DDL."],"exampleFix":"// before\nawait tools.call('database_gateway_execute_query', { sql: 'COMMIT' }); // StatementClassNotSupportedException\n\n// after: use the transaction control tool/path\nawait tools.call('database_gateway_transaction', { operation: 'commit' });","handlingStrategy":"validation","validationCode":"// Keep transaction SQL out of the generic execution tools\nconst TCL_RE = /^\\s*(BEGIN|START\\s+TRANSACTION|COMMIT|ROLLBACK|SAVEPOINT|RELEASE\\s+SAVEPOINT|SET\\s+TRANSACTION)\\b/i;\nif (TCL_RE.test(sql)) {\n  throw new Error('Use the transaction control tool for transaction SQL: ' + sql);\n}\nreturn tools.call(tool, args);","typeGuard":"function isTransactionControlSql(sql) {\n  return /^\\s*(BEGIN|START\\s+TRANSACTION|COMMIT|ROLLBACK|SAVEPOINT|RELEASE\\s+SAVEPOINT)\\b/i.test(sql);\n}","tryCatchPattern":"try {\n  return await tools.call('database_gateway_execute_query', { sql });\n} catch (e) {\n  if (/Statement class is not supported/.test(e.message)) {\n    // log SQL + reported statement class; route transaction SQL to the transaction tool, others report upstream\n  }\n  throw e;\n}","preventionTips":["Send BEGIN/COMMIT/ROLLBACK/SAVEPOINT only through the transaction tooling.","Keep mcp core module versions consistent so StatementClass values match.","Strip transaction wrappers from SQL before submitting to execution tools."],"tags":["mcp","sql","statement-class","transactions","switch"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}