{"record":{"id":"d22373015d0df6b2","repo":"baomidou/mybatis-plus","slug":"sql-where-or-or","errorCode":null,"errorMessage":"非法SQL，where条件中不能使用【or】关键字，错误or信息：{}","messagePattern":"非法SQL，where条件中不能使用【or】关键字，错误or信息：(.+?)","errorType":"exception","errorClass":"MybatisPlusException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java","lineNumber":176,"sourceCode":"        List<Join> joins = delete.getJoins();\n        validWhere(where, table, (Connection) obj);\n        validJoins(joins, table, (Connection) obj);\n    }\n\n    /**\n     * 验证expression对象是不是 or、not等等\n     *\n     * @param expression ignore\n     */\n    private void validExpression(Expression expression) {\n        while (expression instanceof Parenthesis) {\n            Parenthesis parenthesis = (Parenthesis) expression;\n            expression = parenthesis.getExpression();\n        }\n        //where条件使用了 or 关键字\n        if (expression instanceof OrExpression) {\n            OrExpression orExpression = (OrExpression) expression;\n            throw new MybatisPlusException(\"非法SQL，where条件中不能使用【or】关键字，错误or信息：\" + orExpression.toString());\n        } else if (expression instanceof NotEqualsTo) {\n            NotEqualsTo notEqualsTo = (NotEqualsTo) expression;\n            throw new MybatisPlusException(\"非法SQL，where条件中不能使用【!=】关键字，错误!=信息：\" + notEqualsTo.toString());\n        } else if (expression instanceof BinaryExpression) {\n            BinaryExpression binaryExpression = (BinaryExpression) expression;\n            // TODO 升级 jsqlparser 后待实现\n//            if (binaryExpression.isNot()) {\n//                throw new MybatisPlusException(\"非法SQL，where条件中不能使用【not】关键字，错误not信息：\" + binaryExpression.toString());\n//            }\n            if (binaryExpression.getLeftExpression() instanceof Function) {\n                Function function = (Function) binaryExpression.getLeftExpression();\n                throw new MybatisPlusException(\"非法SQL，where条件中不能使用数据库函数，错误函数信息：\" + function.toString());\n            }\n            if (binaryExpression.getRightExpression() instanceof Subtraction) {\n                Subtraction subSelect = (Subtraction) binaryExpression.getRightExpression();\n                throw new MybatisPlusException(\"非法SQL，where条件中不能使用子查询，错误子查询SQL信息：\" + subSelect.toString());\n            }\n        } else if (expression instanceof InExpression) {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-jsqlparser-support/mybatis-plus-jsqlparser-4.9/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java#L158-L194","documentation":"IllegalSQLInnerInterceptor (jsqlparser 4.9) throws when the parsed WHERE condition's top-level expression (after unwrapping parentheses) is an OrExpression. The interceptor is a policy check that forbids OR in WHERE clauses (usually to prevent index-bypassing scans); the offending OR expression is appended to the message.","triggerScenarios":"Executing a mapped statement or wrapper query whose WHERE contains a top-level OR (e.g. name = ? OR age = ?) while the IllegalSQLInnerInterceptor is registered in MybatisPlusInterceptor.","commonSituations":"Team policy bans OR for performance; a developer adds queryWrapper.or(...) or writes native SQL with OR, and the interceptor rejects it at execution time. Parenthesized ORs are unwrapped, so wrapping in parens does not bypass it.","solutions":["Rewrite the predicate without top-level OR: use IN (...), BETWEEN, or split the comparison so the first indexed column stands alone.","If OR is legitimately needed, remove IllegalSQLInnerInterceptor from the interceptor chain for that statement or entirely, or scope it via InterceptorIgnoreHelper (@InterceptorIgnore(illegalSql = \"true\")).","Review with the DBA whether the OR's columns are indexed; if both sides are indexed the policy may be relaxed deliberately."],"exampleFix":"// before\nSELECT * FROM user WHERE name = ? OR id = ?;\n\n// after\nSELECT * FROM user WHERE id = ? OR-deleted -- use indexed equality first / IN list\nSELECT * FROM user WHERE id IN (?) AND name = ?;","handlingStrategy":"validation","validationCode":"// Static guard in code review / unit test: scan mapped SQL for top-level OR\n// e.g. with a test that parses XML/annotations and asserts no OrExpression at WHERE top level,\n// or simply forbid QueryWrapper.or() usage via ArchUnit:\n// noClasses().should().callMethod(QueryWrapper.class, \"or\")","typeGuard":null,"tryCatchPattern":"try {\n    mapper.selectList(wrapper);\n} catch (MybatisPlusException e) {\n    if (String.valueOf(e.getMessage()).contains(\"不能使用【or】\")) {\n        log.error(\"policy violation: rewrite predicate without OR: {}\", e.getMessage());\n    }\n}","preventionTips":["Codify the no-OR policy in review checklists and forbid wrapper.or() via static analysis.","Provide approved rewrites (IN, range predicates) in team docs.","Use @InterceptorIgnore(illegalSql=\"true\") deliberately and track each usage."],"tags":["mybatis-plus","sql-parsing","interceptor","policy","jsqlparser"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}