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

com.oceanbase.tools.sqlparser.adapter.oracle.OracleSelectBodyFactory Maven / Gradle / Ivy

There is a newer version: 1.3.0
Show newest version
/*
 * Copyright (c) 2023 OceanBase.
 *
 * 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.oceanbase.tools.sqlparser.adapter.oracle;

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

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RuleContext;
import org.antlr.v4.runtime.tree.TerminalNode;

import com.oceanbase.tools.sqlparser.adapter.StatementFactory;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.ExprContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.From_listContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Groupby_clauseContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Query_expression_option_listContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_clauseContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_clause_setContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_clause_set_leftContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_clause_set_rightContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_expr_listContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_no_parensContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_with_hierarchical_queryContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Select_with_parensContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Set_expression_optionContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Set_typeContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.Simple_selectContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.SubqueryContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.With_clauseContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParser.With_selectContext;
import com.oceanbase.tools.sqlparser.oboracle.OBParserBaseVisitor;
import com.oceanbase.tools.sqlparser.statement.Expression;
import com.oceanbase.tools.sqlparser.statement.select.FromReference;
import com.oceanbase.tools.sqlparser.statement.select.GroupBy;
import com.oceanbase.tools.sqlparser.statement.select.OrderBy;
import com.oceanbase.tools.sqlparser.statement.select.Projection;
import com.oceanbase.tools.sqlparser.statement.select.RelatedSelectBody;
import com.oceanbase.tools.sqlparser.statement.select.RelationType;
import com.oceanbase.tools.sqlparser.statement.select.SelectBody;
import com.oceanbase.tools.sqlparser.statement.select.WithTable;
import com.oceanbase.tools.sqlparser.statement.select.oracle.Fetch;

import lombok.NonNull;

/**
 * {@link OracleSelectBodyFactory}
 *
 * @author yh263208
 * @date 2022-11-25 16:13
 * @since ODC_release_4.1.0
 * @see OBParserBaseVisitor
 */
public class OracleSelectBodyFactory extends OBParserBaseVisitor implements StatementFactory {

    private SubqueryContext subqueryContext = null;
    private Select_no_parensContext selectNoParensContext = null;
    private With_selectContext withSelectContext = null;
    private Select_with_parensContext selectWithParensContext = null;

    public OracleSelectBodyFactory(@NonNull With_selectContext withSelectContext) {
        this.withSelectContext = withSelectContext;
    }

    public OracleSelectBodyFactory(@NonNull Select_no_parensContext selectNoParensContext) {
        this.selectNoParensContext = selectNoParensContext;
    }

    public OracleSelectBodyFactory(@NonNull SubqueryContext subqueryContext) {
        this.subqueryContext = subqueryContext;
    }

    public OracleSelectBodyFactory(@NonNull Select_with_parensContext selectWithParensContext) {
        this.selectWithParensContext = selectWithParensContext;
    }

    @Override
    public SelectBody generate() {
        if (this.selectNoParensContext != null) {
            return visit(this.selectNoParensContext);
        } else if (this.subqueryContext != null) {
            return visit(this.subqueryContext);
        } else if (this.selectWithParensContext != null) {
            return visit(this.selectWithParensContext);
        } else if (this.withSelectContext != null) {
            return visit(this.withSelectContext);
        }
        throw new IllegalStateException("No Context available");
    }

    @Override
    public SelectBody visitSubquery(SubqueryContext ctx) {
        if (ctx.select_no_parens() != null) {
            return visit(ctx.select_no_parens());
        } else if (ctx.select_with_parens() != null) {
            return visit(ctx.select_with_parens());
        } else if (ctx.with_select() != null) {
            return visit(ctx.with_select());
        }
        throw new IllegalStateException("No alternative node");
    }

    @Override
    public SelectBody visitSelect_with_parens(Select_with_parensContext ctx) {
        if (ctx.select_with_parens() != null) {
            return visit(ctx.select_with_parens());
        }
        SelectBody select;
        if (ctx.select_no_parens() != null) {
            select = new SelectBody(ctx, visit(ctx.select_no_parens()));
        } else if (ctx.with_select() != null) {
            select = new SelectBody(ctx, visit(ctx.with_select()));
        } else {
            throw new IllegalStateException("No alternative node");
        }
        if (ctx.order_by() != null) {
            StatementFactory factory = new OracleOrderByFactory(ctx.order_by());
            select.getLastSelectBody().setOrderBy(factory.generate());
        }
        if (ctx.fetch_next_clause() != null) {
            StatementFactory factory = new OracleFetchFactory(ctx.fetch_next_clause());
            select.getLastSelectBody().setFetch(factory.generate());
        }
        return select;
    }

