001package gudusoft.gsqlparser.stmt.snowflake;
002
003import gudusoft.gsqlparser.EDbObjectType;
004import gudusoft.gsqlparser.EDbVendor;
005import gudusoft.gsqlparser.ESqlStatementType;
006import gudusoft.gsqlparser.TBaseType;
007import gudusoft.gsqlparser.TCustomSqlStatement;
008import gudusoft.gsqlparser.TSourceToken;
009import gudusoft.gsqlparser.nodes.TObjectName;
010import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
011import gudusoft.gsqlparser.nodes.TDummy;
012
013
014public class TDropTaskStmt extends TCustomSqlStatement {
015
016    private TObjectName taskName;
017    private boolean ifExists = false;
018    private boolean cascade = false;
019    private boolean restrict = false;
020
021    public TDropTaskStmt(EDbVendor dbvendor) {
022        super(dbvendor);
023        sqlstatementtype = ESqlStatementType.sstDropTask;
024    }
025
026    public int doParseStatement(TCustomSqlStatement psql) {
027        // When grammar parser provides rootNode, use it
028        if (rootNode != null) {
029            super.doParseStatement(psql);
030            TDummy node = (TDummy)rootNode;
031            taskName = (TObjectName) node.node1;
032            taskName.setDbObjectType(EDbObjectType.task);
033        }
034        // Otherwise taskName was set in dochecksyntax
035        return 0;
036    }
037
038    /**
039     * Override dochecksyntax to parse DROP TASK statement directly from tokens.
040     * This bypasses the grammar parser which may not have the DROP TASK rule.
041     * Syntax: DROP TASK [IF EXISTS] <qualified_name> [CASCADE | RESTRICT]
042     */
043    @Override
044    protected int dochecksyntax(TCustomSqlStatement psql) {
045        isparsed = true;
046
047        // Parse tokens: DROP TASK [IF EXISTS] name [CASCADE|RESTRICT]
048        int index = 0;
049
050        // Helper to skip non-solid tokens (whitespace, comments)
051        while (index < sourcetokenlist.size() && !sourcetokenlist.get(index).issolidtoken()) {
052            index++;
053        }
054
055        // Skip DROP token
056        if (index < sourcetokenlist.size() && sourcetokenlist.get(index).tokencode == TBaseType.rrw_drop) {
057            index++;
058        }
059
060        // Skip non-solid tokens
061        while (index < sourcetokenlist.size() && !sourcetokenlist.get(index).issolidtoken()) {
062            index++;
063        }
064
065        // Skip TASK token (it's an identifier, not a reserved word)
066        if (index < sourcetokenlist.size()) {
067            TSourceToken taskToken = sourcetokenlist.get(index);
068            if (taskToken.toString().equalsIgnoreCase("TASK")) {
069                index++;
070            }
071        }
072
073        // Skip non-solid tokens
074        while (index < sourcetokenlist.size() && !sourcetokenlist.get(index).issolidtoken()) {
075            index++;
076        }
077
078        // Check for IF EXISTS
079        if (index < sourcetokenlist.size()) {
080            TSourceToken token = sourcetokenlist.get(index);
081            if (token.tokencode == TBaseType.rrw_if) {
082                index++;
083                // Skip non-solid tokens
084                while (index < sourcetokenlist.size() && !sourcetokenlist.get(index).issolidtoken()) {
085                    index++;
086                }
087                // Check for EXISTS
088                if (index < sourcetokenlist.size() && sourcetokenlist.get(index).toString().equalsIgnoreCase("EXISTS")) {
089                    ifExists = true;
090                    index++;
091                }
092                // Skip non-solid tokens
093                while (index < sourcetokenlist.size() && !sourcetokenlist.get(index).issolidtoken()) {
094                    index++;
095                }
096            }
097        }
098
099        // Now parse the qualified name (task name)
100        // Collect tokens until we hit semicolon, CASCADE, RESTRICT, or end
101        TSourceToken startToken = null;
102        TSourceToken endToken = null;
103
104        while (index < sourcetokenlist.size()) {
105            TSourceToken token = sourcetokenlist.get(index);
106
107            // Skip non-solid tokens
108            if (!token.issolidtoken()) {
109                index++;
110                continue;
111            }
112
113            // Stop at semicolon
114            if (token.tokencode == ';' || token.toString().equals(";")) {
115                break;
116            }
117
118            // Check for CASCADE or RESTRICT
119            String tokenStr = token.toString().toUpperCase();
120            if (tokenStr.equals("CASCADE")) {
121                cascade = true;
122                index++;
123                continue;
124            }
125            if (tokenStr.equals("RESTRICT")) {
126                restrict = true;
127                index++;
128                continue;
129            }
130
131            // Part of the qualified name
132            if (startToken == null) {
133                startToken = token;
134            }
135            endToken = token;
136            index++;
137        }
138
139        // Create TObjectName from the tokens
140        if (startToken != null) {
141            taskName = new TObjectName();
142            taskName.setStartToken(startToken);
143            taskName.setEndToken(endToken != null ? endToken : startToken);
144            taskName.setDbObjectType(EDbObjectType.task);
145        }
146
147        return 0;
148    }
149
150    public TObjectName getTaskName() {
151        return taskName;
152    }
153
154
155    public boolean isIfExists() {
156        return ifExists;
157    }
158
159    public void setIfExists(boolean ifExists) {
160        this.ifExists = ifExists;
161    }
162
163    public boolean isCascade() {
164        return cascade;
165    }
166
167    public void setCascade(boolean cascade) {
168        this.cascade = cascade;
169    }
170
171    public boolean isRestrict() {
172        return restrict;
173    }
174
175    public void setRestrict(boolean restrict) {
176        this.restrict = restrict;
177    }
178
179    public void accept(TParseTreeVisitor v){
180        v.preVisit(this);
181        v.postVisit(this);
182    }
183
184    public void acceptChildren(TParseTreeVisitor v){
185        v.preVisit(this);
186        v.postVisit(this);
187    }
188}