sql解析,转换列表和表名

sql解析,转换列表和表名

1、 jsqlparse介绍

JSqlParse是一款很精简的sql解析工具,它可以将常用的sql文本解析成具有层级结构的"语法树",我们可以针对解析后的"树节点(也即官网里说的有层次结构的java类)"进行处理进而生成符合我们要求的sql形式。

官网给的介绍很简洁:JSqlParser 解析 SQL 语句并将其转换为 Java 类的层次结构。生成的层次结构可以使用访问者模式进行访问(官网地址:JSqlParser - Home)。

2 pom坐标

复制代码
  <dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.3</version>
</dependency>

3 解析工具类

复制代码
private static String convertSql(String sql, Class<?> clazz) throws Exception {

		Select select = (Select) CCJSqlParserUtil.parse(sql);
		SelectBody selectBody = select.getSelectBody();
		if (selectBody instanceof PlainSelect) {
			PlainSelect plainSelect = (PlainSelect) selectBody;
			Table table = (Table) plainSelect.getFromItem();
			String originTableName = table.getName().toLowerCase();
			Matcher matcher = pattern.matcher(originTableName);
			//如果不符合原来的的表名格式就返回原sql
			if (!matcher.find()) {
				return sql;
			}
			String day = matcher.group().replace("_", "-");
			long start = 0;
			long end = 10;
			//转换where条件
			Expression where = plainSelect.getWhere();
			where.accept(new MyWhereExpressionVisitorAdapter());
			// 不管原来有没有时间条件,都拼接上当天的时间条件
			String condExpr = where + " and time >= " + start + " and time <= " + end;
			Expression newCondition = CCJSqlParserUtil.parseCondExpression(condExpr);
			plainSelect.setWhere(newCondition);
			//设置表名
			TableName annotation = clazz.getAnnotation(TableName.class);
			table.setName(annotation.value());
			//转换select的列
			for (SelectItem selectItem : plainSelect.getSelectItems()) {
				SelectExpressionItem item = (SelectExpressionItem) selectItem;
				item.accept(new MySelectExpressionVisitorAdapter(item, KEY_MAP.get(clazz)));
			}
		}
		//加时间排序
		return select + " order by time asc";

	}
3 列名转换
复制代码
public class MySelectExpressionVisitorAdapter extends ExpressionVisitorAdapter {

	private SelectExpressionItem item;

	private Map<String, String> columnMap;

	public MySelectExpressionVisitorAdapter(SelectExpressionItem item, Map<String, String> columnMap) {
		this.item = item;
		this.columnMap = columnMap;
	}

	@Override
	public void visit(Column column) {
		Expression expression = item.getExpression();
		String originColumnName = column.getColumnName();
		String changeColumnName = columnMap.get(originColumnName.toUpperCase());
		if (changeColumnName != null) {
			column.setColumnName(changeColumnName);
			//把原列名当做别名
			if (!originColumnName.equals(changeColumnName) && expression instanceof Column && item.getAlias() == null) {
				item.setAlias(new Alias(originColumnName));
			}
		}

	}


	
	@Override
	public void visit(Function function) {
		String name = function.getName();
		if ("round".equalsIgnoreCase(name)) {
			function.getParameters().getExpressions().remove(1);
			function.setName("");
		}
		super.visit(function);
	}
4 条件转换
复制代码
public class MyWhereExpressionVisitorAdapter extends ExpressionVisitorAdapter {


	@Override
	protected void visitBinaryExpression(BinaryExpression expression) {
		if (!(expression instanceof ComparisonOperator)) {
			super.visitBinaryExpression(expression);
			return;
		}
		Column column = (Column) expression.getLeftExpression();
		String columnName = column.getColumnName();
		if ("isAgain".equalsIgnoreCase(columnName)) {
			column.setColumnName("isAgain");
			Expression rightExpression = expression.getRightExpression();
			if (rightExpression instanceof LongValue) {
				LongValue tmp = (LongValue) rightExpression;
				tmp.setStringValue(String.valueOf(tmp.getValue()>0));
			}
		} else if ("time".equalsIgnoreCase(columnName)) {
			column.setColumnName("time");
			changeTime((ComparisonOperator) expression);
		} else if (changeWhereSerialColumName(columnName)) {
			column.setColumnName("serialNum");
		}
	}

	/**
	 * 转换时间条件列
	 * @param comparisonOperator
	 */
	private void changeTime(ComparisonOperator comparisonOperator) {
		Expression rightExpression = comparisonOperator.getRightExpression();
		 if (rightExpression instanceof StringValue) {
			long value = DateTimeUtilJdk8.getTimeMilli(((StringValue) rightExpression).getValue());
			LongValue longValue = new LongValue();
			longValue.setValue(value);
			comparisonOperator.setRightExpression(longValue);
		}
	}

	private  boolean changeWhereSerialColumName(String column) {
		return LindormUtil.getOriginalSerialNumName().contains(column.toUpperCase());
	}
测试
复制代码
public static void main(String[] args) throws Exception {
		String sql = "select ID, username,password  from Tbl_db_2023_06_26 where id='007'";
		System.out.println(convertSql(sql, Object.class));
	}
相关推荐
松树戈3 分钟前
PostgreSQL使用LIKE右模糊没有走索引分析&验证
数据库·postgresql
文牧之10 分钟前
PostgreSQL 常用日志
运维·数据库·postgresql
TE-茶叶蛋34 分钟前
Redis 原子操作
数据库·redis·缓存
Linux运维老纪37 分钟前
Python文件操作及数据库交互(Python File Manipulation and Database Interaction)
linux·服务器·数据库·python·云计算·运维开发
Bruce_Liuxiaowei43 分钟前
MCP Python SDK构建的**SQLite浏览器**的完整操作指南
数据库·python·sqlite
数据与人工智能律师1 小时前
正确应对监管部门的数据安全审查
大数据·网络·数据库·人工智能·区块链
2401_897930061 小时前
什么是非关系型数据库
数据库·oracle
鱼丸丶粗面1 小时前
Python 读取 txt 文件详解 with ... open()
linux·数据库·python
拾荒者.1261 小时前
设计一个关键字统计程序:利用HashMap存储关键字统计信息,对用户输入的关键字进行个数统计。
数据库·python·mysql
encoding-console1 小时前
欧拉环境(openEuler 22.03 LTS SP3)安装移动磐维数据库(PanWeiDB_V2.0-S2.0.2_B01)步骤
数据库·虚拟机·欧拉·磐维数据库