{"record":{"id":"f8336325dd44500a","repo":"apache/shardingsphere","slug":"unsupported-sql-statement-s-in-sql-federation-f83363","errorCode":null,"errorMessage":"unsupported SQL statement %s in sql federation","messagePattern":"unsupported SQL statement (.+?) in sql federation","errorType":"exception","errorClass":"UnsupportedSQLOperationException","httpStatus":null,"severity":"error","filePath":"kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java","lineNumber":54,"sourceCode":"import java.util.Collection;\nimport java.util.HashSet;\nimport java.util.List;\n\n/**\n * Single SQL federation decider.\n */\npublic final class SingleSQLFederationDecider implements SQLFederationDecider<SingleRule> {\n    \n    @Override\n    public boolean decide(final SQLStatementContext sqlStatementContext, final List<Object> parameters, final RuleMetaData globalRuleMetaData,\n                          final ShardingSphereDatabase database, final SingleRule rule, final Collection<DataNode> includedDataNodes) {\n        if (sqlStatementContext instanceof SelectStatementContext) {\n            return decide0(sqlStatementContext, database, rule, includedDataNodes);\n        } else if (sqlStatementContext instanceof ExplainStatementContext) {\n            ExplainStatementContext explainStatementContext = (ExplainStatementContext) sqlStatementContext;\n            return decide(explainStatementContext.getExplainableSQLStatementContext(), parameters, globalRuleMetaData, database, rule, includedDataNodes);\n        }\n        throw new UnsupportedSQLOperationException(String.format(\"unsupported SQL statement %s in sql federation\", sqlStatementContext.getSqlStatement().getClass().getSimpleName()));\n    }\n    \n    private boolean decide0(final SQLStatementContext sqlStatementContext, final ShardingSphereDatabase database, final SingleRule rule, final Collection<DataNode> includedDataNodes) {\n        Collection<QualifiedTable> singleTables = getSingleTables(sqlStatementContext, database, rule);\n        if (singleTables.isEmpty()) {\n            return false;\n        }\n        if (containsView(database, singleTables)) {\n            return true;\n        }\n        if (!includedDataNodes.isEmpty() && !isInnerCommaJoin(sqlStatementContext.getSqlStatement())) {\n            return true;\n        }\n        boolean result = rule.isAllTablesInSameComputeNode(includedDataNodes, singleTables, database);\n        includedDataNodes.addAll(getTableDataNodes(rule, singleTables, database));\n        return !result;\n    }\n    ","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/kernel/single/core/src/main/java/org/apache/shardingsphere/single/decider/SingleSQLFederationDecider.java#L36-L72","documentation":"SingleSQLFederationDecider.decide only knows how to decide federation for SelectStatementContext (and ExplainStatementContext by recursing into the wrapped statement). Any other SQLStatementContext type falls through to UnsupportedSQLOperationException naming the statement class. This indicates federation decision logic invoked for a statement kind the single-rule decider never handles.","triggerScenarios":"The federation engine asks the decider about a non-SELECT statement context (INSERT/UPDATE/DELETE/DDL contexts), which should normally be filtered before federation. Reaching this throw means a caller invoked decide() directly or a new statement type was routed into federation decision without a guard.","commonSituations":"Custom code calling SQLFederationDecider.decide for arbitrary statements; version skew where a new statement context type reaches the decider; misconfigured sql-federation=true interacting with statement types not intended for federation.","solutions":["Only invoke the decider for SELECT (or EXPLAIN SELECT) statement contexts; gate callers on sqlStatementContext instanceof SelectStatementContext first.","Update ShardingSphere to a version whose decider handles the statement type you are feeding it.","If hit inside the proxy during normal traffic, capture the SQL and report it — federation should not attempt non-query statements."],"exampleFix":"// before\ndecider.decide(sqlStatementContext, parameters, globalRuleMetaData, database, rule, includedDataNodes);\n// after\nif (sqlStatementContext instanceof SelectStatementContext || sqlStatementContext instanceof ExplainStatementContext) {\n    decider.decide(sqlStatementContext, parameters, globalRuleMetaData, database, rule, includedDataNodes);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean isFederationDecidable(SQLStatementContext ctx) {\n    return ctx instanceof SelectStatementContext || ctx instanceof ExplainStatementContext;\n}","tryCatchPattern":"try {\n    federated = decider.decide(ctx, params, ruleMetaData, database, rule, dataNodes);\n} catch (final UnsupportedSQLOperationException ex) {\n    federated = false; // fall back to normal routing for non-query contexts\n}","preventionTips":["Gate decider calls on Select/Explain contexts.","Do not enable federation paths for DML/DDL traffic.","Regression-test custom federation integrations with INSERT/UPDATE statements."],"tags":["sql-federation","single","decider","statement-type"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}