在最近的项目开发中,有这样一个需求,就是给定一个查询的sql,在where语句中添加几个条件语句。刚开始想的是,是否能用正则去做这个事情呢?其实不用语法树还是有一点困难的。

经过一系列google,看到了我们国产的druid里面sql parse的稳当还是比较详尽。具体参考这个文档SQL Parser

还是回到之前的需求:

public List<Map<String, Object>> search(String sql, Map<String, Object> conditions) {
List<Map<String, Object>> result = new ArrayList<>();
// SQLParserUtils.createSQLStatementParser可以将sql装载到Parser里面
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtils.MYSQL);
// parseStatementList的返回值SQLStatement本身就是druid里面的语法树对象
List<SQLStatement> stmtList = parser.parseStatementList(); SQLStatement stmt = stmtList.get(0);
if (stmt instanceof SQLSelectStatement) {
// convert conditions to 'and' statement
StringBuffer constraintsBuffer = new StringBuffer();
Set<String> keys = conditions.keySet();
Iterator<String> keyIter = keys.iterator();
if (keyIter.hasNext()) {
constraintsBuffer.append(keyIter.next()).append(" = ?");
}
while (keyIter.hasNext()) {
constraintsBuffer.append(" AND ").append(keyIter.next()).append(" = ?");
}
SQLExprParser constraintsParser = SQLParserUtils.createExprParser(constraintsBuffer.toString(), JdbcUtils.MYSQL);
SQLExpr constraintsExpr = constraintsParser.expr(); SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;
// 拿到SQLSelect 通过在这里打断点看对象我们可以看出这是一个树的结构
SQLSelect sqlselect = selectStmt.getSelect();
SQLSelectQueryBlock query = (SQLSelectQueryBlock) sqlselect.getQuery();
SQLExpr whereExpr = query.getWhere();
// 修改where表达式
if (whereExpr == null) {
query.setWhere(constraintsExpr);
} else {
SQLBinaryOpExpr newWhereExpr = new SQLBinaryOpExpr(whereExpr, SQLBinaryOperator.BooleanAnd, constraintsExpr);
query.setWhere(newWhereExpr);
}
sqlselect.setQuery(query);
sql = sqlselect.toString();
Session session = sessionFactory.openSession();
SQLQuery sqlQuery = session.createSQLQuery(sql);
Collection values = conditions.values();
int index = 1;
for (Object value : values) {
sqlQuery.setParameter(index, value);
index++;
}
result = sqlQuery.list();
session.close();
} else {
throw new Exception("not select statement");
}
return result;
}

利用druid sql parser搞一些事情的更多相关文章

  1. com.alibaba.druid.sql.parser.ParserException: syntax error, QUES %, pos 80 like报错解决

    最近,把各应用的jdbc连接池统一从dbcp2改成了druid,运行时druid报sql解析错误,如下: select * from test         where 1=1         &l ...

  2. 【spring boot】集成了druid后,同样的mybatis模糊查询语句出错Caused by: com.alibaba.druid.sql.parser.ParserException: syntax error, error in :'name LIKE '%' ? '%'

    druid版本是 <!-- https://mvnrepository.com/artifact/com.alibaba/druid 数据库连接池--> <dependency> ...

  3. ORA-00907: 缺失右括号问题或com.alibaba.druid.sql.parser.ParserException: TODO :IDENTIFIER的原因

    以上只是说明错误的原因的一种.

  4. 利用 druid 的 sql parser 模块解析 sql 语句

    druid 是阿里开源在 github 上面的数据库连接池,里面有一个专门解析 sql 语句的模块   源码位置: https://github.com/alibaba/druid SQL Parse ...

  5. Druid SQL注入防御模块技术浅析

    官方参考: https://www.bookstack.cn/read/Druid/ffdd9118e6208531.md 前置知识 什么是Druid? Druid是一个高效的数据查询系统,主要解决的 ...

  6. Druid SQL 解析器概览

    概览 Druid 的官方 wiki 对 SQL 解析器部分的讲解内容并不多,但虽然不多,也有利于完全没接触过 Druid 的人对 SQL 解析器有个初步的印象. 说到解析器,脑海里便很容易浮现 par ...

  7. sql注入搞事情(连载一)

    SQL注入搞事情(连载一) 概述 写在最前面 为了有个合理的训练计划,山人准备长期开放自己的训练计划以及内容以供大家参考.山人专业是信息对抗技术,不是web方向的博客保证句句手打,如有问题请及时小窗. ...

  8. sql parser

    最近在整理很多SQL代码, 需要分析出每个SQL的目标表和源表各有哪些, 网上没有找到工作具, 打算写个工具. Java调研结果:1. 商业组件包 sqlparser 有试用版组件, 限制SQL少于1 ...

  9. Spark SQL catalyst概述和SQL Parser的具体实现

    之前已经对spark core做了较为深入的解读,在如今SQL大行其道的背景下,spark中的SQL不仅在离线batch处理中使用广泛,structured streamming的实现也严重依赖spa ...

随机推荐

  1. 作为web开发人员,你必须要知道的问题! (持续更新)

    GET 和 POST 的区别 GET请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:/test/demo_form.asp?name1=value1&name2=val ...

  2. 七十五:flask.Restful之Restful.API介绍

    restful api是用于在前端与后台进行通信的一套规范,使用这个规范可以让前后端开发变得更加轻松 协议:http或者https 数据传输格式:使用json url链接:url链接中不能有动词(/g ...

  3. HTML <canvas> 学习笔记

    Professional JavaScript for Web Developers    P552 Basic Usage The <canvas> element requires a ...

  4. Python学习之认知(二)

    第二章(二) 2.1.5 变量 ​ 变量:将运算的中间结果暂存到内存,以便后续程序调⽤. 变量的命名规则: ​ 1.变量由字母, 数字,下划线搭配组合⽽成 ​ 2.不可以⽤数字开头,更不能是全数字 ​ ...

  5. 【Python开发】Lambda表达式使用

    lambda只是一个表达式,函数体比def简单很多. lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去. lambda表达式是起到一个函数速写的作用.允 ...

  6. 【VS开发】CTimeSpan类

    CTimeSpan类.        日期和时间类简介        CTime类的对象表示的时间是基于格林威治标准时间(GMT)的.CTimeSpan类的对象表示的是时间间隔.        CTi ...

  7. javaScript学习总结(二)——jQuery插件的开发

    概要 jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定 ...

  8. 面向服务架构之RPC原理与实例

    1.RPC概述 RPC(Remote Procedure Call)即远程过程调用,允许一台计算机调用另一台计算机上的程序得到结果,而代码中不需要做额外的编程,就像在本地调用一样.主要是为了应对当前互 ...

  9. Entity Framework常用方法及案例

    ⒈Skip(int count) 说明:跳过集合的前n个元素:延迟.即我们跳过给定的数目返回后面的结果集. ⒉Take(int count) 说明:获取集合的前n个元素:延迟.即只返回限定数量的结果集 ...

  10. Luogu P1600[NOIP2016]day1 T2天天爱跑步

    号称是noip2016最恶心的题 基本上用了一天来搞明白+给sy讲明白(可能还没讲明白 具体思路是真的不想写了(快吐了 如果要看,参见洛谷P1600 天天爱跑步--题解 虽然这样不好但我真的不想写了 ...