MyCATApache/Mycat-Server · error · SQLNonTransientException
Unhandled SQL AST node type encountered:
Error message
Unhandled SQL AST node type encountered:
What it means
During sharding-column update detection, Mycat's columnInExpr only understands simple column identifiers (SQLIdentifierExpr) and qualified names (SQLPropertyExpr). Any other AST node on the left side of a comparison (function calls, casts, arithmetic expressions) is rejected with this message, which includes the unexpected Java class.
Solutions
- Rewrite the SQL so the sharding column appears as a bare column (optionally qualified) on one side of the comparison, with the value/expression on the other side
- Move the function/expression to the value side: WHERE id=UPPER('abc') instead of WHERE UPPER(id)='ABC'
- Remove arithmetic or casts around the sharding key in WHERE clauses
Example fix
// before
UPDATE t SET x=1 WHERE UPPER(shard_col)='ABC';
// after
UPDATE t SET x=1 WHERE shard_col=UPPER('abc'); Defensive patterns
Strategy: try-catch
Validate before calling
// inspect your SQL: ensure the sharding column appears bare in comparisons
if (sql.matches("(?i).*WHERE\\s+(UPPER|LOWER|CONCAT|CAST)\\s*\\(\\s*" + shardCol + ".*")) {
rewriteToMoveFunctionToValueSide();
} Type guard
boolean isSimpleColumnExpr(SQLExpr e) {
return e instanceof SQLIdentifierExpr || e instanceof SQLPropertyExpr;
} Try / catch
try { confirmShardColumnNotUpdated(schema, rrs, update, tableName, joinKey, hasParent) } catch (SQLNonTransientException e) { if (e.getMessage().contains("Unhandled SQL AST node type")) { /* simplify WHERE expression on shard column */ } } Prevention
- Never wrap the sharding column in functions or arithmetic in WHERE/SET clauses
- Write shard-key comparisons as col = literal
- Lint SQL for functions applied to sharding keys
When it happens
Trigger: shardColCanBeUpdated/confirmShardColumnNotUpdated encounter a WHERE or SET comparison where the column side is an expression, e.g. WHERE UPPER(id)=..., WHERE id+0=..., or a function/cast applied to the sharding column, while checking whether the sharding column is being updated.
Common situations: Legacy SQL using functions on the sharding key in comparisons; generated SQL from ORMs that wrap column references; type-wrapping like CONCAT(id,'')='5' in WHERE clauses.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- multi table related update not supported,tables:
- global table is not supported in multi table related update
- SQL AST nodes type mismatch!
- Sharding column can't be updated ->
- Parent relevant column can't be updated ->
AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11).
Data as JSON: /api/errors/5c7e7b9e3ba871e4.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidUpdateParser.java:116
TableStat ts = tableMap.get(_name);
updateTableCount += ts.getUpdateCount();
}
return updateTableCount;
}
/*
* 判断字段是否在SQL AST的节点中,比如 col 在 col = 'A' 中,这里要注意,一些子句中可能会在字段前加上表的别名,
* 比如 t.col = 'A',这两种情况, 操作符(=)左边被druid解析器解析成不同的对象SQLIdentifierExpr(无表别名)和
* SQLPropertyExpr(有表别名)
*/
private static boolean columnInExpr(SQLExpr sqlExpr, String colName) throws SQLNonTransientException {
String column;
if (sqlExpr instanceof SQLIdentifierExpr) {
column = StringUtil.removeBackquote(((SQLIdentifierExpr) sqlExpr).getName()).toUpperCase();
} else if (sqlExpr instanceof SQLPropertyExpr) {
column = StringUtil.removeBackquote(((SQLPropertyExpr) sqlExpr).getName()).toUpperCase();
} else {
throw new SQLNonTransientException("Unhandled SQL AST node type encountered: " + sqlExpr.getClass());
}
return column.equals(colName.toUpperCase());
}
/*
* 当前节点是不是一个子查询
* IN (select...), ANY, EXISTS, ALL等关键字, IN (1,2,3...) 这种对应的是SQLInListExpr
*/
private static boolean isSubQueryClause(SQLExpr sqlExpr) throws SQLNonTransientException {
return (sqlExpr instanceof SQLInSubQueryExpr || sqlExpr instanceof SQLAnyExpr || sqlExpr instanceof SQLAllExpr
|| sqlExpr instanceof SQLQueryExpr || sqlExpr instanceof SQLExistsExpr);
}
/*
* 遍历where子句的AST,寻找是否有与update子句中更新分片字段相同的条件,
* o 如果发现有or或者xor,然后分片字段的条件在or或者xor中的,这种情况update也无法执行,比如
* update mytab set ptn_col = val, col1 = val1 where col1 = val11 or ptn_col = val;View on GitHub (pinned to 65f8d8beb7)