001package gudusoft.gsqlparser.stmt.oceanbase;
002
003import gudusoft.gsqlparser.EDbVendor;
004import gudusoft.gsqlparser.ESqlStatementType;
005import gudusoft.gsqlparser.TCustomSqlStatement;
006import gudusoft.gsqlparser.TSourceToken;
007import gudusoft.gsqlparser.nodes.TObjectName;
008import gudusoft.gsqlparser.nodes.TParseTreeNode;
009import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
010import gudusoft.gsqlparser.nodes.oceanbase.TOceanbaseCreateOutlineSqlNode;
011
012/**
013 * OceanBase {@code CREATE OUTLINE} statement (Phase 4 Batch 8).
014 *
015 * <p>An OceanBase outline binds a stored execution plan to a SQL
016 * pattern. Downstream tooling can distinguish the two documented forms:
017 * <ul>
018 *   <li>{@link #getBoundStatement()} returns the parsed inner statement
019 *       (typically a {@code TSelectSqlNode} tree) when the outline is
020 *       defined against a SQL pattern inline</li>
021 *   <li>{@link #getSqlId()} returns the SQL ID string when the outline
022 *       is defined against an existing entry in the plan cache</li>
023 * </ul>
024 * Exactly one of the two is non-null for a valid outline.
025 *
026 * <p>The optional {@code USING HINT /*+ ... *&#47;} clause is exposed via
027 * {@link #getUsingHintToken()} as the raw comment token.
028 *
029 * <p>Tagged {@link ESqlStatementType#sstoraclecreateoutline} (reused
030 * per ADR-8 — Oracle already has this enum for the identically-shaped
031 * statement).
032 *
033 * @since 4.0.1.4
034 */
035public class TCreateOutlineSqlStatement extends TCustomSqlStatement {
036
037    private TObjectName outlineName;
038    private TParseTreeNode boundStatement;
039    private TObjectName sqlId;
040    private TSourceToken usingHintToken;
041    private boolean orReplace;
042
043    public TCreateOutlineSqlStatement(EDbVendor dbvendor) {
044        super(dbvendor);
045        this.sqlstatementtype = ESqlStatementType.sstoraclecreateoutline;
046    }
047
048    public TObjectName getOutlineName() {
049        return outlineName;
050    }
051
052    public TParseTreeNode getBoundStatement() {
053        return boundStatement;
054    }
055
056    public TObjectName getSqlId() {
057        return sqlId;
058    }
059
060    public TSourceToken getUsingHintToken() {
061        return usingHintToken;
062    }
063
064    public boolean isOrReplace() {
065        return orReplace;
066    }
067
068    /**
069     * @return the raw text of the {@code USING HINT} comment (including
070     *         the surrounding {@code /*+ ... *&#47;}), or {@code null} when
071     *         not specified.
072     */
073    public String getUsingHintText() {
074        return usingHintToken == null ? null : usingHintToken.toString();
075    }
076
077    @Override
078    public int doParseStatement(TCustomSqlStatement psql) {
079        if (rootNode == null) return -1;
080        super.doParseStatement(psql);
081        TOceanbaseCreateOutlineSqlNode node =
082                (TOceanbaseCreateOutlineSqlNode) rootNode;
083        this.outlineName = node.getOutlineName();
084        this.boundStatement = node.getBoundStatement();
085        this.sqlId = node.getSqlId();
086        this.usingHintToken = node.getUsingHintToken();
087        this.orReplace = node.isOrReplace();
088        return 0;
089    }
090
091    @Override
092    public void accept(TParseTreeVisitor v) {
093        v.preVisit(this);
094        v.postVisit(this);
095    }
096
097    @Override
098    public void acceptChildren(TParseTreeVisitor v) {
099        v.preVisit(this);
100        v.postVisit(this);
101    }
102}