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