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

  1. 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
  2. Move the function/expression to the value side: WHERE id=UPPER('abc') instead of WHERE UPPER(id)='ABC'
  3. 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

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


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)