    @Override
    public SelectBody visitSelect_no_parens(Select_no_parensContext ctx) {
        if (ctx.select_clause() != null) {
            return visit(ctx.select_clause());
        }
        return visit(ctx.select_clause_set());
    }

    @Override
    public SelectBody visitWith_select(With_selectContext ctx) {
        SelectBody select;
        if (ctx.select_no_parens() != null) {
            select = new SelectBody(ctx, visit(ctx.select_no_parens()));
        } else {
            select = new SelectBody(ctx, visit(ctx.select_with_parens()));
        }
        With_clauseContext withClause = ctx.with_clause();
        if (withClause.RECURSIVE() != null) {
            select.setRecursive(true);
        }
        if (withClause.common_table_expr() != null) {
            StatementFactory factory = new OracleWithTableFactory(withClause.common_table_expr());
            select.getWith().add(factory.generate());
        } else if (withClause.with_list() != null) {
            withClause.with_list().common_table_expr().forEach(c -> {
                StatementFactory factory = new OracleWithTableFactory(c);
                select.getWith().add(factory.generate());
            });
        }
        return select;
    }

    @Override
    public SelectBody visitSelect_clause_set(Select_clause_setContext ctx) {
        SelectBody left;
        SelectBody right = visit(ctx.select_clause_set_right());
        if (ctx.select_clause_set() != null) {
            left = new SelectBody(ctx, visit(ctx.select_clause_set()));
        } else if (ctx.select_clause_set_left() != null) {
            left = new SelectBody(ctx, visit(ctx.select_clause_set_left()));
        } else {
            throw new IllegalStateException("Node is not found");
        }
        Set_typeContext type = ctx.set_type();
        if (type == null) {
            throw new IllegalStateException("Missing set top node");
        }
        RelationType relationType;
        if (type.set_type_other() != null) {
            relationType = RelationType.valueOf(type.set_type_other().getText());
        } else {
            Set_expression_optionContext o = type.set_expression_option();
            relationType = RelationType.UNION;
            if (o != null && o.ALL() != null) {
                relationType = RelationType.UNION_ALL;
            }
        }
        left.getLastSelectBody().setRelatedSelect(new RelatedSelectBody(right, relationType));
        return left;
    }

    @Override
    public SelectBody visitSelect_clause_set_right(Select_clause_set_rightContext ctx) {
        if (ctx.simple_select() != null) {
            return visit(ctx.simple_select());
        } else if (ctx.select_with_hierarchical_query() != null) {
            return visit(ctx.select_with_hierarchical_query());
        }
        return visit(ctx.select_with_parens());
    }

    @Override
    public SelectBody visitSelect_clause_set_left(Select_clause_set_leftContext ctx) {
        return visit(ctx.select_clause_set_right());
    }

    @Override
    public SelectBody visitSelect_clause(Select_clauseContext ctx) {
        if (ctx.simple_select() != null) {
            return visit(ctx.simple_select());
        }
        return visit(ctx.select_with_hierarchical_query());
    }

    @Override
    public SelectBody visitSelect_with_hierarchical_query(Select_with_hierarchical_queryContext ctx) {
        SelectBody select = visitSelect(new SelectContext() {
            @Override
            public ParserRuleContext getTarget() {
                return ctx;
            }

            @Override
            public Select_expr_listContext projectionList() {
                return ctx.select_expr_list();
            }

            @Override
            public From_listContext fromList() {
                return ctx.from_list();
            }

            @Override
            public Groupby_clauseContext groupClause() {
                return ctx.groupby_clause();
            }

            @Override
            public TerminalNode whereNode() {
                return ctx.WHERE();
            }

            @Override
            public TerminalNode havingNode() {
                return ctx.HAVING();
            }

            @Override
            public List exprList() {
                return ctx.expr();
            }

            @Override
            public Query_expression_option_listContext queryOptionList() {
                return ctx.query_expression_option_list();
            }
        });
        if (ctx.start_with() != null) {
            StatementFactory factory = new OracleExpressionFactory(ctx.start_with().expr());
            select.setStartWith(factory.generate());
        }
        if (ctx.connect_by() != null) {
            StatementFactory factory = new OracleExpressionFactory(ctx.connect_by().expr());
            select.setConnectBy(factory.generate());
        }
        return select;
    }

