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           if (this.stringValues.getExpression(0).getExpressionType() == EExpressionType.simple_object_name_t){
198               TObjectName var = this.stringValues.getExpression(0).getObjectOperand();
199               if (var.getDbObjectType() == EDbObjectType.variable){
200                   TVariable symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),var.toString());
201                   if (symbolVariable != null){
202                       //this.getSqlEnv().getVariableValue(symbolVariable.getQualifiedName(),symbolVariable.getVariableStr());
203                       this.sqlText = symbolVariable.getVariableStr();
204                       //System.out.println(this.sqlText);
205                   }
206               }
207           }
208           this.linkServerName = node.getLinkServerName();
209           this.executeAsUser = node.getExecuteAsUser();
210           this.executeAsLogin = node.getExecuteAsLogin();
211       }else if (node.getExecType() == TBaseType.metNoExecKeyword){
212            //the first statement in a batch or an osql or sqlcmd script, EXEC is not required.
213            //dbo.uspGetEmployeeManagers @BusinessEntityID = 6;
214            if (this.sourcetokenlist.size() > 0){
215                TSourceToken st1 = this.sourcetokenlist.get(0);
216                String errMsg = "syntax error";
217                TSourceToken errToken = st1;
218                TSyntaxError err = new TSyntaxError(st1.toString(),st1.lineNo,st1.columnNo,"syntax error",EErrorType.sperror
219                        ,TBaseType.MSG_ERROR_SYNTAX_ERROR,this,st1.posinlist);
220                if (!isValidProcedureCall(this.sourcetokenlist,err))
221                    this.parseerrormessagehandle( err);
222
223              //  moduleName = (TObjectName)this.parser.getNf().createNode(ENodeType.T_ObjectName.getId()); //new TObjectName();
224                moduleName = new TObjectName();
225                moduleName.setGsqlparser(this.getGsqlparser());
226                int j = 0;
227                for(int i=0;i<this.sourcetokenlist.size();i++){
228                   if ((this.sourcetokenlist.get(i).tokentype == ETokenType.ttwhitespace)
229                           || (this.sourcetokenlist.get(i).tokentype == ETokenType.ttreturn)
230                           ||(this.sourcetokenlist.get(i).tokentype == ETokenType.ttsemicolon)
231                       ){
232                      break;
233                   }
234                    j++;
235                }
236                switch(j){
237                    case 1:
238                        moduleName.init(this.sourcetokenlist.get(0));
239                        break;
240                    case 3:
241                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2));
242                        break;
243                    case 5:
244                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4));
245                        break;
246                    case 7:
247                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4),this.sourcetokenlist.get(6));
248                        break;
249                    default:
250                        moduleName = null;
251                        break;
252                }
253
254                if (moduleName != null){
255                    //moduleName.setObjectType(TObjectName.ttobjProcedureName);
256                    moduleName.setDbObjectType(EDbObjectType.procedure);
257                }
258
259            }
260
261        }
262      return 0;
263   }
264
265    public TObjectName getLinkServerName() {
266        return linkServerName;
267    }
268
269    private TObjectName linkServerName;
270
271    private TObjectName executeAsUser;
272    private TObjectName executeAsLogin;
273
274    public TObjectName getExecuteAsUser() {
275        return executeAsUser;
276    }
277
278    public TObjectName getExecuteAsLogin() {
279        return executeAsLogin;
280    }
281
282   public void accept(TParseTreeVisitor v){
283       v.preVisit(this);
284       v.postVisit(this);
285   }
286    public void acceptChildren(TParseTreeVisitor v){
287        v.preVisit(this);
288        v.postVisit(this);
289    }
290
291    public void setModuleName(TObjectName moduleName) {
292        this.moduleName = moduleName;
293    }
294
295    public void setReturnStatus(TObjectName returnStatus) {
296        this.returnStatus = returnStatus;
297    }
298
299    public void setParameters(TExecParameterList parameters) {
300        this.parameters = parameters;
301    }
302
303    public void setStringValues(TExpressionList stringValues) {
304        this.stringValues = stringValues;
305    }
306
307    public void setExecType(int execType) {
308        this.execType = execType;
309    }
310}