All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alilitech.mybatis.jpa.pagination.sqlparser.SqlParser Maven / Gradle / Ivy

The newest version!
/*
 *    Copyright 2017-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.alilitech.mybatis.jpa.pagination.sqlparser;

import com.alilitech.mybatis.jpa.EntityMetaDataRegistry;
import com.alilitech.mybatis.jpa.StatementRegistry;
import com.alilitech.mybatis.jpa.definition.MethodDefinition;
import com.alilitech.mybatis.jpa.meta.ColumnMetaData;
import com.alilitech.mybatis.jpa.meta.EntityMetaData;
import com.alilitech.mybatis.jpa.util.LRUCache;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Zhou Xiaoxiang
 * @since 2.2
 */
public class SqlParser {

    protected static final List COUNT_SELECT_COLUMNS = Collections.singletonList(
            new SelectExpressionItem(new Column().withColumnName("COUNT(*)"))
    );

    /**
     * key: original sql
     */
    private final LRUCache sqlParserCache = new LRUCache<>(10000);

    private static final SqlParser SQL_PARSER = new SqlParser();
    public static SqlParser getInstance() {
        return SQL_PARSER;
    }
    private SqlParser() {
    }

    public String parseCountSql(String originalSql, String statementId) throws JSQLParserException {
        // custom sql
        if(!StatementRegistry.getInstance().contains(statementId)) {
            return String.format("SELECT COUNT(*) FROM ( %s ) TOTAL", originalSql);
        }

        ParseResult parseResult = parse(originalSql);

        PlainSelect plainSelect = parseResult.getSelect();

        PlainSelect plainSelectCount = new PlainSelect()
                .withSelectItems(plainSelect.getSelectItems())
                .withJoins(plainSelect.getJoins())
                .withFromItem(plainSelect.getFromItem())
                .withWhere(plainSelect.getWhere());
        Select selectCount = new Select().withSelectBody(plainSelectCount);
        // 只有主表时
        if(parseResult.isOnlyMainTable()) {
            plainSelectCount.setOrderByElements(null);
            plainSelectCount.setJoins(null);
            plainSelectCount.setSelectItems(COUNT_SELECT_COLUMNS);
        } else {
            // 有子表时将查询用 count(distinct t_0.id1, t_0.id2), 并将要关联的join带出即可,其它不需要
            List countSelectColumnsWithSub = Collections.singletonList(
                    new SelectExpressionItem(new Column().withColumnName(buildCountSelect(statementId)))
            );

            plainSelectCount.setSelectItems(countSelectColumnsWithSub);

            List joins = new ArrayList<>();

            parseResult.getJoinMap().forEach((key, value) -> {
                if(parseResult.getWhereTables().contains(key)) {
                    joins.add(value);
                }
            });
            plainSelectCount.setJoins(joins);
        }
        return selectCount.toString();
    }

    public ParseResult parse(String originalSql) throws JSQLParserException {
        if(sqlParserCache.containsKey(originalSql)) {
            return sqlParserCache.get(originalSql);
        }

        return new ParseResult(originalSql);
    }

    private String buildCountSelect(String statementId) {
        MethodDefinition methodDefinition = StatementRegistry.getInstance().getMethodDefinition(statementId);

        EntityMetaData entityMetaData = EntityMetaDataRegistry.getInstance().get(methodDefinition.getMapperDefinition().getGenericType().getDomainType());

        String mainTableAliasAndDot = entityMetaData.getTableAlias() + "_0.";

        List primaryColumnMetaDatas = entityMetaData.getPrimaryColumnMetaDatas();
        String selectColumns = primaryColumnMetaDatas.stream().map(columnMetaData -> mainTableAliasAndDot + columnMetaData.getColumnName()).collect(Collectors.joining(", "));
        return "COUNT(distinct " + selectColumns + ")";
    }

    /**
     * 判断是否是主表查询
     */
//    private boolean judgeIsMainTable(Expression where, List orderByElements, MethodDefinition methodDefinition) {
//        if(methodDefinition.getJoinStatementDefinitions().isEmpty()) {
//            return true;
//        }
//        List joinTablesAndDot = methodDefinition.getJoinStatementDefinitions().stream().map(joinStatementDefinition -> joinStatementDefinition.getTableIndexAlias() + ".").collect(Collectors.toList());
//        if(where != null) {
//            String whereString = where.toString();
//            Optional optional = joinTablesAndDot.stream().filter(whereString::contains).findFirst();
//            if (optional.isPresent()) {
//                return false;
//            }
//        }
//
//        if(orderByElements != null) {
//            List orderStrings = orderByElements.stream().map(orderByElement -> orderByElement.getExpression().toString()).collect(Collectors.toList());
//            for (String orderString : orderStrings) {
//                Optional optional = joinTablesAndDot.stream().filter(orderString::contains).findFirst();
//                if (optional.isPresent()) {
//                    return false;
//                }
//            }
//        }
//
//        return true;
//    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy