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));
	}
相关推荐
光影少年21 小时前
postgrsql和mysql区别?
数据库·mysql·postgresql
Hello.Reader21 小时前
Flink SQL Window Top-N窗口榜单的正确打开方式
数据库·sql·flink
wsx_iot21 小时前
MySQL 的 MVCC(多版本并发控制)详解
数据库·mysql
Hello.Reader21 小时前
Flink SQL Deduplication用 ROW_NUMBER 做流式去重
大数据·sql·flink
Shingmc321 小时前
MySQL表的增删改查
数据库·mysql
敲上瘾21 小时前
MySQL主从集群解析:从原理到Docker实战部署
android·数据库·分布式·mysql·docker·数据库架构
电子_咸鱼21 小时前
【QT——信号和槽(1)】
linux·c语言·开发语言·数据库·c++·git·qt
pandarking21 小时前
[CTF]攻防世界:web-unfinish(sql二次注入)
前端·数据库·sql·web安全·ctf
程序猿202321 小时前
MySQL索引性能分析
数据库·mysql
TDengine (老段)21 小时前
TDengine 新性能基准测试工具 taosgen
大数据·数据库·物联网·测试工具·时序数据库·tdengine·涛思数据