001package gudusoft.gsqlparser.stmt.oracle;
002
003import gudusoft.gsqlparser.EDbObjectType;
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.ESqlStatementType;
006import gudusoft.gsqlparser.TCustomSqlStatement;
007import gudusoft.gsqlparser.TSourceToken;
008import gudusoft.gsqlparser.TBaseType;
009import gudusoft.gsqlparser.nodes.TObjectName;
010import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
011
012/**
013 * Oracle CREATE CLUSTER statement.
014 *
015 * <p>The Oracle grammar currently does not build a dedicated AST for
016 * {@code CREATE CLUSTER}, so this statement locates the cluster name by
017 * scanning the raw source tokens of the statement for the first qualified
018 * name that follows the {@code CLUSTER} keyword.</p>
019 *
020 * @since 4.1.0.11
021 */
022public class TOracleCreateClusterStmt extends TCustomOracleSqlStmt {
023
024    private TObjectName clusterName;
025    private String clusterNameText;
026
027    public String getClusterNameText() { return clusterNameText; }
028
029    public TOracleCreateClusterStmt(EDbVendor dbvendor) {
030        super(dbvendor);
031        sqlstatementtype = ESqlStatementType.sstoraclecreatecluster;
032    }
033
034    public TObjectName getClusterName() {
035        return clusterName;
036    }
037
038    protected int dochecksyntax(TCustomSqlStatement psql) {
039        // Oracle grammar has no rule for CREATE CLUSTER; bypass yacc check.
040        isparsed = true;
041        return 0;
042    }
043
044    public int doParseStatement(TCustomSqlStatement psql) {
045        // Oracle grammar does not build a dedicated AST for CREATE CLUSTER,
046        // so we must not call super.doParseStatement() (which requires a
047        // rootNode). Instead scan the raw source tokens.
048        if (getStartToken() == null || this.sourcetokenlist == null) return 0;
049        int start = getStartToken().posinlist;
050        int end = (getEndToken() != null) ? getEndToken().posinlist : this.sourcetokenlist.size() - 1;
051        // Locate CLUSTER keyword after CREATE.
052        int clusterIdx = -1;
053        for (int i = start; i <= end && i < this.sourcetokenlist.size(); i++) {
054            TSourceToken t = (TSourceToken) this.sourcetokenlist.get(i);
055            if (t == null) continue;
056            if (TBaseType.mycomparetext(t.toString(), "cluster") == 0) {
057                clusterIdx = i;
058                break;
059            }
060        }
061        if (clusterIdx < 0) return 0;
062        StringBuilder sb = new StringBuilder();
063        for (int j = clusterIdx + 1; j <= end && j < this.sourcetokenlist.size(); j++) {
064            TSourceToken nx = (TSourceToken) this.sourcetokenlist.get(j);
065            if (nx == null) continue;
066            String text = nx.getAstext();
067            if (text == null || text.trim().length() == 0) continue;
068            if (text.equals("(") || TBaseType.mycomparetext(text, "size") == 0
069                    || TBaseType.mycomparetext(text, "hashkeys") == 0
070                    || TBaseType.mycomparetext(text, "tablespace") == 0
071                    || TBaseType.mycomparetext(text, "storage") == 0) {
072                break;
073            }
074            sb.append(text);
075        }
076        String name = sb.toString().trim();
077        this.clusterNameText = name;
078        if (name.length() > 0) {
079            clusterName = TObjectName.createObjectName(this.dbvendor, EDbObjectType.cluster, name);
080        }
081        return 0;
082    }
083
084    public void accept(TParseTreeVisitor v) {
085        v.preVisit(this);
086        v.postVisit(this);
087    }
088
089    public void acceptChildren(TParseTreeVisitor v) {
090        v.preVisit(this);
091        v.postVisit(this);
092    }
093}