001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.compiler.TSymbolTableManager;
005import gudusoft.gsqlparser.compiler.TVariable;
006import gudusoft.gsqlparser.nodes.TExpression;
007import gudusoft.gsqlparser.nodes.TObjectName;
008import gudusoft.gsqlparser.nodes.TParseTreeVisitor;
009import gudusoft.gsqlparser.nodes.TParseTreeNode;
010import gudusoft.gsqlparser.nodes.TSelectSqlNode;
011import gudusoft.gsqlparser.nodes.TTypeName;
012
013/**
014 * The assignment statement sets the current value of a variable, field, parameter,
015 * or element that has been declared in the current scope.
016 */
017
018public class TAssignStmt extends TCustomSqlStatement {
019
020    public enum AssignType  {normal, variableAssignment, cursorAssignment,resultsetAssignment};
021
022    private AssignType assignType = AssignType.normal;
023
024    private TParseTreeNode queryNode;
025    private TSelectSqlStatement query;
026
027    public TSelectSqlStatement getQuery() {
028        return query;
029    }
030
031    public AssignType getAssignType() {
032        return assignType;
033    }
034
035    private TObjectName resultsetName;
036
037    public TObjectName getResultsetName() {
038        return resultsetName;
039    }
040
041    private TObjectName variableName;
042
043    public TObjectName getVariableName() {
044        return variableName;
045    }
046
047    /**
048     * The data type of the variable in a LET statement (Snowflake).
049     * For example, in "let x INTEGER := 10;", this returns the INTEGER type.
050     */
051    private TTypeName dataType;
052
053    public TTypeName getDataType() {
054        return dataType;
055    }
056
057    public void setDataType(TTypeName dataType) {
058        this.dataType = dataType;
059    }
060
061    public TAssignStmt(){
062       this(EDbVendor.dbvoracle);
063    }
064
065    public TAssignStmt(TExpression pLeft, TExpression pExpr){
066        this(EDbVendor.dbvoracle);
067        this.left = pLeft;
068        this.expression = pExpr;
069    }
070
071
072     public TAssignStmt(EDbVendor dbvendor){
073        super(dbvendor);
074        sqlstatementtype = ESqlStatementType.sst_assignstmt;
075    }
076
077    void buildsql() {
078    }
079
080    void clear() {
081    }
082
083    String getasprettytext() {
084        return "";
085    }
086
087    void iterate(TVisitorAbs pvisitor) {
088    }
089
090
091
092    private TExpression left = null;
093
094    /**
095     * @return The expression whose value is to be assigned to the target (the item to the left of the
096     * assignment operator) when the assignment statement executes.
097     */
098    public TExpression getExpression() {
099        return expression;
100    }
101
102    /**
103     * Lefe side of this assignment, can be
104     * <ul>
105     * <li>attribute_name</li>
106     * <li>collection_name</li>
107     * <li>cursor_variable_name</li>
108     * <li>field_name</li>
109     * <li>host_cursor_variable_name</li>
110     * <li>host_variable_name</li>
111     * <li>object_name</li>
112     * <li>parameter_name</li>
113     * <li>record_name</li>
114     * <li>variable_name</li>
115     * </ul>
116     * @return  A TExpression object.
117     */
118    public TExpression getLeft() {
119        return left;
120    }
121
122    private TExpression expression = null;
123
124    public void setLeft(TExpression left) {
125        this.left = left;
126    }
127
128    public void setExpression(TExpression expression) {
129        this.expression = expression;
130    }
131
132    public void init(Object arg1,Object arg2)
133    {
134        if (arg1 instanceof TObjectName){
135            variableName = (TObjectName)arg1;
136        }else if (arg1 instanceof  TExpression){
137            left = (TExpression)arg1;
138        }
139
140        if (arg2 instanceof TExpression){
141            expression = (TExpression)arg2;
142        }else if (arg2 instanceof TSelectSqlNode){
143            // Vertica PLvSQL truncating assignment: var <- SELECT ...
144            this.queryNode = (TParseTreeNode)arg2;
145        }
146    }
147
148    public void init(Object arg1, Object arg2,Object arg3){
149        this.assignType = (AssignType) arg1;
150        switch (this.assignType){
151            case variableAssignment:
152                this.variableName = (TObjectName) arg2;
153                this.expression = (TExpression) arg3;
154                break;
155            case cursorAssignment:
156                this.variableName = (TObjectName) arg2;
157                this.queryNode = (TParseTreeNode)arg3;
158                break;
159            case resultsetAssignment:
160                this.variableName = (TObjectName) arg2;
161                this.resultsetName = (TObjectName) arg3;
162                break;
163        }
164
165    }
166
167    /**
168     * Init method for LET statement with datatype (Snowflake).
169     * @param arg1 AssignType
170     * @param arg2 variable name (TObjectName)
171     * @param arg3 datatype (TTypeName), can be null
172     * @param arg4 expression (TExpression)
173     */
174    public void init(Object arg1, Object arg2, Object arg3, Object arg4){
175        this.assignType = (AssignType) arg1;
176        if (this.assignType == AssignType.variableAssignment){
177            this.variableName = (TObjectName) arg2;
178            if (arg3 instanceof TTypeName){
179                this.dataType = (TTypeName) arg3;
180            }
181            this.expression = (TExpression) arg4;
182        }
183    }
184
185    public int doParseStatement(TCustomSqlStatement psql) {
186        super.doParseStatement(psql);
187
188        switch (getAssignType()){
189            case normal:
190                if (expression != null) {
191                    if (left != null){
192                        left.doParse(this,ESqlClause.spAssignValue);
193                        if (left.getExpressionType() == EExpressionType.simple_object_name_t){
194                            TVariable symbolVariable =  TSymbolTableManager.searchSymbolVariable(this.getFrameStack(), left.getObjectOperand().toString());
195                            if (symbolVariable != null){
196                                expression.evaluate(this.getFrameStack(),this);
197                                // only record the value when the expression resolved to an
198                                // actual string (literal, or concatenation seeded by one).
199                                // A bare function call such as REPLACE(cur.rule_sql, ...) or an
200                                // unresolved variable only yields a placeholder name; recording
201                                // it would make EXECUTE IMMEDIATE parse that placeholder as SQL
202                                // and report a bogus syntax error (MantisBT 4503)
203                                if (this.expression.getVal() != null){
204                                    symbolVariable.setVariableStr(this.expression.getPlainText());
205                                    symbolVariable.setVariableStrPartial(this.expression.isValPartial());
206                                    if (expression.getStartToken() != null){
207                                        symbolVariable.setLineNo(expression.getStartToken().lineNo);
208                                        symbolVariable.setColumnNo(expression.getStartToken().columnNo);
209                                    }
210                                }else{
211                                    // the assignment replaced the variable's value with an
212                                    // unknowable one - clear any previously recorded value so a
213                                    // later EXECUTE IMMEDIATE does not parse stale SQL
214                                    symbolVariable.setVariableStr(null);
215                                    symbolVariable.setVariableStrPartial(false);
216                                }
217                            }
218                        }
219                    }
220                    expression.doParse(this,ESqlClause.spAssignValue);
221                } else if (queryNode instanceof TSelectSqlNode) {
222                    // Vertica PLvSQL truncating assignment: var <- SELECT ...
223                    query = new TSelectSqlStatement(this.dbvendor);
224                    query.rootNode = (TSelectSqlNode) queryNode;
225                    query.doParseStatement(this);
226                }
227                break;
228            case variableAssignment:
229                if (expression != null) {
230                    expression.doParse(this,ESqlClause.spAssignValue);
231                }
232                break;
233            case cursorAssignment:
234                if (queryNode instanceof TSelectSqlNode) {
235                    query = new TSelectSqlStatement(this.dbvendor);
236                    query.rootNode = (TSelectSqlNode) queryNode;
237                    query.doParseStatement(this);
238                }
239                break;
240        }
241
242        return 0;
243    }
244
245    public void accept(TParseTreeVisitor v){
246        v.preVisit(this);
247        v.postVisit(this);
248    }
249
250    public void acceptChildren(TParseTreeVisitor v){
251        v.preVisit(this);
252        if (left != null){
253            left.acceptChildren(v);
254        }
255        if (expression != null){
256            expression.acceptChildren(v);
257        }else{
258            TBaseType.log("Value expression in assign statement is not specified",TLog.WARNING);
259        }
260
261        v.postVisit(this);
262    }
263}