Tencent/APIJSON · error · IllegalArgumentException

字符 {expression} 不合法!预编译模式下 {example} 中 function 必须符合小写英文单词的

Error message

字符 {expression} 不合法!预编译模式下 {example} 中 function 必须符合小写英文单词的 SQL 函数名格式!不能同时存在窗口函数关键词 OVER 和全文索引关键词 AGAINST!

What it means

parseSQLExpression detects both the window-function marker ")OVER(" and the full-text marker ")AGAINST(" in one @column expression, which is not a supported shape — the parser can handle one of the two, never both, and refuses rather than mis-parse. It is an anti-injection/robustness guard on function expressions.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:2548

				if (KEY_COLUMN.equals(key)) {
					example = key + ":\"column0,column1:alias1;function0(arg0,arg1,...);function1(...):alias2...\"";
				}
				//	和 key{}:"" 一样		else if (KEY_HAVING.equals(key) || KEY_HAVING_AND.equals(key)) {
				//					exeptionExample = key + ":\"function0(arg0,arg1,...)>1;function1(...)%5<=3...\"";
				//				}
				else {
					example = key + ":\"column0!=0;column1+3*2<=10;function0(arg0,arg1,...)>1;function1(...)%5<=3...\"";
				}
			}

			//有函数,但不是窗口函数
			int overIndex = expression.indexOf(")OVER(");  // 传参不传空格,拼接带空格  ") OVER (");
			int againstIndex = expression.indexOf(")AGAINST(");  // 传参不传空格,拼接带空格  ") AGAINST (");
			boolean containOver = overIndex > 0 && overIndex < expression.length() - ")OVER(".length();
			boolean containAgainst = againstIndex > 0 && againstIndex < expression.length() - ")AGAINST(".length();

			if (containOver && containAgainst) {
				throw new IllegalArgumentException("字符 " + expression + " 不合法!预编译模式下 " + example
						+ " 中 function 必须符合小写英文单词的 SQL 函数名格式!不能同时存在窗口函数关键词 OVER 和全文索引关键词 AGAINST!");
			}

			if (containOver == false && containAgainst == false) {
				int end = expression.lastIndexOf(')');
				if (start >= end) {
					throw new IllegalArgumentException("字符 " + expression + " 不合法!"
							+ key + ":value 中 value 里的 SQL函数必须为 function(arg0,arg1,...) 这种格式!");
				}
				String fun = expression.substring(0, start);
				if (fun.isEmpty() == false) {
					if (SQL_FUNCTION_MAP == null || SQL_FUNCTION_MAP.isEmpty()) {
						if (StringUtil.isName(fun) == false) {
							throw new IllegalArgumentException("字符 " + fun + " 不合法!预编译模式下 " + example
									+ " 中 function 必须符合小写英文单词的 SQL 函数名格式!");
						}
					} else if (SQL_FUNCTION_MAP.containsKey(fun) == false) {
						throw new IllegalArgumentException("字符 " + fun + " 不合法!预编译模式下 " + example

View on GitHub (pinned to 5284052872)

Solutions

  1. Split into two ';'-separated expressions so each contains only one of OVER or AGAINST.
  2. Write the complex expression as server-side @raw and reference its alias.
  3. Verify the target SQL dialect even supports the combination before trying to express it here.

Example fix

// before
{"Comment":{"@column":"match(content)AGAINST('api')OVER(PARTITION BY id)"}}
// after (two items)
{"Comment":{"@column":"match(content)AGAINST('api');row_number()OVER(PARTITION BY id)"}}
Defensive patterns

Strategy: validation

Validate before calling

if (expr.includes(')OVER(') && expr.includes(')AGAINST(')) throw new Error('OVER and AGAINST cannot coexist in one expression');

Type guard

null

Try / catch

catch IllegalArgumentException; split the expression and retry as two items

Prevention

When it happens

Trigger: An @column item literally containing both ')OVER(' and ')AGAINST(', e.g. an attempt to nest a full-text match inside a window function: "match(name) AGAINST ('a') OVER (PARTITION BY id)" written without spaces, or fuzzed/adversarial input probing the parser.

Common situations: Attempting to combine MATCH...AGAINST with window framing in one expression (not valid in this DSL); copy-pasting SQL containing both keywords without spaces; penetration-test payloads.

Related errors


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/d84e0c3c6e9be79f. Report an issue: GitHub.