001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.compiler.TSymbolTableManager;
005import gudusoft.gsqlparser.compiler.TVariable;
006import gudusoft.gsqlparser.nodes.*;
007
008
009/**
010 * execute statement
011 *
012 * db: couchbase, netezza,greenplum,mysql, postgresql,redshift
013 *
014 * @TODO: 2024/2/7  {@link  gudusoft.gsqlparser.stmt.mssql.TMssqlExecute}, {@link TExecImmeStmt} should merge into this class
015 */
016public class TExecuteSqlStatement extends TCustomSqlStatement {
017
018    private String preparedSqlText;
019
020    public void setPreparedSqlText(String preparedSqlText) {
021        this.preparedSqlText = preparedSqlText;
022    }
023
024    public String getPreparedSqlText() {
025        return preparedSqlText;
026    }
027
028    private EExecType executeType = EExecType.unknown;
029
030    public EExecType getExecuteType() {
031        return executeType;
032    }
033
034    private TCustomSqlStatement stmt;
035
036    public TCustomSqlStatement getStmt() {
037        return stmt;
038    }
039
040    public TExecuteSqlStatement(){
041        this(EDbVendor.dbvpostgresql);
042    }
043
044    public TExecuteSqlStatement(EDbVendor dbvendor) {
045        super(dbvendor);
046        sqlstatementtype = ESqlStatementType.sstExecute;
047    }
048
049    public int doParseStatement(TCustomSqlStatement psql) {
050
051        if (rootNode == null) return -1;
052        super.doParseStatement(psql);
053
054        TExecuteSqlNode sqlNode = (TExecuteSqlNode)rootNode;
055        this.executeType = sqlNode.getExecuteType();
056
057        switch (dbvendor){
058            case dbvpostgresql:
059                this.stmtString = sqlNode.getStmtString();
060                this.intoVariable = sqlNode.getIntoVariable();
061                this.usingVariables = sqlNode.getUsingVariables();
062
063                sqlText = stmtString.toString();
064                if (stmtString.getExpressionType() == EExpressionType.function_t){
065                    if (stmtString.toString().startsWith("format")){
066                        //postgresql format function
067                        TFunctionCall functionCall = stmtString.getFunctionCall();
068                        sqlText = functionCall.getArgs().getExpression(0).toString();
069                        sqlText = sqlText.replaceAll("%s","PLACEHOLDER");
070                    }
071                }
072               // System.out.println(sqlText);
073
074                this.moduleName = sqlNode.getModuleName();
075                this.statementName = sqlNode.getModuleName();
076                this.parameters = sqlNode.getStringValues();
077
078                break;
079            case dbvsnowflake:
080                this.stmtString = sqlNode.getStmtString();
081                //System.out.println(stmtString.toString());
082                TSourceToken st = stmtString.getStartToken();
083                if (st.toString().startsWith("$$")){
084                    TGSqlParser parser = new TGSqlParser(EDbVendor.dbvsnowflake);
085                    parser.sqltext = TBaseType.stringBlock((int)st.lineNo - 1,(int)st.columnNo)+ TBaseType.getStringInsideLiteral(st.toString());
086                    int ret = parser.parse();
087                    if (ret == 0){
088                        stmt = parser.sqlstatements.get(0);
089                    }else{
090                        for(int j=0;j<parser.getErrorCount();j++){
091                            this.parseerrormessagehandle(parser.getSyntaxErrors().get(j));
092                        }
093                    }
094                }
095
096                break;
097            case dbvnetezza:
098                this.moduleName = sqlNode.getModuleName();
099                this.statementName = sqlNode.getModuleName();
100                this.parameters = sqlNode.getStringValues();
101                preparedValue = sqlNode.getPreparedValue();
102                if (preparedValue != null){
103                    preparedValue.doParse(this, ESqlClause.unknown);
104                }
105
106                switch (executeType){
107                    case expr:
108                        if (sqlNode.getPreparedValue().getExpressionType() == EExpressionType.function_t){
109                            TFunctionCall functionCall = sqlNode.getPreparedValue().getFunctionCall();
110                            this.moduleName = functionCall.getFunctionName();
111                            this.parameters = functionCall.getArgs();
112                            this.executeType = EExecType.module;
113                        }
114                        break;
115                    default:
116                        break;
117                }
118
119                break;
120            case dbvredshift:
121                this.moduleName = sqlNode.getModuleName();
122                this.statementName = sqlNode.getModuleName();
123                this.parameters = sqlNode.getStringValues();
124                preparedValue = sqlNode.getPreparedValue();
125                if (preparedValue != null){
126                    preparedValue.doParse(this, ESqlClause.unknown);
127
128                    if (this.preparedValue.getExpressionType() == EExpressionType.simple_object_name_t){
129                        TObjectName var = this.preparedValue.getObjectOperand();
130                        //  if (var.getDbObjectType() == EDbObjectType.variable){
131                        TVariable symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(),var.toString());
132                        if (symbolVariable != null){
133                            this.sqlText = symbolVariable.getVariableStr();
134                            //System.out.println(this.sqlText);
135                        }
136                        // }
137                    }
138
139                }
140                break;
141            default:
142                this.moduleName = sqlNode.getModuleName();
143                this.statementName = sqlNode.getModuleName();
144                this.parameters = sqlNode.getStringValues();
145                preparedValue = sqlNode.getPreparedValue();
146                if (preparedValue != null){
147                    preparedValue.doParse(this, ESqlClause.unknown);
148                }
149
150                // available in TMssqlExecute currently, maybe will be moved to here in later version
151                //this.stringValues = sqlNode.getStringValues();
152                //this.linkServerName = sqlNode.getLinkServerName();
153
154                break;
155        }
156        return 0;
157    }
158
159    static TGSqlParser sqlparser = null;
160    static {
161        // Todo: hardcode to redshift, need to change according to dbvendor
162        sqlparser = new TGSqlParser(EDbVendor.dbvredshift);
163    }
164
165    private TStatementList dynamicStatements = null;
166
167    /**
168     *
169     * @return sql statement instance that generated dynamically based on {@link #sqlText}
170     */
171    public synchronized TStatementList getDynamicStatements() {
172        if (this.dynamicStatements != null) return this.dynamicStatements;
173        if (this.sqlText == null) return null;
174
175
176        String query = this.sqlText;
177        if((this.preparedValue != null) && (this.preparedValue.getPlainTextLineNo() != -1)){
178            long lineNo = this.preparedValue.getPlainTextLineNo();
179            long columnNo = this.preparedValue.getPlainTextColumnNo();
180            query = TBaseType.stringBlock((int)lineNo - 1,(int)columnNo)+ this.sqlText;
181        }
182
183
184        sqlparser.sqltext = query;
185        int ret = sqlparser.parse();
186
187        if ( ret != 0){
188            for(int j=0;j<sqlparser.getErrorCount();j++){
189                this.parseerrormessagehandle(sqlparser.getSyntaxErrors().get(j));
190            }
191
192            return null;
193        }
194
195        this.dynamicStatements = new TStatementList();
196        for(int i=0;i<sqlparser.sqlstatements.size();i++){
197            if (this.getParentStmt() == null){
198                sqlparser.sqlstatements.get(i).setParentStmt(this);
199            }else{
200                sqlparser.sqlstatements.get(i).setParentStmt(this.getParentStmt());
201            }
202
203            this.dynamicStatements.add(sqlparser.sqlstatements.get(i));
204        }
205        return dynamicStatements;
206    }
207
208    public TObjectName getLinkServerName() {
209        return linkServerName;
210    }
211
212    private TObjectName linkServerName;
213    private TExpressionList stringValues = null;
214
215    public TExpressionList getStringValues() {
216        return stringValues;
217    }
218
219    private TObjectName moduleName;
220
221    public TObjectName getModuleName() {
222        return moduleName;
223    }
224
225    private TExpression stmtString;
226    private TObjectName intoVariable;
227    private TExpressionList usingVariables;
228
229    private TObjectName statementName;
230    private TExpressionList parameters;
231    private TExpression preparedValue;//couchbase
232
233    public void setSqlText(String sqlText) {
234        this.sqlText = sqlText;
235    }
236
237    private String sqlText = null;
238
239    public String getSqlText() {
240        return sqlText;
241    }
242
243    public void init(Object arg1){
244        stmtString = (TExpression)arg1;
245        sqlText = stmtString.toString();
246        switch (stmtString.getExpressionType()){
247            case simple_object_name_t:
248                moduleName = stmtString.getObjectOperand();
249                //moduleName.setObjectType(TObjectName.ttobjProcedureName);
250                moduleName.setDbObjectType(EDbObjectType.procedure);
251                break;
252            case function_t:
253                if (stmtString.toString().startsWith("format")){
254                    //postgresql format function
255                    TFunctionCall functionCall = stmtString.getFunctionCall();
256                    sqlText = functionCall.getArgs().getExpression(0).toString();
257                    sqlText = sqlText.replaceAll("%s","PLACEHOLDER");
258                }
259                break;
260        }
261
262    }
263    public void init(Object arg1,Object arg2){
264        init(arg1);
265        intoVariable = (TObjectName)arg2;
266
267    }
268
269    public TObjectName getIntoVariable() {
270        return intoVariable;
271    }
272
273    public TExpression getStmtString() {
274        return stmtString;
275    }
276
277    public TExpressionList getUsingVariables() {
278        return usingVariables;
279    }
280
281    public void init(Object arg1,Object arg2, Object arg3){
282        init(arg1,arg2);
283        usingVariables = (TExpressionList)arg3;
284
285    }
286
287    public void accept(TParseTreeVisitor v){
288        v.preVisit(this);
289        v.postVisit(this);
290    }
291
292    public void acceptChildren(TParseTreeVisitor v){
293        v.preVisit(this);
294        v.postVisit(this);
295    }
296
297    public void setStmtString(TExpression stmtString) {
298        this.stmtString = stmtString;
299    }
300
301    public void setIntoVariable(TObjectName intoVariable) {
302        this.intoVariable = intoVariable;
303    }
304
305    public void setUsingVariables(TExpressionList usingVariables) {
306        this.usingVariables = usingVariables;
307    }
308
309    public TObjectName getStatementName() {
310        return statementName;
311    }
312    public TExpressionList getParameters() {
313        return parameters;
314    }
315    public void setStatementName(TObjectName statementName) {
316        this.statementName = statementName;
317    }
318    public void setParameters(TExpressionList parameters) {
319        this.parameters = parameters;
320    }
321    public TExpression getPreparedValue() {
322        return preparedValue;
323    }
324
325}