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                TExecParameter parameter = this.parameters.getExecParameter(0);
156                if (parameter.getParameterValue().getExpressionType() == EExpressionType.simple_object_name_t){
157                    TObjectName var = parameter.getParameterValue().getObjectOperand();
158                    if (var.getDbObjectType() == EDbObjectType.variable){
159                        TVariable symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),var.toString());
160                        if (symbolVariable != null){
161                            this.sqlText = symbolVariable.getVariableStr();
162                            //System.out.println(this.sqlText);
163                        }
164                    }
165                }else{
166                    parameter.getParameterValue().evaluate(this.getFrameStack(),this);
167                    this.sqlText = parameter.getParameterValue().getPlainText();
168                }
169            }else {
170                // exec a procedure with parameter, put the parameter as a variable into scope
171                TVariable variable = null;
172                int i=0;
173
174                //System.out.println(this.moduleName.toString());
175                if (this.parameters != null){
176                    if (this.parameters.size() > 0){
177                        for(TExecParameter p:this.parameters){
178                            TObjectName variableName =  TObjectName.createObjectName (this.dbvendor,  EDbObjectType.variable, new TSourceToken("$"+i));
179                            variable = new TVariable(variableName,p,this.moduleName);
180                            variable.setVariableStr(TBaseType.getStringInsideLiteral(p.getParameterValue().toString()));
181                            if ((psql != null) && (psql.getStmtScope() != null)) {
182                                psql.getStmtScope().addSymbol(variable);
183                            }else{
184                                //TODO: execute 中的变量应该放在gloabl scope中吗?
185                                this.getGlobalScope().addSymbol(variable);
186                            }
187
188                            i++;
189                            //System.out.println(p.getParameterValue().toString());
190                        }
191                    }
192                }
193            };
194        }else if (node.getExecType() == TBaseType.metExecStringCmd){
195           this.stringValues = node.getStringValues();
196           if (this.stringValues.getExpression(0).getExpressionType() == EExpressionType.simple_object_name_t){
197               TObjectName var = this.stringValues.getExpression(0).getObjectOperand();
198               if (var.getDbObjectType() == EDbObjectType.variable){
199                   TVariable symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),var.toString());
200                   if (symbolVariable != null){
201                       //this.getSqlEnv().getVariableValue(symbolVariable.getQualifiedName(),symbolVariable.getVariableStr());
202                       this.sqlText = symbolVariable.getVariableStr();
203                       //System.out.println(this.sqlText);
204                   }
205               }
206           }
207           this.linkServerName = node.getLinkServerName();
208           this.executeAsUser = node.getExecuteAsUser();
209           this.executeAsLogin = node.getExecuteAsLogin();
210       }else if (node.getExecType() == TBaseType.metNoExecKeyword){
211            //the first statement in a batch or an osql or sqlcmd script, EXEC is not required.
212            //dbo.uspGetEmployeeManagers @BusinessEntityID = 6;
213            if (this.sourcetokenlist.size() > 0){
214                TSourceToken st1 = this.sourcetokenlist.get(0);
215                String errMsg = "syntax error";
216                TSourceToken errToken = st1;
217                TSyntaxError err = new TSyntaxError(st1.toString(),st1.lineNo,st1.columnNo,"syntax error",EErrorType.sperror
218                        ,TBaseType.MSG_ERROR_SYNTAX_ERROR,this,st1.posinlist);
219                if (!isValidProcedureCall(this.sourcetokenlist,err))
220                    this.parseerrormessagehandle( err);
221
222              //  moduleName = (TObjectName)this.parser.getNf().createNode(ENodeType.T_ObjectName.getId()); //new TObjectName();
223                moduleName = new TObjectName();
224                moduleName.setGsqlparser(this.getGsqlparser());
225                int j = 0;
226                for(int i=0;i<this.sourcetokenlist.size();i++){
227                   if ((this.sourcetokenlist.get(i).tokentype == ETokenType.ttwhitespace)
228                           || (this.sourcetokenlist.get(i).tokentype == ETokenType.ttreturn)
229                           ||(this.sourcetokenlist.get(i).tokentype == ETokenType.ttsemicolon)
230                       ){
231                      break;
232                   }
233                    j++;
234                }
235                switch(j){
236                    case 1:
237                        moduleName.init(this.sourcetokenlist.get(0));
238                        break;
239                    case 3:
240                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2));
241                        break;
242                    case 5:
243                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4));
244                        break;
245                    case 7:
246                        moduleName.init(this.sourcetokenlist.get(0),this.sourcetokenlist.get(2),this.sourcetokenlist.get(4),this.sourcetokenlist.get(6));
247                        break;
248                    default:
249                        moduleName = null;
250                        break;
251                }
252
253                if (moduleName != null){
254                    //moduleName.setObjectType(TObjectName.ttobjProcedureName);
255                    moduleName.setDbObjectType(EDbObjectType.procedure);
256                }
257
258            }
259
260        }
261      return 0;
262   }
263
264    public TObjectName getLinkServerName() {
265        return linkServerName;
266    }
267
268    private TObjectName linkServerName;
269
270    private TObjectName executeAsUser;
271    private TObjectName executeAsLogin;
272
273    public TObjectName getExecuteAsUser() {
274        return executeAsUser;
275    }
276
277    public TObjectName getExecuteAsLogin() {
278        return executeAsLogin;
279    }
280
281   public void accept(TParseTreeVisitor v){
282       v.preVisit(this);
283       v.postVisit(this);
284   }
285    public void acceptChildren(TParseTreeVisitor v){
286        v.preVisit(this);
287        v.postVisit(this);
288    }
289
290    public void setModuleName(TObjectName moduleName) {
291        this.moduleName = moduleName;
292    }
293
294    public void setReturnStatus(TObjectName returnStatus) {
295        this.returnStatus = returnStatus;
296    }
297
298    public void setParameters(TExecParameterList parameters) {
299        this.parameters = parameters;
300    }
301
302    public void setStringValues(TExpressionList stringValues) {
303        this.stringValues = stringValues;
304    }
305
306    public void setExecType(int execType) {
307        this.execType = execType;
308    }
309}