package com.jn.sqlhelper.jsqlparser.instrument; import com.jn.langx.annotation.NonNull; import com.jn.langx.lifecycle.InitializationException; import com.jn.langx.text.StringTemplates; import com.jn.langx.util.Emptys; import com.jn.langx.util.Preconditions; import com.jn.langx.util.function.Supplier; import com.jn.sqlhelper.dialect.instrument.AbstractClauseTransformer; import com.jn.sqlhelper.dialect.instrument.SQLTransformException; import com.jn.sqlhelper.dialect.instrument.TransformConfig; import com.jn.sqlhelper.dialect.instrument.orderby.OrderByTransformer; import com.jn.sqlhelper.dialect.orderby.OrderBy; import com.jn.sqlhelper.dialect.orderby.OrderByItem; import com.jn.sqlhelper.dialect.orderby.OrderByType; import com.jn.sqlhelper.dialect.sqlparser.SQLParseException; import com.jn.sqlhelper.dialect.sqlparser.SqlStatementWrapper; import com.jn.sqlhelper.jsqlparser.utils.JSqlParsers; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectBody; import java.util.ArrayList; import java.util.List; public class JSqlParserOrderByTransformer extends AbstractClauseTransformer<Statement> implements OrderByTransformer<Statement> { @Override public void init() throws InitializationException { } @Override public SqlStatementWrapper<Statement> transform(@NonNull SqlStatementWrapper<Statement> sw, @NonNull TransformConfig config) { Preconditions.checkNotNull(sw); Preconditions.checkNotNull(config); OrderBy orderBy = Preconditions.checkNotNull(config.getOrderBy()); final Statement statement = sw.get(); Preconditions.checkNotNull(statement, "statement is null"); Preconditions.checkTrue(statement instanceof Select, new Supplier<Object[], String>() { @Override public String get(Object[] input) { return StringTemplates.formatWithPlaceholder("statement is not a select statement: {}", statement.toString()); } }); tranaform((Select) statement, orderBy); sw.setChanged(true); return sw; } public static void tranaform(@NonNull Select select, @NonNull OrderBy orderBy) throws SQLParseException { try { SelectBody selectBody = select.getSelectBody(); PlainSelect plainSelect = JSqlParsers.extractPlainSelect(selectBody); if (plainSelect == null) { return; } List<OrderByElement> orderByElements = plainSelect.getOrderByElements(); if (Emptys.isNotEmpty(orderByElements)) { String orderByStringInSql = PlainSelect.orderByToString(orderByElements); if (orderByStringInSql.contains("?")) { throw new SQLTransformException("Can't instrument order by because the original sql has '?' in order by clause"); } } if (orderBy.isValid()) { if (orderByElements == null) { orderByElements = new ArrayList<OrderByElement>(); } for (OrderByItem item : orderBy) { Expression exprForAppend = CCJSqlParserUtil.parseExpression(item.getExpression()); boolean needAppend = true; for (OrderByElement orderByElement : orderByElements) { Expression exprInSql = orderByElement.getExpression(); if (exprForAppend.getClass() == exprInSql.getClass()) { if (JSqlParsers.expressionEquals(exprForAppend, exprInSql)) { needAppend = false; // do asc, desc change if (item.getType() == null) { orderByElement.setAscDescPresent(false); } else { orderByElement.setAsc(item.getType() == OrderByType.ASC); } } } } if (needAppend) { OrderByElement orderByElement = new OrderByElement(); if (item.getType() == null) { orderByElement.setAscDescPresent(false); } else { orderByElement.setAsc(item.getType() == OrderByType.ASC); } orderByElement.setExpression(exprForAppend); orderByElements.add(orderByElement); } } if (!orderByElements.isEmpty()) { plainSelect.setOrderByElements(orderByElements); } } } catch (JSQLParserException ex) { throw new SQLParseException(ex); } } }