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}