001package gudusoft.gsqlparser.stmt; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.nodes.*; 005 006import java.util.ArrayList; 007import java.util.HashMap; 008 009/** 010 * The EXECUTE IMMEDIATE statement builds and executes a dynamic SQL statement in 011 * a single operation. 012 */ 013public class TExecImmeStmt extends TBlockSqlStatement { 014 015 private TExpression dynamicStringExpr = null; 016 private TBindArgumentList bindArguments = null; 017 private TExpressionList intoVariables = null; 018 private TObjectNameList returnNames = null; 019 private String dynamicSQL = null; 020 private TStatementList dynamicStatements = null; 021 022 public ArrayList<String> getEvaluatedDynamicSQLs() { 023 return evaluatedDynamicSQLs; 024 } 025 026 private ArrayList <String> evaluatedDynamicSQLs = new ArrayList<String>(); 027 028 static TGSqlParser sqlparser = null; 029 static { 030 sqlparser = new TGSqlParser(EDbVendor.dbvoracle); 031 } 032 033 /** 034 * 035 * @return sql statement instance that generated dynamically based on {@link #dynamicSQL} 036 */ 037 public synchronized TStatementList getDynamicStatements() { 038 if (this.dynamicStatements != null) return this.dynamicStatements; 039 if (this.getDynamicSQL() == null) return null; 040 041 String query = this.getDynamicSQL(); 042 043 if(this.getDynamicStringExpr().getPlainTextLineNo() != -1){ 044 long lineNo = this.getDynamicStringExpr().getPlainTextLineNo(); 045 long columnNo = this.getDynamicStringExpr().getPlainTextColumnNo(); 046 query = TBaseType.stringBlock((int)lineNo - 1,(int)columnNo)+ this.getDynamicSQL(); 047 } 048 049 050 sqlparser.sqltext = query; 051 int ret = sqlparser.parse(); 052 053 if ( ret != 0){ 054 for(int j=0;j<sqlparser.getErrorCount();j++){ 055 this.parseerrormessagehandle(sqlparser.getSyntaxErrors().get(j)); 056 } 057 058 return null; 059 } 060 061 this.dynamicStatements = new TStatementList(); 062 for(int i=0;i<sqlparser.sqlstatements.size();i++){ 063 if (this.getParentStmt() == null){ 064 sqlparser.sqlstatements.get(i).setParentStmt(this); 065 }else{ 066 sqlparser.sqlstatements.get(i).setParentStmt(this.getParentStmt()); 067 } 068 069 this.dynamicStatements.add(sqlparser.sqlstatements.get(i)); 070 } 071 return dynamicStatements; 072 } 073 074 /** 075 * 076 * @return String representation of dynamic sql statement. if there is a variable in 077 * {@link #dynamicStringExpr}, value of this variable will be returned. 078 */ 079 080 public String getDynamicSQL() { 081 if (!this.getEvaluatedDynamicSQLs().isEmpty()){ 082 // 使用 TASTEvaluator 计算动态 SQL 后,将结果保存在 evaluatedDynamicSQLs 中,如果有值,采用这个更精确的 SQL 值 083 StringBuilder concatenatedSQL = new StringBuilder(); 084 085 for (int i = 0; i < this.getEvaluatedDynamicSQLs().size(); i++) { 086 String sql = this.getEvaluatedDynamicSQLs().get(i); 087 concatenatedSQL.append(sql); 088 if (i < this.getEvaluatedDynamicSQLs().size() - 1) { 089 concatenatedSQL.append(";"); 090 concatenatedSQL.append(TBaseType.newline); 091 } 092 } 093 094 this.dynamicSQL = concatenatedSQL.toString(); 095 } 096 return this.dynamicSQL; 097 098// if (this.dynamicSQL != null) return this.dynamicSQL; 099// 100// if (dynamicStringExpr.getExpressionType() == EExpressionType.simple_constant_t) 101// { 102// this.dynamicSQL = TBaseType.getStringInsideLiteral(this.dynamicStringExpr.toString()); 103// }else if (dynamicStringExpr.getExpressionType() == EExpressionType.simple_object_name_t){ 104// // this is a variable, we have to search 105// String lcvar = this.getDynamicStringExpr().toString(); 106// TCustomSqlStatement topsql = this.getTopStatement(); 107// if (topsql instanceof TBlockSqlStatement){ 108// TCustomSqlStatement stmt = null; 109// for(int i=0;i< ((TBlockSqlStatement)topsql).getBodyStatements().size();i++){ 110// stmt = ((TBlockSqlStatement)topsql).getBodyStatements().get(i); 111// if (stmt instanceof TAssignStmt){ 112// if ( ((TAssignStmt)stmt).getLeft().toString().compareToIgnoreCase(lcvar) == 0 ) 113// { 114// if (((TAssignStmt)stmt).getExpression().getExpressionType() == EExpressionType.simple_constant_t){ 115// this.dynamicSQL = ((TAssignStmt)stmt).getExpression().toString().substring(1,((TAssignStmt)stmt).getExpression().toString().length() - 1); 116// }else{ 117// this.dynamicSQL = null; 118// } 119// break; 120// } 121// } 122// } 123// } 124// if ((this.getParentStmt() instanceof TBlockSqlStatement)&&(this.dynamicSQL == null)){ 125// TBlockSqlStatement blockSqlStatement = (TBlockSqlStatement)this.getParentStmt(); 126// for(int i=0;i< blockSqlStatement.getBodyStatements().size();i++){ 127// TCustomSqlStatement stmt = blockSqlStatement.getBodyStatements().get(i); 128// if (stmt instanceof TAssignStmt){ 129// if ( ((TAssignStmt)stmt).getLeft().toString().compareToIgnoreCase(lcvar) == 0 ) 130// { 131// if (((TAssignStmt)stmt).getExpression().getExpressionType() == EExpressionType.simple_constant_t){ 132// this.dynamicSQL = ((TAssignStmt)stmt).getExpression().toString().substring(1,((TAssignStmt)stmt).getExpression().toString().length() - 1); 133// }else{ 134// this.dynamicSQL = null; 135// } 136// break; 137// } 138// } 139// } 140// } 141// 142// }else{ 143// calculateExprVisitor cv = new calculateExprVisitor(); 144// this.dynamicStringExpr.postOrderTraverse(cv); 145// //this.dynamicStringExpr.evaluate(); 146// 147// this.dynamicSQL = this.dynamicStringExpr.getPlainText(); 148//// if (this.dynamicSQL.charAt(0) == '\''){ 149//// this.dynamicSQL = this.dynamicSQL.substring(1,this.dynamicSQL.toString().length() - 2); 150//// } 151// } 152// return this.dynamicSQL ; 153 } 154 155 /** 156 * bind arguments 157 * @return bind arguments in using clause. 158 */ 159 public TBindArgumentList getBindArguments() { 160 return bindArguments; 161 } 162 163 /** 164 * String expr 165 * 166 * @return A string literal, string variable, or string expression that represents any SQL statement. 167 * this is the original string of dynamic sql statement. 168 */ 169 170 public TExpression getDynamicStringExpr() { 171 return dynamicStringExpr; 172 } 173 174 /** 175 * Into variable 176 * 177 * @return variable names in the into clause. 178 */ 179 public TExpressionList getIntoVariables() { 180 return intoVariables; 181 } 182 183 /** 184 * 185 * Used if and only if dynamic_sql_stmt has a RETURNING INTO clause, this clause 186 * returns the column values of the rows affected by dynamic_sql_stmt, in either 187 * individual variables or records 188 * 189 * @return 190 */ 191 192 public TObjectNameList getReturnNames() { 193 return returnNames; 194 } 195 196 public TExecImmeStmt(EDbVendor dbvendor){ 197 super(dbvendor); 198 sqlstatementtype = ESqlStatementType.sstplsql_execimmestmt ; 199 } 200 201 void buildsql() { 202 } 203 204 void clear() { 205 } 206 207 String getasprettytext() { 208 return ""; 209 } 210 211 void iterate(TVisitorAbs pvisitor) { 212 } 213 214 public int doParseStatement(TCustomSqlStatement psql) { 215 if (rootNode == null) return -1; 216 super.doParseStatement(psql); 217 218 TExecImmeNode execImmeNode = (TExecImmeNode)rootNode; 219 this.bindArguments = execImmeNode.getBindArguments(); 220 this.intoVariables = execImmeNode.getIntoVariables(); 221 this.dynamicStringExpr = execImmeNode.getDynamicStringExpr(); 222 this.returnNames = execImmeNode.getReturnNames(); 223 224 this.dynamicStringExpr.evaluate(this.getFrameStack(),this); 225 this.dynamicSQL = this.dynamicStringExpr.getPlainText(); 226 227 //TODO parse the dynamicSQL, 先不在这里解析动态 SQL, 考虑和 TASTEvaluator 结合 228 // getDynamicStatements(); 229 230 return 0; 231 } 232 233 public void accept(TParseTreeVisitor v){ 234 v.preVisit(this); 235 v.postVisit(this); 236 } 237 238 public void acceptChildren(TParseTreeVisitor v){ 239 v.preVisit(this); 240 this.dynamicStringExpr.acceptChildren(v); 241 v.postVisit(this); 242 } 243 244 public void setDynamicStringExpr(TExpression dynamicStringExpr) { 245 this.dynamicStringExpr = dynamicStringExpr; 246 } 247 248 public void setBindArguments(TBindArgumentList bindArguments) { 249 this.bindArguments = bindArguments; 250 } 251 252 public void setIntoVariables(TExpressionList intoVariables) { 253 this.intoVariables = intoVariables; 254 } 255 256 public void setReturnNames(TObjectNameList returnNames) { 257 this.returnNames = returnNames; 258 } 259 260 public void setDynamicSQL(String dynamicSQL) { 261 this.dynamicSQL = dynamicSQL; 262 } 263 264 public void setDynamicStatements(TStatementList dynamicStatements) { 265 this.dynamicStatements = dynamicStatements; 266 } 267 268// private String EvaluateExpr(){ 269// if (this.dynamicStringExpr == null) return ""; 270// return this.dynamicStringExpr.getPlainText(); 271// } 272} 273 274//class calculateExprVisitor implements IExpressionVisitor { 275// Stack<TExpression> expressionStack = new Stack<>(); 276// 277// public boolean exprVisit(TParseTreeNode pNode,boolean isLeafNode){ 278// if (isLeafNode){ 279// expressionStack.push((TExpression)pNode); 280// } 281// 282// TExpression expr = (TExpression)pNode; 283// switch (expr.getExpressionType()){ 284// case concatenate_t: 285// TExpression expr1 = expressionStack.pop(); 286// TExpression expr2 = expressionStack.pop(); 287// 288// String expr1Str = expr1.getPlainText(); 289// String expr2Str = expr2.getPlainText(); 290// switch (expr1.getExpressionType()){ 291// case simple_constant_t: 292// expr1Str = TBaseType.getStringInsideLiteral(expr1Str); 293// break; 294// case function_t: 295// expr1Str = expr1.getFunctionCall().getFunctionName().toString(); 296// break; 297// case simple_object_name_t: 298// expr1Str = expr1Str.replace(".","_"); 299// break; 300// default: 301// break; 302// } 303// 304// switch (expr2.getExpressionType()){ 305// case simple_constant_t: 306// expr2Str = TBaseType.getStringInsideLiteral(expr2Str); 307// break; 308// case function_t: 309// expr2Str = expr2.getFunctionCall().getFunctionName().toString(); 310// break; 311// case simple_object_name_t: 312// expr2Str = expr2Str.replace(".","_"); 313// break; 314// default: 315// break; 316// } 317// 318// 319// //TExpression expr3 = expressionStack.peek(); 320// ((TExpression)pNode).setPlainText(expr2Str+expr1Str); 321// 322// expressionStack.push((TExpression)pNode); 323// 324// break; 325// } 326// return true; 327// }; 328// 329//} 330