001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.compiler.TFrame;
005import gudusoft.gsqlparser.compiler.TVariable;
006import gudusoft.gsqlparser.nodes.*;
007
008/**
009 * A LOOP statement executes a sequence of statements multiple times. PL/SQL provides
010 * these loop statements:
011 * <ul>
012 * <li>Basic loop</li>
013 * <li>WHILE loop</li>
014 * <li>FOR loop
015 * <p>FOR indexName IN lower_bound .. upper_bound LOOP statements END LOOP
016 * </li>
017 * <li>Cursor FOR loop</li>
018 * </ul>
019 *
020 * @see TBlockSqlStatement#bodyStatements
021 */
022
023public class TLoopStmt extends TBlockSqlStatement {
024
025    public final static int basic_loop = 1;
026    public final static int while_loop = 2;
027    public final static int for_loop = 3;
028    public final static int cursor_for_loop = 4;
029
030    private int kind = basic_loop;
031
032    public void setKind(int kind) {
033        this.kind = kind;
034        if (this.kind == cursor_for_loop){
035            this.recordName = this.indexName;
036        }
037    }
038
039    /**
040     *
041     * @return What's kind of loop statement: simple, while or for.
042
043     */
044    public int getKind() {
045        return kind;
046    }
047
048    public TLoopStmt(){
049        this(EDbVendor.dbvoracle);
050    }
051
052     public TLoopStmt(EDbVendor dbvendor){
053        super(dbvendor);
054        sqlstatementtype = ESqlStatementType.sst_loopstmt;
055        }
056
057    private TObjectNameList scalarVariables;
058
059    public TObjectNameList getScalarVariables() {
060        return scalarVariables;
061    }
062
063    /**
064     * An undeclared identifier that names the loop index.
065     * Or, it should be a record-name when kind is cursor_for_loop.
066     * @return Index name used in for-loop-statement.
067     */
068    public TObjectName getIndexName() {
069        return indexName;
070    }
071
072    private TObjectName indexName = null;
073
074    public TObjectName getRecordName() {
075        return recordName;
076    }
077
078    private  TObjectName recordName = null;
079
080    private TStatementListSqlNode stmts = null;
081
082    private TExpression lower_bound = null;
083    private TExpression upper_bound = null;
084
085    private  boolean  isReverse = false;
086
087    public void setReverse(boolean reverse) {
088        isReverse = reverse;
089    }
090
091    public boolean isReverse() {
092
093        return isReverse;
094    }
095
096    /**
097     * Used in for-loop-statement.
098     * @return
099     */
100    public TExpression getUpper_bound() {
101
102        return upper_bound;
103    }
104
105    /**
106     * Used in for-loop-statement.
107     * @return
108     */
109    public TExpression getLower_bound() {
110
111        return lower_bound;
112    }
113
114
115
116    public void setSubquery(TSelectSqlStatement subquery) {
117        this.subquery = subquery;
118    }
119
120    /**
121     *
122     * @return Select statement when {@link #kind} is cursor_for_loop.
123     */
124    public TSelectSqlStatement getSubquery() {
125        return subquery;
126    }
127
128    private TSelectSqlStatement subquery = null;
129    private TSelectSqlNode selectSqlNode = null;
130
131    public void setSelectSqlNode(TSelectSqlNode selectSqlNode) {
132        this.selectSqlNode = selectSqlNode;
133    }
134
135    private TExpressionList cursorParameterNames = null;
136
137    public void setCursorParameterNames(TExpressionList cursorParameterNames) {
138        this.cursorParameterNames = cursorParameterNames;
139    }
140
141    /**
142     *
143     * @return  Cursor parameter names  when {@link #kind} is cursor_for_loop if any.
144     */
145    public TExpressionList getCursorParameterNames() {
146
147        return cursorParameterNames;
148    }
149
150    void buildsql() {
151    }
152
153    void clear() {
154    }
155
156    String getasprettytext() {
157        return "";
158    }
159
160    void iterate(TVisitorAbs pvisitor) {
161    }
162
163    public void init(Object arg1)
164    {
165        stmts = (TStatementListSqlNode)arg1;
166    }
167
168    public void init(Object arg1,Object arg2)
169    {
170        stmts = (TStatementListSqlNode)arg1;
171        if (arg2 instanceof TExpression){
172            this.condition = (TExpression)arg2;
173        }else if (arg2 instanceof TObjectNameList){
174           this.scalarVariables = (TObjectNameList) arg2;
175           this.indexName = this.scalarVariables.getObjectName(0);
176        }else{
177            this.indexName = (TObjectName)arg2;
178        }
179    }
180
181    public void init(Object arg1,Object arg2,Object arg3)
182    {
183        init(arg1,arg2);
184        cursorName = (TObjectName)arg3;
185    }
186
187    public void init(Object arg1,Object arg2,Object arg3,Object arg4)
188    {
189        init(arg1,arg2);
190
191        lower_bound = (TExpression)arg3;
192        upper_bound = (TExpression)arg4;
193    }
194
195    /**
196     *
197     * @return Cursor name when {@link #kind} is cursor_for_loop.
198     */
199    public TObjectName getCursorName() {
200        return cursorName;
201    }
202
203    private TObjectName cursorName = null;
204    
205
206    /**
207     * Used in while-loop-statement
208     * @return If and only if the value of this expression is TRUE,
209     * the statements in while will execute.
210     */
211    public TExpression getCondition() {
212        return condition;
213    }
214
215    private TExpression condition = null;
216
217    private TExpression executeExpr;
218    private TExpressionList executeUsingVars;
219
220    public void setExecuteExpr(TExpression executeExpr) {
221        this.executeExpr = executeExpr;
222    }
223
224    public void setExecuteUsingVars(TExpressionList executeUsingVars) {
225        this.executeUsingVars = executeUsingVars;
226    }
227
228    public TExpression getExecuteExpr() {
229
230        return executeExpr;
231    }
232
233    public TExpressionList getExecuteUsingVars() {
234        return executeUsingVars;
235    }
236
237    public int doParseStatement(TCustomSqlStatement psql) {
238        super.doParseStatement(psql);
239        this.stmtScope.setValidToDeclareVariable(true);
240
241        TFrame currentFrame = new TFrame(this.stmtScope);
242        currentFrame.pushMeToStack(getFrameStack());
243
244        switch (dbvendor){
245            case dbvmysql:
246            case dbvteradata:
247            case dbvbigquery:
248                if (rootNode == null) return -1;
249                TLoopSqlNode loopSqlNode = (TLoopSqlNode)rootNode;
250                setLabelName(loopSqlNode.getLabelName());
251
252                loopSqlNode.getStmts().doParse(this,ESqlClause.unknown);
253                for(int i=0;i<loopSqlNode.getStmts().size();i++){
254                    this.getBodyStatements().add(loopSqlNode.getStmts().getStatementSqlNode(i).getStmt());
255                }
256                break;
257            default:
258                //super.doParseStatement(psql);
259
260                if (indexName != null){
261                    this.getTopStatement().getSymbolTable().push( new TSymbolTableItem(TObjectName.ttobjParameter,this, indexName));
262                    TVariable variable = new TVariable(indexName);
263                    this.stmtScope.addSymbol(variable);
264                }
265                if (this.condition != null){
266                    this.condition.doParse(this,ESqlClause.unknown);
267                }
268                if (subquery != null){
269                    subquery.parsestatement(this,false);
270                }else if (selectSqlNode != null){
271                    //postgresql
272                    subquery = new TSelectSqlStatement(this.dbvendor);
273                    subquery.rootNode = selectSqlNode;
274                    subquery.doParseStatement(this);
275                }
276
277                stmts.doParse(this,ESqlClause.unknown);
278                for(int i=0;i<stmts.size();i++){
279                    this.getBodyStatements().add(stmts.getStatementSqlNode(i).getStmt());
280                }
281                if (indexName != null) {
282                    this.getTopStatement().getSymbolTable().pop();
283                }
284
285                break;
286        }
287
288        currentFrame.popMeFromStack(getFrameStack());
289
290        return 0;
291    }
292
293    public void accept(TParseTreeVisitor v){
294        v.preVisit(this);
295        v.postVisit(this);
296    }
297
298    public void acceptChildren(TParseTreeVisitor v){
299        v.preVisit(this);
300        if (this.condition != null) condition.acceptChildren(v);
301        if (subquery != null) subquery.acceptChildren(v);
302        getBodyStatements().acceptChildren(v);
303        v.postVisit(this);
304    }
305
306    public void setIndexName(TObjectName indexName) {
307        this.indexName = indexName;
308    }
309
310    public void setRecordName(TObjectName recordName) {
311        this.recordName = recordName;
312    }
313
314    public void setLower_bound(TExpression lower_bound) {
315        this.lower_bound = lower_bound;
316    }
317
318    public void setUpper_bound(TExpression upper_bound) {
319        this.upper_bound = upper_bound;
320    }
321
322    public void setCursorName(TObjectName cursorName) {
323        this.cursorName = cursorName;
324    }
325
326    public void setCondition(TExpression condition) {
327        this.condition = condition;
328    }
329}