1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.reference.ClassName; 25 import org.apache.derby.iapi.reference.SQLState; 26 27 import org.apache.derby.iapi.services.classfile.VMOpcode; 28 29 import org.apache.derby.iapi.services.sanity.SanityManager; 30 31 import org.apache.derby.iapi.error.StandardException; 32 33 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 34 35 import org.apache.derby.iapi.services.compiler.LocalField; 36 import org.apache.derby.iapi.services.compiler.MethodBuilder; 37 import org.apache.derby.iapi.sql.compile.Visitable; 38 import org.apache.derby.iapi.sql.compile.Visitor; 39 40 import java.lang.reflect.Modifier ; 41 42 import java.util.Iterator ; 43 import java.util.Vector ; 44 45 104 105 public class CoalesceFunctionNode extends ValueNode 106 { 107 String functionName; ValueNodeList argumentsList; ValueNode firstNonParameterNode; 111 117 public void init(Object functionName, Object argumentsList) 118 { 119 this.functionName = (String ) functionName; 120 this.argumentsList = (ValueNodeList) argumentsList; 121 } 122 123 135 public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, 136 Vector aggregateVector) 137 throws StandardException 138 { 139 argumentsList.bindExpression(fromList, subqueryList, aggregateVector); 141 142 if (argumentsList.size() < 2) 144 throw StandardException.newException(SQLState.LANG_DB2_NUMBER_OF_ARGS_INVALID, functionName); 145 146 if (argumentsList.containsAllParameterNodes()) 148 throw StandardException.newException(SQLState.LANG_DB2_COALESCE_FUNCTION_ALL_PARAMS); 149 150 int argumentsListSize = argumentsList.size(); 151 for (int index = 0; index < argumentsListSize; index++) 153 { 154 if (!(((ValueNode) argumentsList.elementAt(index)).requiresTypeFromContext())) 155 { 156 firstNonParameterNode = (ValueNode) argumentsList.elementAt(index); 157 break; 158 } 159 } 160 161 for (int index = 0; index < argumentsListSize; index++) 163 { 164 if (((ValueNode) argumentsList.elementAt(index)).requiresTypeFromContext()) continue; 166 argumentsList.compatible((ValueNode) argumentsList.elementAt(index)); 167 } 168 169 setType(argumentsList.getDominantTypeServices()); 171 172 for (int index = 0; index < argumentsListSize; index++) 174 { 175 if (((ValueNode) argumentsList.elementAt(index)).requiresTypeFromContext()) 176 { 177 ((ValueNode)argumentsList.elementAt(index)).setType(getTypeServices()); 178 break; 179 } 180 } 181 return this; 182 } 183 184 192 193 public void generateExpression(ExpressionClassBuilder acb, 194 MethodBuilder mb) 195 throws StandardException 196 { 197 int argumentsListSize = argumentsList.size(); 198 String receiverType = ClassName.DataValueDescriptor; 199 String argumentsListInterfaceType = ClassName.DataValueDescriptor + "[]"; 200 201 LocalField arrayField = 203 acb.newFieldDeclaration(Modifier.PRIVATE, argumentsListInterfaceType); 204 205 209 210 MethodBuilder cb = acb.getConstructor(); 211 cb.pushNewArray(ClassName.DataValueDescriptor, argumentsListSize); 212 cb.setField(arrayField); 213 214 215 int numConstants = 0; 216 MethodBuilder nonConstantMethod = null; 217 MethodBuilder currentConstMethod = cb; 218 for (int index = 0; index < argumentsListSize; index++) 219 { 220 MethodBuilder setArrayMethod; 221 222 if (argumentsList.elementAt(index) instanceof ConstantNode) 223 { 224 numConstants++; 225 226 234 if(currentConstMethod.statementNumHitLimit(1)) 235 { 236 MethodBuilder genConstantMethod = acb.newGeneratedFun("void", Modifier.PRIVATE); 237 currentConstMethod.pushThis(); 238 currentConstMethod.callMethod(VMOpcode.INVOKEVIRTUAL, 239 (String ) null, 240 genConstantMethod.getName(), 241 "void", 0); 242 if(currentConstMethod != cb){ 244 currentConstMethod.methodReturn(); 245 currentConstMethod.complete(); 246 } 247 currentConstMethod = genConstantMethod; 248 } 249 setArrayMethod = currentConstMethod; 250 } else { 251 if (nonConstantMethod == null) 252 nonConstantMethod = acb.newGeneratedFun("void", Modifier.PROTECTED); 253 setArrayMethod = nonConstantMethod; 254 255 } 256 257 setArrayMethod.getField(arrayField); 258 ((ValueNode) argumentsList.elementAt(index)).generateExpression(acb, setArrayMethod); 259 setArrayMethod.upCast(receiverType); 260 setArrayMethod.setArrayElement(index); 261 } 262 263 if(currentConstMethod != cb){ 265 currentConstMethod.methodReturn(); 266 currentConstMethod.complete(); 267 } 268 269 if (nonConstantMethod != null) { 270 nonConstantMethod.methodReturn(); 271 nonConstantMethod.complete(); 272 mb.pushThis(); 273 mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String ) null, nonConstantMethod.getName(), "void", 0); 274 } 275 276 282 283 firstNonParameterNode.generateExpression(acb, mb); mb.upCast(ClassName.DataValueDescriptor); 285 286 mb.getField(arrayField); 288 LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, receiverType); 291 acb.generateNull(mb, getTypeCompiler()); 292 mb.upCast(ClassName.DataValueDescriptor); 293 mb.putField(field); 294 295 mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, "coalesce", receiverType, 2); 296 if (getTypeId().variableLength()) { 298 boolean isNumber = getTypeId().isNumericTypeId(); 299 mb.dup(); 301 302 mb.push(isNumber ? getTypeServices().getPrecision() : getTypeServices().getMaximumWidth()); 303 mb.push(getTypeServices().getScale()); 304 mb.push(true); 305 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3); 306 } 307 } 308 309 312 public String toString() 313 { 314 if (SanityManager.DEBUG) 315 { 316 return super.toString()+functionName+"("+argumentsList+")\n"; 317 } 318 else 319 { 320 return ""; 321 } 322 } 323 324 327 protected boolean isEquivalent(ValueNode o) throws StandardException 328 { 329 if (!isSameNodeType(o)) 330 { 331 return false; 332 } 333 334 CoalesceFunctionNode other = (CoalesceFunctionNode)o; 335 if (other.argumentsList.size() != argumentsList.size()) 336 { 337 return false; 338 339 } 340 341 int size = argumentsList.size(); 342 for (int index = 0; index < size; index++) 343 { 344 ValueNode v1 = (ValueNode)argumentsList.elementAt(index); 345 ValueNode v2 = (ValueNode)other.argumentsList.elementAt(index); 346 if (!v1.isEquivalent(v2)) 347 { 348 return false; 349 } 350 } 351 return true; 352 } 353 public Visitable accept(Visitor v) throws StandardException 354 { 355 Visitable returnNode = v.visit(this); 356 357 if (v.skipChildren(this) || v.stopTraversal()) 358 { 359 return returnNode; 360 } 361 362 int size = argumentsList.size(); 363 for (int index = 0; index < size; index++) 364 { 365 argumentsList.setElementAt( 366 (QueryTreeNode)(argumentsList.elementAt(index)).accept(v), index); 367 } 368 return returnNode; 369 } 370 385 public ValueNode preprocess(int numTables, 386 FromList outerFromList, 387 SubqueryList outerSubqueryList, 388 PredicateList outerPredicateList) 389 throws StandardException 390 { 391 int argumentsListSize = argumentsList.size(); 392 for (int i=0; i < argumentsListSize; i++) { 393 ((ValueNode)argumentsList.elementAt(i)).preprocess 394 (numTables, 395 outerFromList, 396 outerSubqueryList, 397 outerPredicateList); 398 } 399 return this; 400 } 401 402 403 409 410 public void printSubNodes(int depth) 411 { 412 if (SanityManager.DEBUG) 413 { 414 super.printSubNodes(depth); 415 printLabel(depth, "argumentsList: "); 416 int argumentsListSize = argumentsList.size(); 417 for (int i=0; i < argumentsListSize; i++) { 418 ((ValueNode)argumentsList.elementAt(i)).treePrint(depth+1); 419 } 420 } 421 } 422 423 } 424 | Popular Tags |