001package gudusoft.gsqlparser.stmt.mssql; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.compiler.TSymbolTableManager; 005import gudusoft.gsqlparser.compiler.TVariable; 006import gudusoft.gsqlparser.nodes.*; 007import gudusoft.gsqlparser.nodes.mssql.TExecuteOption; 008import gudusoft.gsqlparser.stmt.TCreateFunctionStmt; 009import gudusoft.gsqlparser.stmt.TCreateProcedureStmt; 010import gudusoft.gsqlparser.stmt.TRoutine; 011import gudusoft.gsqlparser.stmt.TStoredProcedureSqlStatement; 012 013/** 014 * Execute a stored procedure or function, 015 * or Execute a character string 016 */ 017public class TMssqlExecute extends TCustomSqlStatement { 018 public TMssqlExecute (EDbVendor dbvendor){ 019 super(dbvendor); 020 sqlstatementtype = ESqlStatementType.sstmssqlexec ; 021 } 022 023 void buildsql() { 024 } 025 026 void clear() { 027 } 028 029 String getasprettytext() { 030 return ""; 031 } 032 033 void iterate(TVisitorAbs pvisitor) { 034 } 035 036 037 private String sqlText = null; 038 039 private TObjectName moduleName = null; 040 private TObjectName returnStatus = null; 041 private TExecParameterList parameters = null; 042 043 public String getSqlText() { 044 return sqlText; 045 } 046 047 public TObjectName getModuleName() { 048 return moduleName; 049 } 050 051 public TExecParameterList getParameters() { 052 return parameters; 053 } 054 055 public TObjectName getReturnStatus() { 056 return returnStatus; 057 } 058 059 public TExpressionList getStringValues() { 060 return stringValues; 061 } 062 063 public int getExecType() { 064 return execType; 065 } 066 067 private TExpressionList stringValues = null; 068 private int execType = TBaseType.metExecSp; 069 070 public TExpression getPreparedValue() { 071 return preparedValue; 072 } 073 074 private TExpression preparedValue;//couchbase 075 076 private boolean isValidProcedureCall(TSourceTokenList stList,TSyntaxError err){ 077 boolean ret = false; 078 079 if (stList.size() <= 1) return false; 080 TSourceToken st = stList.get(0); 081 if (st.tokencode == TBaseType.rrw_drop){ 082 TSourceToken nextst = stList.nextsolidtoken(st,1,false); 083 err.hint = "Unknown object type in drop statement"; 084 if (nextst != null){ 085 err.tokentext = nextst.toString(); 086 err.lineNo = nextst.lineNo; 087 err.columnNo = nextst.columnNo; 088 } 089 090 return false; 091 } 092 if (stList.get(1).tokentype == ETokenType.ttperiod) return true; 093 if (st.toString().toLowerCase().startsWith("sp")) return true; 094 if (st.toString().toLowerCase().startsWith("select")) return false; 095 if (st.toString().toLowerCase().startsWith("del")) return false; 096 if (st.toString().toLowerCase().startsWith("update")) return false; 097 if (st.toString().toLowerCase().startsWith("insert")) return false; 098 if (st.toString().toLowerCase().startsWith("create")) return false; 099 100 return ret; 101 } 102 private TExecuteOption executeOption; 103 104 public TExecuteOption getExecuteOption() { 105 return executeOption; 106 } 107 108 public EExecType getExecuteType() { 109 return executeType; 110 } 111 112 private EExecType executeType = EExecType.unknown; 113 114 private TObjectName intoVariable; 115 private TExpressionList usingVariables; 116 117 public TObjectName getIntoVariable() { 118 return intoVariable; 119 } 120 121 public TExpressionList getUsingVariables() { 122 return usingVariables; 123 } 124 125 public int doParseStatement(TCustomSqlStatement psql) { 126 if (rootNode == null) return -1; 127 if (!(rootNode instanceof TExecuteSqlNode)){ 128 if (this.sourcetokenlist.size() > 0){ 129 TSourceToken st1 = this.sourcetokenlist.get(0); 130 TSyntaxError err = new TSyntaxError(st1.toString(),st1.lineNo,st1.columnNo,"syntax error",EErrorType.sperror 131 ,TBaseType.MSG_ERROR_SYNTAX_ERROR 132 ,this,st1.posinlist); 133 if (!isValidProcedureCall(this.sourcetokenlist,err)) 134 this.parseerrormessagehandle(err); 135 } 136 return -1; 137 } 138 TExecuteSqlNode node = (TExecuteSqlNode)rootNode; 139 this.execType = node.getExecType(); 140 this.executeType = node.getExecuteType(); 141 this.preparedValue = node.getPreparedValue(); 142 this.intoVariable = node.getIntoVariable(); 143 this.usingVariables = node.getUsingVariables(); 144 145 this.executeOption = node.getExecuteOption(); 146 super.doParseStatement(psql); 147 148 149 if ((node.getExecType() == TBaseType.metExecSp)){ 150 this.moduleName = node.getModuleName(); 151 this.parameters = node.getParameters(); 152 this.returnStatus = node.getReturnStatus(); 153 this.linkServerName = node.getLinkServerName(); 154 if ((this.moduleName != null)&&(this.moduleName.toString().equalsIgnoreCase("sp_executesql")) 155 && (this.parameters != null) && (this.parameters.size() > 0)){ 156 TExecParameter parameter = this.parameters.getExecParameter(0); 157 if (parameter.getParameterValue().getExpressionType() == EExpressionType.simple_object_name_t){ 158 TObjectName var = parameter.getParameterValue().getObjectOperand(); 159 if (var.getDbObjectType() == EDbObjectType.variable){ 160 TVariable symbolVariable = TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),var.toString()); 161 if (symbolVariable != null){ 162 this.sqlText = symbolVariable.getVariableStr(); 163 //System.out.println(this.sqlText); 164 } 165 } 166 }else{ 167 parameter.getParameterValue().evaluate(this.getFrameStack(),this); 168 this.sqlText = parameter.getParameterValue().getPlainText(); 169 } 170 }else { 171 // exec a procedure with parameter, put the parameter as a variable into scope 172 TVariable variable = null; 173 int i=0; 174 175 //System.out.println(this.moduleName.toString()); 176 if (this.parameters != null){ 177 if (this.parameters.size() > 0){ 178 for(TExecParameter p:this.parameters){ 179 TObjectName variableName = TObjectName.createObjectName (this.dbvendor, EDbObjectType.variable, new TSourceToken("$"+i)); 180 variable = new TVariable(variableName,p,this.moduleName); 181 variable.setVariableStr(TBaseType.getStringInsideLiteral(p.getParameterValue().toString())); 182 if ((psql != null) && (psql.getStmtScope() != null)) { 183 psql.getStmtScope().addSymbol(variable); 184 }else{ 185 //TODO: execute 中的变量应该放在gloabl scope中吗? 186 this.getGlobalScope().addSymbol(variable); 187 } 188 189 i++; 190 //System.out.println(p.getParameterValue().toString()); 191 } 192 } 193 } 194 }; 195 }else if (node.getExecType() == TBaseType.metExecStringCmd){ 196 this.stringValues = node.getStringValues(); 197 TExpression execStringExpr = this.stringValues.getExpression(0); 198 TObjectName execStringVar = (execStringExpr.getExpressionType() == EExpressionType.simple_object_name_t) 199 ? execStringExpr.getObjectOperand() : null; 200 if (execStringVar != null && execStringVar.getDbObjectType() == EDbObjectType.variable){ 201 TVariable symbolVariable = TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),execStringVar.toString()); 202 if (symbolVariable != null){ 203 //this.getSqlEnv().getVariableValue(symbolVariable.getQualifiedName(),symbolVariable.getVariableStr()); 204 this.sqlText = symbolVariable.getVariableStr(); 205 //System.out.println(this.sqlText); 206 } 207 } else { 208 // EXEC('<literal>') or a constant concatenation. T-SQL stores the concatenation operands 209 // as separate elements of stringValues (EXEC('a' + 'b') -> ['a','b']). Fold every element 210 // and only adopt the result when ALL parts are fully literal (getVal() set and not 211 // partial), so getSqlText() never becomes a partial / speculative value that every 212 // downstream TMssqlExecute consumer would then try to parse. 213 StringBuilder folded = new StringBuilder(); 214 boolean fullyLiteral = true; 215 for (int si = 0; si < this.stringValues.size(); si++){ 216 TExpression part = this.stringValues.getExpression(si); 217 part.evaluate(this.getFrameStack(), this); 218 if (part.getVal() != null && !part.isValPartial()){ 219 // append the gated value (unquoted, via getStringInsideLiteral), not the mutable 220 // plainText display field, so N'...' / escaped quotes fold correctly 221 folded.append(part.getVal()); 222 } else { 223 fullyLiteral = false; 224 break; 225 } 226 } 227 if (fullyLiteral && folded.length() > 0){ 228 this.sqlText = folded.toString(); 229 } 230 } 231 this.linkServerName = node.getLinkServerName(); 232 this.executeAsUser = node.getExecuteAsUser(); 233 this.executeAsLogin = node.getExecuteAsLogin(); 234 }else if (node.getExecType() == TBaseType.metNoExecKeyword){ 235 //the first statement in a batch or an osql or sqlcmd script, EXEC is not required. 236 //dbo.uspGetEmployeeManagers @BusinessEntityID = 6; 237 if (this.sourcetokenlist.size() > 0){ 238 TSourceToken st1 = this.sourcetokenlist.get(0); 239 String errMsg = "syntax error"; 240 TSourceToken errToken = st1; 241 TSyntaxError err = new TSyntaxError(st1.toString(),st1.lineNo,st1.columnNo,"syntax error",EErrorType.sperror 242 ,TBaseType.MSG_ERROR_SYNTAX_ERROR,this,st1.posinlist); 243 if (!isValidProcedureCall(this.sourcetokenlist,err)) 244 this.parseerrormessagehandle( err); 245 246 // moduleName = (TObjectName)this.parser.getNf().createNode(ENodeType.T_ObjectName.getId()); //new TObjectName(); 247 moduleName = new TObjectName(); 248 moduleName.setGsqlparser(this.getGsqlparser()); 249 int j = 0; 250 for(int i=0;i<this.sourcetokenlist.size();i++){ 251 if ((this.sourcetokenlist.get(i).tokentype == ETokenType.ttwhitespace) 252 || (this.sourcetokenlist.get(i).tokentype == ETokenType.ttreturn) 253 ||(this.sourcetokenlist.get(i).tokentype == ETokenType.ttsemicolon) 254 ){ 255 break; 256 } 257 j++; 258 } 259 switch(j){ 260 case 1: 261 moduleName.init(this.sourcetokenlist.get(0)); 262 break; 263 case 3: 264 moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2)); 265 break; 266 case 5: 267 moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4)); 268 break; 269 case 7: 270 moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4),this.sourcetokenlist.get(6)); 271 break; 272 default: 273 moduleName = null; 274 break; 275 } 276 277 if (moduleName != null){ 278 //moduleName.setObjectType(TObjectName.ttobjProcedureName); 279 moduleName.setDbObjectType(EDbObjectType.procedure); 280 } 281 282 } 283 284 } 285 return 0; 286 } 287 288 public TObjectName getLinkServerName() { 289 return linkServerName; 290 } 291 292 private TObjectName linkServerName; 293 294 private TObjectName executeAsUser; 295 private TObjectName executeAsLogin; 296 297 public TObjectName getExecuteAsUser() { 298 return executeAsUser; 299 } 300 301 public TObjectName getExecuteAsLogin() { 302 return executeAsLogin; 303 } 304 305 public void accept(TParseTreeVisitor v){ 306 v.preVisit(this); 307 v.postVisit(this); 308 } 309 public void acceptChildren(TParseTreeVisitor v){ 310 v.preVisit(this); 311 v.postVisit(this); 312 } 313 314 public void setModuleName(TObjectName moduleName) { 315 this.moduleName = moduleName; 316 } 317 318 public void setReturnStatus(TObjectName returnStatus) { 319 this.returnStatus = returnStatus; 320 } 321 322 public void setParameters(TExecParameterList parameters) { 323 this.parameters = parameters; 324 } 325 326 public void setStringValues(TExpressionList stringValues) { 327 this.stringValues = stringValues; 328 } 329 330 public void setExecType(int execType) { 331 this.execType = execType; 332 } 333}