{"record":{"id":"041a6ecf1b674ef1","repo":"Tencent/APIJSON","slug":"ck-column-value-value","errorCode":null,"errorMessage":"字符 {ck} 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项 column:alias 中 column 必须是1个单词！如果有alias，则alias也必须为1个单词！关键字必须全大写，且以空格分隔的参数，空格必须只有 1 个！其它情况不允许空格！","messagePattern":"字符 (.+?) 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项 column:alias 中 column 必须是1个单词！如果有alias，则alias也必须为1个单词！关键字必须全大写，且以空格分隔的参数，空格必须只有 1 个！其它情况不允许空格！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":2730,"sourceCode":"\t\t\t\t\t// 参数不包含\",\",即不是字符串\n\t\t\t\t\t// 解析参数:1. 字段 ,2. 是以空格分隔的参数 eg: cast(now() as date)\n\t\t\t\t\tif (\"=null\".equals(ck)) {\n\t\t\t\t\t\torigin = SQL.isNull();\n\t\t\t\t\t}\n\t\t\t\t\telse if (\"!=null\".equals(ck)) {\n\t\t\t\t\t\torigin = SQL.isNull(false);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\torigin = ck;\n\t\t\t\t\t\talias = null;\n\t\t\t\t\t\tif (allowAlias) {\n\t\t\t\t\t\t\tint index = isColumn ? ck.lastIndexOf(\":\") : -1; //StringUtil.split返回数组中，子项不会有null\n\t\t\t\t\t\t\torigin = index < 0 ? ck : ck.substring(0, index); //获取 : 之前的\n\t\t\t\t\t\t\talias = index < 0 ? null : ck.substring(index + 1);\n\t\t\t\t\t\t\tif (isPrepared()) {\n\t\t\t\t\t\t\t\tif (isColumn) {\n\t\t\t\t\t\t\t\t\tif (StringUtil.isName(origin) == false || (alias != null && StringUtil.isName(alias) == false)) {\n\t\t\t\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"字符 \" + ck + \" 不合法！\"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \"预编译模式下 @column:value 中 value里面用 , 分割的每一项\"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \" column:alias 中 column 必须是1个单词！如果有alias，则alias也必须为1个单词！\"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \"关键字必须全大写，且以空格分隔的参数，空格必须只有 1 个！其它情况不允许空格！\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tif (origin.startsWith(\"_\") || origin.contains(\"--\")) {\n\t\t\t\t\t\t\t\t\t\t// || PATTERN_FUNCTION.matcher(origin).matches() == false) {\n\t\t\t\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"字符 \" + ck + \" 不合法！\"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \"预编译模式下 @column:\\\"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias...\\\"\"\n\t\t\t\t\t\t\t\t\t\t\t\t+ \" 中所有 arg 都必须是1个不以 _ 开头的单词 或者符合正则表达式 \"\n\t\t\t\t\t\t\t\t\t\t\t\t+ PATTERN_FUNCTION + \" 且不包含连续减号 -- ！\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\"DISTINCT 必须全大写，且后面必须有且只有 1 个空格！其它情况不允许空格！\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 以空格分割参数","sourceCodeStart":2712,"sourceCodeEnd":2748,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2712-L2748","documentation":"In parseArgsSplitWithComma with isColumn=true and allowAlias=true under prepared mode, every comma-separated item split at ':' must yield a single-word origin and (if present) a single-word alias. Spaces around ':', multi-word tokens, or SQL keywords mixed into column items all fail StringUtil.isName and throw this IllegalArgumentException — the message also notes keywords must be UPPERCASE with exactly one space for space-separated args.","triggerScenarios":"\"@column\":\"id : name\" (spaces around colon), \"@column\":\"user.id:name\" (dot), \"@column\":\"distinct id,name\" (lowercase keyword), or \"@column\":\"id,\" (trailing comma producing an empty token).","commonSituations":"Building @column by joining a list with ', ' (comma+space) instead of ','; copying SQL fragments verbatim; case-sensitive DISTINCT/CAST keywords written lowercase.","solutions":["Join items with ',' only — no space: \"id,name,sex\".","No spaces around ':' in column:alias.","Write keywords like DISTINCT fully uppercase with exactly one following space: \"DISTINCT id\".","Ensure each token is a bare identifier; drop trailing commas."],"exampleFix":"// before\n{\"User\":{\"@column\":\"id, name, distinct sex\"}}\n// after\n{\"User\":{\"@column\":\"id,name,DISTINCT sex\"}}","handlingStrategy":"validation","validationCode":"const NAME=/^[A-Za-z][A-Za-z0-9_]*$/;\nfunction okColList(v){return v.split(',').every(it=>{const i=it.lastIndexOf(':');const o=i<0?it:it.slice(0,i);const a=i<0?null:it.slice(i+1);return NAME.test(o)&&(a==null||a===''||NAME.test(a))});}\nif(!okColList(colVal))throw new Error('each column:alias must be single words, comma without spaces');","typeGuard":"function isValidColumnList(v) { return v.split(',').every(it => { const i = it.lastIndexOf(':'); const o = i < 0 ? it : it.slice(0, i); const a = i < 0 ? null : it.slice(i + 1); return /^[A-Za-z][A-Za-z0-9_]*$/.test(o) && (a == null || a === '' || /^[A-Za-z][A-Za-z0-9_]*$/.test(a)); }); }","tryCatchPattern":"catch IllegalArgumentException; normalize (strip spaces, fix keyword case) and retry once","preventionTips":["Join columns with ',' not ', '","Write keywords like DISTINCT fully uppercase with exactly one space","No spaces around ':' in column:alias items"],"tags":["apijson","sql","input-validation","column-name","alias"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}