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

com.github.chengyuxing.sql.dsl.clause.CriteriaBuilder Maven / Gradle / Ivy

Go to download

Light wrapper of JDBC, support ddl, dml, query, plsql/procedure/function, transaction and manage sql file.

There is a newer version: 9.0.2
Show newest version
package com.github.chengyuxing.sql.dsl.clause;

import com.github.chengyuxing.common.tuple.Pair;
import com.github.chengyuxing.common.utils.StringUtil;
import com.github.chengyuxing.sql.dsl.clause.condition.*;
import com.github.chengyuxing.sql.dsl.types.Logic;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import static com.github.chengyuxing.sql.dsl.types.StandardOperator.IS_NOT_NULL;
import static com.github.chengyuxing.sql.dsl.types.StandardOperator.IS_NULL;

public abstract class CriteriaBuilder extends ColumnHelper {
    protected CriteriaBuilder(@NotNull Class clazz) {
        super(clazz);
    }

    protected abstract char namedParamPrefix();

    protected void doCheck(Condition condition) {
        if (isIllegalColumn(condition.getColumn())) {
            throw new IllegalArgumentException("unexpected column: '" + condition.getColumn() + "' on condition: " + condition);
        }
        if (isIllegalOperator(condition.getOperator())) {
            throw new IllegalArgumentException("Illegal operator: '" + condition.getOperator().getValue() + "' at condition: " + condition + ", add trusted operator into operatorWhiteList");
        }
    }

    protected final @NotNull Pair> build(AtomicInteger uniqueIndex, List criteriaList, Logic logicOperator, int identLevel) {
        StringBuilder sb = new StringBuilder();
        String ident = StringUtil.repeat("    ", identLevel);
        Map params = new HashMap<>();
        for (int i = 0, j = criteriaList.size(); i < j; i++) {
            Criteria criteria = criteriaList.get(i);
            if (criteria instanceof Condition) {
                @SuppressWarnings("unchecked") Condition condition = (Condition) criteria;

                doCheck(condition);

                int unique = uniqueIndex.getAndIncrement();

                if (condition instanceof InCondition) {
                    @SuppressWarnings({"rawtypes", "unchecked"}) Pair> result = ((InCondition) condition).buildStatement(unique, namedParamPrefix());
                    sb.append(result.getItem1());
                    params.putAll(result.getItem2());
                } else if (condition instanceof BetweenCondition) {
                    Pair> result = ((BetweenCondition) condition).buildStatement(unique, namedParamPrefix());
                    sb.append(result.getItem1());
                    params.putAll(result.getItem2());
                } else {
                    if (condition.getOperator() == IS_NULL || condition.getOperator() == IS_NOT_NULL) {
                        sb.append(condition.getColumn())
                                .append(" ")
                                .append(condition.getOperator().getValue());
                    } else {
                        String key = condition.getKey(unique);
                        sb.append(condition.getColumn())
                                .append(condition.getOperator().padWithSpace())
                                .append(namedParamPrefix()).append(key);
                        params.put(key, condition.getValue());
                    }
                }
            } else if (criteria instanceof AndGroup) {
                List andGroup = ((AndGroup) criteria).getGroup();
                if (!andGroup.isEmpty()) {
                    int groupSize = andGroup.size();
                    Pair> result = build(uniqueIndex, andGroup, Logic.OR, groupSize == 1 ? identLevel : identLevel + 1);
                    if (groupSize == 1) {
                        sb.append(result.getItem1());
                    } else {
                        sb.append("(").append(result.getItem1()).append(")");
                    }
                    params.putAll(result.getItem2());
                }
            } else if (criteria instanceof OrGroup) {
                List orGroup = ((OrGroup) criteria).getGroup();
                if (!orGroup.isEmpty()) {
                    int groupSize = orGroup.size();
                    Pair> result = build(uniqueIndex, orGroup, Logic.AND, groupSize == 1 ? identLevel : identLevel + 1);
                    if (groupSize == 1) {
                        sb.append(result.getItem1());
                    } else {
                        sb.append("(").append(result.getItem1()).append(")");
                    }
                    params.putAll(result.getItem2());
                }
            }

            if (i < j - 1) {
                sb.append("\n").append(ident);
                Criteria next = criteriaList.get(i + 1);
                // set current logical operator where the next 'and' and 'or' group invoked
                if (next instanceof AndGroup) {
                    sb.append(Logic.AND.padWithSpace());
                } else if (next instanceof OrGroup) {
                    sb.append(Logic.OR.padWithSpace());
                } else {
                    sb.append(logicOperator.padWithSpace());
                }
            }
        }
        return Pair.of(sb.toString(), params);
    }
}