SqlWhereUtil.java 11.3 KB
package com.xly.util;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.expression.LongValue;

@Slf4j
public class SqlWhereUtil {

    /**
     * 去除为空的条件 和 bCheck=1 的条件
     * 然后判断是否还有有效的 WHERE 条件
     *
     * @param sql 原始SQL
     * @return true: 去除后还有有效条件; false: 去除后没有条件了
     */
    public static boolean hasValidConditionAfterClean(String sql) {
        if (StrUtil.isBlank(sql)) {
            return false;
        }

        try {
            Statement statement = CCJSqlParserUtil.parse(sql);
            Expression whereExpression = null;

            if (statement instanceof Select) {
                Select select = (Select) statement;
                PlainSelect plainSelect = select.getPlainSelect();
                if (plainSelect != null) {
                    whereExpression = plainSelect.getWhere();
                }
            } else if (statement instanceof Update) {
                Update update = (Update) statement;
                whereExpression = update.getWhere();
            } else if (statement instanceof Delete) {
                Delete delete = (Delete) statement;
                whereExpression = delete.getWhere();
            }

            if (whereExpression == null) {
                return false;
            }

            // 清理条件
            Expression cleanedExpression = cleanExpression(whereExpression);
            return cleanedExpression != null;

        } catch (JSQLParserException e) {
            log.warn("SQL 解析失败,使用简单判断: {}", sql, e);
            return hasValidConditionAfterCleanSimple(sql);
        }
    }

    /**
     * 递归清理表达式
     * 返回 null 表示整个表达式被清空
     */
    private static Expression cleanExpression(Expression expression) {
        if (expression == null) {
            return null;
        }

        // 处理 AND 表达式
        if (expression instanceof AndExpression) {
            AndExpression and = (AndExpression) expression;
            Expression left = cleanExpression(and.getLeftExpression());
            Expression right = cleanExpression(and.getRightExpression());

            if (left == null && right == null) {
                return null;
            } else if (left == null) {
                return right;
            } else if (right == null) {
                return left;
            } else {
                return new AndExpression(left, right);
            }
        }

        // 处理 OR 表达式
        if (expression instanceof OrExpression) {
            OrExpression or = (OrExpression) expression;
            Expression left = cleanExpression(or.getLeftExpression());
            Expression right = cleanExpression(or.getRightExpression());

            if (left == null && right == null) {
                return null;
            } else if (left == null) {
                return right;
            } else if (right == null) {
                return left;
            } else {
                return new OrExpression(left, right);
            }
        }

        // 处理括号表达式
        if (expression instanceof Parenthesis) {
            Parenthesis parenthesis = (Parenthesis) expression;
            Expression content = cleanExpression(parenthesis.getExpression());
            if (content == null) {
                return null;
            }
            return new Parenthesis(content);
        }

        // 判断是否为需要去除的条件
        if (shouldRemoveCondition(expression)) {
            return null;
        }

        return expression;
    }

