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));
	}
相关推荐
sdaxue.com25 分钟前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)1 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长1 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_1 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui12 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记2 小时前
MHA binlog server
数据库·mysql
lovelin+v175030409662 小时前
安全性升级:API接口在零信任架构下的安全防护策略
大数据·数据库·人工智能·爬虫·数据分析
DT辰白3 小时前
基于Redis的网关鉴权方案与性能优化
数据库·redis·缓存
2401_871213303 小时前
mysql高阶语句
数据库·mysql