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.JDBC30Translation; 26 27 import org.apache.derby.iapi.util.JBitSet; 28 29 import org.apache.derby.iapi.services.loader.GeneratedMethod; 30 31 import org.apache.derby.iapi.services.compiler.MethodBuilder; 32 33 import org.apache.derby.iapi.services.sanity.SanityManager; 34 35 import org.apache.derby.iapi.error.StandardException; 36 37 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 38 import org.apache.derby.iapi.sql.compile.Optimizable; 39 40 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 41 42 import org.apache.derby.iapi.store.access.Qualifier; 43 import org.apache.derby.iapi.store.access.ScanController; 44 45 import org.apache.derby.iapi.types.DataValueDescriptor; 46 import org.apache.derby.iapi.types.TypeId; 47 import org.apache.derby.iapi.types.DataValueDescriptor; 48 49 import org.apache.derby.iapi.types.Orderable; 50 51 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 52 53 import java.sql.Types ; 54 55 61 62 public class BinaryRelationalOperatorNode 63 extends BinaryComparisonOperatorNode 64 implements RelationalOperator 65 { 66 private int operatorType; 67 68 69 private BaseTableNumbersVisitor btnVis; 72 73 JBitSet optBaseTables; 76 JBitSet valNodeBaseTables; 77 78 public void init(Object leftOperand, Object rightOperand) 79 { 80 String methodName = ""; 81 String operatorName = ""; 82 83 switch (getNodeType()) 84 { 85 case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE: 86 methodName = "equals"; 87 operatorName = "="; 88 operatorType = RelationalOperator.EQUALS_RELOP; 89 break; 90 91 case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE: 92 methodName = "greaterOrEquals"; 93 operatorName = ">="; 94 operatorType = RelationalOperator.GREATER_EQUALS_RELOP; 95 break; 96 97 case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE: 98 methodName = "greaterThan"; 99 operatorName = ">"; 100 operatorType = RelationalOperator.GREATER_THAN_RELOP; 101 break; 102 103 case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE: 104 methodName = "lessOrEquals"; 105 operatorName = "<="; 106 operatorType = RelationalOperator.LESS_EQUALS_RELOP; 107 break; 108 109 case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE: 110 methodName = "lessThan"; 111 operatorName = "<"; 112 operatorType = RelationalOperator.LESS_THAN_RELOP; 113 break; 114 case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE: 115 methodName = "notEquals"; 116 operatorName = "<>"; 117 operatorType = RelationalOperator.NOT_EQUALS_RELOP; 118 break; 119 120 default: 121 if (SanityManager.DEBUG) 122 { 123 SanityManager.THROWASSERT("init for BinaryRelationalOperator called with wrong nodeType = " + getNodeType()); 124 } 125 break; 126 } 127 super.init(leftOperand, rightOperand, operatorName, methodName); 128 btnVis = null; 129 } 130 131 132 public ColumnReference getColumnOperand( 133 Optimizable optTable, 134 int columnPosition) 135 { 136 FromTable ft = (FromTable) optTable; 137 138 143 ColumnReference cr; 144 boolean walkSubtree = true; 145 if (leftOperand instanceof ColumnReference) 146 { 147 151 cr = (ColumnReference) leftOperand; 152 if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) 153 { 154 157 if (cr.getSource().getColumnPosition() == columnPosition) 158 { 159 160 return cr; 161 } 162 } 163 walkSubtree = false; 164 } 165 166 if (rightOperand instanceof ColumnReference) 167 { 168 172 cr = (ColumnReference) rightOperand; 173 if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) 174 { 175 178 if (cr.getSource().getColumnPosition() == columnPosition) 179 { 180 181 return cr; 182 } 183 } 184 } 185 186 187 return null; 188 } 189 190 191 public ColumnReference getColumnOperand(Optimizable optTable) 192 { 193 ColumnReference cr; 194 195 boolean walkSubtree = true; 196 if (leftOperand instanceof ColumnReference) 197 { 198 202 cr = (ColumnReference) leftOperand; 203 if (valNodeReferencesOptTable( 204 cr, (FromTable)optTable, false, walkSubtree)) 205 { 206 209 return cr; 210 } 211 walkSubtree = false; 212 } 213 214 if (rightOperand instanceof ColumnReference) 215 { 216 220 cr = (ColumnReference) rightOperand; 221 if (valNodeReferencesOptTable(cr, 222 (FromTable)optTable, false, walkSubtree)) 223 { 224 227 return cr; 228 } 229 } 230 231 232 return null; 233 } 234 235 238 public ValueNode getExpressionOperand( 239 int tableNumber, 240 int columnPosition, 241 FromTable ft) 242 { 243 ColumnReference cr; 244 boolean walkSubtree = true; 245 246 if (leftOperand instanceof ColumnReference) 247 { 248 252 cr = (ColumnReference) leftOperand; 253 if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) 254 { 255 258 if (cr.getSource().getColumnPosition() == columnPosition) 259 { 260 264 return rightOperand; 265 } 266 } 267 walkSubtree = false; 268 } 269 270 if (rightOperand instanceof ColumnReference) 271 { 272 276 cr = (ColumnReference) rightOperand; 277 if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) 278 { 279 282 if (cr.getSource().getColumnPosition() == columnPosition) 283 { 284 288 return leftOperand; 289 } 290 } 291 } 292 293 return null; 294 } 295 296 299 public ValueNode getOperand(ColumnReference cRef, 300 int refSetSize, boolean otherSide) 301 { 302 initBaseTableVisitor(refSetSize, true); 305 306 try { 313 314 btnVis.setTableMap(optBaseTables); 316 cRef.accept(btnVis); 317 318 btnVis.setTableMap(valNodeBaseTables); 320 321 ColumnReference cr; 322 if (leftOperand instanceof ColumnReference) 323 { 324 328 cr = (ColumnReference) leftOperand; 329 cr.accept(btnVis); 330 valNodeBaseTables.and(optBaseTables); 331 if (valNodeBaseTables.getFirstSetBit() != -1) 332 { 333 336 if (cr.getSource().getColumnPosition() == 337 cRef.getColumnNumber()) 338 { 339 343 if (otherSide) 344 return rightOperand; 345 return leftOperand; 346 } 347 } 348 } 349 350 if (rightOperand instanceof ColumnReference) 351 { 352 356 valNodeBaseTables.clearAll(); 357 cr = (ColumnReference) rightOperand; 358 cr.accept(btnVis); 359 valNodeBaseTables.and(optBaseTables); 360 if (valNodeBaseTables.getFirstSetBit() != -1) 361 { 362 365 if (cr.getSource().getColumnPosition() == 366 cRef.getColumnNumber()) 367 { 368 372 if (otherSide) 373 return leftOperand; 374 return rightOperand; 375 } 376 } 377 } 378 379 } catch (StandardException se) { 380 if (SanityManager.DEBUG) 381 { 382 SanityManager.THROWASSERT("Failed when trying to " + 383 "find base table number for column reference check:\n" + 384 se.getMessage()); 385 } 386 } 387 388 return null; 389 } 390 391 396 public void generateExpressionOperand( 397 Optimizable optTable, 398 int columnPosition, 399 ExpressionClassBuilder acb, 400 MethodBuilder mb) 401 throws StandardException 402 { 403 ColumnReference cr; 404 FromBaseTable ft; 405 406 if (SanityManager.DEBUG) 407 { 408 SanityManager.ASSERT(optTable instanceof FromBaseTable); 409 } 410 ft = (FromBaseTable) optTable; 411 412 ValueNode exprOp = getExpressionOperand( 413 ft.getTableNumber(), columnPosition, ft); 414 415 if (SanityManager.DEBUG) 416 { 417 if (exprOp == null) 418 { 419 SanityManager.THROWASSERT( 420 "ColumnReference for correct column (columnPosition = " + 421 columnPosition + 422 ", exposed table name = " + ft.getExposedName() + 423 ") not found on either side of BinaryRelationalOperator"); 424 } 425 } 426 427 exprOp.generateExpression(acb, mb); 428 } 429 430 434 public boolean selfComparison(ColumnReference cr) 435 throws StandardException 436 { 437 ValueNode otherSide; 438 JBitSet tablesReferenced; 439 440 444 if (leftOperand == cr) 445 { 446 otherSide = rightOperand; 447 } 448 else if (rightOperand == cr) 449 { 450 otherSide = leftOperand; 451 } 452 else 453 { 454 otherSide = null; 455 if (SanityManager.DEBUG) 456 { 457 SanityManager.THROWASSERT( 458 "ColumnReference not found on either side of binary comparison."); 459 } 460 } 461 462 tablesReferenced = otherSide.getTablesReferenced(); 463 464 465 return tablesReferenced.get(cr.getTableNumber()); 466 } 467 468 469 public boolean usefulStartKey(Optimizable optTable) 470 { 471 475 int columnSide = columnOnOneSide(optTable); 476 477 if (columnSide == NEITHER) 478 return false; 479 else 480 return usefulStartKey(columnSide == LEFT); 481 } 482 483 499 protected boolean keyColumnOnLeft(Optimizable optTable) 500 { 501 ColumnReference cr; 502 boolean left = false; 503 504 505 if (leftOperand instanceof ColumnReference) 506 { 507 511 cr = (ColumnReference) leftOperand; 512 if (valNodeReferencesOptTable( 513 cr, (FromTable)optTable, false, true)) 514 { 515 516 left = true; 517 } 518 } 519 520 if (SanityManager.DEBUG) 522 { 523 if (!left) 524 { 525 SanityManager.ASSERT( 526 (rightOperand instanceof ColumnReference) && 527 valNodeReferencesOptTable((ColumnReference)rightOperand, 528 (FromTable)optTable, false, true), 529 "Key column not found on either side."); 530 } 531 } 532 533 return left; 534 } 535 536 537 protected static final int LEFT = -1; 538 protected static final int NEITHER = 0; 539 protected static final int RIGHT = 1; 540 541 552 protected int columnOnOneSide(Optimizable optTable) 553 { 554 ColumnReference cr; 555 boolean left = false; 556 boolean walkSubtree = true; 557 558 559 if (leftOperand instanceof ColumnReference) 560 { 561 565 cr = (ColumnReference) leftOperand; 566 if (valNodeReferencesOptTable( 567 cr, (FromTable)optTable, false, walkSubtree)) 568 { 569 570 return LEFT; 571 } 572 walkSubtree = false; 573 } 574 575 if (rightOperand instanceof ColumnReference) 576 { 577 581 cr = (ColumnReference) rightOperand; 582 if (valNodeReferencesOptTable( 583 cr, (FromTable)optTable, false, walkSubtree)) 584 { 585 586 return RIGHT; 587 } 588 } 589 590 return NEITHER; 591 } 592 593 594 public boolean usefulStopKey(Optimizable optTable) 595 { 596 600 int columnSide = columnOnOneSide(optTable); 601 602 if (columnSide == NEITHER) 603 return false; 604 else 605 return usefulStopKey(columnSide == LEFT); 606 } 607 608 617 618 public void generateAbsoluteColumnId(MethodBuilder mb, 619 Optimizable optTable) 620 { 621 int columnPosition = getAbsoluteColumnPosition(optTable); 623 624 mb.push(columnPosition); 625 } 626 627 628 public void generateRelativeColumnId(MethodBuilder mb, 629 Optimizable optTable) 630 { 631 int columnPosition = getAbsoluteColumnPosition(optTable); 633 columnPosition = optTable.convertAbsoluteToRelativeColumnPosition( 635 columnPosition); 636 637 mb.push(columnPosition); 638 } 639 640 648 private int getAbsoluteColumnPosition(Optimizable optTable) 649 { 650 ColumnReference cr; 651 ConglomerateDescriptor bestCD; 652 int columnPosition; 653 654 if (keyColumnOnLeft(optTable)) 655 { 656 cr = (ColumnReference) leftOperand; 657 } 658 else 659 { 660 cr = (ColumnReference) rightOperand; 661 } 662 663 bestCD = optTable.getTrulyTheBestAccessPath(). 664 getConglomerateDescriptor(); 665 666 669 columnPosition = cr.getSource().getColumnPosition(); 670 671 675 if (bestCD != null && bestCD.isIndex()) 676 { 677 columnPosition = bestCD.getIndexDescriptor(). 678 getKeyColumnPosition(columnPosition); 679 680 if (SanityManager.DEBUG) 681 { 682 SanityManager.ASSERT(columnPosition > 0, 683 "Base column not found in index"); 684 } 685 } 686 687 return columnPosition - 1; 689 } 690 691 694 public void generateQualMethod(ExpressionClassBuilder acb, 695 MethodBuilder mb, 696 Optimizable optTable) 697 throws StandardException 698 { 699 700 MethodBuilder qualMethod = acb.newUserExprFun(); 701 702 706 if (keyColumnOnLeft(optTable)) 707 { 708 rightOperand.generateExpression(acb, qualMethod); 709 } 710 else 711 { 712 leftOperand.generateExpression(acb, qualMethod); 713 } 714 715 qualMethod.methodReturn(); 716 qualMethod.complete(); 717 718 719 acb.pushMethodReference(mb, qualMethod); 720 } 721 722 723 public void generateOrderedNulls(MethodBuilder mb) 724 { 725 mb.push(false); 726 } 727 728 729 public boolean orderedNulls() 730 { 731 return false; 732 } 733 734 738 public boolean isQualifier(Optimizable optTable, boolean forPush) 739 throws StandardException 740 { 741 FromTable ft; 742 ValueNode otherSide = null; 743 JBitSet tablesReferenced; 744 ColumnReference cr = null; 745 boolean found = false; 746 boolean walkSubtree = true; 747 748 ft = (FromTable) optTable; 749 750 if (leftOperand instanceof ColumnReference) 751 { 752 756 cr = (ColumnReference) leftOperand; 757 if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree)) 758 { 759 otherSide = rightOperand; 760 found = true; 761 } 762 walkSubtree = false; 763 } 764 765 if ( ( ! found) && (rightOperand instanceof ColumnReference) ) 766 { 767 771 cr = (ColumnReference) rightOperand; 772 if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree)) 773 { 774 otherSide = leftOperand; 775 found = true; 776 } 777 } 778 779 780 if ( ! found) 781 { 782 786 return false; 787 } 788 789 794 return !valNodeReferencesOptTable(otherSide, ft, forPush, true); 795 } 796 797 802 public int getOrderableVariantType(Optimizable optTable) 803 throws StandardException 804 { 805 808 if (keyColumnOnLeft(optTable)) 809 { 810 return rightOperand.getOrderableVariantType(); 811 } 812 else 813 { 814 return leftOperand.getOrderableVariantType(); 815 } 816 } 817 818 819 public boolean compareWithKnownConstant(Optimizable optTable, boolean considerParameters) 820 { 821 ValueNode node = null; 822 node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand; 823 824 if (considerParameters) 825 { 826 return (node instanceof ConstantNode) || 827 ((node.requiresTypeFromContext()) && 828 (((ParameterNode)node).getDefaultValue() != null)); 829 } 830 else 831 { 832 return node instanceof ConstantNode; 833 } 834 } 835 836 841 public DataValueDescriptor getCompareValue(Optimizable optTable) 842 throws StandardException 843 { 844 ValueNode node = null; 845 846 849 node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand; 850 851 if (node instanceof ConstantNode) 852 { 853 return ((ConstantNode)node).getValue(); 854 } 855 else if (node.requiresTypeFromContext()) 856 { 857 ParameterNode pn; 858 if (node instanceof UnaryOperatorNode) 859 pn = ((UnaryOperatorNode)node).getParameterOperand(); 860 else 861 pn = (ParameterNode) (node); 862 return pn.getDefaultValue(); 863 } 864 else 865 { 866 return null; 867 } 868 } 869 870 871 875 protected double booleanSelectivity(Optimizable optTable) 876 throws StandardException 877 { 878 TypeId typeId = null; 879 double retval = -1.0d; 880 int columnSide; 881 882 columnSide = columnOnOneSide(optTable); 883 884 if (columnSide == LEFT) 885 typeId = leftOperand.getTypeId(); 886 else if (columnSide == RIGHT) 887 typeId = rightOperand.getTypeId(); 888 889 if (typeId != null && (typeId.getJDBCTypeId() == Types.BIT || 890 typeId.getJDBCTypeId() == JDBC30Translation.SQL_TYPES_BOOLEAN)) 891 retval = 0.5d; 892 893 return retval; 894 } 895 896 901 public String getReceiverInterfaceName() { 902 return ClassName.DataValueDescriptor; 903 } 904 905 908 BinaryOperatorNode getNegation(ValueNode leftOperand, 909 ValueNode rightOperand) 910 throws StandardException 911 { 912 BinaryOperatorNode negation; 913 if (SanityManager.DEBUG) 914 SanityManager.ASSERT(dataTypeServices != null, 915 "dataTypeServices is expected to be non-null"); 916 917 negation = (BinaryOperatorNode) 918 getNodeFactory().getNode(getNegationNode(), 919 leftOperand, rightOperand, 920 getContextManager()); 921 negation.setType(dataTypeServices); 922 return negation; 923 } 924 925 926 private int getNegationNode() 927 { 928 switch (getNodeType()) 929 { 930 case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE: 931 return C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE; 932 933 case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE: 934 return C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE; 935 936 case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE: 937 return C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE; 938 939 case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE: 940 return C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE; 941 942 case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE: 943 return C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE; 944 945 case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE: 946 return C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE; 947 } 948 949 if (SanityManager.DEBUG) 950 { 951 SanityManager.THROWASSERT("getNegationNode called with invalid nodeType: " + getNodeType()); 952 } 953 954 return -1; 955 } 956 957 965 protected boolean usefulStartKey(boolean columnOnLeft) 966 { 967 switch (operatorType) 968 { 969 case RelationalOperator.EQUALS_RELOP: 970 return true; 971 case RelationalOperator.NOT_EQUALS_RELOP: 972 return false; 973 case RelationalOperator.GREATER_THAN_RELOP: 974 case RelationalOperator.GREATER_EQUALS_RELOP: 975 return columnOnLeft; 977 case RelationalOperator.LESS_THAN_RELOP: 978 case RelationalOperator.LESS_EQUALS_RELOP: 979 return !columnOnLeft; 981 default: 982 return false; 983 } 984 985 986 } 987 988 989 protected boolean usefulStopKey(boolean columnOnLeft) 990 { 991 switch (operatorType) 992 { 993 case RelationalOperator.EQUALS_RELOP: 994 return true; 995 case RelationalOperator.NOT_EQUALS_RELOP: 996 return false; 997 case RelationalOperator.GREATER_THAN_RELOP: 998 case RelationalOperator.GREATER_EQUALS_RELOP: 999 return !columnOnLeft; 1001 case RelationalOperator.LESS_EQUALS_RELOP: 1002 case RelationalOperator.LESS_THAN_RELOP: 1003 return columnOnLeft; 1005 default: 1006 return false; 1007 } 1008 } 1009 1010 1011 public int getStartOperator(Optimizable optTable) 1012 { 1013 switch (operatorType) 1014 { 1015 case RelationalOperator.EQUALS_RELOP: 1016 case RelationalOperator.LESS_EQUALS_RELOP: 1017 case RelationalOperator.GREATER_EQUALS_RELOP: 1018 return ScanController.GE; 1019 case RelationalOperator.LESS_THAN_RELOP: 1020 case RelationalOperator.GREATER_THAN_RELOP: 1021 return ScanController.GT; 1022 case RelationalOperator.NOT_EQUALS_RELOP: 1023 if (SanityManager.DEBUG) 1024 SanityManager.THROWASSERT("!= cannot be a start operator"); 1025 return ScanController.NA; 1026 default: 1027 return ScanController.NA; 1028 1029 } 1030 } 1031 1032 1033 public int getStopOperator(Optimizable optTable) 1034 { 1035 switch (operatorType) 1036 { 1037 case RelationalOperator.EQUALS_RELOP: 1038 case RelationalOperator.GREATER_EQUALS_RELOP: 1039 case RelationalOperator.LESS_EQUALS_RELOP: 1040 return ScanController.GT; 1041 case RelationalOperator.LESS_THAN_RELOP: 1042 case RelationalOperator.GREATER_THAN_RELOP: 1043 return ScanController.GE; 1044 case RelationalOperator.NOT_EQUALS_RELOP: 1045 if (SanityManager.DEBUG) 1046 SanityManager.THROWASSERT("!= cannot be a stop operator"); 1047 return ScanController.NA; 1048 default: 1049 return ScanController.NA; 1050 } 1051 } 1052 1053 1054 public void generateOperator(MethodBuilder mb, 1055 Optimizable optTable) 1056 { 1057 switch (operatorType) 1058 { 1059 case RelationalOperator.EQUALS_RELOP: 1060 mb.push(Orderable.ORDER_OP_EQUALS); 1061 break; 1062 1063 case RelationalOperator.NOT_EQUALS_RELOP: 1064 mb.push(Orderable.ORDER_OP_EQUALS); 1065 break; 1066 1067 case RelationalOperator.LESS_THAN_RELOP: 1068 case RelationalOperator.GREATER_EQUALS_RELOP: 1069 mb.push(keyColumnOnLeft(optTable) ? 1070 Orderable.ORDER_OP_LESSTHAN : Orderable.ORDER_OP_LESSOREQUALS); 1071 break; 1072 case RelationalOperator.LESS_EQUALS_RELOP: 1073 case RelationalOperator.GREATER_THAN_RELOP: 1074 mb.push(keyColumnOnLeft(optTable) ? 1075 Orderable.ORDER_OP_LESSOREQUALS : Orderable.ORDER_OP_LESSTHAN); 1076 1077 } 1078 } 1079 1080 1081 public void generateNegate(MethodBuilder mb, Optimizable optTable) 1082 { 1083 switch (operatorType) 1084 { 1085 case RelationalOperator.EQUALS_RELOP: 1086 mb.push(false); 1087 break; 1088 case RelationalOperator.NOT_EQUALS_RELOP: 1089 mb.push(true); 1090 break; 1091 case RelationalOperator.LESS_THAN_RELOP: 1092 case RelationalOperator.LESS_EQUALS_RELOP: 1093 mb.push(!keyColumnOnLeft(optTable)); 1094 break; 1095 case RelationalOperator.GREATER_THAN_RELOP: 1096 case RelationalOperator.GREATER_EQUALS_RELOP: 1097 mb.push(keyColumnOnLeft(optTable)); 1098 break; 1099 } 1100 1101 return; 1102 } 1103 1104 1105 public int getOperator() 1106 { 1107 return operatorType; 1108 } 1109 1110 1112 public double selectivity(Optimizable optTable) 1113 throws StandardException 1114 { 1115 double retval = booleanSelectivity(optTable); 1116 1117 if (retval >= 0.0d) 1118 return retval; 1119 1120 switch (operatorType) 1121 { 1122 case RelationalOperator.EQUALS_RELOP: 1123 return 0.1; 1124 case RelationalOperator.NOT_EQUALS_RELOP: 1125 case RelationalOperator.LESS_THAN_RELOP: 1126 case RelationalOperator.LESS_EQUALS_RELOP: 1127 case RelationalOperator.GREATER_EQUALS_RELOP: 1128 if (getBetweenSelectivity()) 1129 return 0.5d; 1130 1131 case RelationalOperator.GREATER_THAN_RELOP: 1132 return 0.33; 1133 } 1134 1135 return 0.0; 1136 } 1137 1138 1139 public RelationalOperator getTransitiveSearchClause(ColumnReference otherCR) 1140 throws StandardException 1141 { 1142 return (RelationalOperator)getNodeFactory().getNode(getNodeType(), 1143 otherCR, 1144 rightOperand, 1145 getContextManager()); 1146 } 1147 1148 public boolean equalsComparisonWithConstantExpression(Optimizable optTable) 1149 { 1150 if (operatorType != EQUALS_RELOP) 1151 return false; 1152 1153 boolean retval = false; 1154 ValueNode comparand = null; 1155 1156 int side = columnOnOneSide(optTable); 1157 if (side == LEFT) 1158 { 1159 retval = rightOperand.isConstantExpression(); 1160 } 1161 else if (side == RIGHT) 1162 { 1163 retval = leftOperand.isConstantExpression(); 1164 } 1165 1166 return retval; 1167 } 1168 1169 1170 public boolean isRelationalOperator() 1171 { 1172 return true; 1173 } 1174 1175 public boolean isBinaryEqualsOperatorNode() 1176 { 1177 return (operatorType == RelationalOperator.EQUALS_RELOP); 1178 } 1179 1180 1181 public boolean optimizableEqualityNode(Optimizable optTable, 1182 int columnNumber, 1183 boolean isNullOkay) 1184 throws StandardException 1185 { 1186 if (operatorType != EQUALS_RELOP) 1187 return false; 1188 1189 ColumnReference cr = getColumnOperand(optTable, 1190 columnNumber); 1191 if (cr == null) 1192 return false; 1193 1194 if (selfComparison(cr)) 1195 return false; 1196 1197 if (implicitVarcharComparison()) 1198 return false; 1199 1200 return true; 1201 } 1202 1203 1214 1215 private boolean implicitVarcharComparison() 1216 throws StandardException 1217 { 1218 TypeId leftType = leftOperand.getTypeId(); 1219 TypeId rightType = rightOperand.getTypeId(); 1220 1221 if (leftType.isStringTypeId() && !rightType.isStringTypeId()) 1222 return true; 1223 1224 if (rightType.isStringTypeId() && (!leftType.isStringTypeId())) 1225 return true; 1226 1227 return false; 1228 } 1229 1230 1233 public ValueNode genSQLJavaSQLTree() throws StandardException 1234 { 1235 if (operatorType == EQUALS_RELOP) 1236 return this; 1237 1238 return super.genSQLJavaSQLTree(); 1239 } 1240 1241 1292 public ValueNode getScopedOperand(int whichSide, 1293 JBitSet parentRSNsTables, ResultSetNode childRSN, 1294 int [] whichRC) throws StandardException 1295 { 1296 ResultColumn rc = null; 1297 ColumnReference cr = 1298 whichSide == LEFT 1299 ? (ColumnReference)leftOperand 1300 : (ColumnReference)rightOperand; 1301 1302 1320 JBitSet crTables = new JBitSet(parentRSNsTables.size()); 1321 BaseTableNumbersVisitor btnVis = 1322 new BaseTableNumbersVisitor(crTables); 1323 cr.accept(btnVis); 1324 1325 1336 if (!parentRSNsTables.contains(crTables)) 1337 return (ColumnReference)cr.getClone(); 1338 1339 1375 if (whichRC[0] == -1) 1376 { 1377 1391 1392 int [] sourceColPos = new int[] {-1}; 1394 ResultSetNode sourceRSN = cr.getSourceResultSet(sourceColPos); 1395 1396 if (SanityManager.DEBUG) 1397 { 1398 1403 SanityManager.ASSERT(sourceRSN != null, 1404 "Failed to find source result set when trying to " + 1405 "scope column reference '" + cr.getTableName() + 1406 "." + cr.getColumnName()); 1407 } 1408 1409 rc = childRSN.getResultColumns() 1411 .getResultColumn(sourceColPos[0], sourceRSN, whichRC); 1412 } 1413 else 1414 { 1415 1429 rc = childRSN.getResultColumns().getResultColumn(whichRC[0]); 1430 } 1431 1432 if (SanityManager.DEBUG) 1435 { 1436 SanityManager.ASSERT(rc != null, 1437 "Failed to locate scope target result column when trying to " + 1438 "scope operand '" + cr.getTableName() + "." + 1439 cr.getColumnName() + "'."); 1440 } 1441 1442 1462 1463 if (rc.getExpression() instanceof ColumnReference) 1464 { 1465 1470 ColumnReference cRef = (ColumnReference) 1471 ((ColumnReference)rc.getExpression()).getClone(); 1472 cRef.markAsScoped(); 1473 return cRef; 1474 } 1475 1476 1483 return rc.getExpression(); 1484 } 1485 1486 1505 private boolean valNodeReferencesOptTable(ValueNode valNode, 1506 FromTable optTable, boolean forPush, boolean walkOptTableSubtree) 1507 { 1508 initBaseTableVisitor(optTable.getReferencedTableMap().size(), 1511 walkOptTableSubtree); 1512 1513 boolean found = false; 1514 try { 1515 1516 if (walkOptTableSubtree) 1522 buildTableNumList(optTable, forPush); 1523 1524 btnVis.setTableMap(valNodeBaseTables); 1528 valNode.accept(btnVis); 1529 1530 valNodeBaseTables.and(optBaseTables); 1532 found = (valNodeBaseTables.getFirstSetBit() != -1); 1533 1534 } catch (StandardException se) { 1535 if (SanityManager.DEBUG) 1536 { 1537 SanityManager.THROWASSERT("Failed when trying to " + 1538 "find base table numbers for reference check:\n" + 1539 se.getMessage()); 1540 } 1541 } 1542 1543 return found; 1544 } 1545 1546 1557 private void initBaseTableVisitor(int numTablesInQuery, 1558 boolean initOptBaseTables) 1559 { 1560 if (valNodeBaseTables == null) 1561 valNodeBaseTables = new JBitSet(numTablesInQuery); 1562 else 1563 valNodeBaseTables.clearAll(); 1564 1565 if (initOptBaseTables) 1566 { 1567 if (optBaseTables == null) 1568 optBaseTables = new JBitSet(numTablesInQuery); 1569 else 1570 optBaseTables.clearAll(); 1571 } 1572 1573 if (btnVis == null) 1577 btnVis = new BaseTableNumbersVisitor(valNodeBaseTables); 1578 } 1579 1580 1595 private void buildTableNumList(FromTable ft, boolean forPush) 1596 throws StandardException 1597 { 1598 if (ft.getTableNumber() >= 0) 1602 optBaseTables.set(ft.getTableNumber()); 1603 1604 if (forPush) 1605 return; 1607 1608 optBaseTables.or(ft.getReferencedTableMap()); 1611 1612 btnVis.setTableMap(optBaseTables); 1621 ft.accept(btnVis); 1622 return; 1623 } 1624 1625} 1626 | Popular Tags |