    /**
     * 判断条件是否应该被去除
     */
    private static boolean shouldRemoveCondition(Expression expression) {
        // 1. IS NULL / IS NOT NULL
        if (expression instanceof IsNullExpression) {
            return true;
        }

        // 2. 等值比较: = '' , != '' , <> ''
        if (expression instanceof EqualsTo) {
            EqualsTo equals = (EqualsTo) expression;
            if (isEmptyString(equals.getRightExpression()) || isEmptyString(equals.getLeftExpression())) {
                return true;
            }
            // bCheck = 1
            if (isCheckOneCondition(equals)) {
                return true;
            }
        }

        // !=
        if (expression instanceof NotEqualsTo) {
            NotEqualsTo notEquals = (NotEqualsTo) expression;
            if (isEmptyString(notEquals.getRightExpression()) || isEmptyString(notEquals.getLeftExpression())) {
                return true;
            }
        }

        // 3. 函数判断为空: IFNULL(col, '') = '' , TRIM(col) = '' , NVL(col, '') = '' 等
        if (expression instanceof EqualsTo) {
            EqualsTo equals = (EqualsTo) expression;
            if (isFunctionReturnEmptyCheck(equals)) {
                return true;
            }
        }

        // 4. 其他比较操作符中可能包含空值判断
        if (expression instanceof ComparisonOperator) {
            ComparisonOperator comp = (ComparisonOperator) expression;
            if (isEmptyString(comp.getLeftExpression()) || isEmptyString(comp.getRightExpression())) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断表达式是否为空字符串常量 ''
     */
    private static boolean isEmptyString(Expression expression) {
        if (expression == null) {
            return false;
        }
        if (expression instanceof StringValue) {
            StringValue stringValue = (StringValue) expression;
            return "".equals(stringValue.getValue());
        }
        return false;
    }

    /**
     * 判断是否为 bCheck = 1 或 1 = bCheck
     */
    private static boolean isCheckOneCondition(EqualsTo equals) {
        Expression left = equals.getLeftExpression();
        Expression right = equals.getRightExpression();

        // bCheck = 1
        if (isColumnNameCheck(left) && isOneValue(right)) {
            return true;
        }
        // 1 = bCheck
        if (isOneValue(left) && isColumnNameCheck(right)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否为 bCheck 列(不区分大小写)
     */
    private static boolean isColumnNameCheck(Expression expression) {
        if (expression instanceof Column) {
            Column column = (Column) expression;
            String columnName = column.getColumnName();
            return columnName != null && columnName.equalsIgnoreCase("bCheck");
        }
        return false;
    }

    /**
     * 判断是否为数字 1
     */
    private static boolean isOneValue(Expression expression) {
        if (expression instanceof LongValue) {
            LongValue longValue = (LongValue) expression;
            return longValue.getValue() == 1;
        }
        return false;
    }

    /**
     * 判断是否为函数返回空值判断,如:IFNULL(col, '') = ''
     */
    private static boolean isFunctionReturnEmptyCheck(EqualsTo equals) {
        Expression left = equals.getLeftExpression();
        Expression right = equals.getRightExpression();

        // 情况1: 函数 = ''
        if (isNullReturnFunction(left) && isEmptyString(right)) {
            return true;
        }
        // 情况2: '' = 函数
        if (isEmptyString(left) && isNullReturnFunction(right)) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否为可能返回 NULL 的函数(在空值判断场景下)
     * 如: IFNULL(col, '') , NVL(col, '') , TRIM(col) , COALESCE(col, '')
     */
    private static boolean isNullReturnFunction(Expression expression) {
        if (!(expression instanceof Function)) {
            return false;
        }

        Function function = (Function) expression;
        String funcName = function.getName();

        if (funcName == null) {
            return false;
        }

        String upperName = funcName.toUpperCase();

        // 常见的空值处理函数
        switch (upperName) {
            case "IFNULL":
            case "NVL":
            case "NVL2":
            case "COALESCE":
            case "NULLIF":
                return true;
            case "TRIM":
            case "LTRIM":
            case "RTRIM":
                // TRIM 函数去除空格后判断为空
                return true;
            default:
                return false;
        }
    }

    // ===================== 简单判断方法(降级方案) =====================

    /**
     * 简单判断:去除条件后是否还有有效条件
     */
    private static boolean hasValidConditionAfterCleanSimple(String sql) {
        if (StrUtil.isBlank(sql)) {
            return false;
        }

        String upper = sql.toUpperCase();

        // 先找到 WHERE 位置
        int whereIdx = upper.indexOf("WHERE");
        if (whereIdx == -1) {
            return false;
        }

        // 提取 WHERE 后面的条件
        String whereClause = sql.substring(whereIdx + 5);

        // 去除 GROUP BY、ORDER BY、LIMIT 之后的内容
        int groupIdx = upper.indexOf("GROUP BY", whereIdx);
        int orderIdx = upper.indexOf("ORDER BY", whereIdx);
        int limitIdx = upper.indexOf("LIMIT", whereIdx);
        int endIdx = sql.length();
        if (groupIdx != -1) endIdx = Math.min(endIdx, groupIdx);
        if (orderIdx != -1) endIdx = Math.min(endIdx, orderIdx);
        if (limitIdx != -1) endIdx = Math.min(endIdx, limitIdx);

        String condition = sql.substring(whereIdx + 5, endIdx);

        // 去除需要过滤的条件
        String cleaned = condition;

        // 去除 IS NULL / IS NOT NULL
        cleaned = cleaned.replaceAll("(?i)\\bIS\\s+(NOT\\s+)?NULL\\b", "");

        // 去除 = '' / != '' / <> ''
        cleaned = cleaned.replaceAll("(?i)\\s*(=|!=|<>)\\s*''\\s*", "");
        cleaned = cleaned.replaceAll("(?i)\\s*''\\s*(=|!=|<>)\\s*", "");

        // 去除 bCheck = 1
        cleaned = cleaned.replaceAll("(?i)\\bbCheck\\s*=\\s*1\\b", "");

        // 去除函数空值判断: IFNULL(..., '') = ''
        cleaned = cleaned.replaceAll("(?i)\\b(IFNULL|NVL|COALESCE|TRIM)\\s*\\([^)]+\\)\\s*=\\s*''", "");
        cleaned = cleaned.replaceAll("(?i)\\b''\\s*=\\s*(IFNULL|NVL|COALESCE|TRIM)\\s*\\([^)]+\\)", "");

        // 去除多余的 AND/OR
        cleaned = cleaned.replaceAll("(?i)\\s+(AND|OR)\\s+", " ");
        cleaned = cleaned.trim();

        // 判断是否还有有效条件(非空且不是纯粹的 true/false)
        if (StrUtil.isBlank(cleaned)) {
            return false;
        }

        // 如果只剩下 1=1 或 true 等恒真条件,也算无效
        if (cleaned.matches("(?i)^\\s*(1\\s*=\\s*1|true)\\s*$")) {
            return false;
        }

        return true;
    }
}