1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.sql.compile.Visitable; 25 import org.apache.derby.iapi.sql.compile.Visitor; 26 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 27 import org.apache.derby.iapi.error.StandardException; 28 29 import org.apache.derby.iapi.services.sanity.SanityManager; 30 import org.apache.derby.iapi.services.compiler.MethodBuilder; 31 import org.apache.derby.iapi.services.compiler.LocalField; 32 import org.apache.derby.iapi.services.io.StoredFormatIds; 33 34 import java.lang.reflect.Modifier ; 35 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 36 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 37 import org.apache.derby.iapi.types.StringDataValue; 38 import org.apache.derby.iapi.types.TypeId; 39 import org.apache.derby.iapi.types.DataTypeDescriptor; 40 import org.apache.derby.iapi.types.SqlXmlUtil; 41 42 import org.apache.derby.iapi.store.access.Qualifier; 43 44 import org.apache.derby.iapi.reference.ClassName; 45 import org.apache.derby.iapi.reference.SQLState; 46 47 import org.apache.derby.iapi.util.JBitSet; 48 import org.apache.derby.iapi.services.classfile.VMOpcode; 49 50 import java.sql.Types ; 51 import java.util.Vector ; 52 53 61 62 public class BinaryOperatorNode extends ValueNode 63 { 64 String operator; 65 String methodName; 66 ValueNode receiver; 68 71 public final static int PLUS = 1; 72 public final static int MINUS = 2; 73 public final static int TIMES = 3; 74 public final static int DIVIDE = 4; 75 public final static int CONCATENATE = 5; 76 public final static int EQ = 6; 77 public final static int NE = 7; 78 public final static int GT = 8; 79 public final static int GE = 9; 80 public final static int LT = 10; 81 public final static int LE = 11; 82 public final static int AND = 12; 83 public final static int OR = 13; 84 public final static int LIKE = 14; 85 86 ValueNode leftOperand; 87 ValueNode rightOperand; 88 89 String leftInterfaceType; 90 String rightInterfaceType; 91 String resultInterfaceType; 92 int operatorType; 93 94 102 public final static int XMLEXISTS_OP = 0; 103 public final static int XMLQUERY_OP = 1; 104 105 108 static final String [] BinaryOperators = { 109 "xmlexists", 110 "xmlquery" 111 }; 112 113 static final String [] BinaryMethodNames = { 114 "XMLExists", 115 "XMLQuery" 116 }; 117 118 static final String [] BinaryResultTypes = { 119 ClassName.BooleanDataValue, ClassName.XMLDataValue }; 122 123 static final String [][] BinaryArgTypes = { 124 {ClassName.StringDataValue, ClassName.XMLDataValue}, {ClassName.StringDataValue, ClassName.XMLDataValue} }; 127 128 private SqlXmlUtil sqlxUtil; 131 132 143 144 public void init( 145 Object leftOperand, 146 Object rightOperand, 147 Object operator, 148 Object methodName, 149 Object leftInterfaceType, 150 Object rightInterfaceType) 151 { 152 this.leftOperand = (ValueNode) leftOperand; 153 this.rightOperand = (ValueNode) rightOperand; 154 this.operator = (String ) operator; 155 this.methodName = (String ) methodName; 156 this.leftInterfaceType = (String ) leftInterfaceType; 157 this.rightInterfaceType = (String ) rightInterfaceType; 158 this.operatorType = -1; 159 } 160 161 public void init( 162 Object leftOperand, 163 Object rightOperand, 164 Object leftInterfaceType, 165 Object rightInterfaceType) 166 { 167 this.leftOperand = (ValueNode) leftOperand; 168 this.rightOperand = (ValueNode) rightOperand; 169 this.leftInterfaceType = (String ) leftInterfaceType; 170 this.rightInterfaceType = (String ) rightInterfaceType; 171 this.operatorType = -1; 172 } 173 174 182 public void init( 183 Object leftOperand, 184 Object rightOperand, 185 Object opType) 186 { 187 this.leftOperand = (ValueNode)leftOperand; 188 this.rightOperand = (ValueNode)rightOperand; 189 this.operatorType = ((Integer )opType).intValue(); 190 this.operator = BinaryOperators[this.operatorType]; 191 this.methodName = BinaryMethodNames[this.operatorType]; 192 this.leftInterfaceType = BinaryArgTypes[this.operatorType][0]; 193 this.rightInterfaceType = BinaryArgTypes[this.operatorType][1]; 194 this.resultInterfaceType = BinaryResultTypes[this.operatorType]; 195 } 196 197 203 204 public String toString() 205 { 206 if (SanityManager.DEBUG) 207 { 208 return "operator: " + operator + "\n" + 209 "methodName: " + methodName + "\n" + 210 super.toString(); 211 } 212 else 213 { 214 return ""; 215 } 216 } 217 218 223 void setOperator(String operator) 224 { 225 this.operator = operator; 226 this.operatorType = -1; 227 } 228 229 234 void setMethodName(String methodName) 235 { 236 this.methodName = methodName; 237 this.operatorType = -1; 238 } 239 240 245 public void setLeftRightInterfaceType(String iType) 246 { 247 leftInterfaceType = iType; 248 rightInterfaceType = iType; 249 this.operatorType = -1; 250 } 251 252 257 public void setClause(int clause) 258 { 259 super.setClause(clause); 260 leftOperand.setClause(clause); 261 rightOperand.setClause(clause); 262 } 263 264 270 271 public void printSubNodes(int depth) 272 { 273 if (SanityManager.DEBUG) 274 { 275 super.printSubNodes(depth); 276 277 if (leftOperand != null) 278 { 279 printLabel(depth, "leftOperand: "); 280 leftOperand.treePrint(depth + 1); 281 } 282 283 if (rightOperand != null) 284 { 285 printLabel(depth, "rightOperand: "); 286 rightOperand.treePrint(depth + 1); 287 } 288 } 289 } 290 291 304 305 public ValueNode bindExpression( 306 FromList fromList, SubqueryList subqueryList, 307 Vector aggregateVector) 308 throws StandardException 309 { 310 leftOperand = leftOperand.bindExpression(fromList, subqueryList, 311 aggregateVector); 312 rightOperand = rightOperand.bindExpression(fromList, subqueryList, 313 aggregateVector); 314 315 if ((operatorType == XMLEXISTS_OP) || (operatorType == XMLQUERY_OP)) 316 return bindXMLQuery(); 317 318 319 if (leftOperand.requiresTypeFromContext()) 320 { 321 324 if (rightOperand.requiresTypeFromContext()) 325 { 326 throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS, 327 operator); 328 } 329 330 331 leftOperand.setType(rightOperand.getTypeServices()); 332 } 333 334 335 if (rightOperand.requiresTypeFromContext()) 336 { 337 338 rightOperand.setType(leftOperand.getTypeServices()); 339 } 340 341 return genSQLJavaSQLTree(); 342 } 343 344 351 public ValueNode bindXMLQuery() 352 throws StandardException 353 { 354 TypeId leftOperandType = leftOperand.getTypeId(); 356 TypeId rightOperandType = rightOperand.getTypeId(); 357 358 if (!(leftOperand instanceof CharConstantNode)) 362 { 363 throw StandardException.newException( 364 SQLState.LANG_INVALID_XML_QUERY_EXPRESSION); 365 } 366 else { 367 sqlxUtil = new SqlXmlUtil(); 369 sqlxUtil.compileXQExpr( 370 ((CharConstantNode)leftOperand).getString(), 371 (operatorType == XMLEXISTS_OP ? "XMLEXISTS" : "XMLQUERY")); 372 } 373 374 if ((rightOperandType != null) && 380 !rightOperandType.isXMLTypeId()) 381 { 382 throw StandardException.newException( 383 SQLState.LANG_INVALID_CONTEXT_ITEM_TYPE, 384 rightOperandType.getSQLTypeName()); 385 } 386 387 if (rightOperand.requiresTypeFromContext()) 389 { 390 throw StandardException.newException( 393 SQLState.LANG_ATTEMPT_TO_BIND_XML); 394 } 395 396 if (operatorType == XMLEXISTS_OP) { 398 setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true)); 404 } 405 else { 406 setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor( 410 StoredFormatIds.XML_TYPE_ID)); 411 } 412 413 return genSQLJavaSQLTree(); 414 } 415 416 420 public ValueNode genSQLJavaSQLTree() throws StandardException 421 { 422 TypeId leftTypeId = leftOperand.getTypeId(); 423 424 if (leftTypeId.userType()) 425 leftOperand = leftOperand.genSQLJavaSQLTree(); 426 427 TypeId rightTypeId = rightOperand.getTypeId(); 428 if (rightTypeId.userType()) 429 rightOperand = rightOperand.genSQLJavaSQLTree(); 430 431 return this; 432 } 433 434 449 public ValueNode preprocess(int numTables, 450 FromList outerFromList, 451 SubqueryList outerSubqueryList, 452 PredicateList outerPredicateList) 453 throws StandardException 454 { 455 leftOperand = leftOperand.preprocess(numTables, 456 outerFromList, outerSubqueryList, 457 outerPredicateList); 458 rightOperand = rightOperand.preprocess(numTables, 459 outerFromList, outerSubqueryList, 460 outerPredicateList); 461 return this; 462 } 463 464 473 474 public void generateExpression(ExpressionClassBuilder acb, 475 MethodBuilder mb) 476 throws StandardException 477 { 478 String resultTypeName; 479 String receiverType; 480 481 487 488 boolean xmlGen = 491 (operatorType == XMLQUERY_OP) || (operatorType == XMLEXISTS_OP); 492 493 if (xmlGen) { 494 mb.pushNewStart( 507 "org.apache.derby.impl.sql.execute.SqlXmlExecutor"); 508 mb.pushNewComplete(addXmlOpMethodParams(acb, mb)); 509 } 510 511 516 if (leftOperand.getTypeId().typePrecedence() > 517 rightOperand.getTypeId().typePrecedence()) 518 { 519 receiver = leftOperand; 520 527 receiverType = (operatorType == -1) 528 ? getReceiverInterfaceName() 529 : leftInterfaceType; 530 531 536 537 leftOperand.generateExpression(acb, mb); 538 mb.cast(receiverType); 541 mb.dup(); 542 mb.cast(leftInterfaceType); 543 545 rightOperand.generateExpression(acb, mb); 546 mb.cast(rightInterfaceType); } 549 else 550 { 551 receiver = rightOperand; 552 559 receiverType = (operatorType == -1) 560 ? getReceiverInterfaceName() 561 : rightInterfaceType; 562 563 576 577 rightOperand.generateExpression(acb, mb); 578 mb.cast(receiverType); 581 if (!xmlGen) { 582 mb.dup(); 583 mb.cast(rightInterfaceType); 584 } 586 587 leftOperand.generateExpression(acb, mb); 588 mb.cast(leftInterfaceType); 591 mb.swap(); 592 } 594 595 596 resultTypeName = (operatorType == -1) 597 ? getTypeCompiler().interfaceName() 598 : resultInterfaceType; 599 600 boolean needField = !getTypeId().isBooleanTypeId(); 602 603 if (needField) { 604 605 606 LocalField resultField = 607 acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName); 608 609 612 mb.getField(resultField); initializeResultField(acb, mb, resultField); 616 617 620 int jdbcType; 621 if ((dataTypeServices != null) && 622 ((jdbcType = dataTypeServices.getJDBCTypeId()) == java.sql.Types.DECIMAL || 623 jdbcType == java.sql.Types.NUMERIC) && 624 operator.equals("/")) 625 { 626 mb.push(dataTypeServices.getScale()); mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 4); 628 } 629 else if (xmlGen) { 630 mb.callMethod(VMOpcode.INVOKEVIRTUAL, null, 633 methodName, resultTypeName, 3); 634 } 635 else 636 mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 3); 637 638 if (getTypeId().variableLength()) { 641 if (getTypeId().isNumericTypeId()) 642 { 643 mb.dup(); 645 646 mb.push(getTypeServices().getPrecision()); 647 mb.push(getTypeServices().getScale()); 648 mb.push(true); 649 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3); 650 } 651 } 652 653 654 658 659 mb.putField(resultField); 660 } else { 661 if (xmlGen) { 662 mb.callMethod(VMOpcode.INVOKEVIRTUAL, null, 665 methodName, resultTypeName, 2); 666 } 667 else { 668 mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, 669 methodName, resultTypeName, 2); 670 } 671 } 672 } 673 674 protected void initializeResultField(ExpressionClassBuilder acb, MethodBuilder mb, LocalField resultField) 677 throws StandardException 678 { 679 } 680 681 686 public void setLeftOperand(ValueNode newLeftOperand) 687 { 688 leftOperand = newLeftOperand; 689 } 690 691 696 public ValueNode getLeftOperand() 697 { 698 return leftOperand; 699 } 700 701 706 public void setRightOperand(ValueNode newRightOperand) 707 { 708 rightOperand = newRightOperand; 709 } 710 711 716 public ValueNode getRightOperand() 717 { 718 return rightOperand; 719 } 720 721 746 public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) 747 throws StandardException 748 { 749 boolean pushable; 750 pushable = leftOperand.categorize(referencedTabs, simplePredsOnly); 751 pushable = (rightOperand.categorize(referencedTabs, simplePredsOnly) && pushable); 752 return pushable; 753 } 754 755 763 public ValueNode remapColumnReferencesToExpressions() 764 throws StandardException 765 { 766 leftOperand = leftOperand.remapColumnReferencesToExpressions(); 767 rightOperand = rightOperand.remapColumnReferencesToExpressions(); 768 return this; 769 } 770 771 776 public boolean isConstantExpression() 777 { 778 return (leftOperand.isConstantExpression() && 779 rightOperand.isConstantExpression()); 780 } 781 782 783 public boolean constantExpression(PredicateList whereClause) 784 { 785 return (leftOperand.constantExpression(whereClause) && 786 rightOperand.constantExpression(whereClause)); 787 } 788 789 798 public String getReceiverInterfaceName() throws StandardException { 799 if (SanityManager.DEBUG) 800 { 801 SanityManager.ASSERT(receiver!=null,"can't get receiver interface name until receiver is set"); 802 } 803 804 return receiver.getTypeCompiler().interfaceName(); 805 } 806 807 820 protected int getOrderableVariantType() throws StandardException 821 { 822 int leftType = leftOperand.getOrderableVariantType(); 823 int rightType = rightOperand.getOrderableVariantType(); 824 825 return Math.min(leftType, rightType); 826 } 827 828 831 void swapOperands() 832 { 833 String tmpInterfaceType = leftInterfaceType; 834 ValueNode tmpVN = leftOperand; 835 836 leftOperand = rightOperand; 837 rightOperand = tmpVN; 838 leftInterfaceType = rightInterfaceType; 839 rightInterfaceType = tmpInterfaceType; 840 } 841 842 850 public Visitable accept(Visitor v) 851 throws StandardException 852 { 853 Visitable returnNode = v.visit(this); 854 855 if (v.skipChildren(this)) 856 { 857 return returnNode; 858 } 859 860 if (leftOperand != null && !v.stopTraversal()) 861 { 862 leftOperand = (ValueNode)leftOperand.accept(v); 863 } 864 865 if (rightOperand != null && !v.stopTraversal()) 866 { 867 rightOperand = (ValueNode)rightOperand.accept(v); 868 } 869 870 return returnNode; 871 } 872 873 876 protected boolean isEquivalent(ValueNode o) throws StandardException 877 { 878 if (!isSameNodeType(o)) 879 { 880 return false; 881 } 882 BinaryOperatorNode other = (BinaryOperatorNode)o; 883 return methodName.equals(other.methodName) 884 && leftOperand.isEquivalent(other.leftOperand) 885 && rightOperand.isEquivalent(other.rightOperand); 886 } 887 888 900 private int addXmlOpMethodParams(ExpressionClassBuilder acb, 901 MethodBuilder mb) throws StandardException 902 { 903 acb.pushThisAsActivation(mb); 907 908 mb.push(getCompilerContext().addSavedObject(sqlxUtil)); 911 912 return 2; 914 } 915 } 916 | Popular Tags |