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}