{"record":{"id":"9a711a7e1ec4fd88","repo":"Tencent/APIJSON","slug":"method-having-column-value-func","errorCode":null,"errorMessage":"字符 ${method} 不合法！预编译模式下 @having:\"column?value;function(arg0,arg1,...)?value...\" 中 function 必须符合小写英文单词的 SQL 函数名格式！","messagePattern":"字符 (.+?) 不合法！预编译模式下 @having:\"column\\?value;function\\(arg0,arg1,\\.\\.\\.\\)\\?value\\.\\.\\.\" 中 function 必须符合小写英文单词的 SQL 函数名格式！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":1786,"sourceCode":"\t\t\t\tthrow new UnsupportedOperationException(\"字符串 \" + expression + \" 不合法！\"\n\t\t\t\t\t\t+ \"预编译模式下 @having:\\\"column?value;function(arg0,arg1,...)?value...\\\"\"\n\t\t\t\t\t\t+ \" 中 column?value 必须符合正则表达式 \" + PATTERN_FUNCTION + \" 且不包含连续减号 -- ！不允许空格！\");\n\t\t\t}\n\t\t\t\n\t\t\treturn parseSQLExpression(KEY_HAVING, expression, containRaw, false, null);\n\t\t}\n\n\t\tint end = expression.lastIndexOf(\")\");\n\t\tif (start >= end) {\n\t\t\tthrow new IllegalArgumentException(\"字符 \" + expression + \" 不合法！\"\n\t\t\t\t\t+ \"@having:value 中 value 里的 SQL函数必须为 function(arg0,arg1,...) 这种格式！\");\n\t\t}\n\n\t\tString method = expression.substring(0, start);\n\t\tif (method.isEmpty() == false) {\n\t\t\tif (SQL_FUNCTION_MAP == null || SQL_FUNCTION_MAP.isEmpty()) {\n\t\t\t\tif (StringUtil.isName(method) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"字符 \" + method + \" 不合法！\"\n\t\t\t\t\t\t\t+ \"预编译模式下 @having:\\\"column?value;function(arg0,arg1,...)?value...\\\"\"\n\t\t\t\t\t\t\t+ \" 中 function 必须符合小写英文单词的 SQL 函数名格式！\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (SQL_FUNCTION_MAP.containsKey(method) == false) {\n\t\t\t\tthrow new IllegalArgumentException(\"字符 \" + method + \" 不合法！\"\n\t\t\t\t\t\t+ \"预编译模式下 @column:\\\"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias...\\\"\"\n\t\t\t\t\t\t+ \" 中 function 必须符合小写英文单词的 SQL 函数名格式！且必须是后端允许调用的 SQL 函数!\");\n\t\t\t}\n\t\t}\n\n\t\treturn method + parseSQLExpression(KEY_HAVING, expression.substring(start), containRaw, false, null);\n\t}\n\n\t@Override\n\tpublic String getSample() {\n\t\treturn sample;\n\t}","sourceCodeStart":1768,"sourceCodeEnd":1804,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L1768-L1804","documentation":"For a function call in @having, when the backend has no SQL_FUNCTION_MAP configured (null or empty) the fallback check StringUtil.isName(method) applies: the function name before '(' must be a plain identifier. Otherwise IllegalArgumentException. This is the lenient path — it validates shape but cannot whitelist.","triggerScenarios":"\"@having\": \"ma x(1)>0\" (space in name), \"@having\": \"1max(a)>0\" (starts with digit), \"@having\": \"max-(a)>0\" — the extracted method substring fails isName when SQL_FUNCTION_MAP is unset.","commonSituations":"Self-hosted APIJSON where SQL_FUNCTION_MAP was never populated; typos in function names producing stray characters; trying schema-qualified names like schema.func().","solutions":["Use a clean single-word function name: \"@having\": \"max(amount)>10\"","Backend: configure SQL_FUNCTION_MAP so functions are whitelist-checked instead","Avoid qualified/odd names; alias complex expressions via @raw"],"exampleFix":"// before\n{\"@having\": \"schema.max(amount)>10\"}\n// after\n{\"@having\": \"max(amount)>10\"}","handlingStrategy":"validation","validationCode":"const fnName = hv.slice(0, hv.indexOf('('));\nif (fnName && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(fnName)) {\n  throw new Error(`@having function '${fnName}' must be a plain identifier when SQL_FUNCTION_MAP is unset`);\n}","typeGuard":"const isPlainFunctionName = s => /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);","tryCatchPattern":"try { await api.get(req); } catch (e) { if (e.message.includes('SQL 函数名格式') && e.message.includes('@having')) suggestConfiguringFunctionMap(); else throw e; }","preventionTips":["Use unqualified function names (no schema. prefix)","Configure SQL_FUNCTION_MAP in production so names are whitelisted, not just shape-checked"],"tags":["apijson","having","function-name","config"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}