    @Override
    public SelectBody visitSimple_select(Simple_selectContext ctx) {
        return visitSelect(new SelectContext() {
            @Override
            public ParserRuleContext getTarget() {
                return ctx;
            }

            @Override
            public Select_expr_listContext projectionList() {
                return ctx.select_expr_list();
            }

            @Override
            public From_listContext fromList() {
                return ctx.from_list();
            }

            @Override
            public Groupby_clauseContext groupClause() {
                return ctx.groupby_clause();
            }

            @Override
            public TerminalNode whereNode() {
                return ctx.WHERE();
            }

            @Override
            public TerminalNode havingNode() {
                return ctx.HAVING();
            }

            @Override
            public List exprList() {
                return ctx.expr();
            }

            @Override
            public Query_expression_option_listContext queryOptionList() {
                return ctx.query_expression_option_list();
            }
        });
    }

    private SelectBody visitSelect(SelectContext ctx) {
        List selectItems = visitProjectionList(ctx.projectionList());
        List froms = visitFromList(ctx.fromList());
        SelectBody select = new SelectBody(ctx.getTarget(), selectItems, froms);
        ExprContext where = null;
        ExprContext having = null;
        if (ctx.whereNode() != null && ctx.havingNode() != null) {
            // 既有 where 子句,也有 having 子句,此时第一个 expr 是 where 的,第二个是 having 的
            where = ctx.exprList().get(0);
            if (where == null) {
                throw new IllegalStateException("Missing where clause");
            }
            having = ctx.exprList().get(1);
            if (having == null) {
                throw new IllegalStateException("Missing having clause");
            }
        } else if (ctx.whereNode() == null && ctx.havingNode() != null) {
            having = ctx.exprList().get(0);
        } else if (ctx.havingNode() == null && ctx.whereNode() != null) {
            where = ctx.exprList().get(0);
        }
        if (where != null) {
            StatementFactory factory = new OracleExpressionFactory(where);
            select.setWhere(factory.generate());
        }
        if (having != null) {
            StatementFactory factory = new OracleExpressionFactory(having);
            select.setHaving(factory.generate());
        }
        if (ctx.groupClause() != null) {
            select.setGroupBy(visitGroupByClause(ctx.groupClause()));
        }
        if (ctx.queryOptionList() != null) {
            select.setQueryOptions(getQueryExpr(ctx.queryOptionList()));
        }
        return select;
    }

    private String getQueryExpr(Query_expression_option_listContext context) {
        return context.query_expression_option().stream().map(RuleContext::getText).collect(Collectors.joining(" "));
    }

    private List visitProjectionList(Select_expr_listContext context) {
        return context.projection().stream().map(child -> {
            OracleProjectionFactory factory = new OracleProjectionFactory(child);
            return factory.generate();
        }).collect(Collectors.toList());
    }

    private List visitFromList(From_listContext context) {
        return context.table_references().table_reference().stream().map(c -> {
            StatementFactory factory = new OracleFromReferenceFactory(c);
            return factory.generate();
        }).collect(Collectors.toList());
    }

    private List visitGroupByClause(Groupby_clauseContext context) {
        return context.groupby_element_list().groupby_element().stream().map(c -> {
            StatementFactory factory = new OracleGroupByFactory(c);
            return factory.generate();
        }).collect(Collectors.toList());
    }

    /**
     * {@link SelectContext}
     *
     * @author yh263208
     * @date 2022-12-07 18:21
     * @since ODC_release_4.1.0
     */
    interface SelectContext {

        ParserRuleContext getTarget();

        Select_expr_listContext projectionList();

        From_listContext fromList();

        Groupby_clauseContext groupClause();

        TerminalNode whereNode();

        TerminalNode havingNode();

        List exprList();

        Query_expression_option_listContext queryOptionList();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy