MyCATApache/Mycat-Server · error · IllegalArgumentException

sql 注释 语法错误

Error message

sql 注释 语法错误

What it means

Mycat's statement pre-processing scans for comment/feature prefixes (e.g. to strip comments and detect 'describe'); when it encounters '/*' it requires a closing '*/' later in the statement. If the comment is unterminated, the scanner throws IllegalArgumentException 'sql 注释 语法错误' (SQL comment syntax error).

Solutions

  1. Fix the SQL so every '/*' comment is properly closed with '*/'.
  2. Remove the malformed comment from the statement entirely.
  3. Check the client/proxy for truncation of long SQL strings and increase its max packet/length limits.
  4. Validate the statement in the application (count balanced '/*' and '*/') before sending it to Mycat.

Example fix

// before
SELECT * FROM t /*+ read hint FROM node_a LIMIT 10;
// after
SELECT * FROM t /*+ read hint from node_a */ LIMIT 10;
Defensive patterns

Strategy: validation

Validate before calling

// ensure comment blocks are terminated before sending SQL
int open = 0;
for (int i = 0; i < sql.length() - 1; i++) {
    if (sql.startsWith("/*", i)) open++;
    if (sql.startsWith("*/", i)) open--;
}
if (open != 0) throw new IllegalArgumentException("Unterminated /* comment in SQL");

Type guard

boolean commentsTerminated(String sql) {
    if (sql == null) return false;
    int depth = 0;
    for (int i = 0; i < sql.length() - 1; i++) {
        if (sql.regionMatches(i, "/*", 0, 2)) depth++;
        else if (sql.regionMatches(i, "*/", 0, 2)) depth--;
    }
    return depth == 0;
}

Try / catch

try { stmt = preprocess(stmt); } catch (IllegalArgumentException e) {
    if (e.getMessage().contains("sql 注释 语法错误")) {
        throw new IllegalArgumentException("SQL contains an unterminated /* comment; fix and retry");
    } else throw e;
}

Prevention

When it happens

Trigger: Sending SQL containing '/*' without a matching '*/' — e.g. truncated hint comments like '/*' or '/*+hint' with no terminator — through the statement pre-processing in DruidMycatRouteStrategy (pos+4 < stmt.length() guard also means very short statements with '/*' near the end can hit it).

Common situations: Hand-written hint comments missing the closing */; string truncation by an upstream proxy or client cutting the SQL; generated SQL from tools that emit malformed comments; pasted SQL where a comment's tail was lost.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/b034c4a2d02553d9. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/impl/DruidMycatRouteStrategy.java:830

	 * @return RouteResultset		(数据路由集合)
	 * @author mycat
	 */
	private static RouteResultset analyseDescrSQL(SchemaConfig schema,
			RouteResultset rrs, String stmt, int ind) {

		final String MATCHED_FEATURE = "DESCRIBE ";
		final String MATCHED2_FEATURE = "DESC ";
		int pos = 0;
		while (pos < stmt.length()) {
			char ch = stmt.charAt(pos);
			// 忽略处理注释 /* */ BEN
			if(ch == '/' &&  pos+4 < stmt.length() && stmt.charAt(pos+1) == '*') {
				if(stmt.substring(pos+2).indexOf("*/") != -1) {
					pos += stmt.substring(pos+2).indexOf("*/")+4;
					continue;
				} else {
					// 不应该发生这类情况。
					throw new IllegalArgumentException("sql 注释 语法错误");
				}
			} else if(ch == 'D'||ch == 'd') {
				// 匹配 [describe ]
				if(pos+MATCHED_FEATURE.length() < stmt.length() && (stmt.substring(pos).toUpperCase().indexOf(MATCHED_FEATURE) != -1)) {
					pos = pos + MATCHED_FEATURE.length();
					break;
				} else if(pos+MATCHED2_FEATURE.length() < stmt.length() && (stmt.substring(pos).toUpperCase().indexOf(MATCHED2_FEATURE) != -1)) {
					pos = pos + MATCHED2_FEATURE.length();
					break;
				} else {
					pos++;
				}
			} else {
				break;
			}
		}

		// 重置ind坐标。BEN GONG

View on GitHub (pinned to 65f8d8beb7)