美文网首页
druid分析SQL

druid分析SQL

作者: anyly | 来源:发表于2019-08-07 20:20 被阅读0次

    sql解析工具 druid

    1.优点:因为本身做连接池,sql解析比jsqlparse要彻底
    2.操作sql方便,直接操作对象

    需求:在所有的条件后面拼接

    is_delete =0 or name IN ('lisr', 'gqq') // 如果表有别名自动获取,否则用表全名

    代码->支持复杂的连表查询:
     @Test
        public void testDruidParserSql() {
            String sql = SqlConfig.IN1;
            //将string类型转换为sql对象
            SQLExpr exp = SQLUtils.toSQLExpr(sql);
            sqlExpr(exp);
            System.out.println(" sql print :->>>>>>>>>>>>>>>> \r\n" + exp.toString());
        }
    
        /**
         * @param exp
         */
        public void sqlExpr(SQLExpr exp) {
            if (exp != null && exp instanceof SQLQueryExpr) {
                sqlSelect(((SQLQueryExpr) exp).getSubQuery());
            } else if (exp instanceof SQLInSubQueryExpr) {
                sqlSelect(((SQLInSubQueryExpr) exp).getSubQuery());
            } else if (exp instanceof SQLBinaryOpExpr) {
                sqlExpr(((SQLBinaryOpExpr) exp).getRight());
                sqlExpr(((SQLBinaryOpExpr) exp).getRight());
            } else if (exp instanceof SQLInListExpr
                    || exp instanceof SQLIntegerExpr
                    || exp instanceof SQLCharExpr
                    || exp instanceof SQLPropertyExpr
            ) {
                return;
            } else {
                System.out.println(exp.getClass() + ":遇到无法解析的对象:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            }
        }
    
        /**
         * sql select
         *
         * @param sqlSelect
         */
        private void sqlSelect(SQLSelect sqlSelect) {
            sqlSelectQuery(sqlSelect.getQuery());
        }
    
        /**
         * @param sqlSelectQuery
         */
        private void sqlSelectQuery(SQLSelectQuery sqlSelectQuery) {
            if (sqlSelectQuery instanceof SQLSelectQueryBlock) {
                if (((SQLSelectQueryBlock) sqlSelectQuery).getSelectList().size() > 1) {
                    List<SQLSelectItem> sqlSelectItems = ((SQLSelectQueryBlock) sqlSelectQuery).getSelectList();
                    sqlSelectItems.forEach(sqlSelectItem -> sqlExpr(sqlSelectItem.getExpr()));
                }
                sqlTableSource(((SQLSelectQueryBlock) sqlSelectQuery).getFrom());
            } else if (sqlSelectQuery instanceof SQLUnionQuery) {
                sqlSelectQuery(((SQLUnionQuery) sqlSelectQuery).getLeft());
                sqlSelectQuery(((SQLUnionQuery) sqlSelectQuery).getRight());
            } else {
                System.out.println(sqlSelectQuery.getClass() + ":遇到无法解析的对象:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            }
        }
    
        /**
         * @param sqlTableSource
         */
        private void sqlTableSource(SQLTableSource sqlTableSource) {
            // 右边是连接查询
            if (sqlTableSource instanceof SQLJoinTableSource) {
                sqlTableSource(((SQLJoinTableSource) sqlTableSource).getRight());
                sqlTableSource(((SQLJoinTableSource) sqlTableSource).getLeft());
                // 右边是子查询
            } else if (sqlTableSource instanceof SQLSubqueryTableSource) {
                sqlSelect(((SQLSubqueryTableSource) sqlTableSource).getSelect());
                // 右边是 union
            } else if (sqlTableSource instanceof SQLUnionQueryTableSource) {
                sqlSelectQuery(((SQLUnionQueryTableSource) sqlTableSource).getUnion());
                //  右边是table
            } else if (sqlTableSource instanceof SQLExprTableSource) { // 当tablesource 为 SQLExprTableSource 时候即可拼接sql
                String alias = getAlias(sqlTableSource);
                System.out.println("table:" + sqlTableSource + "> alias:" + alias);
                SQLSelectQueryBlock sqlSelectQueryBlock = getSelectQueryBlock(sqlTableSource);
                if (sqlSelectQueryBlock != null) {
                    sqlSelectQueryBlock(sqlSelectQueryBlock, alias);
                }
            } else {
                System.out.println(sqlTableSource.getClass() + ":遇到无法解析的对象:" + Thread.currentThread().getStackTrace()[1].getMethodName());
            }
        }
    
        /**
         * 通过迭代获取 MySqlSelectQueryBlock
         *
         * @param sqlObject
         * @return
         */
        private SQLSelectQueryBlock getSelectQueryBlock(SQLObject sqlObject) {
            if (sqlObject.getParent() instanceof SQLSelectQueryBlock) {
                return (SQLSelectQueryBlock) sqlObject.getParent();
            } else {
                return getSelectQueryBlock(sqlObject.getParent());
            }
        }
    
        /**
         * sql 拼接
         *
         * @param sqlSelectQueryBlock
         * @param alias
         */
        private void sqlSelectQueryBlock(SQLSelectQueryBlock sqlSelectQueryBlock, String alias) {
            if (sqlSelectQueryBlock.getWhere() != null) {
                sqlExpr(sqlSelectQueryBlock.getWhere());
            }
    
            SQLBinaryOpExpr sqlBinaryOpExpr = new SQLBinaryOpExpr(new SQLPropertyExpr(alias, "is_delete"),
                    new SQLIntegerExpr(0), SQLBinaryOperator.Equality);
            // 第一个条件
            //     whereAdd(sqlSelectQueryBlock, sqlBinaryOpExpr);
    
            SQLInListExpr sqlInListExpr = new SQLInListExpr();
            sqlInListExpr.setExpr(new SQLPropertyExpr(alias, "name"));
            List<SQLExpr> list = new ArrayList();
            list.add(new SQLCharExpr("lisr"));
            list.add(new SQLCharExpr("gqq"));
            sqlInListExpr.setTargetList(list);
            // 第二个条件
            // whereAdd(sqlSelectQueryBlock, sqlInListExpr);
    
            SQLBinaryOpExpr whereExpr = new SQLBinaryOpExpr(sqlBinaryOpExpr, SQLBinaryOperator.BooleanOr, sqlInListExpr);
            whereAdd(sqlSelectQueryBlock, whereExpr);
    
        }
    
        public void whereAdd(SQLSelectQueryBlock sqlSelectQueryBlock, SQLExpr sqlExpr) {
            if (sqlSelectQueryBlock.getWhere() != null) {
                SQLExpr sqlExprWhere = sqlSelectQueryBlock.getWhere();
                List<SQLObject> sqlList = sqlExprWhere.getChildren();
                List<SQLObject> sqlObjectList = sqlExpr.getChildren();
                if (sqlList != null && sqlList.size() > 1) {
                    // 原有的where 如果是or 则不拆
                    if (sqlExprWhere instanceof SQLBinaryOpExpr) {
                        if (!((SQLBinaryOpExpr) sqlExprWhere).getOperator().equals(SQLBinaryOperator.BooleanOr)) {
                            // 原有where 和需要拼接的where
                            if (sqlObjectList != null && sqlObjectList.size() > 1) {
                                if (!((SQLBinaryOpExpr) sqlExpr).getOperator().equals(SQLBinaryOperator.BooleanOr)) {
                                    sqlObjectList.forEach(sqlObject -> {
                                        if (!sqlList.contains(sqlObject)) {
                                            sqlSelectQueryBlock.addWhere((SQLExpr) sqlObject);
                                        }
                                    });
                                } else {
                                    if (!sqlList.contains(sqlExpr)) {
                                        sqlSelectQueryBlock.addWhere(sqlExpr);
                                    }
                                }
                            } else {
                                if (!sqlList.contains(sqlExpr)) {
                                    sqlSelectQueryBlock.addWhere(sqlExpr);
                                }
                            }
                        } else {
                            sqlSelectQueryBlock.addWhere(sqlExpr);
                        }
                    } else if (sqlExprWhere instanceof SQLInSubQueryExpr) {
                        sqlSelectQueryBlock.addWhere(sqlExpr);
                    } else {
                        sqlSelectQueryBlock.addWhere(sqlExpr);
                    }
                } else {
                    sqlSelectQueryBlock.addWhere(sqlExpr);
                }
            } else {
                sqlSelectQueryBlock.addWhere(sqlExpr);
            }
    
        }
    
        /**
         * 获取别名
         *
         * @param tableSource
         * @return
         */
        private String getAlias(SQLTableSource tableSource) {
            if (StringUtils.isEmpty(tableSource.getAlias())) {
                if (((SQLExprTableSource) tableSource).getExpr() instanceof SQLIdentifierExpr) {
                    return ((SQLIdentifierExpr) ((SQLExprTableSource) tableSource).getExpr()).getName();
                }
            }
            return tableSource.getAlias();
        }
    
    • 下面看sql例子
    example1 自带in
    SELECT *
    FROM t_sys_user tsu
    WHERE tsu.name IN (
        SELECT tsc.id
        FROM t_sys_config tsc
        WHERE tsc.id = 1
    )
    
    example1执行后结果
    SELECT *
    FROM t_sys_user tsu
    WHERE tsu.name IN (
        SELECT tsc.id
        FROM t_sys_config tsc
        WHERE tsc.id = 1
        AND (tsc.is_delete = 0
            OR tsc.name IN ('lisr', 'gqq'))
    )
    AND (tsu.is_delete = 0
        OR tsu.name IN ('lisr', 'gqq'))
    

    example2 带左连接
    SELECT temp.*
    FROM (
        SELECT tsc.*
        FROM t_sys_config tsc
            LEFT JOIN t_sys_user tsu ON tsc.id = tsu.id
        WHERE tsc.id = 1
        ORDER BY tsc.id
    ) temp
    WHERE temp.id = 1
        AND temp.id = 2
    
    example2执行后结果
    SELECT temp.*
    FROM (
        SELECT tsc.*
        FROM t_sys_config tsc
            LEFT JOIN t_sys_user tsu ON tsc.id = tsu.id
        WHERE tsc.id = 1
        AND (tsu.is_delete = 0
            OR tsu.name IN ('lisr', 'gqq'))
        AND (tsc.is_delete = 0
            OR tsc.name IN ('lisr', 'gqq'))
        ORDER BY tsc.id
    ) temp
    WHERE temp.id = 1
        AND temp.id = 2
    

    example3 连接子查询
    SELECT tsu.*
    FROM t_sys_user tsu
        RIGHT JOIN (
            SELECT *
            FROM t_sys_config
        ) tsc
        ON tsc.id = tsu.id
    
    example3执行后结果
    SELECT tsu.*
    FROM t_sys_user tsu
        RIGHT JOIN (
            SELECT *
            FROM t_sys_config
            WHERE t_sys_config.is_delete = 0
            OR t_sys_config.name IN ('lisr', 'gqq')
        ) tsc
        ON tsc.id = tsu.id
    WHERE tsu.is_delete = 0
    OR tsu.name IN ('lisr', 'gqq')
    

    example4 用union
    SELECT *
    FROM t_sys_user tsu
    WHERE tsu.id = 1
        AND tsu.is_delete = 0
    UNION ALL
    SELECT *
    FROM t_sys_config tsc
    WHERE tsc.id = 2
        AND tsc.is_delete = 0
    
    example4执行后结果
    SELECT *
    FROM t_sys_user tsu
    WHERE tsu.id = 1
    AND tsu.is_delete = 0
    AND (tsu.is_delete = 0
        OR tsu.name IN ('lisr', 'gqq'))
    UNION ALL
    SELECT *
    FROM t_sys_config tsc
    WHERE tsc.id = 2
    AND tsc.is_delete = 0
    AND (tsc.is_delete = 0
        OR tsc.name IN ('lisr', 'gqq'))
    

    example5 普通sql
    SELECT *
    FROM t_sys_user tsu
        LEFT JOIN t_config tc
        ON tc.id = tsu.id
            AND tsu.name = 'test'
    
    example5执行后结果
    SELECT *
    FROM t_sys_user tsu
        LEFT JOIN t_config tc
        ON tc.id = tsu.id
            AND tsu.name = 'test'
    WHERE (tc.is_delete = 0
        OR tc.name IN ('lisr', 'gqq'))
    AND (tsu.is_delete = 0
        OR tsu.name IN ('lisr', 'gqq'))
    
    上面的代码支持复杂的sql拼接,但也有很多sql不支持,也可以提供给我改善代码,代码只为告诉大家有一个这么叼的工具,至于做什么不多说.

    相关文章

      网友评论

          本文标题:druid分析SQL

          本文链接:https://www.haomeiwen.com/subject/nyafrctx.html