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

io.github.imsejin.mybatis.pagination.dialect.MySQLDialect Maven / Gradle / Ivy

package io.github.imsejin.mybatis.pagination.dialect;

import io.github.imsejin.mybatis.pagination.constant.RebuildMode;
import io.github.imsejin.mybatis.pagination.model.Pageable;
import io.github.imsejin.mybatis.pagination.support.InterceptorSupport;
import io.github.imsejin.mybatis.pagination.support.rebuilder.Rebuilder;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.statement.select.*;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;

import static java.util.stream.Collectors.toList;

public class MySQLDialect implements Dialect {

    @Override
    public BoundSql createCountBoundSql(BoundSql origin, Configuration config) {
        PlainSelect select = InterceptorSupport.parseSelect(origin.getSql());

        List parameterMappings = getFilteredParameterMappings(origin, select);

        // Add "COUNT(*)" as select item into root select.
        Function countFunc = new Function();
        countFunc.setName("COUNT");
        countFunc.setAllColumns(true);
        List selectItems = Collections.singletonList(new SelectExpressionItem(countFunc));
        select.setSelectItems(selectItems);

        // Removes statements "ORDER BY", "LIMIT", "OFFSET".
        select.setOrderByElements(null);
        select.setLimit(null);
        select.setOffset(null);

        return Rebuilder.init(origin, RebuildMode.WRAP).config(config)
                .sql(select.toString()).parameterMappings(parameterMappings).rebuild();
    }

    @Override
    public BoundSql createOffsetLimitBoundSql(BoundSql origin, Configuration config, Pageable pageable) {
        PlainSelect select = InterceptorSupport.parseSelect(origin.getSql());

        Limit limit = new Limit();
        limit.setRowCount(new LongValue(pageable.getLimit()));
        select.setLimit(limit);

        Offset offset = new Offset();
        offset.setOffset(pageable.getOffset());
        select.setOffset(offset);

        return Rebuilder.init(origin, RebuildMode.WRAP).config(config).sql(select.toString()).rebuild();
    }

    private static List getFilteredParameterMappings(BoundSql boundSql, PlainSelect select) {
        List mappings = new ArrayList<>(boundSql.getParameterMappings());

        // Indexes of parameter mappings in "SELECT" statement.
        List indexes = IntStream.range(0, select.getSelectItems().stream().map(Object::toString)
                .mapToInt(it -> StringUtils.countOccurrencesOf(it, MAPPED_PARAMETER_CHARACTER)).sum())
                .boxed().collect(toList());

        int count = 0;

        Offset offset = select.getOffset();
        if (offset != null) {
            count += StringUtils.countOccurrencesOf(offset.toString(), MAPPED_PARAMETER_CHARACTER);
        }

        Limit limit = select.getLimit();
        if (limit != null) {
            count += StringUtils.countOccurrencesOf(limit.toString(), MAPPED_PARAMETER_CHARACTER);
        }

        List orderBy = select.getOrderByElements();
        if (!CollectionUtils.isEmpty(orderBy)) {
            for (OrderByElement order : orderBy) {
                count += StringUtils.countOccurrencesOf(order.toString(), MAPPED_PARAMETER_CHARACTER);
            }
        }

        // Adds indexes of parameter mappings in "OFFSET", "LIMIT", "ORDER BY" statements.
        int lastIndex = mappings.size() - 1;
        indexes.addAll(IntStream.range(lastIndex - count, lastIndex).boxed().collect(toList()));

        // Removes parameter mappings in that statements.
        indexes.forEach(i -> mappings.set(i, null));
        return mappings.stream().filter(Objects::nonNull).collect(toList());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy