MyCATApache/Mycat-Server · error · SQLNonTransientException
SQL AST nodes type mismatch!
Error message
SQL AST nodes type mismatch!
What it means
When a comparison clause in the UPDATE statement matches col = value where col is the sharding column, Mycat checks whether the right side equals the value being SET. It first requires both sides to be the same AST node class; if e.g. the WHERE literal is an integer and the SET value is a string (or vice versa), it throws 'SQL AST nodes type mismatch!' instead of silently allowing or denying the update.
Solutions
- Make the literal types consistent: use the same form of the value in the WHERE clause and the SET clause (both quoted or both unquoted)
- Quote consistently for string sharding keys, e.g. SET id='5' ... WHERE id='5'
- Avoid updating the sharding column at all; update other columns only
Example fix
// before UPDATE t SET id=5 WHERE id='5'; // after UPDATE t SET id='5' WHERE id='5';
Defensive patterns
Strategy: validation
Validate before calling
// keep literal types consistent between WHERE and SET for the shard key
String setVal = "'5'", whereVal = "'5'"; // both quoted for string keys
if (isNumericShardKey) { setVal = setVal.replace("'",""); whereVal = whereVal.replace("'",""); } Type guard
boolean sameLiteralKind(SQLExpr a, SQLExpr b) {
return a.getClass().equals(b.getClass());
} Try / catch
try { router.route(...) } catch (SQLNonTransientException e) { if ("SQL AST nodes type mismatch!".equals(e.getMessage())) { normalizeLiteralsAndRetry(); } } Prevention
- Quote consistently: string keys always quoted, numeric keys never quoted
- Don't update the sharding column in application code
- Parameterize values with consistent types from the ORM
When it happens
Trigger: confirmShardColumnNotUpdated -> shardColCanBeUpdated finds leftExpr column equals the partition column, and rightExpr.getClass() != value.getClass() — e.g. WHERE id='5' but SET id=5 (string literal vs SQLIntegerExpr), or any literal/parameter-type difference between the two sides.
Common situations: Quoting numeric sharding keys in one clause but not the other; ORM-generated SQL mixing typed and untyped literals; implicit MySQL type coercion assumptions that the Druid AST does not share.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- multi table related update not supported,tables:
- global table is not supported in multi table related update
- Unhandled SQL AST node type encountered:
- 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/3a2069523a5a9436.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/io/mycat/route/parser/druid/impl/DruidUpdateParser.java:180
* 条件中有or或者xor的,如果分片字段出现在or/xor的一个子句中,则此update
* 语句无法执行
*/
if ((nodeOpExpr.getOperator() == SQLBinaryOperator.BooleanOr) ||
(nodeOpExpr.getOperator() == SQLBinaryOperator.BooleanXor)) {
parentHasOR = true;
}
// 发现类似 col = value 的子句
if (nodeOpExpr.getOperator() == SQLBinaryOperator.Equality) {
boolean foundCol;
SQLExpr leftExpr = nodeOpExpr.getLeft();
SQLExpr rightExpr = nodeOpExpr.getRight();
foundCol = columnInExpr(leftExpr, column);
// 发现col = value子句,col刚好是分片字段,比较value与update要更新的值是否一样,并且是否在or/xor子句中
if (foundCol) {
if (rightExpr.getClass() != value.getClass()) {
throw new SQLNonTransientException("SQL AST nodes type mismatch!");
}
canUpdate = rightExpr.toString().equals(value.toString()) && (!hasOR) && (!parentHasOR);
}
} else if (nodeOpExpr.getOperator().isLogical()) {
if (nodeOpExpr.getLeft() != null) {
if (nodeOpExpr.getLeft() instanceof SQLBinaryOpExpr) {
canUpdate = shardColCanBeUpdated(nodeOpExpr.getLeft(), column, value, parentHasOR);
}
// else
// 此子语句不是 =,>,<等关系运算符(对应的类是SQLBinaryOpExpr)。比如between X and Y
// 或者 NOT,或者单独的子查询,这些情况,我们不做处理
}
if ((!canUpdate) && nodeOpExpr.getRight() != null) {
if (nodeOpExpr.getRight() instanceof SQLBinaryOpExpr) {
canUpdate = shardColCanBeUpdated(nodeOpExpr.getRight(), column, value, parentHasOR);
}
// elseView on GitHub (pinned to 65f8d8beb7)