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