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

io.quarkus.panache.hibernate.common.runtime.CountParserVisitor Maven / Gradle / Ivy

package io.quarkus.panache.hibernate.common.runtime;

import org.antlr.v4.runtime.tree.TerminalNode;
import org.hibernate.grammars.hql.HqlParser.JoinContext;
import org.hibernate.grammars.hql.HqlParser.QueryContext;
import org.hibernate.grammars.hql.HqlParser.QueryOrderContext;
import org.hibernate.grammars.hql.HqlParser.SelectClauseContext;
import org.hibernate.grammars.hql.HqlParser.SimpleQueryGroupContext;
import org.hibernate.grammars.hql.HqlParserBaseVisitor;

public class CountParserVisitor extends HqlParserBaseVisitor {

    private int inSimpleQueryGroup;
    private StringBuilder sb = new StringBuilder();

    @Override
    public String visitSimpleQueryGroup(SimpleQueryGroupContext ctx) {
        inSimpleQueryGroup++;
        try {
            return super.visitSimpleQueryGroup(ctx);
        } finally {
            inSimpleQueryGroup--;
        }
    }

    @Override
    public String visitQuery(QueryContext ctx) {
        super.visitQuery(ctx);
        if (inSimpleQueryGroup == 1 && ctx.selectClause() == null) {
            // insert a count because there's no select
            sb.append(" select count( * )");
        }
        return null;
    }

    @Override
    public String visitSelectClause(SelectClauseContext ctx) {
        if (inSimpleQueryGroup == 1) {
            if (ctx.SELECT() != null) {
                ctx.SELECT().accept(this);
            }
            if (ctx.DISTINCT() != null) {
                sb.append(" count(");
                ctx.DISTINCT().accept(this);
                if (ctx.selectionList().children.size() != 1) {
                    // FIXME: error message should include query
                    throw new RuntimeException("Cannot count on more than one column");
                }
                ctx.selectionList().children.get(0).accept(this);
                sb.append(" )");
            } else {
                sb.append(" count( * )");
            }
        } else {
            super.visitSelectClause(ctx);
        }
        return null;
    }

    @Override
    public String visitJoin(JoinContext ctx) {
        if (inSimpleQueryGroup == 1 && ctx.FETCH() != null) {
            // ignore fetch joins for main query
            return null;
        }
        return super.visitJoin(ctx);
    }

    @Override
    public String visitQueryOrder(QueryOrderContext ctx) {
        if (inSimpleQueryGroup == 1) {
            // ignore order/limit/offset for main query
            return null;
        }
        return super.visitQueryOrder(ctx);
    }

    @Override
    public String visitTerminal(TerminalNode node) {
        append(node.getText());
        return null;
    }

    @Override
    protected String defaultResult() {
        return null;
    }

    @Override
    protected String aggregateResult(String aggregate, String nextResult) {
        if (nextResult != null) {
            append(nextResult);
        }
        return null;
    }

    private void append(String nextResult) {
        // don't add space at start, or around dots
        if (!sb.isEmpty() && sb.charAt(sb.length() - 1) != '.' && !nextResult.equals(".")) {
            sb.append(" ");
        }
        sb.append(nextResult);
    }

    public String result() {
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy